Skip to content Skip to sidebar Skip to footer

Tutorial 2.4″ TFT LCD Shield Arduino (3. Menampilkan Bitmap)

Daftar Tutorial 2.4″ TFT LCD Shield Arduino:

2.4″ TFT LCD Shield Arduino Bitmap – Pada tutorial sebelumnya (menampilkan font) kita telah bisa menggunakan library GFX dari adafruit untuk menampilkan tulisan. Sekarang kita akan menampilkan bitmap atau gambar di LCD. Ada dua metode yang akan kita lakukan yaitu, membaca gambar dari memori arduino dan membaca gambar dari memori SD Card.


1. Membaca Gambar Dari Memori  Arduino

Membaca dari memori Arduino ini  maksudnya adalah membaca dari SRAM ATmega328. Gambar yang ingin kita buat, kita konversi terlebh dahulu menjadi array. Kemudian array tersebut kita program kedalam arduino. Array ini bisa berupa data gambar RGB atau Hitam Putih. Caranya adalah teman-teman download aplikasi konversi yang namanya ImageConverter 565 dibawah ini:


Kemudian Jalankan Aplikasi. Ikuti cara ini:
a. Klik Open Image. Dalam contoh ini saya ingin menampilkan gambar doraemon.


b. Setelah masukkan gambar, kemudian Atur Resolusi seperti gambar dibawah:


c. Klik Save dengan extensi file .c dan target Board Arduino (AVR).

d. Setelah selesai di save, teman-teman akan mendapatkan file doraemon.c dengan isiannya seperti ini:


e. Buka Arduino IDE teman-teman, kemudian gunakan program berikut:

//-------------------//
//hamboelektronik.com//
//-------------------//

#include "MCUFRIEND_kbv.h"
MCUFRIEND_kbv tft;

#define LOWFLASH (defined(__AVR_ATmega328P__) && defined(MCUFRIEND_KBV_H_))

#include "bitmap.h"     //masukkan file bitmap.h

//definisikan warna dengan kode warna
#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 GREY    0x8410
#define ORANGE  0xE880

void setup()
{
  Serial.begin(9600);
  uint16_t ID = tft.readID(); //akan membaca ID dari tipe LCD
  tft.begin(ID);

  int x = 5, y, w = 240, h = 320; //definisikan piksel yang akan digunakan
  const int SZ = w * h ;
  uint8_t sram[SZ];

  tft.fillScreen(BLACK);
  y = 0; 
  tft.drawRGBBitmap(x, y, doraemon, 100, 82); //tampilkan gambar di LCD
}

void loop(void)
{

}

f. Kemudian buat sebuah tab baru dan tulis dengan nama bitmap.h. Lihat pada gambar dibawah:


g. copy semua data yang ada pada file doraemon.c, kemudian paste-kan kedalam bitmap.h. Kemudian ganti kata unsigned short menjadi uint16_t. Terlihat pada gambar berikut.


h. Klik Upload, maka gambar akan tampil seperti pada gambar dibawah:


2. Membaca Gambar Dari Memori Card

Membaca gambar dari memori lebih baik digunakan kerena tidak menggunakan SRAM. Jadi, gambar yang ditampilkan mencarapi resolusi 320*240 piksel. Pada tutorial ini, contoh akan menampilkan gambar dengan format gambar adalah .bmp. Ikuti langkah-langkah berikut:

a. Pada tutorial ini saya menggunakan gambar “doraemon.png”, dan saya konvert ke “doraemon.bmp” menggunakan aplikasi “Paint” yang merupakan aplikasi bawaan Windows. Gambar ini memiliki resolusi 290×238 px.


b. Letakkan gambar tersebut kedalam memori card dan masukkan memori card kedalam slot di LCD.
c.Gunakan program berikut:

//-------------------//
//hamboelektronik.com//
//-------------------//

#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#if defined(ESP32)
#define SD_CS     5
#else
#define SD_CS     10
#endif

#define NAMEMATCH "doraemon"   // doraemon.bmp
#define PALETTEDEPTH   0
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL      20

char namaBuffer[32] = "/";   //karakter "/" artinya root, atau halaman awal memori bukan folder
//char namaBuffer[32] = "/namaFolder/";  //jika gambar berada didalam folder maka ditulis "/namaFolder/doraemon.bmp
int bmpWidth, bmpHeight;    // lebar dan tinggi gambar dalam satuan piksel
uint8_t bmpDepth;
uint32_t bmpImageoffset;    // memulai data gambar pada file
uint32_t rowSize;
uint8_t sdbuffer[3 * BUFFPIXEL];    // piksel didalam buffer (R+G+B per piksel)
uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
uint8_t bitmask, bitshift;
boolean flip = true;        // File gambar nanti akan di simpan dari baris bawah ke atas
//Jika nilainya adalah "false" maka tampilan akan dimulai dari bawah ke atas gambar
//Jika nilainya adalah "true" maka tampilan akan dimulai dari atas ke kebawah
int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
uint32_t pos;
boolean is565 = false;
uint16_t bmpID;
uint16_t n;                 // blok baca
uint8_t ret;
int pjgPath;
char *nm = namaBuffer + pjgPath;
uint32_t start;

File root;
File f;

void setup()
{
  uint16_t ID;
  ID = tft.readID();
  tft.begin(ID);
  tft.setRotation(1);     //Jadikan tampilan landscape, jika "0" maka akan potrait
  tft.fillScreen(0x001F); //tetapkan warna latar sebelum memuat gambar

  //cek apakah ada memori card
  bool ada = SD.begin(SD_CS);
  if (!ada) {                                   //jika tidak ada
    Serial.print(F("SD tidak terdeteksi"));     //beritahu melalui serial monitor
    while (1);
  }

  root = SD.open(namaBuffer); //root artinya buka pada halaman awal memori atau "/"
  pjgPath = strlen(namaBuffer); //menghitung panjang dari sebuah string dari namaBuffer
}

void loop()
{
  f = root.openNextFile();
  if (f != NULL) {
#ifdef USE_SDFAT
    f.getName(nm, 32 - pjgPath);
#else
    strcpy(nm, (char *)f.name());
#endif
    f.close();
    strlwr(nm);
    if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH) != NULL) {
      Serial.print(namaBuffer);
      Serial.print(F(" - "));
      tft.fillScreen(0);
      start = millis();
      ret = showBMP(namaBuffer, 5, 5);
      delay(10000);
    }
  }
  else root.rewindDirectory();

}


uint16_t read16(File& f) {
  uint16_t result;
  f.read((uint8_t*)&result, sizeof(result));
  return result;
}

uint32_t read32(File& f) {
  uint32_t result;
  f.read((uint8_t*)&result, sizeof(result));
  return result;
}

uint8_t showBMP(char *nm, int x, int y)
{
  File bmpFile;
  if ((x >= tft.width()) || (y >= tft.height()))
    return 1;               // matikan layar

  bmpFile = SD.open(nm);      // Penguraian file BMP
  bmpID = read16(bmpFile);    // BMP signature
  (void) read32(bmpFile);     // Baca dan abaikan ukuran file
  (void) read32(bmpFile);     // Baca dan abaikan byte pembuat
  bmpImageoffset = read32(bmpFile);       // Mulai dari data gambar
  (void) read32(bmpFile);     // Baca & abaikan ukuran header DIB
  bmpWidth = read32(bmpFile);
  bmpHeight = read32(bmpFile);
  n = read16(bmpFile);        // bidang harus 1
  bmpDepth = read16(bmpFile); // bit per pixel
  pos = read32(bmpFile);      // format
  if (bmpID != 0x4D42) ret = 2; // ID yang buruk
  else if (n != 1) ret = 3;   // terlalu banyak bidang
  else if (pos != 0 && pos != 3) ret = 4; // format: 0 = tidak terkompresi, 3 = 565
  else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
  else {
    bool first = true;
    is565 = (pos == 3);               // Sudah dalam format 16-bit?
    // Baris BMP diisi (jika perlu) hingga batas 4-byte
    rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
    if (bmpHeight < 0) {              // Jika negatif, gambar berada dalam urutan top-down.
      bmpHeight = -bmpHeight;
      flip = false;
    }

    w = bmpWidth;
    h = bmpHeight;
    if ((x + w) >= tft.width())      // Pangkas area yang akan dimuat
      w = tft.width() - x;
    if ((y + h) >= tft.height())
      h = tft.height() - y;

    if (bmpDepth <= PALETTEDEPTH) {  // Mode ini memiliki palet terpisah
      bmpFile.seek(BMPIMAGEOFFSET); // palet selalu @ 54
      bitmask = 0xFF;
      if (bmpDepth < 8)
        bitmask >>= bmpDepth;
      bitshift = 8 - bmpDepth;
      n = 1 << bmpDepth;
      lcdbufsiz -= n;
      palette = lcdbuffer + lcdbufsiz;
      for (col = 0; col < n; col++) {
        pos = read32(bmpFile);    // peta palet ke 5-6-5
        palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
      }
    }

    // Tetapkan jendela alamat TFT untuk memotong batas gambar
    tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
    for (row = 0; row < h; row++) { // Untuk setiap garis pemindaian ...
      uint8_t r, g, b, *sdptr;
      int lcdidx, lcdleft;
      if (flip)
        pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
      else
        pos = bmpImageoffset + row * rowSize;
      if (bmpFile.position() != pos) {
        bmpFile.seek(pos);
        buffidx = sizeof(sdbuffer); // Paksa muat ulang buffer
      }

      for (col = 0; col < w; ) {  //piksel dalam baris
        lcdleft = w - col;
        if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
        for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer sekaligus
          uint16_t color;
          // Waktu untuk membaca lebih banyak data piksel?
          if (buffidx >= sizeof(sdbuffer)) { // Indeed
            bmpFile.read(sdbuffer, sizeof(sdbuffer));
            buffidx = 0; // Set index untuk pemulaian
            r = 0;
          }

          switch (bmpDepth) {          // Konversi pixel dari BMP ke format TFT
            case 1:
            case 4:
            case 8:
              if (r == 0)
                b = sdbuffer[buffidx++], r = 8;
              color = palette[(b >> bitshift) & bitmask];
              r -= bmpDepth;
              b <<= bmpDepth;
              break;
            case 24:
              b = sdbuffer[buffidx++];
              g = sdbuffer[buffidx++];
              r = sdbuffer[buffidx++];
              color = tft.color565(r, g, b);
              break;
            case 16:
              b = sdbuffer[buffidx++];
              r = sdbuffer[buffidx++];
              if (is565)
                color = (r << 8) | (b);
              else
                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
              break;
          }
          lcdbuffer[lcdidx] = color;
        }
        tft.pushColors(lcdbuffer, lcdidx, first);
        first = false;
        col += lcdidx;
      }           // berakhir kolom
    }               // berakhir baris
    tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //kembalikan layar penuh
    ret = 0;
  }
  bmpFile.close();
  return (ret);
}

d. Upload program diatas ke arduino.

e. Hasilnya adalah sebagai berikut:


Demikian tutorial 2.4″ TFT LCD menggunakan Arduino. Selanjutnya akan dibuat tutorial bagaimana menggunakan layar sentuh pada 2.4″ TFT LCD menggunakan Arduino.

Post a Comment for "Tutorial 2.4″ TFT LCD Shield Arduino (3. Menampilkan Bitmap)"