Arduino UNO, 2.4" TFT LCD shield

Hi,

I want to display a simple image (woof.bmp) on 2.4" TFT LCD shield using Uno. I used the example code that came with Adafruit_TFTLCD library: tftbmp_shield.ino. But all I see is gibberish image. I tried changing the input images, but I still get a bad image on the TFT.
So, I started working on the code. I tried displaying using the drawBitmap function of Adafruit_GFX library - via the PROGMEM. I found that Adafuit_TFTLCD extends Adafruit_GFX, except the drawBitmap function. So, I included the function directly into my program. So, now my program was doing this:

  1. Read Image from SD card (purple.bmp now).
  2. Convert to Bitmap (in chunks of 60 pixels at a time) using tft.color565 function.
  3. Put the converted chunk in a PROGMEM var
  4. Call drawBitmap

I still see a gibberish image.

Next I learnt about the LCD image convertor tool. So, I removed the first two steps of my algorithm. I made an image in bitmap using this tool and converted to C code. I used the array received directly in my code. I still see a gibberish image.

Below is my code after LCD Image convertor:

// BMP-loading example specifically for the TFTLCD Arduino shield.
// If using the breakout board, use the tftbmp.pde sketch instead!
// If using an Arduino Mega and your sheild does not use the ICSP header for
// SPI, make sure the SD library is configured for ‘soft’ SPI in the file Sd2Card.h.
// If in doubt, update the library to use ‘soft’ SPI.

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

// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
// There are examples in the sketch folder

// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF

#define SD_CS 10 // Card select for shield use
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

//Adafruit_TFTLCD tft;
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
void drawBitmap(int16_t x, int16_t y,
const uint16_t *bitmap, int16_t w, int16_t h,
uint16_t color, uint16_t bg) ;

uint8_t spi_save;

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

tft.reset();

uint16_t identifier = tft.readID();

if(identifier == 0x9341) {
Serial.println(F(“Found ILI9341 LCD driver”));
} else {
Serial.print(F("Unknown LCD driver chip: "));
Serial.println(identifier, HEX);
return;
}

tft.begin(identifier);

Serial.print(F(“Initializing SD card…”));
if (!SD.begin(SD_CS)) {
Serial.println(F(“failed!”));
return;
}
Serial.println(F(“OK!”));
spi_save = SPCR;

delay(1000);
}

void loop()
{
}

void bmpDraw(char *filename, int x, int y) {

static const PROGMEM uint8_t myImage[300] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff
};
drawBitmap(0, 0, myImage, 30, 30, BLACK, WHITE);

}

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

// Draw a 1-bit color bitmap at the specified x, y position from the
// provided bitmap buffer (must be PROGMEM memory) using color as the
// foreground color and bg as the background color.
void drawBitmap(int16_t x, int16_t y,
const uint8_t *bitmap, int16_t w, int16_t h,
uint16_t color, uint16_t bg) {

int16_t i, j, byteWidth = (w + 7) / 8;

for(j=0; j<h; j++) {
for(i=0; i<w; i++ ) {
if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
tft.drawPixel(x+i, y+j, color);
}
else {
tft.drawPixel(x+i, y+j, bg);
}
}
}
}

I am out of ideas now. Please suggest a way out.

Hi,
thanks for the reply. Apologies for the missing content.
I am using this TFT LCD shield : http://www.amazon.in/inch-touch-Screen-Arduino-Shield/dp/B00S9NN3X6?tag=googinhydr18418-21&tag=googinkenshoo-21&ascsubtag=b7051ff4-cf1a-40c0-ad48-da917acf9888

Code:

// BMP-loading example specifically for the TFTLCD Arduino shield.
// If using the breakout board, use the tftbmp.pde sketch instead!
// If using an Arduino Mega and your sheild does not use the ICSP header for 
// SPI, make sure the SD library is configured for 'soft' SPI in the file Sd2Card.h.
// If in doubt, update the library to use 'soft' SPI.

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

// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
// There are examples in the sketch folder

// Assign human-readable names to some common 16-bit color values:
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define SD_CS 10 // Card select for shield use
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

//Adafruit_TFTLCD tft;
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
void drawBitmap(int16_t x, int16_t y,
            const uint16_t *bitmap, int16_t w, int16_t h,
            uint16_t color, uint16_t bg) ; 
            
uint8_t         spi_save;

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

  uint16_t identifier = tft.readID();

  if(identifier == 0x9341) {
    Serial.println(F("Found ILI9341 LCD driver"));
  } else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    return;
  }
 
  tft.begin(identifier);

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

  bmpDraw("myImage", 0, 0); 
  delay(1000);
}

void loop()
{
}

void bmpDraw(char *filename, int x, int y) {
        
    static const PROGMEM uint8_t myImage[300] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 
    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 
    0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff
};
    drawBitmap(0, 0, myImage, 30, 30, BLACK, WHITE); 

}

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

// Draw a 1-bit color bitmap at the specified x, y position from the
// provided bitmap buffer (must be PROGMEM memory) using color as the
// foreground color and bg as the background color.
void drawBitmap(int16_t x, int16_t y,
            const uint8_t *bitmap, int16_t w, int16_t h,
            uint16_t color, uint16_t bg) {

  int16_t i, j, byteWidth = (w + 7) / 8;
  
  for(j=0; j<h; j++) {
    for(i=0; i<w; i++ ) {
      if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
        tft.drawPixel(x+i, y+j, color);
      }
      else {
        tft.drawPixel(x+i, y+j, bg);
      }
    }
  }
}

Result is the image attached.

20160626_062443[1].jpg

OK.

You have saved your graphic as a 24 bit color image. But are printing it as if its 1 bit per pixel. So each pixel is printing as 24 pixels!

Save it in the correct format and try again.

I think the graphic image should look like C5?

If you use this in your drawBitmap function it will print 1 pixel for every 24! But you should then see your graphic.

Call it with:

drawBitmap(0, 0, myImage, 240, 10, BLACK, WHITE);

  for(j=0; j<h; j++) {
    for(i=0; i<w; i++ ) {
      if (i % 24 == 0) {
        if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
          tft.drawPixel(x+i, y+j, color);
        }
        else {
          tft.drawPixel(x+i, y+j, bg);
        }
      }
    }
  }

Done!!!

I converted the 24-bit color image to 1-bit monochrome image. But I removed the code though:

 if (i % 24 == 0)

And I got the result image in the attachment.

Thanks a ton!!!

Yay! Looking good. :slight_smile: Best of luck with your project.