Using a 40X2 Picaxe with Picaxe 40X2 protoboard to control individually 10 RGB LEDs

johnhr

New Member
I'm new to this and could use some help setting this up. I've attached 4 wires to each led and have a strand 5 feet long. Can I use one common cathode wire attached to all leds instead of a common cathode wire attached to each and therefore needing 10 ground holes on my breadboard instead of one?

Do I need a LED controller or could I control each led with my program? I want to create a program that will make the leds randomly turn on and off to create patterns and change colors also. I think I need 30 outputs to do this, 3 per led, and will the 40x2 have enough voltage and current to do this? I'm using a 5.1V, 700mA wallwart. My leds are 5mm and medium brightness.

Any programming approaches and/or ideas would be gladly appreciated.

The bottom of the breadboard has a red rubberish layer covering the wire holes. When I place a wire in the hole it either stays and holds the wire or breaks out and the wire is loose??

Thanks
 

nick12ab

Senior Member
Welcome to the PICAXE Forum.

I'm new to this and could use some help setting this up. I've attached 4 wires to each led and have a strand 5 feet long. Can I use one common cathode wire attached to all leds instead of a common cathode wire attached to each and therefore needing 10 ground holes on my breadboard instead of one?
Yes you can use one common ground. But don't start that without reading the rest of this post.

Do I need a LED controller or could I control each led with my program? I want to create a program that will make the leds randomly turn on and off to create patterns and change colors also.
You can control the LEDs with the PICAXE.

I think I need 30 outputs to do this, 3 per led
The PICAXE-40X2 has four 8-bit ports which total to 32 I/O pins that you can use as outputs. This leaves you with two pins free plus the Serial In pin. You might prefer to multiplex the LEDs - this will have a small reduction in brightness, a significant reduction in power consumption and greatly reduce the number of pins used e.g. 13 pins for 10x3 multiplex. If using multiplexing, you can't use a common ground for all the RGB LEDs but you will be able to make other pins common.

and will the 40x2 have enough voltage and current to do this?
Voltage won't be the issue. Current may be. This depends on whether you will be multiplexing the LEDs or not and what the value of I (see below) you're using is.

I'm using a 5.1V, 700mA wallwart.
Should be no problem with that. Make sure that it is a regulated supply though - if it is unregulated then it could produce up to 7 volts which will fry the PICAXE. Check it with a multimeter and don't forget bulk and decoupling capacitors in your circuit.

My leds are 5mm and medium brightness.
"Medium brightness"...

You should find out the current and forward voltage by checking the datasheet. Then use the equation R=V/I where V is the power supply voltage minus the LED forward voltage and I is the current in Amps. You can use a higher value resistor or lower value of I if you want lower brightness.

The bottom of the breadboard has a red rubberish layer covering the wire holes. When I place a wire in the hole it either stays and holds the wire or breaks out and the wire is loose??
Breadboard? The Rev-Ed project boards have this and you are meant to peel it off. I've never seen breadboards with a red rubberish layer.
 

johnhr

New Member
Welcome to the PICAXE Forum.

Yes you can use one common ground. But don't start that without reading the rest of this post.

You can control the LEDs with the PICAXE.

The PICAXE-40X2 has four 8-bit ports which total to 32 I/O pins that you can use as outputs. This leaves you with two pins free plus the Serial In pin. You might prefer to multiplex the LEDs - this will have a small reduction in brightness, a significant reduction in power consumption and greatly reduce the number of pins used e.g. 13 pins for 10x3 multiplex. If using multiplexing, you can't use a common ground for all the RGB LEDs but you will be able to make other pins common.



Voltage won't be the issue. Current may be. This depends on whether you will be multiplexing the LEDs or not and what the value of I (see below) you're using is.

Should be no problem with that. Make sure that it is a regulated supply though - if it is unregulated then it could produce up to 7 volts which will fry the PICAXE. Check it with a multimeter and don't forget bulk and decoupling capacitors in your circuit.

"Medium brightness"...

You should find out the current and forward voltage by checking the datasheet. Then use the equation R=V/I where V is the power supply voltage minus the LED forward voltage and I is the current in Amps. You can use a higher value resistor or lower value of I if you want lower brightness.



Breadboard? The Rev-Ed project boards have this and you are meant to peel it off. I've never seen breadboards with a red rubberish layer.
How do you multiplex?
They are red, 12.mA with 180ohm, green, 14.4mA with 150ohm, and blue, 16.1mA with 100ohm.
Thanks
 

westaust55

Moderator
If you are trying to drive multiple LEDs (and an RGB LED counts as 3 LED’s) directly from a PICAXE chip then you need to also keep in mind the current limits for the PICAXE chip.

See the Rev Ed webpage here for links to the corresponding PIC datasheets: http://www.picaxe.com/What-is-PICAXE/PICAXE-Chip-Labels/

From the datasheet relating to the 40X2 here are some of the pertinent data:
Maximum current into VDD pin (-40°C to +85°C) .................. 200 mA
Maximum current into VDD pin (+85°C to +125°C) ..................85 mA

Maximum output current sourced by any I/O pin .....................25 mA

Maximum current sourced by all ports (-40°C to +85°C).....................185 mA
Maximum current sourced by all ports (+85°C to +125°C) ...................70 mA
From this data were can see that for all of the ports in total the maximum current is 70 mA and we should endeavour not to operate right at this Absolute Maximum limit.

Lets say we consider 60 mA as the total current then with just 1 RGB led the max current into all 3 colours at once would be 20 mA.

You would be better to use either an LED driver chip or some transistors.

A few years ago I did an 8x8 RGB matrix. See here for some details.
http://www.picaxeforum.co.uk/showthread.php?10836-Looking-for-RGB-LEDs-in-Australia/page4
This project did no allow for PWM’ing of the outputs to have a full range of colours so limited to 8 colours on each RGB LED. This still needed transistors to drive the LEDs and used multiplexing techniques as mentioned above by nick12ab.

Some LED driver chips although intended primarily for 7-Segment multi-digit displays can also be used for discrete LED and RGB control.
These include the SAA1064 and the MAX7219 but these chips cannot control the current of each RGB element individually so again limited range of colours without great effort.

Chips such as the WS2801, WS2803, etc are intended to drive RGB LEDs and can be daisy chained for longer strings with multiple RGB LEDs. Such chips allow control of each colour independently so the full range of colurs is achievable. See my thread here for some information withr espect to the WS2801:
http://www.picaxeforum.co.uk/showthread.php?22713-Getting-Started-with-the-WS2801-3-Channel-RGB-LED-Driver-with-PWM-output

The WS2801 which I used is a 3 channel chip to drive one RGB LED. the WS2803 is an 18 channel chip capable of driving 6 RGB LEDs with a single chip.
The code is similar and I helped another forum member recently (see this forum) to get a Ws2803 running.
 
Last edited:

nick12ab

Senior Member
How do you multiplex?
They are red, 12.mA with 180ohm, green, 14.4mA with 150ohm, and blue, 16.1mA with 100ohm.
In multiplexing only one 'set' of LEDs will be on at any one time but each 'set' will be lit in quick succession to make it look like they are all on at the same time. This is an extremely common technique and is often used for 7-segment LED displays and also OLED displays - if you have something that uses those look at it and it will look like all the segments are on at once but if you move your eyes from side to side quickly you should see it flicker.

If you won't use the PICAXE above 85°C then you have a 185mA current limit.

Using the 10x3 layout I suggested earlier, you can connect the red terminal for all the LEDs together, the green terminal for all the LEDs together and the blue terminal for all the LEDs together. You now have three terminals for the colours and one cathode for each RGB LED. With your 16.1mA blue LED, that makes a total of 161mA if you have all 10 blue LEDs on which I'd say is pushing your luck a little and when low power NPN transistors are practically given away I would recommend that you use them. Use an NPN transistor for each cathode and a PNP transistor for each of the three colour anodes. The PNP transistors will need to source up to 161mA each so you won't just be able to use a small 100mA transistor but you won't need a 10A one! Finally you need a base resistor for each transistor - 1k usually works. Don't forget the resistors for the LEDs themselves.

After you have that set up, to display something you simply turn on each PNP transistor in turn and the NPN transistors that you have turned on at that point determines which colours are shown. Turn off all the NPN transistors before you change which PNP transistor is on to prevent 'ghosting'. Finally don't forget that a PNP transistor is 'on' when the base is pulled low and 'off' when the base is high - this is the opposite of an NPN transistor.
 

johnhr

New Member
I read your help with the ws2803. This sounds like a better build and once done I could expand to more LEDs, which is my ultimate goal anyway.
My 40X2 has a EEPROM slot. As long as I'm buying would having one help me along the way with my LEDs?

I really appreciate your help! Thanks
 

johnhr

New Member
The i2c socket takes a 24LCxx series EEPROM which has 8 pins, if that is the correct terminology, the 8 pins I mean.
 

westaust55

Moderator
If your 40X2 proto-board is the Rev Ed AXE022 then yes there is one EEPROM socket with the three slave address pins set as %001. Full slave address is %10100010.

The PICAXE internal EEPROM has only 256 bytes so can be limiting if you are storing all of the data for a light show sequence if using look-up data and not maths based sequences.
If you are going to store a range of sequences then adding a 24LC256 or 24LC512 EEPROM can give you a lot of needed space to save many sequences for the 10 RGB LEDs.


It you think in terms of two WS2803 chips for your 10 RGB LED's that equates 30 bytes of data in total per instant.
If you change the data at say 0.5 second increments then for a 1 minute sequence you would need
30 * 60 / 0.5 = 3600 bytes of data.

A 24LC256 has 32,768 bytes of EEPROM space which allows for ~9 mins of sequences (the 24LC512 doubles that).
 

johnhr

New Member
I now have a 24LC512 and a couple WS2803 on the way. Now I need to prepare my AXE022 40X2 proto-board, which I'm not sure what I need to do. I will need to study the schematics to see how the WS2803s are wired to the 40X2. Thanks for all your help.
 

johnhr

New Member
Westy,
If I'm going to use a 24LC512 in my EEPROM socket and 2 WS2803s to drive my 16 LEDs, does each LED need a common cathode wire or can one common cathode wire be in series with all 16 LEDs? I have already soldered a common to each LED.
Thanks
 

westaust55

Moderator
Hi John,

sorry, but I missed the point previously that you were looking at using common cathode RGB LED's.
The WS2801, WS2803 and even some other chips such as the TLC5940 have outputs that are in effect low side switches and sink the current from the LED's not source current to the LEDs.

As such, to use the WS2803, you would need common Anode type RGB LED's.
 

johnhr

New Member
Hi John,

sorry, but I missed the point previously that you were looking at using common cathode RGB LED's.
The WS2801, WS2803 and even some other chips such as the TLC5940 have outputs that are in effect low side switches and sink the current from the LED's not source current to the LEDs.

As such, to use the WS2803, you would need common Anode type RGB LED's.
So each LED would need its own anode lead and not one anode lead in series for all the LEDs?
 

besupreme

New Member
Maybe it's a good idea to download and read the WS2803 data sheet. Each WS2803 has 18 current sinks that you can program by software and a resistor. All your LED's anodes go to your supply voltage. I'm just making a board for 2 WS2803's. To give you an idea on how to connect the LED's, look at this schematic:
PIC LED36 WS2803 S.JPG
You see that on my 20 pin connectors, I put 2 (+) pins where all LED's connect to. You can also use only 1 supply wire for all 36 LED's that your 2 WS2803's can drive.

I use a separate +C supply pin on this board, because the LED rows I'll control will have about 24V for 6 LED in series. If you control only 1 LED per pin, use 5V.

Ah, I didn't delete the german text.. ;-)
 

johnhr

New Member
Each WS2803 has 18 current sinks that you can program by software and a resistor. All your LED's anodes go to your supply voltage. I'm just making a board for 2 WS2803's. To give you an idea on how to connect the LED's.
I'm coming from a AXE022 protoboard with a 40X2 chip. I added a 24LC512 EEPROM chip but don't know where I'm supposed to add the 100nF miniature cap. I have 3 WS2803 RGB LED drivers, so I can have 6 LEDs on each 2803, each lead with its own pin. Looking at your data sheet I don't know where your X1, X2, and X3 come from. Any help here?
 
Last edited by a moderator:

johnhr

New Member
I've worked this out and have 6 RGB LEDs lit using westaust55s program for the WS2801, with a few adjustments. I've added 2 more WS2803s for a total of 18 RGB LEDs and need to adjust the program again. I've also used some of REB100s thread: WS2803, to help me along. When I'm all done I'll post my schematic and program.
 

johnhr

New Member
westaust,

I added the remaining 12 RGB LEDs with two more WS2803 LED drivers and ran your program with my TotalMods = 1 and Data_Sets = 18 and your pattern expanded to all 18 LEDs without me adjusting the Mods to 3 and Data_Sets to (I don't know to what). I thought that the Mods = 1 would only drive my single WS2803 and that I would have to change it to 3 to drive the three WS2803s. I'm just trying to under your code and why it lit all 18 LEDs without me changing your program.

Thanks
 

westaust55

Moderator
My original program concept was to use the TotalMods parameter to define how many modules/chips were connected.
Then send groups of data on a module/chip basis (3 bytes for WS2801, 18 bytes for WS2803).
Sounds as if you have made your code treat the entire display as a single module and pump out all necessary data So it still works.
With respect to my program for the WS2801, to work with the WS2803 as originally written the line
No_LEDs = 3 * TotalMods
Would need the "3" changed to "18"
Better to consider a code change and use a SYMBOL statement as a pre definition of the No of LED/channels per module/chip rather than hard code within body of program to make my code more flexible for use with both WS chips.
 
Last edited:

johnhr

New Member
I'm now trying to adjust your program to do a run of red going from LED 1 to LED 18. I'm having difficulty because I really don't understand your code. I've gotten the LEDs to flash and change colors but I can't get them to light one at a time and in sequence. Any tips or hints? Thanks
 

westaust55

Moderator
Have a try with this code. Passes the syntax check but I have not tested it.

Code:
; =================================================
;   File....... 40X2 3xWS2803
;   Purpose.... An untested demo program to show control of a three WS2803 RGB LED drivers
;   Author..... Westaust55
;   E-mail.....
;   Started.... 13-05-2013
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
; A program to to demonstrate the control of a short string of three WS2803 RGB LED driver chips
;  
; -----[ Revision History ]---------------------------------------------------
;
; A = 13-05-2013	First release	total program size = 232 bytes
; =================================================
;
#PICAXE 40X2
SETFREQ M8   ; default clock speed is 8 MHz. Cannot be run at 4 MHz with multiple SHIFTOUT lines
;
; -----[ I/O Definitions ]-------------------------------------------------- 

; - - - DIGITAL INPUT PINS  - - -
; none used
;
; - - - DIGITAL OUTPUT PINS - - -
SYMBOL SData	= B.6 ; SDI Pin on the WS2801
SYMBOL SClock	= B.7 ; CKI Pin on the WS2801

; -----[ Constants ]-------------------------------------------------------
SYMBOL TotalMods	= 3 ; Define how many WS2801 modules are connected
SYMBOL LEDperMod  = 6 ; define how many LEDs per module
SYMBOL Data_Sets	= 4	; define how many sets of data are held in EEPROM
SYMBOL SeqStep_Delay = 500 ; for 0.500 sec delay at 8 MHz

; Define EEPROM locations for some colour data - expand the data and pointer list to suit
SYMBOL Red 		= $00
SYMBOL Green 	= $03
SYMBOL Blue 	= $06
SYMBOL Magenta 	= $09
SYMBOL Yellow 	= $0C
SYMBOL Cyan 	= $0F
SYMBOL White	= $12
SYMBOL Black	= $15

; -----[ Variables ]-------------------------------------------------------
SYMBOL LED_Data	= b0
SYMBOL No_LEDs	= b1
SYMBOL CycleLen	= b2
SYMBOL MemAddr 	= b3

SYMBOL LED_Index	= b4
SYMBOL WhichIsRed = b5
SYMBOL Counter	= b6

; Define some colours with 3 Bytes per colour at quarter intensity - $FF for max intensity
EEPROM $00, ($3F, $00, $00) ; Red
EEPROM $03, ($00, $3F, $00) ; Green
EEPROM $06, ($00, $00, $3F) ; Blue
EEPROM $09, ($3F, $00, $3F) ; Magenta
EEPROM $0C, ($3F, $3F, $00) ; Yellow
EEPROM $0F, ($00, $3F, $3F) ; Cyan
EEPROM $12, ($3F, $3F, $3F) ; White
EEPROM $15, ($00, $00, $00) ; Black = no colour segment illuminated

; -----[ Initialization ]--------------------------------------------------
Init:
	Low SData
	Low Sclock
	MemAddr = 0				  ; set the EEPROM data pointer to the first location
	No_LEDs = LEDperMod * TotalMods ; calculate the total number of individual LED channels
	CycleLen = No_LEDs * Data_Sets  ; calculate the number of bytes of EEPROM data in the cycle
;
; -----[ Program Code ]----------------------------------------------------	
Main:
    DO
	WhichIsRed = LED_Index // No_LEDs  ;  for each loop of the program, this defines a new value 0 to 17 for the 18 RGB LED's. That LED is Red and all others are off
    	ptr = 0					 ; set pointer to first scratchpad location for next datasets
    	For Counter = 1 TO No_LEDs
    		IF Counter = WhichIsRed THEN
    			MemAddr = Red
    		ELSE
    			MemAddr = Black
    		ENDIF
    		GOSUB FetchColour	; Fetch Colour definition from EEPROM and save in next scratchpad location
    	NEXT Counter
    	GOSUB SendData		; call subroutine to transfer all data to the WS2803 string
	PAUSE SeqStep_Delay	; delay to give user time to see the new colour pattern  	
  	LED_Index = LED_Index + 1 // 252	; any multiple of 18 will work if we let counter get to 255 and roll over to 0 then display will "jump"
    LOOP						; loop forever

;
; -----[ Subroutines ]----------------------------------------------------- 
;
; ***** Subroutine to fetch the data from EEPROM and save into Scratchpad for one RGB LED colour
  
  FetchColour:
	READ MemAddr, LED_Data	; Fetch the Red component of the specified colour
	@PtrInc = LED_Data	; save into the scratchpad RAM at required location
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Green component of the specified colour
	@PtrInc = LED_Data
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Blue component of the specified colour
	@PtrInc = LED_Data
  	RETURN		; Return after the RGB data for one RGB LED (3 channels) has been placed into the Scratchpad
;
; Subroutine to serially clock out the data through the WS2803 chips for THREE RGB LEDs
; NOTE this is limited to three WS2803 chips without adding more variables/field to the SHIFTOUT command
SendData:
	Ptr = 0
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of first WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of second WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of third WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	RETURN
For long patterns rather than trying to store lots of data in memory, if you can use maths and create a formula to calculate which LED and what colour then the code can be far simpler and shorter.

Have a look what I did in post 15 here: http://www.picaxeforum.co.uk/showthread.php?22713-Getting-Started-with-the-WS2801-3-Channel-RGB-LED-Driver-with-PWM-output/page2
It is for a small string of WS2801's but the same concepts apply.

with your three WS2803's you have to send out 18 bytes of data per chip. It is just a case of defining how you want to control/define that data.
 
Last edited:

johnhr

New Member
Hi westaust

I tried the above code. I get the first 6 LEDs flashing red up the line with high intensity, the next 6 flashing red with very low intensity, and the remaining 6 flashing red with high intensity again. They repeat alternating from high to low intensity and all flashing simultaneously.

It's too late to go back to just using the 40X2 chip because I'm all wired with the three WS2803s. I understand how to control the lights just using the 40X2 with highs and lows on the different A, B, C, and D pins. I don't understand how to light the first LED with OUT0, OUT1, OUT2 and then LED2, using OUT3, OUT4, and OUT5, and so forth up the chip and then the next WS2803 and then the third WS2803. I just want to light the first LED and then the next LED and then the next LED, etc. I've spent days trying different things with your various code but cannot do the above. What am I missing or not understanding?
 

westaust55

Moderator
Can you please post your code as you are currently trying - rather than folks here trying to guess at exactly where you are at.

Maybe attach a short video clip to show exactly what is happening. (A picture is work a thousand words and a video even more).

When you say: "first 6 LEDs flashing red up the line"
is that a case with only one RED LED on at any time and the illuminated LED moving along the row of LEDs - which is what is intended by my last code.


Are the high brighness LEDs always on the same chips and the low brightness LEDs always on the other chips?
If so, that could be a poor/high resistance joint somewhere.
 

johnhr

New Member
Maybe attach a short video clip to show exactly what is happening. (A picture is work a thousand words and a video even more).
I will try this tonight. Posting code and a picture/video might be a challenge for me but I'll try. I still haven't been able to quote correctly like you do.

When you say: "first 6 LEDs flashing red up the line"
is that a case with only one RED LED on at any time and the illuminated LED moving along the row of LEDs
Yes

Are the high brighness LEDs always on the same chips
No, they alternate

and the low brightness LEDs always on the other chips?
No, they alternate

I was reading the Preliminary WS2803 Datasheet under "The Connection and Driving of Cascading Operation", page 7/8, it states,
"The(y) transmit the data over long distance by cascading, the WS2803 integrates push-pull output stage with strong driving capability which enables the data and clock can be transmitted up to 6 meters at 2MHz clock frequency. To prevent the reflection, it is necessary to connect a 50ohm resistor at the data input or output port for impedance match."

My strand is 13 feet long with the 18 LEDs, would this affect me? I have a 1.8k ohm resistor between each GND and IREF going to ground and a 0.1mF cap tight between GND and VCC on each WS2803 chip and that's all.

How do I address specifically OUT0, OUT1, and OUT2 on the WS2803, or pin 6, 7, and 8 from my 40X2? I've been trying to figure this out and keep getting syntax errors with PORT.PIN statements.

Thanks for your help
 

westaust55

Moderator
You do not address the WS2803 outputs in the same manner as PICAXE pins nor as one would on some IO expander chips.
For each WS2803, you must sent one complete byte of data per pin and a total of 18 bytes per entire chip. There is no way to address a single output alone and 18 bytes must be send as one block/packet of data.

The reason each pin needs an entire byte is that the value 0 to 255 sets the intensity level (using internal PWM methods) for that output which is required to adjust the LED brightness. That is how you get many colours from an RGB LED.
 

johnhr

New Member
I will try and post this movie along with what produced it.

How do I insert a .wmv movie or .mov movie? When I find out I will call this Code 1 with Movie 1 because I'm going to send the movie and code for your red lights also, which I will call Code 2 with Movie 2.



Code:
; =================================================
;   File....... 40X2 3xWS2801
;   Purpose.... A demo program to show control of a WS2801 RGB LED drivers
;   Author..... Westaust55
	'Modified by John
	'Started.... 05-04-2013
;   E-mail.....
;   Started.... 25-11-2012
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
; A program to to demonstrate the control of a short string of three WS2801 RGB LED driver chips
; Modified:  A program to control 3 WS2803 RGB LED driver chips
; -----[ Revision History ]---------------------------------------------------
;
; A = 25-11-2012	First release	total program size = 355 bytes
; =================================================
;
#PICAXE 40X2
SETFREQ M8   ; default clock speed is 8 MHz.

; -----[ I/O Definitions ]-------------------------------------------------- 

; - - - DIGITAL INPUT PINS  - - -
; none used
;
; - - - DIGITAL OUTPUT PINS - - -
SYMBOL SData	= C.2 ; on 40X2 going to SDI Pin on the WS2803, pin 5
SYMBOL SClock	= C.1 ; on 40X2 going to CKI Pin on the WS2803, pin 4

; -----[ Constants ]-------------------------------------------------------
SYMBOL TotalMods	= 1 ; Define how many WS2803 modules are connected
SYMBOL Data_Sets	= 18	; define how many sets of data are held in EEPROM
SYMBOL SeqStep_Delay = 500 ; for 0.500 sec delay at 8 MHz

; Define EEPROM locations for some colour data - expand the data and pointer list to suit
SYMBOL Red 		= $00
SYMBOL Green 	= $03
SYMBOL Blue 	= $06
SYMBOL Magenta 	= $09
SYMBOL Yellow 	= $0C
SYMBOL Cyan 	= $0F
SYMBOL White	= $12

; -----[ Variables ]-------------------------------------------------------
SYMBOL LED_Data	= b0
SYMBOL No_LEDs	= b1
SYMBOL CycleLen	= b2
SYMBOL MemAddr 	= b3

; Define some colours with 3 Bytes per colour at quarter intensity - $FF for max intensity
EEPROM $00, ($3F, $00, $00) ; Red
EEPROM $03, ($00, $3F, $00) ; Green
EEPROM $06, ($00, $00, $3F) ; Blue
EEPROM $09, ($3F, $00, $3F) ; Magenta
EEPROM $0C, ($3F, $3F, $00) ; Yellow
EEPROM $0F, ($00, $3F, $3F) ; Cyan
EEPROM $12, ($3F, $3F, $3F) ; White

; -----[ Initialization ]--------------------------------------------------
Init:
	Low SData
	Low Sclock
	MemAddr = 0				  ; set the EEPROM data pointer to the first location
	No_LEDs = 18 * TotalMods		  ; calculate the total number of individual LED channels
	CycleLen = No_LEDs * Data_Sets  ; calculate the number of bytes of EEPROM data in the cycle
;
; -----[ Program Code ]----------------------------------------------------	
Main:
    DO
	ptr = 0					 ; set pointer to first scratchpad location for next sets
	MemAddr = Red : GOSUB FetchColour	 ; colour for 1st WS2801 and save data to Scratchpad
	MemAddr = Yellow : GOSUB FetchColour ; colour for 2nd WS2801 and save data to Scratchpad
	MemAddr = Green : GOSUB FetchColour  ; colour for 3rd WS2801 and save data to Scratchpad 
	GOSUB SendData			 ; call subroutine to transfer all data to the WS2801 string
	PAUSE SeqStep_Delay		 ; delay to give user time to see the new colour pattern
	
	ptr = 0
	MemAddr = Yellow : GOSUB FetchColour
	MemAddr = Green : GOSUB FetchColour
	MemAddr = Cyan : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Green : GOSUB FetchColour
	MemAddr = Cyan : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Cyan : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	MemAddr = Magenta : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Blue : GOSUB FetchColour
	MemAddr = Magenta : GOSUB FetchColour
	MemAddr = White : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Magenta : GOSUB FetchColour
	MemAddr = White : GOSUB FetchColour
	MemAddr = Yellow : GOSUB FetchColour
	GOSUB SendData
	PAUSE 500
	ptr = 0
	MemAddr = White : GOSUB FetchColour
	MemAddr = Yellow : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Yellow : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	MemAddr = Cyan : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay
    LOOP						; loop forever

;
; -----[ Subroutines ]----------------------------------------------------- 
;
; ***** Subroutine to fetch the data from EEPROM and save into Scratchpad for one RGB LED colour
  
  FetchColour:
	READ MemAddr, LED_Data	; Fetch the Red component of the specified colour
	@PtrInc = LED_Data	; save into the scratchpad RAM at required location
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Green component of the specified colour
	@PtrInc = LED_Data
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Blue component of the specified colour
	@PtrInc = LED_Data
  	RETURN		; Return after the RGB data for WS2801 module has been placed into the Scratchpad
;
; Subroutine to serially clock out the data through the SW2801 chips for THREE RGB LEDs
; NOTE this is limited to three WS2801 chips without adding more variables/field to the SHIFTOUT command
SendData:
	Ptr = 0
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	RETURN


[/code]
 

johnhr

New Member
This is Code 2 for Movie 2 when I figure out how to attach it.



Code:
; =================================================
;   File....... 40X2 3xWS2803
;   Purpose.... An untested demo program to show control of a three WS2803 RGB LED drivers
;   Author..... Westaust55
;   E-mail.....
;   Started.... 13-05-2013
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
; A program to to demonstrate the control of a short string of three WS2803 RGB LED driver chips
;  
; -----[ Revision History ]---------------------------------------------------
;
; A = 13-05-2013	First release	total program size = 232 bytes
; =================================================
;Modified by Johnhr 14-05-2013 for the 40X2

#PICAXE 40X2
SETFREQ M8   ; default clock speed is 8 MHz. Cannot be run at 4 MHz with multiple SHIFTOUT lines
;
; -----[ I/O Definitions ]-------------------------------------------------- 

; - - - DIGITAL INPUT PINS  - - -
; none used
;
; - - - DIGITAL OUTPUT PINS - - -
SYMBOL SData	= C.2 ; SDI Pin on the WS2803
SYMBOL SClock	= C.1 ; CKI Pin on the WS2803

; -----[ Constants ]-------------------------------------------------------
SYMBOL TotalMods	= 1 ; Define how many WS2803 modules are connected
SYMBOL LEDperMod  = 18 ; define how many LEDs per module
SYMBOL Data_Sets	= 18	; define how many sets of data are held in EEPROM
SYMBOL SeqStep_Delay = 500 ; for 0.500 sec delay at 8 MHz

; Define EEPROM locations for some colour data - expand the data and pointer list to suit
SYMBOL Red 		= $00
SYMBOL Green 	= $03
SYMBOL Blue 	= $06
SYMBOL Magenta 	= $09
SYMBOL Yellow 	= $0C
SYMBOL Cyan 	= $0F
SYMBOL White	= $12
SYMBOL Black	= $15

; -----[ Variables ]-------------------------------------------------------
SYMBOL LED_Data	= b0
SYMBOL No_LEDs	= b1
SYMBOL CycleLen	= b2
SYMBOL MemAddr 	= b3

SYMBOL LED_Index	= b4
SYMBOL WhichIsRed = b5
SYMBOL Counter	= b6

; Define some colours with 3 Bytes per colour at quarter intensity - $FF for max intensity
EEPROM $00, ($3F, $00, $00) ; Red
EEPROM $03, ($00, $3F, $00) ; Green
EEPROM $06, ($00, $00, $3F) ; Blue
EEPROM $09, ($3F, $00, $3F) ; Magenta
EEPROM $0C, ($3F, $3F, $00) ; Yellow
EEPROM $0F, ($00, $3F, $3F) ; Cyan
EEPROM $12, ($3F, $3F, $3F) ; White
EEPROM $15, ($00, $00, $00) ; Black = no colour segment illuminated

; -----[ Initialization ]--------------------------------------------------
Init:
	Low SData
	Low Sclock
	MemAddr = 0				  ; set the EEPROM data pointer to the first location
	No_LEDs = LEDperMod * TotalMods ; calculate the total number of individual LED channels
	CycleLen = No_LEDs * Data_Sets  ; calculate the number of bytes of EEPROM data in the cycle
;
; -----[ Program Code ]----------------------------------------------------	
Main:
    DO
	WhichIsRed = LED_Index // No_LEDs  ;  for each loop of the program, this defines a new value 0 to 17 for the 18 RGB LED's. That LED is Red and all others are off
    	ptr = 0					 ; set pointer to first scratchpad location for next datasets
    	For Counter = 1 TO No_LEDs
    		IF Counter = WhichIsRed THEN
    			MemAddr = Red
    		ELSE
    			MemAddr = Black
    		ENDIF
    		GOSUB FetchColour	; Fetch Colour definition from EEPROM and save in next scratchpad location
    	NEXT Counter
    	GOSUB SendData		; call subroutine to transfer all data to the WS2803 string
	PAUSE SeqStep_Delay	; delay to give user time to see the new colour pattern  	
  	LED_Index = LED_Index + 1 // 252	; any multiple of 18 will work if we let counter get to 255 and roll over to 0 then display will "jump"
    LOOP						; loop forever

;
; -----[ Subroutines ]----------------------------------------------------- 
;
; ***** Subroutine to fetch the data from EEPROM and save into Scratchpad for one RGB LED colour
  
  FetchColour:
	READ MemAddr, LED_Data	; Fetch the Red component of the specified colour
	@PtrInc = LED_Data	; save into the scratchpad RAM at required location
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Green component of the specified colour
	@PtrInc = LED_Data
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Blue component of the specified colour
	@PtrInc = LED_Data
  	RETURN		; Return after the RGB data for one RGB LED (3 channels) has been placed into the Scratchpad
;
; Subroutine to serially clock out the data through the WS2803 chips for THREE RGB LEDs
; NOTE this is limited to three WS2803 chips without adding more variables/field to the SHIFTOUT command
SendData:
	Ptr = 0
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of first WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of second WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of third WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	RETURN
 

westaust55

Moderator
I cannot see anything in the program that would cause the problem you indicate with the last posted code.
I ran it in the PE simulator and it is doing what I expected. You have indicated the illuminated RED LED steps along the sequence. It is the alternating brightness I cannot find a reason for.

It almost seems like some WS2803 chips get the data pushed along a bit so the value into each WS2803 register is lower in value (ie /2 or /4) causing the LEDs to be less bright but that is discounted if the next chip in the string is back to normal brightness.

One line I did spot that is not the cause of you problem but needs fixing for accuracy is the line:
WhichIsRed = LED_Index // No_LEDs + 1 ; for each loop of the program, this defines a new value 1 to 18 for the 18 RGB LED's. That LED is Red and all others are off
with the added "+ 1" so on the first pass, the first LED is illuminated (not waiting till the second pass).

Purely a suggestion, but in case timing is borderline even with the SHIFTOUT command, try increasing the PICAXE speed.
Note the 40X2 is very slightly slower than 40X1 as the X2 parts have a few more overheads to handle.
So change the SETFREQ M8 to SETFREQ M16
 

johnhr

New Member
Someone on Utube who was working with the WS2803 chip said that data is sent to the last chip first, so for me it would be chip 3, then 2, then 1. I don't know if this is correct but if it is maybe that is why the bright string is broken up from the lighter string.

I am adding code that I combined to show 3 of your patterns. I get a syntax OK, but when I simulate it I keep getting a "stack error - return without gosub" once it reaches the RETURN at the end of FetchColour (I highlighted it). I have the counter set at 1 for now because it takes a long time to get through Simulate otherwise.

I'm using the branch command and am trying to get out of Pattern1. Once that is solved I'm sure I will have to solve getting out of Pattern2.

I haven't combined programs like this before and just tried to put the actual program code in each branch. I'm not sure if the subroutines could be placed outside of each branch or not.

The code is too long so I will need to do this in two steps.

Code:
b12 = 0
b10 = 0

MAIN:

BRANCH b12, (PATTERN1, PATTERN2, PATTERN3)


; =================================================
;   File....... 40X2 3xWS2801
;   Purpose.... A demo program to show control of a WS2801 RGB LED drivers
;   Author..... Westaust55
	'Modified by John
	'Started.... 05-04-2013
;   E-mail.....
;   Started.... 25-11-2012
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
; A program to to demonstrate the control of a short string of three WS2801 RGB LED driver chips
; Modified:  A program to control 3 WS2803 RGB LED driver chips
; -----[ Revision History ]---------------------------------------------------
;
; A = 25-11-2012	First release	total program size = 355 bytes
; =================================================
;
#PICAXE 40X2
SETFREQ M8   ; default clock speed is 8 MHz.

; -----[ I/O Definitions ]-------------------------------------------------- 

; - - - DIGITAL INPUT PINS  - - -
; none used
;
; - - - DIGITAL OUTPUT PINS - - -
SYMBOL SData	= C.2 ; on 40X2 going to SDI Pin on the WS2803, pin 5
SYMBOL SClock	= C.1 ; on 40X2 going to CKI Pin on the WS2803, pin 4

; -----[ Constants ]-------------------------------------------------------
SYMBOL TotalMods	= 1 ; Define how many WS2803 modules are connected
SYMBOL Data_Sets	= 18	; define how many sets of data are held in EEPROM
SYMBOL LEDperMod  = 18 ; define how many LEDs per module
SYMBOL SeqStep_Delay = 500 ; for 0.500 sec delay at 8 MHz


; Define EEPROM locations for some colour data - expand the data and pointer list to suit
SYMBOL Red 		= $00
SYMBOL Green 	= $03
SYMBOL Blue 	= $06
SYMBOL Magenta 	= $09
SYMBOL Yellow 	= $0C
SYMBOL Cyan 	= $0F
SYMBOL White	= $12
SYMBOL Black	= $15

; -----[ Variables ]-------------------------------------------------------
SYMBOL LED_Data	= b0
SYMBOL No_LEDs	= b1
SYMBOL CycleLen	= b2
SYMBOL MemAddr 	= b3
SYMBOL LED_Index	= b4
SYMBOL WhichIsRed = b5
SYMBOL Counter	= b6

; Define some colours with 3 Bytes per colour at quarter intensity - $FF for max intensity
EEPROM $00, ($3F, $00, $00) ; Red
EEPROM $03, ($00, $3F, $00) ; Green
EEPROM $06, ($00, $00, $3F) ; Blue
EEPROM $09, ($3F, $00, $3F) ; Magenta
EEPROM $0C, ($3F, $3F, $00) ; Yellow
EEPROM $0F, ($00, $3F, $3F) ; Cyan
EEPROM $12, ($3F, $3F, $3F) ; White
EEPROM $15, ($00, $00, $00) ; Black = no colour segment illuminated

; -----[ Initialization ]--------------------------------------------------
Init:
	Low SData
	Low Sclock
	MemAddr = 0				  ; set the EEPROM data pointer to the first location
	No_LEDs = 18 * TotalMods		  ; calculate the total number of individual LED channels
	CycleLen = No_LEDs * Data_Sets  ; calculate the number of bytes of EEPROM data in the cycle
;

PATTERN1:

; -----[ Program Code ]----------------------------------------------------	
Main1:
    DO
     
	ptr = 0					 ; set pointer to first scratchpad location for next sets
	MemAddr = Red : GOSUB FetchColour	 ; colour for 1st WS2801 and save data to Scratchpad
	MemAddr = Yellow : GOSUB FetchColour ; colour for 2nd WS2801 and save data to Scratchpad
	MemAddr = Green : GOSUB FetchColour  ; colour for 3rd WS2801 and save data to Scratchpad 
	GOSUB SendData			 ; call subroutine to transfer all data to the WS2801 string
	PAUSE SeqStep_Delay		 ; delay to give user time to see the new colour pattern
	
	ptr = 0
	MemAddr = Yellow : GOSUB FetchColour
	MemAddr = Green : GOSUB FetchColour
	MemAddr = Cyan : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Green : GOSUB FetchColour
	MemAddr = Cyan : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Cyan : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	MemAddr = Magenta : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Blue : GOSUB FetchColour
	MemAddr = Magenta : GOSUB FetchColour
	MemAddr = White : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Magenta : GOSUB FetchColour
	MemAddr = White : GOSUB FetchColour
	MemAddr = Yellow : GOSUB FetchColour
	GOSUB SendData
	PAUSE 500
	ptr = 0
	MemAddr = White : GOSUB FetchColour
	MemAddr = Yellow : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay

	ptr = 0
	MemAddr = Yellow : GOSUB FetchColour
	MemAddr = Blue : GOSUB FetchColour
	MemAddr = Cyan : GOSUB FetchColour
	GOSUB SendData
	PAUSE SeqStep_Delay
	inc b10
    LOOP WHILE b10 < 1					
	
;
; -----[ Subroutines ]----------------------------------------------------- 
;
;         Subroutine to fetch the data from EEPROM and save into Scratchpad for one RGB LED colour
  
  FetchColour:
	READ MemAddr, LED_Data	; Fetch the Red component of the specified colour
	@PtrInc = LED_Data	; save into the scratchpad RAM at required location
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Green component of the specified colour
	@PtrInc = LED_Data
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Blue component of the specified colour
	@PtrInc = LED_Data
        [highlight]RETURN[/highlight]		; Return after the RGB data for WS2801 module has been placed into the Scratchpad

; Subroutine to serially clock out the data through the SW2801 chips for THREE RGB LEDs
; NOTE this is limited to three WS2801 chips without adding more variables/field to the SHIFTOUT command
SendData:
	Ptr = 0
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	RETURN

INC b12
goto MAIN
 
Last edited:

johnhr

New Member
Code:
; =================================================
;   File....... 40X2 3xWS2803
;   Purpose.... An untested demo program to show control of a three WS2803 RGB LED drivers
;   Author..... Westaust55
;   E-mail.....
;   Started.... 13-05-2013
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
; A program to to demonstrate the control of a short string of three WS2803 RGB LED driver chips
;  
; -----[ Revision History ]---------------------------------------------------
;
; A = 13-05-2013	First release	total program size = 232 bytes
; =================================================
;Modified by Johnhr 14-05-2013 for the 40X2


PATTERN2:

; -----[ Program Code ]----------------------------------------------------	
Main2:
    DO
	WhichIsRed = LED_Index // No_LEDs  ;  for each loop of the program, this defines a new value 0 to 17 for the 18 RGB LED's. That LED is Red and all others are off
    	ptr = 0					 ; set pointer to first scratchpad location for next datasets
    	For Counter = 1 TO No_LEDs
    		IF Counter = WhichIsRed THEN
    			MemAddr = Red
    		ELSE
    			MemAddr = Black
    		ENDIF
    		GOSUB FetchColour2	; Fetch Colour definition from EEPROM and save in next scratchpad location
    	NEXT Counter
    	GOSUB SendData2		; call subroutine to transfer all data to the WS2803 string
	PAUSE SeqStep_Delay	; delay to give user time to see the new colour pattern  	
  	LED_Index = LED_Index + 1 // 252	; any multiple of 18 will work if we let counter get to 255 and roll over to 0 then display will "jump"
    LOOP						; loop forever

;
; -----[ Subroutines ]----------------------------------------------------- 
;
; ***** Subroutine to fetch the data from EEPROM and save into Scratchpad for one RGB LED colour
  
  FetchColour2:
	READ MemAddr, LED_Data	; Fetch the Red component of the specified colour
	@PtrInc = LED_Data	; save into the scratchpad RAM at required location
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Green component of the specified colour
	@PtrInc = LED_Data
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Blue component of the specified colour
	@PtrInc = LED_Data
  	RETURN		; Return after the RGB data for one RGB LED (3 channels) has been placed into the Scratchpad
;
; Subroutine to serially clock out the data through the WS2803 chips for THREE RGB LEDs
; NOTE this is limited to three WS2803 chips without adding more variables/field to the SHIFTOUT command
SendData2:
	Ptr = 0
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of first WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of second WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of third WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	RETURN
	
	
INC b12
GOTO MAIN


; =================================================
;   File....... 40X2 3xWS2803
;   Purpose.... An untested demo program to show control of a three WS2803 RGB LED drivers
;   Author..... Westaust55
;   E-mail.....
;   Started.... 13-05-2013
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
; A program to to demonstrate the control of a short string of three WS2803 RGB LED driver chips
;  
; -----[ Revision History ]---------------------------------------------------
;
; A = 13-05-2013	First release	total program size = 232 bytes
; =================================================
;Modified by John 14-05-2013 for the 40X2
;
;   changed Digital Output Pins
;   played with Constants
;   added 12 SYMBOLs
;   added 12 EEPROMs
;   changed a little MAIN code
;
;==================================================


; Define EEPROM locations for some colour data - expand the data and pointer list to suit
'SYMBOL Red1		= $00
'SYMBOL Green1 	= $03
'SYMBOL Blue1 	= $06
'SYMBOL Red2 	= $09
'SYMBOL Green2 	= $0C
'SYMBOL Blue2 	= $0F
'SYMBOL Red3		= $12
'SYMBOL Green3	= $15
SYMBOL Blue3	= $18
SYMBOL Red4		= $1B
SYMBOL Green4 	= $1E
SYMBOL Blue4 	= $B4
SYMBOL Red5 	= $24
SYMBOL Green5 	= $27
SYMBOL Blue5 	= $2A
SYMBOL Red6		= $2D
SYMBOL Green6	= $30
SYMBOL Blue6	= $33


; Define some colours with 3 Bytes per colour at quarter intensity - $FF for max intensity
'EEPROM $00, ($3F, $00, $00) ; Red1
'EEPROM $03, ($00, $3F, $00) ; Green1
'EEPROM $06, ($00, $00, $3F) ; Blue1
'EEPROM $09, ($3F, $00, $00) ; Red2
'EEPROM $0C, ($00, $3F, $00) ; Green2
'EEPROM $0F, ($00, $00, $3F) ; Blue2
'EEPROM $12, ($3F, $00, $00) ; Red3
'EEPROM $15, ($00, $3F, $00) ; Green3
EEPROM $18, ($00, $00, $3F) ; Blue3
EEPROM $1B, ($3F, $00, $00) ; Red4
EEPROM $1E, ($00, $3F, $00) ; Green4
EEPROM $21, ($00, $00, $3F) ; Blue4
EEPROM $24, ($3F, $00, $00) ; Red5
EEPROM $27, ($00, $3F, $00) ; Green5
EEPROM $2A, ($00, $00, $3F) ; Blue5
EEPROM $2D, ($3F, $00, $00) ; Red6
EEPROM $30, ($00, $3F, $00) ; Green6
EEPROM $33, ($00, $00, $3F) ; Blue6



PATTERN3:

; -----[ Program Code ]----------------------------------------------------	
Main3:
    DO
	WhichIsRed = LED_Index // No_LEDs  ;  for each loop of the program, this defines a new value 0 to 17 for the 18 RGB LED's. That LED is Red and all others are off
    	ptr = 0					 ; set pointer to first scratchpad location for next datasets
    	For Counter = 1 TO No_LEDs
    		IF Counter = WhichIsRed THEN
    			MemAddr = Red
    		ENDIF
    		
    			
    	
    		GOSUB FetchColour3	; Fetch Colour definition from EEPROM and save in next scratchpad location
    	NEXT Counter
    	GOSUB SendData3		; call subroutine to transfer all data to the WS2803 string
	PAUSE SeqStep_Delay	; delay to give user time to see the new colour pattern  	
  	LED_Index = LED_Index + 1 // 252	; any multiple of 18 will work if we let counter get to 255 and roll over to 0 then display will "jump"
    LOOP						; loop forever

;
; -----[ Subroutines ]----------------------------------------------------- 
;
; ***** Subroutine to fetch the data from EEPROM and save into Scratchpad for one RGB LED colour
  
  FetchColour3:
	READ MemAddr, LED_Data	; Fetch the Red component of the specified colour
	@PtrInc = LED_Data	; save into the scratchpad RAM at required location
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Green component of the specified colour
	@PtrInc = LED_Data
	INC  MemAddr
	READ MemAddr, LED_Data	; Fetch the Blue component of the specified colour
	@PtrInc = LED_Data
  	RETURN		; Return after the RGB data for one RGB LED (3 channels) has been placed into the Scratchpad
;
; Subroutine to serially clock out the data through the WS2803 chips for THREE RGB LEDs
; NOTE this is limited to three WS2803 chips without adding more variables/field to the SHIFTOUT command
SendData3:
	Ptr = 0
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of first WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of second WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc) ; first half of third WS2803
	SHIFTOUT SClock,SData,MSBFirst_L, (@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc,@PtrInc)
	RETURN
	
	
b12 = 0
goto MAIN
 

westaust55

Moderator
Someone on Utube who was working with the WS2803 chip said that data is sent to the last chip first, so for me it would be chip 3, then 2, then 1. I don't know if this is correct but if it is maybe that is why the bright string is broken up from the lighter string.
Now, if that was the case, how would the first chip know there were 2 or more chips following and to pass on the first xx bits before saving the last 18 bytes ? Unfortunately there are many cases of erroneous technical (we won't go into other fields) data and information on the internet.
Certainly have a look at what is presented in other areas/forums/websites but be aware that it may not work.

Each WS2803 received and latches internally the first 18 bytes it receives and then passes on without change any ongoing data stream.
When there is a pause of >= 500 usec in the clock pulses from first bit received, the WS2803 chips all transfer the data to the output registers/pins.


I would be ensuring that you can get the last program I posted (with the subsequently mentioned edit for 1 line) before you try to combine or modify the program further which may introduce errors that hinder getting you up and running.

I do not have time at the moment to study what you have done with the new code you have posted today. I do note that the code you posted in post 32 does not include the small edit I mentioned yesterday in post 31 for the program line:
WhichIsRed = LED_Index // No_LEDs ; for each loop of the program, this defines a new value 0 to 17 for the 18 RGB LED's. That LED is Red and all others are off​
 
Last edited:

MartinM57

Moderator
Not following thread closely...
johnhr said:
Someone on Utube who was working with the WS2803 chip said that data is sent to the last chip first...
Now, if that was the case, how would the first chip know there were 2 or more chips following and to pass on the first xx bits before saving the last 18 bytes ? Unfortunately there are many cases of erroneous technical (we won't go into other fields) data and information on the internet.
Certainly have a look at what is presented in other areas/forums/websites but be aware that it may not work.

Each WS2803 received and latches internally the first 18 bytes it receives and then passes on without change any ongoing data stream.
That sounds pretty similar to how cascaded MAX7219 LED driver chips work - with two cascaded MAX7219, you:
- assert chip select (set low) for both chips
- send a serial stream that starts with the data for the second (/furthest) chip first, then the first (/closest) chip. The data cascades through the first chip into the second, so at the end of the "send" the chips contain the required values
- de-assert chip select (set high) for both chips - at which point, each chip acts on its received data.

There is a No-Op register that you use if you don't want to affect the value in any of the cascaded chips....from the datasheet...

The no-op register is used when cascading MAX7219s
or MAX7221s. Connect all devices’ LOAD/CS inputs
together and connect DOUT to DIN on adjacent
devices. DOUT is a CMOS logic-level output that easily
drives DIN of successively cascaded parts. (Refer to
the Serial Addressing Modes section for detailed information
on serial input/output timing.) For example, if
four MAX7219s are cascaded, then to write to the
fourth chip, sent the desired 16-bit word, followed by
three no-op codes (hex 0xXX0X, see Table 2). When
LOAD/CS goes high, data is latched in all devices. The
first three chips receive no-op commands, and the
fourth receives the intended data.
The WS2308 data sheet I found shows a specific timing diagram for how cascaded WS2308's work - not exactly the same, but very similar and to the spirit of "sending the data to the last chip first"
 

westaust55

Moderator
Yes, Martin57 is correct. I was )in working from memory) recalling data about a different chip. :mad:

Now in front of a PC rather than iPhone and had a look at my own WS2801 chip program code for a string of 6 chips.
See also this thread: http://www.picaxeforum.co.uk/showthread.php?22713-Getting-Started-with-the-WS2801-3-Channel-RGB-LED-Driver-with-PWM-output/page2

Data does keep cascading through so for example the first bit/byte of data in gets clocked through further and further down the string of cascaded chips and if you kept clocking the data it would "drop" out the end of the string. :D
 
Top