Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 38

Thread: Bitmap with Teensy3.5

  1. #1
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60

    Bitmap with Teensy3.5

    Still working on this project. Morton Kopf helped me find his Site and Code. His code uses BUILTIN_SDCARD FOR THE ChipSelect PIN but the compiler complains - 'BUILTIN_CARD' was not declared in this scope:

    In file included from C:\Users\Owner\Documents\Arduino\libraries\My_bitm apDisplay\My_bitmapDisplay.ino:2:0:

    C:\Users\Owner\Documents\Arduino\libraries\librari es\FastLED/FastLED.h:14:21: note: #pragma message: FastLED version 3.002.001

    # pragma message "FastLED version 3.002.001"

    ^

    My_bitmapDisplay:25: error: 'BUILTIN_CARD' was not declared in this scope
    const int chipSelect = BUILTIN_CARD;

    Here is Morton code:

    Code:
    /*
    This code uses the T3.6 onboard sd card slot, BMP stored on the card are light painted using a cheap strip of ws2811 leds using FastLed
    code derived from lightpainting sketch:
    https://forum.pjrc.com/threads/24535-OctoWS2811-POV-reading-BMP-from-SD-card
    and this post:
    ——> https://forum.pjrc.com/threads/40871-Teensy-6-5-SDFat-BMP-file-read-fail
    */
    
    #include <SPI.h>
    #include <SD.h>
    #include <FastLED.h>
    
    File bmpFile;
    const int chipSelect = BUILTIN_SDCARD;
    
    // you can remove all Serial.print when you have your paint staff
    // set up, this is just for debug
    
    int bmpWidth, bmpHeight;
    uint8_t bmpDepth, bmpImageoffset;
    #define BUFFPIXEL 512
    
    unsigned int Color(byte b, byte r, byte g); //placed here to avoid compiler error
    
    // How many leds in your strip?
    #define NUM_LEDS 432
    
    #define DATA_PIN 2 //the pin that Led strip is attached to
    CRGB leds[NUM_LEDS];
    int paintSpeed = 15; //adjust this to vary image refresh rate
    
    void setup(void) {
    Serial.begin(9600);
    
    FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS);
    
    //test our led strip – you can remove this to the comment line "// if you dont get …"
    for(int x=0;x<NUM_LEDS;x++){
    leds[x] = CRGB::Green;}
    FastLED.show();
    delay(500);
    for(int x=0;x<NUM_LEDS;x++){
    leds[x] = CRGB::Red;}
    FastLED.show();
    delay(500);
    for(int x=0;x<NUM_LEDS;x++){
    leds[x] = CRGB::Blue;}
    FastLED.show();
    delay(500);
    for(int x=0;x<NUM_LEDS;x++){
    leds[x] = CRGB::Black;}
    FastLED.show();
    delay(500);
    // 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!");
    return;
    }
    Serial.println("SD OK!");
    
    }
    void loop() {
    
    bmpDraw("JEM.bmp");//example filename
    bmpDraw("DWARFS.bmp");
    bmpDraw("ISLA.bmp");
    }
    
    //////////////////Function to read BMP and send to Led strip a row at a time/////////////////////
    void bmpDraw(char* filename){
    
    File bmpFile;
    int bmpWidth, bmpHeight; // W+H in pixels
    uint8_t bmpDepth; // Bit depth (currently must report 24)
    uint32_t bmpImageoffset; // Start of image data in file
    uint32_t rowSize; // Not always = bmpWidth; may have padding
    uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
    uint32_t povbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel)//////mg/////this needs to be 24bit per pixel////////
    uint32_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
    boolean goodBmp = false; // Set to true on valid header parse
    boolean flip = true; // BMP is stored bottom-to-top
    int w, h, row, col;
    int r, g, b;
    uint32_t pos = 0, startTime = millis();
    uint8_t povidx = 0;
    boolean first = true;
    
    // Open requested file on SD card
    bmpFile = SD.open(filename);
    Serial.println(filename);
    // Parse BMP header
    if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: ");
    Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: ");
    Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("Header size: ");
    Serial.println(read32(bmpFile));
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes — must be ‘1’
    bmpDepth = read16(bmpFile); // bits per pixel
    Serial.print("Bit Depth: "); Serial.println(bmpDepth);
    if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
    
    goodBmp = true; // Supported BMP format — proceed!
    Serial.print("Image size: ");
    Serial.print(bmpWidth);
    Serial.print(‘x’);
    Serial.println(bmpHeight);
    
    // BMP rows are padded (if needed) to 4-byte boundary
    rowSize = (bmpWidth * 3 + 3) & ~3;
    
    // If bmpHeight is negative, image is in top-down order.
    // This is not canon but has been observed in the wild.
    if(bmpHeight < 0) {
    bmpHeight = -bmpHeight;
    flip = false;
    }
    
    w = bmpWidth;
    h = bmpHeight;
    
    for (row=0; row<h; row++) {
    if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
    pos = bmpImageoffset + (bmpHeight – 1 – row) * rowSize;
    else // Bitmap is stored top-to-bottom
    pos = bmpImageoffset + row * rowSize;
    if(bmpFile.position() != pos) { // Need seek?
    bmpFile.seek(pos);
    buffidx = sizeof(sdbuffer); // Force buffer reload
    }
    
    for (col=0; col<w; col++) { // For each column…
    // read more pixel data
    if (buffidx >= sizeof(sdbuffer)) {
    povidx = 0;
    bmpFile.read(sdbuffer, sizeof(sdbuffer));
    buffidx = 0; // Set index to beginning
    }
    // set pixel
    r = sdbuffer[buffidx++];
    g = sdbuffer[buffidx++];
    b = sdbuffer[buffidx++];
    Serial.print(r);Serial.print(" ");Serial.print(g);Serial.print(" ");Serial.println(b);
    //we need to output BRG 24bit colour//
    povbuffer[povidx++] =(b<<16) + (g<<8) +r;
    }
    
    for(int i=0;i<NUM_LEDS;i++){
    leds[i]=povbuffer[i];}
    FastLED.show();
    delay(paintSpeed);// change the delay time depending effect required
    } // end scanline
    
    } // end goodBmp
    }
    }//end of IF BMP
    Serial.println();
    
    bmpFile.close();
    }
    
    //*************Support Funcitons****************//
    // These read 16- and 32-bit types from the SD card file.
    // BMP data is stored little-endian, Arduino is little-endian too.
    // May need to reverse subscript order if porting elsewhere.
    uint16_t read16(File& f) {
    uint16_t result;
    ((uint8_t *)&result)[0] = f.read(); // LSB
    ((uint8_t *)&result)[1] = f.read(); // MSB
    return result;
    }
    uint32_t read32(File& f) {
    uint32_t result;
    ((uint8_t *)&result)[0] = f.read(); // LSB
    ((uint8_t *)&result)[1] = f.read();
    ((uint8_t *)&result)[2] = f.read();
    ((uint8_t *)&result)[3] = f.read(); // MSB
    return result;

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,085
    Not seeing the code there - but the name used is missing "SD":

    // Use these with the Teensy 3.5 & 3.6 SD card
    //#define SDCARD_CS_PIN BUILTIN_SDCARD
    "BUILTIN_CARD" :: Should be as in the posted code: const int chipSelect = BUILTIN_SDCARD;

  3. #3
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60

    Bitmap with Teensy3.5

    Quote Originally Posted by defragster View Post
    Not seeing the code there - but the name used is missing "SD":



    "BUILTIN_CARD" :: Should be as in the posted code: const int chipSelect = BUILTIN_SDCARD;


    Thank you, Now the hardware initalizes, but lights only the leds on pin 2 of the teensy instead of the 8 by 432 that I expect. I did try some changes like NUM_LEDS NUM_STRIP and TOTAL_LEDS but no change. Here is the basic code:
    Code:
    // [code lang=”arduino” light=”true”]
    /*
    This code uses the T3.6 onboard sd card slot, BMP stored on the card are light painted using a cheap strip of ws2811 leds using FastLed
    code derived from lightpainting sketch:
    https://forum.pjrc.com/threads/24535-OctoWS2811-POV-reading-BMP-from-SD-card
    and this post:
    ——> https://forum.pjrc.com/threads/40871-Teensy-6-5-SDFat-BMP-file-read-fail
    Modified for bmpWidth Height and TOTLA_LEDS lights onlt Datapin 2
    */
    #include <OctoWS2811.h>
    #include <SPI.h>
    #include <SD.h>
    #include <FastLED.h>
    
    File bmpFile;
    const int chipSelect = BUILTIN_SDCARD;
    
    // you can remove all Serial.print when you have your paint staff
    // set up, this is just for debug
    
    int bmpWidth = 72, bmpHeight = 48;
    uint8_t bmpDepth, bmpImageoffset;
    #define BUFFPIXEL 512
    
    unsigned int Color(byte b, byte r, byte g); //placed here to avoid compiler error
    
    // How many leds in your strip?
    #define NUM_LEDS 432
    #define NUM_ROWS 8
    #define TOTAL_LEDS (NUM_LEDS * NUM_ROWS)
    #define DATA_PIN 2 //the pin that Led strip is attached to
    CRGB leds[TOTAL_LEDS];
    int paintSpeed = 15; //adjust this to vary image refresh rate
    
    void setup(void) {
    Serial.begin(9600);
    
    FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, TOTAL_LEDS);
    
    //test our led strip – you can remove this to the comment line "// if you dont get …"
    for(int x=0;x<TOTAL_LEDS;x++){
    leds[x] = CRGB::Green;}
    FastLED.show();
    delay(500);
    for(int x=0;x<TOTAL_LEDS;x++){
    leds[x] = CRGB::Red;}
    FastLED.show();
    delay(500);
    for(int x=0;x<TOTAL_LEDS;x++){
    leds[x] = CRGB::Blue;}
    FastLED.show();
    delay(500);
    for(int x=0;x<TOTAL_LEDS;x++){
    leds[x] = CRGB::White;}
    FastLED.show();
    delay(500);
    // 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!");
    return;
    }
    Serial.println("SD OK!");
    
    }

  4. #4
    Senior Member mortonkopf's Avatar
    Join Date
    Apr 2013
    Location
    London, uk
    Posts
    869
    only works on pin 2 as that is what is declared in the sketch. the call to the leds is using the Fastled library, and that has been initialised to use pin2 in your setup.
    #define DATA_PIN 2 //the pin that Led strip is attached to
    FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, TOTAL_LEDS);
    and using FastLED.show(); to light the leds.

    swap out the fasted.show calls to the ones used for the octopus library if that is what you want to do.

  5. #5
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Thank you once again. My setup is 432 leds per-strip times 8 OctoWS2811 leds for atotal of 3456 leds. My bitmap is cols 72 times rows 48 - this should work - yes?

  6. #6
    Senior Member mortonkopf's Avatar
    Join Date
    Apr 2013
    Location
    London, uk
    Posts
    869
    there are a couple of things to consider such as power supply, supply location for longer strips, delay in refresh rate for longer strips, potential delay in SD card read, etc, but yes, should work. You will also need to rework the led colour setting loop if you are planning to use a zigzag led array rather than straight rows. By the numbers above you will zigzag 6 rows for each strip? so somewhere you need to do some reworking / placement of the colours that are taken for a given location in the bitmap to the placement you want in the led array. There are a couple of ways to do this, either by using a maths function in the loop, or by using a reference array that holds the led numbers you want in the right order.

  7. #7
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    My original idea was to paint the existing bitmap picture to the display after sending some text saying this is a painting. That means I need to load your program to on the SD card with a file for drawing the text and then drawing the bitmap file. Everything would shut down and start over when you push a button.

  8. #8
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Using math functions probably makes the most sense in terms of drawing.

  9. #9
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    It looks like your program did read the SD file and size it. It could not draw it to the leds because of the pin 2 problem. I did see the FastLED has a parallel program function but I do not know how to use it in this context.

  10. #10
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Multi-platform Parallel output

    If you are using a due or a digix or a teensy 3 or a teensy 3.1, FastLED now has some new parallel output controllers that will allow you to drive 8 lines of WS2812 strips in parallel. This means that instead of taking 15.3ms/frame of CPU time to write out 512 bytes of data, it would take closer to 1.9ms/frame. See examples/Multiple/ParallelOutputDemo to see how this works.

    On the teensy 3 and 3.1 there's two sets of pins that we can use for parallel output, described below:

    WS2811_PORTD - the OctoWS2811 pins - 2,14,7,8,6,20,21,5
    WS2811_PORTC - pins 15,22,23,9,10,13,11,12,28,27,29,30 (yes, 12 pins! If you're willing to solder onto pads on the back of the teensy)
    WS2811_PORTDC - pins 2,14,7,8,6,20,21,5,15,22,23,9,10,13,11,12 <-- 16 pins, no soldering onto pads on the back!

  11. #11
    Senior Member mortonkopf's Avatar
    Join Date
    Apr 2013
    Location
    London, uk
    Posts
    869
    Quote Originally Posted by johnwatterson View Post
    Multi-platform Parallel output
    but why not just use OctoWS2811 library for eight output strips?

    So, I guess from here it is run a test sketch to ensure that the SD card bitmap is read, run a test sketch to ensure that all eight strips of leds work, have a sketch that sorts out the zigzag arrangement, and then put it all together.

    you can use the BMP from SD card sketch from the POV project to sort out the first part. I would do a read of the whole bmp file and put it into a buffer array, and then do the loop that sets all led pixels, and then do a single write to the pixels.

  12. #12
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Thanks for your suggestions, OK, I will start on that path - make sure I can light the leds with Octows2811 library, then read the Bitmap from the SD card into a pixel map in memory and do a single pixel write to the leds. I think your program will create a buffered map for the BMP file and the OctoWS2811 library could be easy to use. How about the HID interface Teensy uses rather than a serial interface I need to write to each pixel. That is an on going problem for me because I do not understand the HID relationship. I do understand the serial terminal output that shows the SD card is available. How will the HID interface with the bitmap picture in memory output, because that is serial and DMA used by the teensy creates a conflict it seems. I can read up on the HID interface but my understanding of the teensy application is straight DMA starting with pin 2 and continuing for 8 strips. So I have to read the BMP file into memory of the teensy and then output to the leds in serial or HID? Is this correct? I do not need the speed of DMA for this project but want to be sure I know what I am doing, HID or serial output. I will look up HID right now. Thanks

  13. #13
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    OK, I have a program that writes to all the Leds in my 72 cols by 48 rows panel using 3.5 Teensy/Octows2811 and Mortonkopf's program for reading a bitmap file from the SD card on 3.5. However the BMP file does not write out to the Leds. I can make it down about half way to "goodBmp = true;" statement. Image size does print on serial monitor but no bmpWidth or bmpHeight. I do get 3 cols of 72 lines of code following Serial.print("Image size:") The bitmap file does not print to the Leds. Any ideas?
    Code:
    #define USE_OCTOWS2811
    #include <OctoWS2811.h>
    #include <FastLED.h>
    #include <SPI.h>
    #include <SD.h>
    
    File bmpFile;
    const int chipSelect = BUILTIN_SDCARD;
    
    // you can remove all Serial.print when you have your paint staff
    // set up, this is just for debug
    
    int bmpWidth = 72, bmpHeight = 48;
    uint8_t bmpDepth, bmpImageoffset;
    #define BUFFPIXEL 512
    
    #define NUM_LEDS_PER_STRIP 432
    #define NUM_STRIPS 8
    
    CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
    
    // Pin layouts on the teensy 3:
    // OctoWS2811: 2,14,7,8,6,20,21,5
    
    unsigned int Color(byte b, byte r, byte g); //placed here to avoid compiler error
    int paintSpeed = 15; //adjust this to vary image refresh rate
    
    void setup(void) {
      Serial.begin(9600);
      
      LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
      LEDS.setBrightness(32);
    
    // 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!");
    return;
    }
    Serial.println("SD OK!");
    }
    
    void loop() {
      static uint8_t hue = 0;
      for(int i = 0; i < NUM_STRIPS; i++) {
        for(int j = 0; j < NUM_LEDS_PER_STRIP; j++) {
          leds[(i*NUM_LEDS_PER_STRIP) + j] = CHSV((32*i) + hue+j,192,255);
        }
      }
    
      hue++;
    
      LEDS.show();
      LEDS.delay(10);
    
    
    
    bmpDraw("YONION.bmp");          //("JEM.bmp");//example filename
    //bmpDraw("RONION.bmp");        //("DWARFS.bmp");
                                    // bmpDraw("ISLA.bmp");
    }
    
    //////////////////Function to read BMP and send to Led strip a row at a time/////////////////////
    void bmpDraw(char* filename){
    
    File bmpFile;
    int bmpWidth, bmpHeight; // W+H in pixels
    uint8_t bmpDepth; // Bit depth (currently must report 24)
    uint32_t bmpImageoffset; // Start of image data in file
    uint32_t rowSize; // Not always = bmpWidth; may have padding
    uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
    uint32_t povbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel)//////mg/////this needs to be 24bit per pixel////////
    uint32_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
    boolean goodBmp = false; // Set to true on valid header parse
    boolean flip = true; // BMP is stored bottom-to-top
    int w, h, row, col;
    int r, g, b;
    uint32_t pos = 0, startTime = millis();
    uint8_t povidx = 0;
    boolean first = true;
    
    // Open requested file on SD card
    bmpFile = SD.open(filename);
    Serial.println(filename);
    // Parse BMP header
    if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: ");
    Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: ");
    Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("Header size: ");
    Serial.println(read32(bmpFile));
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes — must be ‘1’
    bmpDepth = read16(bmpFile); // bits per pixel
    Serial.print("Bit Depth: "); Serial.println(bmpDepth);
    if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
    
    goodBmp = true; // Supported BMP format — proceed!
    Serial.print("Image size: ");
    Serial.print(bmpWidth);
    Serial.print('X');                            //Serial.print(‘x’);
    Serial.println(bmpHeight);
    
    // BMP rows are padded (if needed) to 4-byte boundary
    rowSize = (bmpWidth * 3 + 3) & ~3;
    
    // If bmpHeight is negative, image is in top-down order.
    // This is not canon but has been observed in the wild.
    if(bmpHeight < 0) {
    bmpHeight = -bmpHeight;
    flip = false;
    }
    
    w = bmpWidth;
    h = bmpHeight;
    
    for (row=0; row<h; row++) {
    if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
      pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;         //pos = bmpImageoffset + (bmpHeight – 1 – row) * rowSize;
    else // Bitmap is stored top-to-bottom
    pos = bmpImageoffset + row * rowSize;
    if(bmpFile.position() != pos) { // Need seek?
    bmpFile.seek(pos);
    buffidx = sizeof(sdbuffer); // Force buffer reload
    }
    
    for (col=0; col<w; col++) { // For each column…
    // read more pixel data
    if (buffidx >= sizeof(sdbuffer)) {
    povidx = 0;
    bmpFile.read(sdbuffer, sizeof(sdbuffer));
    buffidx = 0; // Set index to beginning
    }
    // set pixel
    r = sdbuffer[buffidx++];
    g = sdbuffer[buffidx++];
    b = sdbuffer[buffidx++];
    Serial.print(r);Serial.print(" ");Serial.print(g);Serial.print(" ");Serial.println(b);
    //we need to output BRG 24bit colour//
    povbuffer[povidx++] =(b<<16) + (g<<8) +r;
    }
    
     for(int i=0;i<(NUM_LEDS_PER_STRIP * NUM_STRIPS);i++){
    //  for(int i=0;i<NUM_LEDS;i++){
    leds[i]=povbuffer[i];}
    //FastLED.show();
    LEDS.show();
    delay(paintSpeed);// change the delay time depending effect required
    } // end scanline
    
    } // end goodBmp
    }
    }//end of IF BMP
    Serial.println();
    
    bmpFile.close();
    }
    
    //*************Support Funcitons****************//
    // These read 16- and 32-bit types from the SD card file.
    // BMP data is stored little-endian, Arduino is little-endian too.
    // May need to reverse subscript order if porting elsewhere.
    uint16_t read16(File& f) {
    uint16_t result;
    ((uint8_t *)&result)[0] = f.read(); // LSB
    ((uint8_t *)&result)[1] = f.read(); // MSB
    return result;
    }
    uint32_t read32(File& f) {
    uint32_t result;
    ((uint8_t *)&result)[0] = f.read(); // LSB
    ((uint8_t *)&result)[1] = f.read();
    ((uint8_t *)&result)[2] = f.read();
    ((uint8_t *)&result)[3] = f.read(); // MSB
    return result;
    }

  14. #14
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,085
    If the prints stop midway it seems the processor is faulted [ on read32(bmpFile) ? ] and nothing is running ?

    Code:
       // ...
    bmpDepth = read16(bmpFile); // bits per pixel
    Serial.print("Bit Depth: "); Serial.println(bmpDepth);
    if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
    
    goodBmp = true; // Supported BMP format — proceed!
    If that is the case I posted "debug_t3" that enables {PJRC's} output on fault trapping and gives some way to get feedback keeping the MCU alive enough to show where it was last seen.

  15. #15
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Great - let me ask you - since I am using SPI.h without pin definitions - will the teensy -Octows2811 combination understand? It looks like I am never getting to the buffer load. For example, I do not see the three lines: Serial.print(bmpWidth); Serial.print ("X"); or Serialprint(bmpHeight); Even though there are 72 row of 3 cols each of code?

  16. #16
    Senior Member mortonkopf's Avatar
    Join Date
    Apr 2013
    Location
    London, uk
    Posts
    869
    Hi. the pins for the SD card are taken care of for you when you define "const int chipSelect = BUILTIN_SDCARD;" the Teensy will library will deal with this if using the onboard sd card slot. Hope that clarifies things.

  17. #17
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Yes, thank you much.

  18. #18
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    My mistake. I am getting all the way down to the line - rowSize=(bmp*3+3) & ~3; then I am getting three cols of 72 lines on the serial monitor but no bitmap display on the LEDs. So far I have not found a debug_t3 file for the hardware. I am continuing to work on this project even though I am not communicating very much on the forum. I am trying to learn enough that the details make sense but it has been years since I did this so it does take time.

  19. #19
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,085
    debug_t3 is Only "posts" on the forum - not a thread yet - a search for my last post :: https://forum.pjrc.com/search.php?searchid=4014784

    seems this is the most recent debug_t3.ZIP posted :: Program-hangs-depending-on-code-length

    There are prior posts in that thread with notes on usage. There are example sketches in the zip.

  20. #20
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,085
    Quote Originally Posted by johnwatterson View Post
    My mistake. I am getting all the way down to the line - rowSize=(bmp*3+3) & ~3; then I am getting three cols of 72 lines on the serial monitor but no bitmap display on the LEDs. ...
    Trusting SerMon output when fault or error happens can be hard to pin down. That was why I looked to find a way to use the PJRC code that is off by default to trap faults and keep the USB output engine running as the processor seems to keep ticking over when it faults it just does an infinite loop. It does it for all Serial# ports it seems - but I haven't looked beyond USB Serial yet as it was evolving and I have to rewrite the code more cleanly to allow that to change at run time - and wire up a second Teensy to proxy that output to SerMon to see it.

    The other thing with the 10 buckets allows following code execution in some fashion without copious printing until something goes wrong or the code gets to a point to check with the 'haltif' or assert, etc.

  21. #21
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Thank you - you guys are away above my head. It will take me some time to go through this stuff. I am wondering if it is worth the time it takes for me to figure it out even with your expert help. Simply I am making a art project using teensy on 3456 leds panel I built. I want to read a bitmap picture from the SD card and send it to the 72X48 panel of leds via the teensy/octows2811. It looked like MortonKopf program would do just that. However I am lost in the details. Does anyone have a suggestion as to how to proceed with my goal in mind? I appreciate any thoughts or suggestions.

  22. #22
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Started over and Morton's program is working. So far unable to get the teensy to light more than one string (432 leds) on pin 2.

  23. #23
    Senior Member mortonkopf's Avatar
    Join Date
    Apr 2013
    Location
    London, uk
    Posts
    869
    @johnwatterson - stick with it. what you learn on this project you will be able to use on another and get up and running very quickly on the next project. So, to recap, can you post the sketch you are using. I think that you may still have the fasted calls rather than the octows2811 calls. we'll go through it with you.

  24. #24
    Member
    Join Date
    Jul 2018
    Location
    El Paso, TX
    Posts
    60
    Yes, you are absolutely right. Probably learn more about coding doing this trouble-shooting problem than any other one thing I could do. And for sure this will open a big vat of chocolate for the future.
    This is the last code I tried - replaces FastLED with the teensy/octows2811 code. lights leds, but interferes with "Open requested file on SD card" section. I certainly appreciate any suggestions.
    Code:
    #define USE_OCTOWS2811,
    #include <OctoWS2811.h>
    #include <FastLED.h>
    #include <SPI.h>
    #include <SD.h>
    
    File bmpFile;
    const int chipSelect = BUILTIN_SDCARD;
    
    // you can remove all Serial.print when you have your paint staff
    // set up, this is just for debug
    
    int bmpWidth = 72, bmpHeight = 48;
    uint8_t bmpDepth, bmpImageoffset;
    #define BUFFPIXEL 512
    
    #define NUM_LEDS_PER_STRIP 432
    #define NUM_STRIPS 8
    
    CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
    
    // Pin layouts on the teensy 3:
    // OctoWS2811: 2,14,7,8,6,20,21,5
    
    unsigned int Color(byte b, byte r, byte g); //placed here to avoid compiler error
    int paintSpeed = 15; //adjust this to vary image refresh rate
    
    void setup(void) {
     Serial.begin(9600);
      
      LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
      LEDS.setBrightness(32);
    
    // 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!");
    return;
    }
    Serial.println("SD OK!");
    }
    
    void loop() {
      static uint8_t hue = 0;
      for(int i = 0; i < NUM_STRIPS; i++) {
        for(int j = 0; j < NUM_LEDS_PER_STRIP; j++) {
          leds[(i*NUM_LEDS_PER_STRIP) + j] = CHSV((32*i) + hue+j,192,255);
        }
      }
    
      hue++;
    
      LEDS.show();
      LEDS.delay(10);
    //} 
    //void loop(){
      bmpDraw("YONION.bmp");          //("JEM.bmp");//example filename
    //bmpDraw("RONION.bmp");        //("DWARFS.bmp");
                                    // bmpDraw("ISLA.bmp");
    }
    //////////////////Function to read BMP and send to Led strip a row at a time/////////////////////
    void bmpDraw(char* filename){
    
    File bmpFile;
    int bmpWidth, bmpHeight; // W+H in pixels
    uint8_t bmpDepth; // Bit depth (currently must report 24)
    uint32_t bmpImageoffset; // Start of image data in file
    uint32_t rowSize; // Not always = bmpWidth; may have padding
    uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
    uint32_t povbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel)//////mg/////this needs to be 24bit per pixel////////
    uint32_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
    boolean goodBmp = false; // Set to true on valid header parse
    boolean flip = true; // BMP is stored bottom-to-top
    int w, h, row, col;
    int r, g, b;
    uint32_t pos = 0, startTime = millis();
    uint8_t povidx = 0;
    boolean first = true;
    
    // Open requested file on SD card
    bmpFile = SD.open(filename);
    Serial.println(filename);
    // Parse BMP header
    if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: ");
    Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: ");
    Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("Header size: ");
    Serial.println(read32(bmpFile));
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes — must be ‘1’
    bmpDepth = read16(bmpFile); // bits per pixel
    Serial.print("Bit Depth: "); Serial.println(bmpDepth);
    if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
    
    goodBmp = true; // Supported BMP format — proceed!
    Serial.print("Image size: ");
    Serial.print(bmpWidth);
    Serial.print('X');                            //Serial.print(‘x’);
    Serial.println(bmpHeight);
    
    // BMP rows are padded (if needed) to 4-byte boundary
    rowSize = (bmpWidth * 3 + 3) & ~3;
    
    // If bmpHeight is negative, image is in top-down order.
    // This is not canon but has been observed in the wild.
    if(bmpHeight < 0) {
    bmpHeight = -bmpHeight;
    flip = false;
    }
    
    w = bmpWidth;
    h = bmpHeight;
    
    for (row=0; row<h; row++) {
    if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
      pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;         //pos = bmpImageoffset + (bmpHeight – 1 – row) * rowSize;
    else // Bitmap is stored top-to-bottom
    pos = bmpImageoffset + row * rowSize;
    if(bmpFile.position() != pos) { // Need seek?
    bmpFile.seek(pos);
    buffidx = sizeof(sdbuffer); // Force buffer reload
    }
    
    for (col=0; col<w; col++) { // For each column…
    // read more pixel data
    if (buffidx >= sizeof(sdbuffer)) {
    povidx = 0;
    bmpFile.read(sdbuffer, sizeof(sdbuffer));
    buffidx = 0; // Set index to beginning
    }
    // set pixel
    r = sdbuffer[buffidx++];
    g = sdbuffer[buffidx++];
    b = sdbuffer[buffidx++];
    Serial.print(r);Serial.print(" ");Serial.print(g);Serial.print(" ");Serial.println(b);
    //we need to output BRG 24bit colour//
    povbuffer[povidx++] =(b<<16) + (g<<8) +r;
    }
    
     for(int i=0;i<(NUM_LEDS_PER_STRIP * NUM_STRIPS);i++){
    //  for(int i=0;i<NUM_LEDS;i++){
    leds[i]=povbuffer[i];}
    //FastLED.show();
    LEDS.show();
    delay(paintSpeed);// change the delay time depending effect required
    } // end scanline
    
    } // end goodBmp
    }
    }//end of IF BMP
    Serial.println();
    
    bmpFile.close();
    }
    
    //*************Support Funcitons****************//
    // These read 16- and 32-bit types from the SD card file.
    // BMP data is stored little-endian, Arduino is little-endian too.
    // May need to reverse subscript order if porting elsewhere.
    uint16_t read16(File& f) {
    uint16_t result;
    ((uint8_t *)&result)[0] = f.read(); // LSB
    ((uint8_t *)&result)[1] = f.read(); // MSB
    return result;
    }
    uint32_t read32(File& f) {
    uint32_t result;
    ((uint8_t *)&result)[0] = f.read(); // LSB
    ((uint8_t *)&result)[1] = f.read();
    ((uint8_t *)&result)[2] = f.read();
    ((uint8_t *)&result)[3] = f.read(); // MSB
    return result;
    }

  25. #25
    Senior Member mortonkopf's Avatar
    Join Date
    Apr 2013
    Location
    London, uk
    Posts
    869
    hi, hopefully I will get a chance to look at this tomorrow, but looks like its going to be regarding BUFFPIXEL, or buffer size, as this sketch was only for sending out the bmp colour data to one row of leds.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •