Successful POV test of self-contained system.  Image from SD Card, lipo battery powered,

Successful POV test of self-contained system. Image from SD Card, lipo battery powered, mini OLED screen working, now for the bluetooth interface… Thanks for all the hard work on RC1/RC2, I’m able to fit WAY more stuff in 32K.

That looks great! Thanks for sharing your work-in-progress! Any lessons learned or tips to pass along?

How many colors are you using?

@Ashley_M_Kirchner_No 24 bit color in the source .BMP file, 8 bits per color.
The nyan 8bit graphic doesn’t have that many in it, obviously.
@Mark_Kriegsman that without the RC1 release of FastSPI_LED2 this project would have been impossible with 32K of flash progmem.

I’m doing something similar, so I’m curious about your setup. How are you reading the images?

.BMP files are made up of B-G-R byte order pixels with an 8 bit per color palette. Using some really hackish code, I use the SD library to grab a .BMP off the card.

The code is baaaaaaaad and not optimized, I may release it later.

I also learned that my teensy 2.0 and WS2811 is quite happy at >3.7V, I was surprised and expected the WS2811 not to work at a voltage that low. I found this out because my DC-DC power supply seems to have lost it’s mind, but the whole rig still works.

Evidently, G+ ate my reply … or I never hit Submit. I’m interested in how you’re parsing the files (even if it’s “baaaaaaaad”.) I’m using full color JPG files however they are pre-processed into a custom file that has a header that gives me the amount of rows and columns plus some other details, then the RGB values for each pixel in the image. I dump all of that into a binary file which I then read back in, 144 bytes at a time (because my POV string will have 48 pixels.)

Would be nice if I can do away with that pre-processing …

Check out the wikipedia article on BMP file format. Basically, for low rez BMPs I’m using, I seek to byte 10, which tells me the byte # for the first pixel’s data. I see to that address and the first read will be B, then G, then R, and then the next pixel’s B,then G, then R.;
imageDataOffset = pattern.peek(); // this is only 1 byte out of 4 and will probably have to change eventually.   

// Serial.print(F(“IDO:”));
// Serial.println(imageDataOffset);;
patWidth =;;
patHeight =;
// return to address of first pixel so we can get down to business.;

and then some
for (int i = 0; i <= patWidth && i < NUM_LEDS; i++) // NUM leds is there for images who have more pixels than the prop does…
leds[i].b =; // first byte is blue
leds[i].g =; // second byte is green
leds[i].r =; // third byte is red

Aight, I’ll go read up on that and see if I can implement it. But now I have to fall back to some of the excellent instructions received from both Mark and Daniel when I was going through the motions of creating/reading my files:

Rather than reading each individual b, g, and r value (and showing it with each call), why not read a whole chunk (necessary to fill the entire string) and pass it on to the leds Array?

for (int cols = 0; cols < patWidth; cols++) {*)leds, NUM_LEDS * 3);;
// stick a delay if you need to

That will read 144 bytes (in my case) and shove it straight into the leds Array. I make sure all my images are exactly 48 pixels tall by whatever long. So I’m always reading 144 bytes. That’s the one good side of pre-processing the images, I can use an image of any dimension, the pro-processor will resize it accordingly. It’s just a small piece of code written in C++.

My C++ is not so great, I’ll try that combined write and try to comment/cleanup my open/read bitmap functions.

It’s easiest to make the BMP so that the width in pixels = the length of your POV string in pixels. Standard BMPs are scanned from the bottom, tho you can invert that with a negative height value. I’ll post a snippit of the code I’ve been using, debug stuff and all.

^^ what he said. In my case I don’t need fixed dimensions because I can crop/repeat segments on my hardware.
I tried the great big write all at once code - it worked but the byte order is wrong :-/