reading - writing two bitmap files to 3.5 teensy

Status
Not open for further replies.

johnwatterson

Well-known member
Ran into trouble writing out two bitmap pictures. Morton Kopf was helping me and I made great progress with him.
Morton had written some code for a Light Painting some years ago using 3.6 teensy. I am using 3.5 teensy. Everything works but can only display one bitmap picture. I need to show one bitmap and 30 seconds later display the other continuously. Best practice? This is a lighted painting but somewhat different.

Code:
//#define USE_OCTOWS2811
#include <SD.h>
#include <OctoWS2811.h>
#include <SPI.h>
//#include <FastLED.h>

//----------set the three below------//
const int ledsPerStrip = 432;
#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;
// File bmpFile;


//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 ArrayG[ARRAY_SIZE];
byte ArrayR[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() {

// paint to bitMap 72X48
// bmpDraw("LEMON1.bmp");
bmpDraw("THISWHT2.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 B, G, R;

 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");
    unsigned int Color (byte b, byte g, byte r);
  /*  
  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();
} */
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();
}

//------- 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 b, byte g, byte r)
{
  //Take the lowest 8 bits of each value and append them end to end
return( ((unsigned int)b & 0x1F )<<16 | ((unsigned int)g & 0x1F)<<8 | (unsigned int)r & 0x1F);
  }
//end of helper function
 
@johnwatterson, sorry, missed this, perhaps keep all questions to the same bitmap thread. Anyhow, you need to put in a timer function of some sort. the easiest way is to count milliseconds. We mark the time that a routine starts, count the number of milliseconds that it has been going for, and when it reaches the milliseconds we have set for it, move on. This can be done by including the counter inside the routine, or in the loop() section. Below is an example of it inside the routine, but I have not tested this our. let me know how you get on.

Code:
//#define USE_OCTOWS2811
#include <SD.h>
#include <OctoWS2811.h>
#include <SPI.h>
//#include <FastLED.h>

//----------set the three below------//
const int ledsPerStrip = 432;
#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;
// File bmpFile;


//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 ArrayG[ARRAY_SIZE];
byte ArrayR[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() {

// paint to bitMap 72X48
// bmpDraw("LEMON1.bmp");


bmpDraw(3000,"THISWHT2.bmp"); //display for 3000 millis, then move on to something else
  
//    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(50);
  } 
}

//////////////////////////////////////////////
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(unsigned long time, char* fileName)
{
unsigned long currentTime = millis();
 while (millis()< currentTime + (time)) {
  
// 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 B, G, R;

 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");
    unsigned int Color (byte b, byte g, byte r);
  /*  
  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();
} */
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();
 }
}

//------- 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 b, byte g, byte r)
{
  //Take the lowest 8 bits of each value and append them end to end
return( ((unsigned int)b & 0x1F )<<16 | ((unsigned int)g & 0x1F)<<8 | (unsigned int)r & 0x1F);
  }
//end of helper function
 
OK, That routine did work to show the bitmap then painted Leds in red.
Here I would like to load and show the second bitmap but the second bitmap does not load and show.
I will post the whole program again with Red leds commented out and bmp file added.


Code:
//#define USE_OCTOWS2811
#include <SD.h>
#include <OctoWS2811.h>
#include <SPI.h>
//#include <FastLED.h>

//----------set the three below------//
const int ledsPerStrip = 432;
#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;
// File bmpFile;


//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 ArrayG[ARRAY_SIZE];
byte ArrayR[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() {

// paint to bitMap 72X48
// bmpDraw("THISWHT2");
// bmpDraw("LEMON1.bmp");


bmpDraw(3000,"THISWHT2.bmp"); //display for 3000 millis, then move on to something else
bmpDraw(10000,"LEMON1,bmp");  //probably 5-10 mins in the end
  

/*
//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(50);
  }
  */
   
}

//////////////////////////////////////////////
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(unsigned long time, char* fileName)
{
unsigned long currentTime = millis();
 while (millis()< currentTime + (time)) {
  
// 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 B, G, R;

 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");
    unsigned int Color (byte b, byte g, byte r);
  /*  
  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();
} */
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();
 }
}

//------- 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 b, byte g, byte r)
{
  //Take the lowest 8 bits of each value and append them end to end
return( ((unsigned int)b & 0x1F )<<16 | ((unsigned int)g & 0x1F)<<8 | (unsigned int)r & 0x1F);
  }
//end of helper function
 
check the spelling of the BMP file in the code. At the moment you have a comma, not a point. That may or may not be the issue, but the code should work if you have the right file name, and the file exists on the card.
Code:
bmpDraw(10000,"LEMON1,bmp");  //probably 5-10 mins in the end
 
OK, my friend that did fix it. Wonderful. I thought we needed a separate function like bmpDraw1 and bmpDraw2 but I love the simple way you got this running for me. Just great. Very happy. I will be glad to send you the gift I offered before (even though it may not be necessary). Send me your mailing address to my email at hotmail account and I will take care of it. Strictly up to you. Really I could not have finished this project without you. Will send a video later. Thanks to all you support guys.
 
great that it's all going now, no need for anything other than the thanks you have already said.
 
Status
Not open for further replies.
Back
Top