PDA

View Full Version : Teensy 3.0 + WS2801



TSK
04-16-2013, 04:25 PM
Hello!

I have 40x WS2801 LED Strips and 8x Teensy 3.0 boards.
Project is - 160x40 led display. Can someone point me where to start?
Or even will this be possible with 8 teensy boards or i need something more powerful?
Also, where i can read about DMA, because i cant find any documentation about teensy uC instructions.

PaulStoffregen
04-17-2013, 10:57 AM
Daniel's new FastSPI library is probably the best way to use WS2801 strips.

TSK
04-17-2013, 02:12 PM
I cant figure out how to convert data from movie2serial to FastSPI_LED2 format.
movie2serial already have 24 bits for each pixel, but fastspi needs data in this format -
struct CRGB { byte r; byte g; byte b; }; - only 3 bytes long.

dgarcia42
04-18-2013, 12:03 AM
each pixel is 24 bits, not bytes - 8 bits for each of r, g, and b. If you're getting raw RGB pixel data as a block of bytes, you can just cast that to an array of struct CRGB pointers - as a CRGB struct is just 3 bytes conveniently grouped together. The biggest problem is going to be the ws2801 data rate - I've heard reports of ws2801 strips being unhappy when going above 500kbps in writing data to them. Your setup will need a total of 153kbits -per-frame- - for 30fps you'll need a setup that can, at least in aggregate, push 4.5Mbps. If you split that out over 5 teensy's that's still 30kbit per frame per teensy, which at best is going to get you 16 frames per second. (Some ws2801 strips can go with higher data rates, which helps in the long term).

I'm assuming you've already obtained the strips? I've been able to push strips of 160 leds at upwards over 22Mbit with the LPD8806 (sidenote: Paul - after some more spec reading i've been able to get rid of a bunch of inter-byte pauses in the SPI system, bringing me up to 22 from 20. Still can't quite hit 24Mbps though, it's like there's a 1-bit sized pause in SPI output every 8 bits - still spec digging to see what the last thing is that I need to get rid of even that gap). I.e. a single teensy3 could push data to your array at about 140fps (after some creating work with using a mux to redirect output around - also, still don't know if mux's can sustain 22mbps data transfer rates). Of course, at that point memory becomes your problem, as you need 19,200 bytes just to store all the rgb data for your array.

TSK
04-18-2013, 12:34 PM
You are right, its 24 bits, not bytes. My bad.
I've been able to run some tests and as you wrote, there is big problem with speed.
I saw there is parameter in FastSPI_LED2 lib that changes SPI speed, but cant find anywhere what is max value for it.
WS2801Controller<11, 13, 10, 3> LedController;
Also had some strange behaviour from lib - when i send one color, there is 1 bit missing for color, but full 24 bit packet is okey.
So on my oscillograph its looks like this - 7 high bits than 8 low and 9 low bits transferred. Same thing with 2 colors at FF - i got 15 bits high, 9 bits low.

dgarcia42
04-18-2013, 04:58 PM
The value is nominally the clock divider for the SPI clock speed - so lower is faster - however, the WS2801 has performance problems if you set that value too low. It seems to be dependent on the source of the chips, though, so play with values. , though its values are a bit skewed right now (i'm going to fix that in the next release, as well as allow people to specify the speed value in terms of Mhz/Khz clock rate vs. just clock divider - testing that code right now).

Are you using the hardware SPI pins (looks like you probably are) - because the bytes that you give me basically just get copied right to the SPI output register. I'll try taking a look on a scope here and see if I can see what's going on. Also, there are some pre-defined divider values that you can use:


#define SPEED_DIV_2 2
#define SPEED_DIV_4 4
#define SPEED_DIV_8 8
#define SPEED_DIV_16 16
#define SPEED_DIV_32 32
#define SPEED_DIV_64 64
#define SPEED_DIV_128 128

(though, again, the values and how they map to real clock speeds are a little bit off at the moment, fixing that).

TSK
04-18-2013, 05:24 PM
Thanks for your reply, now its clear for me.
No, i'm not using hardware SPI. Just copied code from the example. Currently trying to run 5 ledcontrollers on each teensy. Using pins from 14 to 23. Will try to play with scope and timings today and will post at update what i got.

dgarcia42
04-18-2013, 07:27 PM
Ah - ok, it's possible an off by one error snuck in to the software SPI code - i'll dig into that. One of the things that you will (hopefully) be able to do once I get DMA support in is put a MUX or some other gating between the hardware SPI clock/data lines and your 5 lines, and then the library will take care of selecting the appropriate controller when sending output, and pipe output to all your controllers in the background :)

dgarcia42
04-18-2013, 07:31 PM
Also - in the case of the software SPI, the speed sets, roughly the number of cycles to delay between each toggle of the clock (somewhat adjusted for time spent doing other things, it's not terribly exact though - but haven't had a lot of need to make it more exact yet) - but right now, the values may mean something slightly different between hardware and software SPI (I will try to bring those in line witch each other so that the values mean the same thing no matter where you are running or how).

TSK
04-18-2013, 10:24 PM
Rewrote my code a little and get 2 teensys running with 5 strips on each. Also played with clock divider param - 16 working great for me. It seems that now i have no 7bits problem (didnt check with scope but data looks okey), maybe was some errors in example code or with timings, but now i have diffsrent bug - first strip on each teensy is good, but next ones have strange color artifacts, same on both teensys. For example when i stream video, first strips are playing good, and next ones have random color artifacts with video data.

Will investigate this more.

dgarcia42
04-18-2013, 10:32 PM
When you say "first strip" does that mean first strip that you wired up, or the first strip that you're writing to. For example, if you change the order of which strips you are writing to, is the first strip that you write ok, no matter which strip it is, then the rest aren't, or something else?

TSK
04-19-2013, 12:25 AM
Its first strip that i'm writing to. Will try to change order, as you suggest. Thanks.

TSK
04-19-2013, 02:36 AM
Back to basic test program, blinking 5 strips in green color.


// Simple rgb data structure
#include "FastSPI_LED2.h"
#define NUM_LEDS 160
struct CRGB { byte r; byte b; byte g; };
struct CRGB ledData[NUM_LEDS];
struct CRGB ledData2[NUM_LEDS];
struct CRGB ledData3[NUM_LEDS];
struct CRGB ledData4[NUM_LEDS];
struct CRGB ledData5[NUM_LEDS];

WS2801Controller<14, 15, 10, 16> LedController;
WS2801Controller<16, 17, 9, 16> LedController2;
WS2801Controller<19, 18, 8, 16> LedController3;
WS2801Controller<21, 20, 7, 16> LedController4;
WS2801Controller<22, 23, 6, 16> LedController5;

void setup() {
// zero out all the leds
memset(ledData, 0, sizeof(struct CRGB) * NUM_LEDS);
memset(ledData2, 0, sizeof(struct CRGB) * NUM_LEDS);
memset(ledData3, 0, sizeof(struct CRGB) * NUM_LEDS);
memset(ledData4, 0, sizeof(struct CRGB) * NUM_LEDS);
memset(ledData5, 0, sizeof(struct CRGB) * NUM_LEDS);

// initialize the controller
LedController.init();
LedController2.init();
LedController3.init();
LedController4.init();
LedController5.init();
}

void loop() {
for(int i = 0; i < NUM_LEDS; i++) { ledData[i].g = 255; }
LedController.showRGB((byte*)ledData, NUM_LEDS);

for(int i = 0; i < NUM_LEDS; i++) { ledData2[i].g = 255; }
LedController2.showRGB((byte*)ledData2, NUM_LEDS);

for(int i = 0; i < NUM_LEDS; i++) { ledData3[i].g = 255; }
LedController3.showRGB((byte*)ledData3, NUM_LEDS);

for(int i = 0; i < NUM_LEDS; i++) { ledData4[i].g = 255; }
LedController4.showRGB((byte*)ledData4, NUM_LEDS);

for(int i = 0; i < NUM_LEDS; i++) { ledData5[i].g = 255; }
LedController5.showRGB((byte*)ledData5, NUM_LEDS);
delay(5000);

// zero out all the leds
memset(ledData, 0, sizeof(struct CRGB) * NUM_LEDS);
LedController.showRGB((byte*)ledData, NUM_LEDS);

memset(ledData2, 0, sizeof(struct CRGB) * NUM_LEDS);
LedController2.showRGB((byte*)ledData2, NUM_LEDS);

memset(ledData3, 0, sizeof(struct CRGB) * NUM_LEDS);
LedController3.showRGB((byte*)ledData3, NUM_LEDS);

memset(ledData4, 0, sizeof(struct CRGB) * NUM_LEDS);
LedController4.showRGB((byte*)ledData4, NUM_LEDS);

memset(ledData5, 0, sizeof(struct CRGB) * NUM_LEDS);
LedController5.showRGB((byte*)ledData5, NUM_LEDS);
delay(5000);
}

Results (ignore 2 strips at the bottom, they are not connected):
1. http://cl.ly/image/460C1j1A3q25
First step - colors messed up and 6 leds missing at the end of the first strip.

2. http://cl.ly/image/3i3W1g3f1R1p
Second step - Everything must be 0, but last strip didnt cleared.

3. http://cl.ly/image/3d0n3c2u1F2s
Third step - colors changed, first strip colors are now different, but still missing 6 leds at the end.
Next 4 strips are now yellow.

4. http://cl.ly/image/3j3j2x3v1n3F
Everything again goes to 0, but last strip left in yellow.

3 and 4 steps are continue to blink. Never get green again, only restarting teensy is helping.
Whats wrong with my code? Looks like some data added on top of current, but i dont understand how that can be, if memset doing it zero every loop.

The same thing i got with video stream. First frame of video is great, dont have any artifacts, but next frames displaying with artefacts.

P.S.: Got all 40 strips running already, but have 2 not working usb cables, so i only test 30 strips at once and starting to get problems with my laptop - it seems that sending data to 6 uCs is hard for him, framerate of the video stream goes slower. :)

TSK
04-19-2013, 09:51 PM
Played with r g b values and found that strips with code above working correct only with values from 100 to 254.

for(int i = 0; i < NUM_LEDS; i++) { ledData[i].g = 100; }
With other values, colors are messed up on the second frame (when strip lights up in the second time).

Can this be problem with byte to uint8_t cast?

dgarcia42
04-19-2013, 09:57 PM
It's not the cast, byte is uint8_t.

This actually sounds like you are having a power problem - I have a similar thing happen if I turn on too many leds - the leds end up drawing enough power that the teensy loses power and everything gets trapped in a stuck sort of state.

also:

WS2801Controller<21, 20, 7, 16> LedController4;
WS2801Controller<21, 20, 6, 16> LedController5;

might be contributing to your problem - you have controller 4 and 5 marked as using the same pins, which probably means your last strip is never getting sent anything.

TSK
04-19-2013, 10:07 PM
Im not sure about power, because first frame is always perfect, also no metter what color i setup.

About 4 and 5 controller, its just me writing code from my memory.

Edit: Just tested with external power supply for teensy. Same behavior. 100 to 254 values works good, 0 to 99 - first blink ok, next - color messed up. Its for sure data problem.

dgarcia42
04-19-2013, 10:29 PM
What kind of power supply do you have hooked up to the LEDs? What happens if you send the same buffer to all 5 strips (as opposed to sending separate strips?).

The fact that the first strip you write to is ok still makes me think it's a power problem - once that first strip lights up, it's drawing enough power that the other strips are power starved and are having problems with the data.

Those strips will use up to 10 watts per meter, or 50 watts per strip - you need to have at least a 100-200W power supply hooked up to your set of 5 strips to make sure you're pulling down enough power.

As for why lower rgb values are problems - I suspect what's probably happening is with lower rgb values, the odds of a ws2801 chip losing power/ability to run its PWM is increasingly likely while the light is off, vs. on.

What are you doing for power?

TSK
04-19-2013, 10:39 PM
Did another test - it seems that all even values of color works great, and all odd values having problem. Why that can be?

dgarcia42
04-19-2013, 10:46 PM
What if you turn on the first strip - then send zeros down it, then turn on the second strip, then send zeros down it, etc... basically, make sure you are only turning on one strip at a time - see what that does. If everything works in that case (e.g. with no more than one strip's worth of leds on at any given time), then I go back to suggesting you have a power problem.

As for even vs. odd values - the different values probably change the complexity of what's going on with pwm. Or with an even value the last bit sent out for each r.g.b value is 0 - so if a chip slips up and sends that to the next led nothing happens, whereas if it's a 1 (odd value) and things slip around, then that becomes the high bit for the next led (which, again, if you're having a power draw problem, ups your power draw that much more).

Once again - what are you doing for power for the strips? What kind of power supply are you using, and how do you have things wired up between the power supply and the strips?

dgarcia42
04-19-2013, 10:49 PM
Also - another thing you can do - to check whether or not the teensy is completely stopping (which is why your'e getting stuck w/steps 3 and 4 above) is make it so that your code regularly toggles the led on the teensy with each step (toggle pin 13 high and low) - if the led stops changing, then you know that the teensy has stopped operating.

Also, can you provide the actual code that you are running, vs. typing it from memory so I can see what else may be going on in there?

TSK
04-19-2013, 11:10 PM
We have 5 power supplies 350W each for all 40 strips, teensys powered by seperate adapter. So we can exclude power problem. Maked video stream test with sending only even numbers, and everything works great. So only problem in odd numbers.

dgarcia42
04-20-2013, 12:13 AM
Ok - all the behavior you've been describing is consistent with what i've seen with power - which is why I wanted to know the power config.

So, this has to do with the order that you write the strips in right? (trying to rule out the possibility that I have a bad pin/port mapping definition)

dgarcia42
04-20-2013, 12:15 AM
Actually, I may have found the issue - give me an email address, I want to send you a new version of the library to try out (and also, there've been some slight changes between versions of the preview release library - email might be faster to help you over).

For optimization reasons, there are four possible ways to juggle the pins for sending data. One of those four ways is flipping the clock line backwards - i'd like to send you a version of the library with that fixed then see where things go from there.

dgarcia42
04-20-2013, 12:19 AM
Also - somewhat less importantly - do you have any other code involved here doing things involving interrupts? (Also want to rule out/diagnose possible issues with ports interfereing with each other).

TSK
04-20-2013, 01:20 AM
Ok, here is my actual testing code. No any other interrupts or so. Also when i do video streaming, there is no any interrupts too, everything working in the main loop.



// Simple rgb data structure
#include "FastSPI_LED2.h"
#define NUM_LEDS 160
struct CRGB { byte r; byte b; byte g; };
struct CRGB ledData[NUM_LEDS];

WS2801Controller<14, 15, 10, 16> LedController4;
WS2801Controller<16, 17, 10, 16> LedController3;
WS2801Controller<18, 19, 10, 16> LedController2;
WS2801Controller<20, 21, 10, 16> LedController1;
WS2801Controller<22, 23, 10, 16> LedController;

void setup() {
pinMode(13, OUTPUT);

// zero out all the leds
memset(ledData, 0, sizeof(struct CRGB) * NUM_LEDS);

// initialize the controller
LedController.init();
LedController1.init();
LedController2.init();
LedController3.init();
LedController4.init();
digitalWrite(13, HIGH);
}

void loop() {
digitalWrite(13, HIGH);

for(int i = 0; i < NUM_LEDS; i++) { ledData[i].r = 40; } // Only even numbers working
for(int i = 0; i < NUM_LEDS; i++) { ledData[i].g = 40; } // Odd numbers messing with color on
for(int i = 0; i < NUM_LEDS; i++) { ledData[i].b = 40; } // second loop step
LedController.showRGB((byte*)ledData, NUM_LEDS);
LedController1.showRGB((byte*)ledData, NUM_LEDS);
LedController2.showRGB((byte*)ledData, NUM_LEDS);
LedController3.showRGB((byte*)ledData, NUM_LEDS);
LedController4.showRGB((byte*)ledData, NUM_LEDS);
delay(500);

digitalWrite(13, LOW);
// zero out all the leds
memset(ledData, 0, sizeof(struct CRGB) * NUM_LEDS);
LedController.showRGB((byte*)ledData, NUM_LEDS);
LedController1.showRGB((byte*)ledData, NUM_LEDS);
LedController2.showRGB((byte*)ledData, NUM_LEDS);
LedController3.showRGB((byte*)ledData, NUM_LEDS);
LedController4.showRGB((byte*)ledData, NUM_LEDS);
delay(500); /* */
}


Sent you an email in PM.

TSK
04-20-2013, 01:29 AM
So, this has to do with the order that you write the strips in right? (trying to rule out the possibility that I have a bad pin/port mapping definition)
Not exacly. Only odd color values affecting the strips, no meter i send to one or to five strips.