Partage
  • Partager sur Facebook
  • Partager sur Twitter

Arduino mega, ecran tactile et fichier bmp

Problème de carte sd

Sujet résolu
    12 août 2019 à 15:40:01

    Bonjour à tous,

    J'essaie depuis quelques mois de créer une station météo. Pour afficher les informations, mon choix s'est porté sur un écran tactile 3,5 pouces (disponible à l'adresse https://www.amazon.fr/Kuman-Tactile-Arduino-Module-Fonction/dp/B075CXXL1M/ref=sr_1_1?ie=UTF8&qid=1528549257&sr=8-1&keywords=tft+arduino+uno )

    J'ai installé plusieurs librairies telles que AdafruitTFT, AdafruitGFX et MCUfriend.kvb. J'ai testé avec mcufriend le programme GLUE_DEMO_480x320 pour vérifier le bon fonctionnement de mon écran, le programme marche très bien.

    J'ai alors voulu afficher des images au format bmp à partir de ma carte sd, en utilisant la libraire adafruitTFT. Là ont commencé mes problèmes...

    J'ai tout d'abord chargé le programme tftbmp de ladite librairie. Malheureusement en regardant le moniteur série je me suis aperçue que le programme ne reconnaissait pas la puce de mon écran (message : Unknown lcd driver chip : 0). En faisant des recherches j'ai alors découvert que la puce n'était pas une ili9481 ou ili9488 comme indiqué dans le lien amazon mais en vérité ili9486.

    Ensuite, après avoir indiqué la bonne puce la carte SD ne pouvait être lue. Là il s'agissait d'un problème de broches. En effet, les broches SPI (mosi, miso, sck et ss) sont respectivement 11,12,13,10 pour la uno et 51,50,52,53 pour la mega. Ayant une mega, j'ai résolu le problème en reliant les broches du bus SPI aux broches 51,50,52,53.

    J'ai alors écrit mon propre programme que voici

    #include <Adafruit_TFTLCD.h>
    #include <MCUFRIEND_kbv.h>
    #include <Adafruit_GFX.h>    // Core graphics library
    
    #include <Fonts/FreeMonoBoldOblique12pt7b.h>
    #include <Fonts/FreeSansBold12pt7b.h>
    
    #include <SPI.h>
    #include <avr/pgmspace.h>
    #include <SD.h>
    #define SD_CS  53
    
    
    
    
    #define BLACK    0x0000
    #define BLUE     0x001F
    #define RED      0xF800
    #define GREEN    0x07E0
    #define CYAN     0x07FF
    #define MAGENTA  0xF81F
    #define YELLOW   0xFFE0 
    #define WHITE    0xFFFF
    
    MCUFRIEND_kbv tft;
    
    int x, y;
    char currentPage;
    
    void setup() {
      Serial.begin(9600);
      tft.reset();
      tft.begin(0x9486);
      tft.setRotation(1);
      Serial.print("Initializing SD card...");
      if (!SD.begin(SD_CS)) {
        Serial.println("failed!");
        return;
      }
      Serial.println("OK!");
    
    
    }
    
    void loop() {
    
    Homescreen();
    
    while(1);
    }
    
    void Homescreen(){
      bmpDraw("homescreen.bmp",0,0);
      delay(5000); }
    
    #define BUFFPIXEL 20
    
    void bmpDraw(char *filename, int x, int y) {
    
      File     bmpFile;
      int      bmpWidth, bmpHeight;   // W+H in pixels
      uint8_t  bmpDepth;              // Bit depth (currently must be 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)
      uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit per pixel)
      uint8_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;
      uint8_t  r, g, b;
      uint32_t pos = 0, startTime = millis();
      uint8_t  lcdidx = 0;
      boolean  first = true;
    
      if((x >= tft.width()) || (y >= tft.height())) return;
    
      Serial.println();
      Serial.print(F("Loading image '"));
      Serial.print(filename);
      Serial.println('\'');
      // Open requested file on SD card
      if ((bmpFile = SD.open(filename)) == NULL) {
        Serial.println(F("File not found"));
        return;
      }
    
      // Parse BMP header
      if(read16(bmpFile) == 0x4D42) { // BMP signature
        Serial.println(F("File size: ")); Serial.println(read32(bmpFile));
        (void)read32(bmpFile); // Read & ignore creator bytes
        bmpImageoffset = read32(bmpFile); // Start of image data
        Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
        // Read DIB header
        Serial.print(F("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(F("Bit Depth: ")); Serial.println(bmpDepth);
          if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
    
            goodBmp = true; // Supported BMP format -- proceed!
            Serial.print(F("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;
            }
    
            // Crop area to be loaded
            w = bmpWidth;
            h = bmpHeight;
            if((x+w-1) >= tft.width())  w = tft.width()  - x;
            if((y+h-1) >= tft.height()) h = tft.height() - y;
    
            // Set TFT address window to clipped image bounds
            tft.setAddrWindow(x, y, x+w-1, y+h-1);
    
            for (row=0; row<h; row++) { // For each scanline...
              // Seek to start of scan line.  It might seem labor-
              // intensive to be doing this on every line, but this
              // method covers a lot of gritty details like cropping
              // and scanline padding.  Also, the seek only takes
              // place if the file position actually needs to change
              // (avoids a lot of cluster math in SD library).
              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...
                // Time to read more pixel data?
                if (buffidx >= sizeof(sdbuffer)) { // Indeed
                  // Push LCD buffer to the display first
                  if(lcdidx > 0) {
                    tft.pushColors(lcdbuffer, lcdidx, first);
                    lcdidx = 0;
                    first  = false;
                  }
                  bmpFile.read(sdbuffer, sizeof(sdbuffer));
                  buffidx = 0; // Set index to beginning
                }
    
                // Convert pixel from BMP to TFT format
                r = sdbuffer[buffidx++];
                g = sdbuffer[buffidx++];
                b = sdbuffer[buffidx++];
                lcdbuffer[lcdidx++] = tft.color565(r,g,b);
              } // end pixel
            } // end scanline
            // Write any remaining data to LCD
            if(lcdidx > 0) {
              tft.pushColors(lcdbuffer, lcdidx, first);
            } 
            Serial.print(F("Loaded in "));
            Serial.print(millis() - startTime);
            Serial.println(" ms");
          } // end goodBmp
        }
      }
    
      bmpFile.close();
      if(!goodBmp) Serial.println(F("BMP format not recognized."));
    }
    
    // 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;
    }

    (Toute la partie après void bmpDraw est copiée de l'exemple tftbmp de AdafruitTFT)

    La carte SD est bien reconnue (message : Initializing SD card...OK!) mais le fichier bmp lui n'est pas trouvé (message : Loading image : homescreen.bmp File not found). Je précise que j'ai essayé de reformater la carte au format FAT16 et FAT32 sans succès.

    Cela fait des mois que je bloque sur ce problème. Si n'importe qui a une idée voire une solution, je lui en serais très reconnaissant.

    Merci à tous.

    • Partager sur Facebook
    • Partager sur Twitter
      12 août 2019 à 17:42:14

      Bonjour,

      La bibliothèque SD ne gère que les noms courts: 8 caractères, 1 point, 3 caractères d'extension.

      Tu peux soit trouver le nom court correspondant à ton fichier, en utilisant par exemple, l'exemple "List Files", changer le nom de fichier pour qu'il soit conforme à ce qu'attend la bibliothèque, ou utiliser une bibliothèque différente qui gère les noms longs comme SDFat (que tu devrais pouvoir trouver dans le gestionnaire de bibliothèque de l'IDE Arduino).

      • Partager sur Facebook
      • Partager sur Twitter
        12 août 2019 à 18:08:22

        C'était bien mon problème !

        Merci beaucoup pour votre réactivité ! Je passe le sujet en résolu.

        • Partager sur Facebook
        • Partager sur Twitter

        Arduino mega, ecran tactile et fichier bmp

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown