14M2, SPI, and RGB Module

Marcwolf

Senior Member
Hi Folks.
I've run into a big problem with a project. Having testbedded some circuits on an 28X2 shield I now have made the circuit bowrd for it using an 14M2. I now realise that the 14M2 does not do SPI natively and I cannot get it to work using bit-bangin.

The modules I am using are from Freetronix and are based on the WS2801 IC
The principle of them is simple. There are 3 LEDs (RGB) controlled by a number between 0 and 255 So you send the 3 numbers to make any color you want.

If you have multiple modiles string in series they just overflow the additional values to the next module until all sets pf numbers has been passed

To use with as 28X2 I can do

Code:
  spiout sclk, sdata,1, (255,255,255,255,255,255)
and turn all LED's on full.

However my test code of

Code:
High sclk
for b0 = 0 to 47 
 low sclk
 high sdata
 high sclk
next
low sclk
pause 50
Will only control the first module and not the second.

Can anyone help? I really don;t wnat to dump the completed board just becuse the 14M2's cannot handle the SPIOUT command.

Many thanks
Dave
 

hippy

Technical Support
Staff member
Re-reading the WS2801 datasheet that 'less than 500us between bits/bytes' may not be such an absolute as it seemed -

http://www.sparkfun.com/datasheets/Components/LED/WS2801.pdf

Page 11 says, "CLK pin kept low more than 500uS will make the WS2801 internal status register reset", and that's what the timing diagram on page 12 shows.

Providing CLK is never low for 500us or more ( except when intended to start the first bit ) it seems it would be possible to output each bit at a snail's pace so even 4MHz operation would be possible if desired.

The proof of the pudding would be in doing it but I wouldn't spend the effort on that unless needed as it is a little more complicated than simply running at 32MHz. The attached should work on a 14M2 with two WS2801 controllers cascaded ...
 

Attachments

Marcwolf

Senior Member
Thank you so much Hippy.
I have both LED's working. I am going to study your code and see how I can adapt it to work with multiple LED's on each module.

Again many thanks for your help
Dave
 

Ken_Jungles

New Member
Hi. Greetings from Australia.

I'm new to this forum and also to theh PICAXE. I've dabbled in electronics for a few years and have recently ventured into microprocessors. I'm a bit short on theory but long on perseverence and have got to a point where I have developed a number of 08M projects, mainly flashing LEDs and sounding a transducer but have also managed some remote control gadgets using those 433mhz modules. I am however having similar problems to Marcwolf in getting my RGB LED strip to perform as promised. I've been messing around with the code samples that have been provided and attempting to adapt them for the 08M but not having much success. My best efforts only seem to result in a rising level of colour in the first LED in the strip but nothing in the remaining strip. The strip I am using is very similar to those mentioned and uses the WS2801 chip and I'm currently experimenting with a strip of 3 LEDs. I've tried endless permutations of pausing between data frames but am not making any progress and now I'm wondering if the 08M is capable of driving it.
 

hippy

Technical Support
Staff member
Welcome to the PICAXE Forum.

This does sound like a similar issue of not providing the second set of data's first CLK pulse within 500us of the last.

Unless the trick in post #4 works ( I don't have any WS2801 to test with ) the easiest solution is to use an M2 PICAXE that supports 32MHz operation.
 

Ken_Jungles

New Member
Thanks Hippy. Unfortunately I only have a bunch of 08Ms and I've frittered away another evening trying to get something happening. I don't really understand this bit-shifting stuff very well. I've finally managed managed to figure out how to control the colour of the first LED but I'm buggered if I can get it to cascade over to the next. I've upped the frequency to 8mhz but I don't know how to measure how much time it's actually taking to cycle through the data transfer, so I don't really know if shaving a couple of ms off is going to help. I didn't have much luck getting your trick to work, I wasn't quite sure how to get around some of the 14m functions you used. It's a bit frustrating, given that I'm not trying to do much more than change the colours of 3 LEDs. I was hoping to install them in a model plane for night flying tomorrow night but it looks like I'll have to be satisfied with watching others crash.

I've included the code I'm using below in the hope that you may spot something obvious that I'm doing wrong. Meanwhile, I'll order some of the M2 chips and have another go tomorrow. You're probably right though and I'll be wasting my time. I'd appreciate your view on whether or not it's worth sticking the 08s or upgrade to the 14s. .

Code:
' Control 3 individual LEDs on WS2801 controller strip


symbol BLUE_MIX = b0     	' b0 colour
symbol RED_MIX = b1
symbol GREEN_MIX = b2
symbol leds = b3		' b2 number of leds
symbol time = b4		' b3 duration of event in ms 
symbol tcolour = b5 	' b4 temporary colour storage fror bit shifting
symbol i = b6		' bi iterator i
symbol j = b7		' b5 iterator j
symbol l = b8		' b7 iterator l

' Pin numbers

symbol DI = 4		' pin 4 data	
symbol CI = 2		' pin 2 clock

' Set as outputs

output DI 		' output data 
output CI			' output clock

time = 1
leds = 3

BLUE_MIX = 0     	' Colour Mix
RED_MIX = 1
GREEN_MIX =1

main:
setfreq m8

for i = 1 to leds
	let tcolour = BLUE_MIX
	gosub shiftout_MSBFirst	' shift data via SPI bus
	let tcolour = GREEN_MIX	
	gosub shiftout_MSBFirst	
	let tcolour = RED_MIX
	gosub shiftout_MSBFirst		
	pause time
next i
end

shiftout_MSBFirst:
for j = 1 to 8	 		' number of bits
low DI 				' data low
if tcolour = 0 then skipMSB
high DI 				' data high

skipMSB: 
pulsout CI,1 ‘ pulse clock for 10us
tcolour = tcolour * 2 		' shift variable left for MSB

next j
return
 
Last edited by a moderator:

hippy

Technical Support
Staff member
I'd appreciate your view on whether or not it's worth sticking the 08s or upgrade to the 14s.
An 08M2 should work just as well as any other; it's the speed which is important.

Trying to get an 08M working ( if it can ), and any trying to optimise code for speed, takes both experience and a means to measure the results ( scope or logic analyser). I recall the 14M2 was on the right side of borderline at 32MHz so less chance of success if slower than that.

One thing for speed is that you have to forego GOSUB-RETURN and FOR-NEXT loops, have to trim all the excess which comes with those out of it. Of course that makes the program more unwieldy but it does bring speed. For fastest speed you have to know just which instructions to use and which combinations are better than others and also fit what you are attempting to achieve. That can get quite hard and needs a lot of experience when you are pushing to get something over the borderline.

The simple answer is to use something which handles it already; say an X2 with hardware SPI, or an M2 at 32MHz which is known to work. If not willing to do that, the price is paid in terms of effort achieving the same some other way.
 

hippy

Technical Support
Staff member
I've finally managed managed to figure out how to control the colour of the first LED but I'm buggered if I can get it to cascade over to the next.
Completely untested but this 08M code may work to control two LED's. It's the 14M2 code hacked to try the trick in #4 and to use PEEK/POKE rather than @bPtr. Uses your current wiring connections SDO = pin 4, SCK = pin 2.

Worth a try ...
 

Attachments

Ken_Jungles

New Member
Thanks for that Hippy. I've been busy for a couple of days and just got around to trying it. No luck.

Not sure if line 67 - b0 = 256/3 + b0 is correct for the 08m memory. Tried changing it to 129 but still no go. Single LED just cycles through the rainbow. I haven't quite got my head around what's going on in that UpdateLevels subroutine but I'll come back to it.

The good news is that I've received my 08M2's and they seem to be working with the 14M2 code after modifying the LED RAM address (at least I think that's what I'm doing) I've tried it with three LEDs and while I'm not getting the colour I expected, they are all working sequentially. I am encouraged enough to continue with the task so thanks again.
 

hippy

Technical Support
Staff member
The "b0=256/3+b0" is correct; that just ensures the second LED's brightness differs from the first; as one fades up and down, the other fades up and down at the same rate but out of phase with the first. The "UpdateLevels" simply sets what the LED colours / brightness should be every loop.

It's a shame the 08M version did not work but that was really 'fingers crossed, it might'.

Good to hear you are getting there with the 08M2; you are welcome to post your code so myself and others can take a look at it to see if there are any obvious issues in it not giving exactly what you hope for.
 

Ken_Jungles

New Member
You're very generous with your time Hippy.

When I moved to the M2 and got something happening, I eventually figured out what you meant by changing the phase of the LEDs. I'm afraid it's hard to cram new knowledge into this old brain and I'm very much into a trial and error approach. So long as I can see an effect I can generally work out the cause.

What I'm trying to do is control probably 5 separate light strips attached to the wings and fuselage of a model aircraft. Each strip may have anything from 3-6 LEDs and I want to be able to control them in pairs by a PWM signal from the radio receiver. I have so far managed to build a working off/on switch based on the 08m.

At the moment the spec (wish list) includes:
1. Changing the colour of paired LED strips LEDS to R/G/B/W or (some Red, Some Blue etc.) I think I can do this for individual strips now, though I'm still working on White.
2. Making the strips flash on/off (Again, this seems to be working)
3. Strobing the flash rate (Briefly on brightly, with a longer gap between. Still working on this. At the moment I seem to be stuck on 50/50 rate).
4. A pattern where a single lit LED moves up and/or down the strip

I'm not sure if I can achieve all this with a single processor connected to all of the LEDS or I'll need multiple processors. At this stage I'm just trying to develop the individual capabilities and haven't thought too much about integrating them into a single programme.

The code so far, largely thanks to your good self is below:
Code:
' Based on code from PICAXE FORUM (Hippy) at 27/03/2012
'______________________________________________________

Symbol LED0     = 128 - 9	' Put the LED data in RAM location xxx..128, 3 bytes per LED
Symbol LED1     = LED0  + 3
Symbol LED2     = LED1  + 3


Symbol BLU      = 0
Symbol GRN      = 1
Symbol RED      = 2

Symbol SDO      = 4 : Symbol SDO_PIN = pinB.4
Symbol SCK      = 2 

SetFreq M32

Low SDO
Low SCK

Do
  Gosub SendLevels
  Gosub UpdateLevels
  pause 4		 'Controls flash rate?
Loop


SendLevels:

  ' Sends one byte every 1ms approx?
  ' Sends one bit every 122us approx?
  ' Time between bytes is 330us approx?

  bPtr = LED0
  Do
    b0 = @bPtrInc
    SDO_PIN = bit7 : PulsOut SCK, 1
    SDO_PIN = bit6 : PulsOut SCK, 1
    SDO_PIN = bit5 : PulsOut SCK, 1
    SDO_PIN = bit4 : PulsOut SCK, 1
    SDO_PIN = bit3 : PulsOut SCK, 1
    SDO_PIN = bit2 : PulsOut SCK, 1
    SDO_PIN = bit1 : PulsOut SCK, 1
    SDO_PIN = bit0 : PulsOut SCK, 1
  Loop Until bPtr = 0

  Return

UpdateLevels:		'Controls Colours and Rise/fall rate
  
  bPtr = LED0 + red
  b0 = @bPtr
  b0 = b0 + 32		'Controls rate of colour rise/fall?
  @bPtr = b0

  bPtr = LED1 + red
  @bPtr = b0
  
  bPtr = LED2 + red
  @bPtr = b0
 
  Return
 
Last edited by a moderator:

hippy

Technical Support
Staff member
Testing your code ( but without RGB LED strips ) I cannot see anything wrong with it, so it should be working.

Timings seem correct, same as for 14M2.
 
Top