Bitmap with Teensy3.5

Status
Not open for further replies.
Whenever it is convenient for you. I will certain keep working on the details myself as I said - big learning curve here using all the new components hardware and software. Thanks again for your assistance.
 
@johnwatterson. I haven't been able to run this through an array hooked up to the Octows2811 adaptor but it should be a step in the right direction. It put the entire BMP pixel info into three buffers of bytes, one each for RGB. it then puts this data together and send to leds as a 24bit colour value. It includes some code to print some of the image info to the serial monitor so that image size can be checked. Not sure if it will sort all the issues, but it should be a step closer
Code:
#include <SD.h>
#include <OctoWS2811.h>

//----------set the three below------//
const int ledsPerStrip = 72;
#define imageHeight 48
#define imageWidth 72

DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);
#define RED    0xFF0000
const int chipSelect = BUILTIN_SDCARD;


//buffer to hold pixel data. remains size of pixel number//
const int ARRAY_SIZE = imageHeight*imageWidth;
const int byteBuffSize = ARRAY_SIZE*3;
byte pixelBUFFER[byteBuffSize];
byte ArrayB[ARRAY_SIZE];
byte ArrayR[ARRAY_SIZE];
byte ArrayG[ARRAY_SIZE];

/////////////////////
void setup(void) {
  Serial.begin(9600);
  leds.begin();
  leds.show();

// if you dont get all leds lighting then going off, check your wiring

Serial.println("init");
delay(500);
Serial.print("Initializing SD card…");

if (!SD.begin(chipSelect)) {
Serial.println("initialization failed!");
while(1);
}
Serial.println("SD OK!");
}
//////////////////////////////////
void loop() {

  bmpDraw("test.bmp");  
  delay(1000);

//do a colour wipe to set all leds to red
  for (int i=0; i < leds.numPixels(); i++) {
    leds.setPixel(i, RED);
    leds.show();
    delay(5);
  }

}
//////////////////////////////////////////////
int32_t readNbytesInt(File *p_file, int position, byte nBytes)
{
    if (nBytes > 4)
        return 0;

    p_file->seek(position);

    int32_t weight = 1;
    int32_t result = 0;
    for (; nBytes; nBytes--)
    {
        result += weight * p_file->read();
        weight <<= 8;
    }
    return result;
}


void bmpDraw( char* fileName)
{
// Open file
    File bmpImage = SD.open(fileName, FILE_READ);
    
    int32_t dataStartingOffset = readNbytesInt(&bmpImage, 0x0A, 4);

    // Change their types to int32_t (4byte)
    int32_t width = readNbytesInt(&bmpImage, 0x12, 4); //0x12 - dec18
    int32_t height = readNbytesInt(&bmpImage, 0x16, 4); //0x16 - dec22
    int32_t ImgSize = readNbytesInt(&bmpImage, 0x22,4); //-dec34
    
    Serial.println(width);
    Serial.println(height);
    Serial.println(ImgSize);

    int16_t pixelsize = readNbytesInt(&bmpImage, 0x1C, 2);

    if (pixelsize != 24)
    {
        Serial.println("Image is not 24 bpp");
        while (1);
    }

    bmpImage.seek(dataStartingOffset);//skip bitmap header

    byte R, G, B;

 for(int i=0;i<ARRAY_SIZE;i++){
            ArrayB[i] = bmpImage.read();
            ArrayG[i] = bmpImage.read();
            ArrayR[i] = bmpImage.read();
 }          
    bmpImage.close();
    Serial.println("done writing to Buffer");
    
  int ledCount =0;
    for(int i=0; i<width*height;i++){
      leds.setPixel(ledCount,Color(ArrayB[i],ArrayG[i],ArrayR[i]));
        ledCount = ledCount+1;
    }   
    leds.show();
}

//------- HELPER FUNCTION------//
// Create a 24 bit color value from R,G,B ////these strips are BGR, but you might need to change this
unsigned int Color(byte g, byte r, byte b)
{
  //Take the lowest 8 bits of each value and append them end to end
return( ((unsigned int)g & 0x1F )<<16 | ((unsigned int)r & 0x1F)<<8 | (unsigned int)b & 0x1F);
  }
//end of helper function
 
Great - I love your spirit of helping out a beginning programmer. Believe me this support is just what I needed to encourage me to explore the new hardware and software that people around the world are using these days. Reaching out to help others is the basis of living a life with meaning. I appreciate your generosity. Will try this code in an hour or two. Thanks.
 
Great all the leds are lit.
Where do I put my bitmap file name or do I create a varible filename = "RONION.bmp";
I thought it went in place of bpmDraw("test.bmp") but got a teensy error without explanation.
 
Hi, yes you should just replace the filename in bpmDraw("test.bmp"). I did this with three files to test it and did not receive an error. What is the verbose output for the Teensy error? it may be my use of converting a string constant to 'char*'. Does the error stop the programme from working?
 
Started over -looks like the program is working. Thank you so much. Unfortunately the colors are way off. Does not look much like the real bit map. I will work on it and post a couple of pictures so you can see the details. Thanks again - have a nice weekend.
 
the colours are probably off due to my reusing the colour helper function from a previous project where the R G and B were in a different order. Try a couple of changes.

1. change the line "leds.setPixel(ledCount,Color(ArrayB,ArrayG,ArrayR));" to be in RGB order "ArrayR,ArrayG,ArrayB));" and in the helper function at the bottom of the sketch change the order of compiling the 24bit colour value to RGB in both lines.
"unsigned int Color(byte g, byte r, byte b)" goes to r,g,b and
"return( ((unsigned int)g & 0x1F )<<16 | ((unsigned int)r & 0x1F)<<8 | (unsigned int)b & 0x1F);" goes to rgb

thats probably the best starting point

to check the colour setup of your leds you can run the BasicTest sketch in the examples menu under OctoWS2811.
 
OK, I read the data-sheet for WS2812B leds (GRB) that I am using and saw your comment at the bottom so thought that may be the main problem. Really just trial and error since I know what it suppose to look like. Turns out best is BGR. You did a nice job on this program. I appreciate it too. Now I need to play around with these images a little. Try to send you a picture in the next few days. Thanks again.
 
Studio shot of image on laptop and image on led panel. studio_picture1.jpg
 
As you can see the colors are way off so I tried to get the blue in the corners. The red light test worked really good. What if I identify the primary and secondary colors separately in a table. Think that would work.One reason for using the bitmap images is that I can edit them in MS Paint or Photoshop.
I see the Processing language has a lot of geo-shapes & details built - in to the language. Maybe that is a better direction for a novice like me? What do you think. I am working for months on this project but I need to make some little progress on my own or hire someone to work directly with me. Suggestions would be appreciated.
 
I would use a BMP image that has four distinct colours, one in each corner, such as blue, red, green, yellow. So you have four rectangles of colour. This way you can also see if you zigzag maths to redistribute the pixel colour values is correct. At the moment it looks like every other line is off also.
 
color tst

OK, here is the color test: Red Yellow,Green,Blue White line separation. As you thought looks like zigzag is one problem. Tried different combinaions for GRB as that is what the data sheet indicates for WS2812Bs. Ended up with BGR but have no idea why, except I can not get a red otherwise.Color Test.jpg
 
Last edited:
ok, thats very useful. The other thing to know is how are you currently redistributing the colour values in the buffer arrays to account for your zigzag pattern of led strips? Also, what is the zigzag pattern you are using? It look to me as though the colours are not being redistributed to take account of the led strips going in alternate directions.
 
OK, the forward lines are OK but the back lines are being interpreted as a second color so that would mean I need to reverse edit the second line of code. That would mean I need to convert the bitmap into hex code and manually edit the file. That will also take care of the other problem since I can invert the whole image when I am done. My problem is I do not know the format necessary for the teensy 3.5 to read the hex file directly. Can you help me with that and will this code still be valid for reading and writing from the SD card directly?
 
In the bmp file header, the x and y dimensions of the picture are given. This allows you to read the pixel data line by line into a buffer and the write out the buffer each second line in reversed order to the LEDs. It’s not rocket science...
 
the easiest way is to leave all the pixel data alone in the array buffers, and then as you call the data for setting the leds in the for loop, do some redistribution using a reference array. if you describe the led layout I can give you an idea of how to do that.

the code that sets the pixels (below) will still be used, and the bmp read will still be used as is, but in the loop we reference a different array that holds the arrangement of the leds.
int ledCount =0;
for(int i=0; i<width*height;i++){
leds.setPixel(ledCount,Color(ArrayB,ArrayG,ArrayR));
ledCount = ledCount+1;
}
so if your arrangement of leds is something like 0 to 45 top row, then zigzag back means 46 to 89 are backwards, we just write an array that holds those led numbers in that order, and then count through that one at a time to set the right led with the right colour.

so, you have your leds all set on your board, but what is their arrangement.
 
OK, thanks. The arrangement is 72 cols across 48 rows down, left to right from top. There are 432 leds using the 8 teensy DMA connections.
Now the leds.setPixel(ledCount,color(ArrayB,ArrayG,ArrayR); is in a different order (ArrayR,ArrayG,ArrayB) as is the helper function(r g b) and the padding at the bottom (r g b). Do I need to change those three lines to B G R? I get we are having a color sequence issue. The Octows2811 test runs true for all his colorwipes Red Green Blue etc. so it would appear the GRB is the correct order for these WS2812Bs.
Following your suggest we would write 72 pixels top left to right and 72 back.
 
well, you will now need to remap the pixel data to account for the zigzag. This is most usually done in one of two ways.
1) use a reference array. this is when you set out you led numbers in their actual pattern. you then reference this incrementally. This would look like:

int zigzagArray[] =
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,....etc to 71, then 143,142,141,140,139, ...etc to 72, then 144,145,146,147 ..etc, all the way to cover each pixel}
This is a tedious thing to write out, and is not very useable for other arrangements of pixels, but it does the job in an easy to understand way.

you then reference zigzagArray[] incrementally as in the original setPixel loop, but in the leds.setPixel(ledCount,Color(ArrayB,ArrayG,ArrayR)); line you would use something like leds.setPixel(zigzagArray[ledCount],Color(ArrayB,ArrayG,ArrayR));

2. you use some maths in your loop that sets the pixels. this maths changes the direction of counting each time you reach the end of a row. I have tried to write this below, but have not tested it:

Code:
uint32_t ledCount =0;
uint32_t ledLocation = 0;
 for (int y = 0; y<imageHeight; y++){ //for each row
      for(int x =  0; x<imageWidth; x++){ //go through each coloumn
    
    //use the & bitwise method to see if an odd or even row, we start rows at zero, so if row is odd, we go backwards
        if( y & 0x01) {
          ledLocation =  (y*imageWidth) + ((imageWidth -1) -x);

         } else {
        // Even rows go forwards
            ledLocation = (y * imageWidth) + x;
                }
      //set the pixel at ledLocation with the next colour in the colour array
      leds.setPixel(ledLocation,Color(ArrayR[ledCount],ArrayG[ledCount],ArrayB[ledCount]));
      
      //move on the colour array location by one.
      ledCount = ledCount+1;   
      }
   }
   leds.show();

this would replace the entire piece of code:
Code:
int ledCount =0;
    for(int i=0; i<width*height;i++){
      leds.setPixel(ledCount,Color(ArrayR[i],ArrayG[i],ArrayB[i]));
        ledCount = ledCount+1;
    }   
    leds.show();

like i say, I have not tested the above, but the idea is that you switch between adding or taking away each time the row number is even or odd.
 
Great, well I can test it this afternoon. Let you know. One thing I am missing is the relationship to the Green Red Blue order for the leds. Since I am sending bitmap colors into three buffers, how can I assure what order they are sent to the leds? (it seems like it would matter). Thanks - you have been so so helpful.
 
great progress! what approach did you go with, the maths zigzag routine I posted above? or the array approach?
 
Back in the studio now. Hope you had a nice holiday. I also hope you can help me finish this project. I used the math zigzag program. Only the colors are off. So yes, great progress. You have been a big big help to me, but let me know if you are too busy.
 
Status
Not open for further replies.
Back
Top