Low memory cause bitmap not drawing

im trying to make a proper mensive gift for my girlfriend.
my codes work propperly when i remove some of the bitmap drawing,
when i put back all the bitmap, it doesnt show anything just a black screen and screen monitor said file not found everytime i put back all my bitmap drawing its probably an impact from low memory

Sketch uses 26796 bytes (83%) of program storage space. Maximum is 32256 bytes.
Low memory available, stability problems may occur.
Global variables use 1712 bytes (83%) of dynamic memory, leaving 336 bytes for local variables. Maximum is 2048 bytes.

is there is any way to reduce memory usage for this?

here is my code


#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <SD.h>
#include <SPI.h>

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0


#define SD_CS 10     // Set the chip select line to whatever you use (10 doesnt conflict with the library)

#define  BLACK   0x0000
#define MAGENTA 0xF81F
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4);

void setup()
{
  Serial.begin(9600);

  tft.reset();

  uint16_t identifier = tft.readID();
  tft.begin(identifier);

  Serial.print(F("Initializing SD card..."));
  if (!SD.begin(SD_CS)) {
    Serial.println(F("failed!"));
    return;
  }
  Serial.println(F("OK!"));
}

void loop()
{
    tft.fillScreen(BLACK);
  tft.setTextSize(3);
 

  delay(3000);
  tft.setTextColor(WHITE);
   tft.setCursor(31, 95);

  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print("/");
  delay(100);
  tft.print("0");
  delay(100);
  tft.print("7");
  delay(100);
  tft.print("/");
  delay(100);
  tft.print("2");
  delay(100);
  tft.print("0");
  delay(100);
  tft.print("2");
  delay(100);
  tft.print("2");
  delay(100);

  tft.setTextSize(2);
  tft.setTextColor(WHITE);
  tft.setCursor(21, 135);

  tft.print("H");
  delay(100);
  tft.print("A");
  delay(100);
  tft.print("P");
  delay(100);
  tft.print("P");
  delay(100);
  tft.print("Y");
  delay(100);
  tft.print(" ");
  delay(100);

  tft.setTextColor(MAGENTA);
  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print(" M");
  delay(100);
  tft.print("E");
  delay(100);
  tft.print("N");
  delay(100);
  tft.print("S");
  delay(100);
  tft.print("I");
  delay(100);
  tft.print("V");
  delay(100);
  tft.print("E");
  delay(100);

  tft.setCursor(45, 166);
  tft.setTextSize(4);
  tft.setTextColor(WHITE);

  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print("-");
  delay(100);
  tft.print("-");
  delay(500);


  for (int x = 0; x <= 1; x++) {
    tft.fillScreen(BLACK);
    tft.setTextSize(3);
    tft.setTextColor(BLACK);
    tft.setCursor(31, 95);
    tft.print("----------");
    tft.setTextSize(2);
    tft.setTextColor(BLACK);
    tft.setCursor(21, 135);
    tft.print("HAPPY --- ");
    tft.setTextColor(BLACK);
    tft.print("MENSIVE");
    tft.setCursor(45, 166);
    tft.setTextSize(4);
    tft.setTextColor(BLACK);
    tft.print("----------");
    delay(500);
    
    tft.fillScreen(BLACK);
    tft.setTextSize(3);
    tft.setTextColor(WHITE);
    tft.setCursor(31, 95);
    tft.print("----------");
    tft.setTextSize(2);
    tft.setTextColor(WHITE);
    tft.setCursor(21, 135);
    tft.print("HAPPY --- ");
    tft.setTextColor(MAGENTA);
    tft.print("MENSIVE");
    tft.setCursor(45, 166);
    tft.setTextSize(4);
    tft.setTextColor(WHITE);
    tft.print("------");
    delay(500);
  }
  delay(3000);
  tft.fillScreen(BLACK);
  tft.setTextSize(1.8);
  tft.setCursor(10, 65);
  tft.print(" Halo ----- gak kerasa udah ---\n  bulan ajaa, makasih yaaa udah mau\n  nemenin aku selama inii. Bahagiaa\n  banget bisa bareng kamu teruss semoga\n  kita bisa bareng terus terusan sampe \n  besar kaya dinesol benerann. maaf ya\n  aku suka egois sampe bikin kamu kesel\n  sampe marah HAHAHA. i feel lucky to\n  have you in my life, thank you for\n  making me smile every single");
  tft.print(" day\n  ,thank you for being the best\n  girlfriend everr aku sayang kamuu");
  tft.setCursor(25,tft.height() - tft.height()/4);
  tft.setTextColor(MAGENTA);
  tft.print("   Happy --- Mensiversary--");
  delay(33000);
    tft.fillScreen(BLACK);
  bmpDraw("fotowan.bmp", 0, 0);
  delay(4500);
  bmpDraw("fototu.bmp", 0, 0);
  delay(4500);
  bmpDraw("fototri.bmp", 0, 0);
  delay(4500);
  bmpDraw("fotofor.bmp", 0, 0);
  delay(4500);
  bmpDraw("fotofayf.bmp", 0, 0);
  delay(4500);
  bmpDraw("fotosigs.bmp", 0, 0);
  delay(4500);
  bmpDraw("fotosven.bmp", 0, 0);
  delay(4500);
  bmpDraw("fotonayn.bmp", 0, 0);
  delay(4500);
  bmpDraw("foten.bmp", 0, 0);
  delay(4500);
   
  tft.fillScreen(BLACK);
   tft.setTextSize(2);
     tft.setTextColor(WHITE);
  tft.setCursor(10, tft.height()/2 - 30);
tft.print("love you so much--");
    delay(15000);
}
#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;
 
  // 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
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    // Read DIB header
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!

        // 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
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = 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);
        } 
 
      } // end goodBmp
    }
  }

  bmpFile.close();
}

// 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;
}

sorry for censor

First of all try to use the F() macro for constant strings

so instead of

use

bmpDraw(F("fotofor.bmp"), 0, 0);

it saved you some dozens bytes of RAM

Welcome to the forum

Your topic was MOVED to its current forum category as it is more suitable than the original because it is not an Introductory Tutorial

error: cannot convert 'const __FlashStringHelper*' to 'char*' for argument '1' to 'void bmpDraw(char*, int, int)'
   bmpDraw(F("fotofor.bmp"), 0, 0);

any idea ?

it means that the bmpDraw() is not supported this. Rather sad
Try it at least for tft.print() too

You have a lot of repetition in the bitmap file names, they are all named "foto*.bmp" - that may be improved:

...
bmpDraw("wan", ...);
...

void bmpDraw(char* file_id, ...)
{
  char file_name[15] = {0}; //Must be large enough to hold the longest file name + one null char
  strcat(file_name, "foto");
  strcat(file_name, file_id);
  strcat(file_name, ".bmp");
  //file_name = "fotowan.bmp"
  ...
}

You only have 336 bytes of free memory, how large are the bitmaps?

thanks a lot man you saved my life

ill try it, thankss

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.