I'm trying to convert a code for a POV setup to use FastSPI instead. 

I’m trying to convert a code for a POV setup to use FastSPI instead. But I’m having a hard time trying to understand what’s happening with the color code to even begin to figure out how to convert it. So, the data is stored like so:

prog_uchar image1[] PROGMEM = {

Then it gets processed like this for each value in the above array:
// mask to select 2 bits of color
#define maskR 0x60
#define maskG 0x18
#define maskB 0x06

tempG = 0x80 | (uint32_t)((pgm_read_byte_near(&image1[i+j*NLEDS])) & maskR);
tempR = 0x80 | ((uint32_t)((pgm_read_byte_near(&image1[i+j*NLEDS])) & maskG) << 2);
tempB = 0x80 | ((uint32_t)((pgm_read_byte_near(&image1[i+j*NLEDS])) & maskB) << 4);

(yes, I’m aware that the code has the R mask applied to G, and the G mask applied to R. That’s how it’s written and that’s how it appears to work. Don’t ask me why.)

Anyway, someone explained to me that the resulting data after processing looks like this:
tempG = 0b1rr00000;, tempR = 0b1gg00000;, and tempB = 0b1bb00000;

Either way, I have to figure out how to get the 0-255 values that FastSPI wants for each of R, G, and B.

So i suspect the mask values being backwards has to do with the code talking to a strip/leds that aren’t quite wired rgb, but instead something like gdb.

So if you do:
unsigned char cur = pgm_read_byte_near(&image1[i+j*NLEDS]);
unsigned char red = cur & maskR;
unsigned char green = (cur & maskG) << 2;
unsigned char b = (cur & maskB) << 4;

then your values for r, g, and b will be one of 96, 64, 32, and 0. If you don’t want to do any further work on the values you could simply do:

leds[i] = CRGB(cur & maskR, (cur & maskG) <<2, (cur&maskB)<<4);

since you can change the RGB ordering when defining the controller in FastSPI_LED2 you don’t need to worry manually re-juggling your rgb ordering.

Okay, that worked only if I individually set the values:
leds1[i].r = r, leds1[i].g = g, leds1[i].b = b;

If I do
leds1[i] = CRGB(cur & maskR, (cur & maskG) <<2, (cur&maskB)<<4);
leds[i] = CRGB(r, g, b);
I get the following error:

POVTest.ino: In function ‘void loop()’:
POVTest:51: error: no matching function for call to ‘CRGB::CRGB(int, int, int)’
POVTest.ino:3: note: candidates are: CRGB::CRGB()
POVTest.ino:3: note: CRGB::CRGB(const CRGB&)

FastSPI is defined as:

#include “FastSPI_LED2.h”
struct CRGB { byte b; byte g; byte r; };
#define NUM_LEDS 48
struct CRGB leds1[NUM_LEDS];
WS2801Controller<11, 13, 10, 16> LED1;


Oh - damnit, i’m ahead of myself again - Mark and I are going to spend some time over the next few days getting this stuff wrapped up and out (amazing how quickly one gets used to new code, and believing it’s been around always :slight_smile:

So, you should set .r/.g/.b directly for now. Sorry about that one!

Uh huh. Memorial Day has come and will be gone in 10 minutes in my timezone. :slight_smile:

But yes, it works now … at least, I think it does. I need to rig up a strip on something that I can spin … see how it looks.

Yeah yeah - I ended up getting into boston about 5 hours later than was thought at one point, so there was no getting together to wrap up the library tonight. Wednesday night, most likely.

For something to spin - bike wheel?

No, an LED poi. Right now I just want to get stuff displayed before I tackle the next step. So for now I’m using a regular WS2801 strip. Eventually I’m going to create a strip with 48 5mm LEDs packed tightly together.

Nice - for tightly packing - have you seen the individual ws2812’s you can buy now? It’s insane, one smd package w/5050 led and ws2811 together.

Yeah, I’ve been thinking about those, however a couple of red flags instantly go up:

a) all 5050s (that I’ve seen) have a 120 degree viewing angle. Think of a polycarbonate tube with the LEDs in it. I need to be able to view them from all angles. Ok, so if I place four of them pointing out that could work, but even at the corners, they won’t over lap so when spinning, one would notice a drop in brightness as the tube itself rotates. That’s undesirable.

b) Power. Even at 48 LEDs at full 100% duty cycle for all channels, that’s 2.8A. A regular AA battery can provide about 2A (depending on brand.) Granted, I won’t be driving them at full 100%, but I may occasionally pulse all 48. And if I have four sides, that’s 4 x 2.8A. There’s no way.

So this leaves me with potentially only 5mm T1 3/4 LEDs that have a wider viewing angle. I might be able to get away with having the strips in a triangle shape … still, 3 x 2.8 is still way more than a AA battery can supply.

So yeah … real life problems.

I would LOVE to do this with the WS2812 because everything’s built-in. Otherwise I have to use external drivers which makes things bigger … Kinda annoying. But still, I’m still faced with power issues.

also - for POV stuff you might want to (later this summer) take a look at the TM1829’s - the chips that are using pwm will have their own flicker to the leds - which may mess with pov, especially long exposure photos of it - the TM1829’s can do constant current brightness changes - no PWM :slight_smile: I don’t know if i’ll get support for those in this week though, and I need to spend most of the rest of june on a project/installation (which is why I want to get the library wrapped up and out the door)

Yeah, someone else mentioned those recently. Dunno, I may not be able to get this off of the ground at all if I can’t figure out how to solve the power issue …

So hey @Daniel_Garcia , with the very possibility of PWM enabled ICs and LEDs messing with a POV display, can you suggest another way of doing it (other than the TM1829)? Shift register with a bunch of analog LEDs? Is there a way to change the frequency on any of the driver ICs so they do work (better perhaps)?

Pwm ics will definitely be better than shift register and hard wired LEDs, if only because you can get higher pwm rates - how many LEDs per ball - or, more importantly, how many ‘pixels’ of individual led data (that is, 4 rgb LEDs that would always show the same thing would be 1 pixel, effectively).

There’s no getting around the flicker of pwm - there’s just getting the pwm rates high enough that most people and most normal camera exposure times are on for what you want.

It’s a straight tube (attached to a chain, attached to a leather loop that the performer holds.) Each tube will have four “sides”. Each “side” has a strip of 48 RGB LEDs. And yes, the same LED on all four sides will display the same information. So there are 48 “pixels” along the tube.

The WS2812 says a scan frequency no less than 400hz. Typical operating frequency is 800KHz. I don’t know how that translates to fps so the human eye doesn’t notice it.

I’m interested in the same application, actually.

PWM times matter for this. For one thing, if you set a constant intensity less than full, you’ll see the PWM as dots or dashes. If I set the 180x chip to about 10% brightness (value 25), I see dots in the air.


I tested the 180x a bit and no matter how fast you send out new data, it won’t start getting displayed until the next PWM cycle. So there is up to 2.5 ms delay between sending new data and the new data affecting the display, and you cannot change the output more than once very 2.5 ms (not even that really).

The delay isn’t constant; each pixel has its own asynchronous PWM, clock so there could be up to one PWM cycle of time difference between when even adjacent pixels begin displaying the next cycle of data.

And if you try to change the pixel data at close to 2.5ms cycle times, you wind up with effects that are like a beat frequency between your update rate and the PWM. Like if I send red/blue at 400 Hz, there will be long red patches then blue patches, etc. You really need to let it show a couple of PWM cycles at least before changing to a new value.

The 2811/2812 and 180x are the slowest PWM. The 2801 has a higher PWM frequency, and the 8806 even higher (from memory I think 2500 and 4000 Hz but check the data sheets), with the 1829 the highest at 7000 Hz. I’m hoping to try some of them next.

If you are doing custom PCBs (to get the viewing angles you want), you could potentially run several LEDs that you want to show at the same location in series for each channel of the chips; many of the chips can handle 12 or even 24v power (ie: you can stack LEDs). That means fewer chips to buy/solder/control, and potentially somewhat better power efficiency, if your DC-DC step up is efficient. Just an option to explore, it has tradeoffs.

The operating frequency affects how fast you can send new data to the chips. At 800 Kbps for the 2811/2812/180x, it takes 30 us per pixel, so 48 pixels would be about 1.5 ms. That’s fine, since you can’t reliably change colors nearly that fast anyway on those chips (see PWM above). The 2801 is just a little faster (around 1000 kbps). The 1829 is up to 1600 Kbps (high speed variant), or twice that speed. The 8806 is way faster, Dan keeps trying to push 20 Mbps, and 10 Mbps ought to be possible depending on what’s driving it.

So with an 1829 chip, one could send data to 48 pixels in around 750 us, and the PWM cycles are around 140 us so there would be 5+ PWM cycles in that time. I think getting over 1000 refreshes / second is probably doable. So that’s the direction I’m heading.

I’d like to hear how your project goes.

Unfortunately, a) I don’t think you can get just the 1829 ICs yet (at least, I can’t find them for sale on ali-express/-baba) and b) FastSPI doesn’t have support for it yet (at least, it’s not listed that it does yet.) I know Dan has his hands full at the moment …

Ray Wu has had one string offering for a few weeks and recently expended to several more strings and strips. You might contact him if you want just the chips, he does offer some of the other chips.


(You may have to search for TM1829, as the search on AliExpress doesn’t separate letters and numbers like Google etc).

Somebody just reported that Ray told him that all the 1829’s he carries currently are the “low speed” version (800 Kbps, the same as the high speed version of the 2811). But it should still have the higher speed PWM. The timing should be the same as the current 2811/180x of the current library, but (1) You may need to send a current configuration at the start (as in selecting 10mA-41mA), and (2) you need to substitute 254 for 255 in real data so you don’t accidentally trigger the current configuration mode. As far as I understand it, these issues can be handled on our side of the library API for now.

Maybe Dan will put in some automatic filtering code later, along with support for the higher speed mode when strings become available with it. But as best I understand it, the “low speed” version should be workable now.

The other alternative if you don’t want to wait is the 8806. Very fast data rates, and >= 4000 Hz PWM.

I have a string of the tm1829’s with me right now - at dinner, more later, but yes - coming :slight_smile: