Renkli TFT LCD ekranımızda geometrik şekiller çizmeyi ve dokunmatik paneli kullanmayı başardık. Şimdi ise projelerimize profesyonel bir görsel arayüz kazandırmanın zamanı geldi! Bu rehberde, TFT LCD Shield arkasında bulunan MicroSD kart yuvasını aktif edeceğiz. SD kart içerisine yüklediğimiz gerçek (.bmp) formatındaki görselleri sırasıyla okuyup ekranımızda nasıl dijital bir fotoğraf çerçevesi gibi sergileyebileceğimizi ve resmi 4 farklı yöne nasıl döndürebileceğimizi öğreneceğiz.
Ekranımız Arduino üzerine tam oturduğu için ek bir kablo gerekmez. Ancak SD kart modülünün Arduino ile SPI protokolü üzerinden haberleştiğini ve bu ekran modelinde özel olarak Pin 10 üzerinden Chip Select (Seçim pini) sinyali aldığını bilmemiz gerekir:

| Bileşen Sinyali | Arduino Uno Pini | Açıklama |
|---|---|---|
| SD_CS | Pin 10 | SD Kart Seçim Pini (SPI standardı) |
| LCD Kontrol Pinleri | A0, A1, A2, A3, A4 | Ekranın standart grafik ve yönetim pinleri |
| SPI Hatları (Donanımsal) | Pin 11, 12, 13 | SD kart verilerini yüksek hızda taşımak için kullanılır |
Kodun çalışabilmesi için standart SD.h ve ekranınızın TFTLCD.h kütüphanesinin kurulu olması gerekir. Bu yazılım, SD karttaki resmin başlık (Header) bilgilerini çözümler, 24-bitlik renk kodunu ekranın anlayacağı 16-bit (565) formatına dönüştürür ve ekrana basar.
#include <SD.h>
#include "TFTLCD.h"
// TFT LCD Kontrol Pin Tanımlamaları
#define LCD_CS A3 // Chip Select (Çip Seçimi)
#define LCD_CD A2 // Command/Data (Komut/Veri Seçimi)
#define LCD_WR A1 // Write (Yazma Kontrolü)
#define LCD_RD A0 // Read (Okuma Kontrolü)
#define LCD_RESET A4 // Reset (Sıfırlama Pini)
#define SD_CS 10 // SD kart için kütüphane ile çakışmayan seçim pini
// TFT ekran bağlantımızı tanımlıyoruz
TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// Dosya nesnesi
File bmpFile;
// Bitmap resminden ayıklayacağımız genişlik, yükseklik ve derinlik bilgileri
int bmpWidth, bmpHeight;
uint8_t bmpDepth, bmpImageoffset;
void setup() {
Serial.begin(9600);
tft.reset();
// TFT ekran sürücüsünü bulma ve doğrulama
uint16_t identifier = tft.readRegister(0x0);
identifier = 0x9325; // Test için ILI9325 sabitlendi
if (identifier == 0x9325) {
Serial.println("Found ILI9325");
} else if (identifier == 0x9328) {
Serial.println("Found ILI9328");
} else {
Serial.print("Unknown driver chip ");
Serial.println(identifier, HEX);
while (1);
}
tft.initDisplay();
Serial.print("Initializing SD card...");
pinMode(10, OUTPUT);
// SD kart başlatılamazsa durdur
if (!SD.begin(10)) {
Serial.println("failed!");
return;
}
Serial.println("SD OK!");
// İlk resmi açmayı dene
bmpFile = SD.open("woof.bmp");
if (!bmpFile) {
Serial.println("didnt find image");
while (1);
}
// Resim formatını kontrol et
if (!bmpReadHeader(bmpFile)) {
Serial.println("bad bmp");
return;
}
Serial.print("image size ");
Serial.print(bmpWidth, DEC);
Serial.print(", ");
Serial.println(bmpHeight, DEC);
// İlk resmi sol üst köşeden (0,0) çizdir
bmpdraw(bmpFile, 0, 0);
delay(1000);
bmpFile.close();
// İkinci küçük resmi (miniwoof.bmp) döngü için hazırla
bmpFile = SD.open("miniwoof.bmp");
if (!bmpFile) {
Serial.println("didnt find image");
while (1);
}
if (!bmpReadHeader(bmpFile)) {
Serial.println("bad bmp");
return;
}
Serial.print("image size ");
Serial.print(bmpWidth, DEC);
Serial.print(", ");
Serial.println(bmpHeight, DEC);
}
void loop() {
// Ekranı 4 farklı yöne döndürerek resmi (50,50) koordinatında yeniden çizdirir
tft.setRotation(0);
tft.fillScreen(0);
bmpdraw(bmpFile, 50, 50);
delay(1000);
tft.setRotation(1);
tft.fillScreen(0);
bmpdraw(bmpFile, 50, 50);
delay(1000);
tft.setRotation(2);
tft.fillScreen(0);
bmpdraw(bmpFile, 50, 50);
delay(1000);
tft.setRotation(3);
tft.fillScreen(0);
bmpdraw(bmpFile, 50, 50);
delay(1000);
}
/*********************************************/
// Resim Çizdirme Fonksiyonu
#define BUFFPIXEL 20
void bmpdraw(File f, int x, int y) {
bmpFile.seek(bmpImageoffset);
uint32_t time = millis();
uint16_t p;
uint8_t g, b;
int i, j;
uint8_t sdbuffer[3 * BUFFPIXEL]; // Piksel tampon belleği (Her piksel için 3 bayt)
uint8_t buffidx = 3 * BUFFPIXEL;
Serial.print("rotation = ");
Serial.println(tft.getRotation(), DEC);
for (i = 0; i < bmpHeight; i++) {
// BMP dosyaları pikselleri tersten (aşağıdan yukarıya) sakladığı için yön ayarı yapılıyor
if (tft.getRotation() == 0) {
tft.goTo(x, y + i);
} else if (tft.getRotation() == 1) {
tft.goTo(x + i, y);
} else if (tft.getRotation() == 2) {
tft.goTo(x + (bmpWidth - 1), y + (bmpHeight - 1 - i));
} else if (tft.getRotation() == 3) {
tft.goTo(x + (bmpHeight - 1 - i), y + (bmpWidth - 1));
}
for (j = 0; j < bmpWidth; j++) {
// Tampon boşaldıkça SD karttan yeni pikselleri oku
if (buffidx >= 3 * BUFFPIXEL) {
bmpFile.read(sdbuffer, 3 * BUFFPIXEL);
buffidx = 0;
}
// Rengi 24-bit (888) formatından TFT ekranın uyumlu olduğu 16-bit (565) formatına dönüştür
b = sdbuffer[buffidx++]; // Mavi
g = sdbuffer[buffidx++]; // Yeşil
p = sdbuffer[buffidx++]; // Kırmızı
p >>= 3;
p <<= 6;
g >>= 2;
p |= g;
p <<= 5;
b >>= 3;
p |= b;
// Oluşan 16-bitlik renk verisini ekrana yaz
tft.writeData(p);
}
}
Serial.print(millis() - time, DEC);
Serial.println(" ms");
}
// BMP Dosya Başlığı Okuma ve Doğrulama Fonksiyonu
boolean bmpReadHeader(File f) {
uint32_t tmp;
// BMP sihirli imzasını kontrol et (0x4D42 = "BM")
if (read16(f) != 0x4D42) {
return false;
}
// Dosya boyutunu oku
tmp = read32(f);
Serial.print("size 0x");
Serial.println(tmp, HEX);
// Yapımcı bilgilerini geç (Gereksiz veri)
read32(f);
bmpImageoffset = read32(f);
Serial.print("offset ");
Serial.println(bmpImageoffset, DEC);
// DIB başlık boyutunu oku
tmp = read32(f);
Serial.print("header size ");
Serial.println(tmp, DEC);
bmpWidth = read32(f);
bmpHeight = read32(f);
if (read16(f) != 1)
return false;
bmpDepth = read16(f); // Bit derinliği (Örn: 24-bit)
Serial.print("bitdepth ");
Serial.println(bmpDepth, DEC);
if (read32(f) != 0) {
// Sıkıştırılmış resimler desteklenmiyor!
return false;
}
Serial.print("compression ");
Serial.println(tmp, DEC);
return true;
}
// SD Karttan Little-Endian formatındaki verileri okuma yardımcı fonksiyonları
uint16_t read16(File f) {
uint16_t d;
uint8_t b;
b = f.read();
d = f.read();
d <<= 8;
d |= b;
return d;
}
uint32_t read32(File f) {
uint32_t d;
uint16_t b;
b = read16(f);
d = read16(f);
d <<= 16;
d |= b;
return d;
}
Bu projenin çalışmamasındaki en büyük sebep yanlış formatta resim yüklemektir. Paint veya Photoshop programlarında hazırladığınız görselleri SD karta kaydederken şu kurallara kesinlikle dikkat etmelisiniz:
woof.bmp doğrudur, benim_guzel_kopegimin_resmi.bmp açılmaz).Çözüm: SD kartınızın dosya sistemi Arduino'nun tanıyamayacağı bir formatta (Örn: exFAT veya NTFS) olabilir. Kartınızı bilgisayara takıp biçimlendir dedikten sonra dosya sistemini FAT32 veya FAT (FAT16) olarak değiştirip tekrar deneyin. Ayrıca kartın tam yuvaya oturduğundan emin olun.
Çözüm: Resim isminin kod içerisindeki SD.open("woof.bmp") satırıyla birebir aynı harflerle (büyük/küçük harfe duyarlıdır) yazıldığından emin olun. "Bad bmp" hatası alıyorsanız resminiz 24-bit formatında kaydedilmemiş demektir. Resmi bilgisayarda Paint ile açıp "Farklı Kaydet -> BMP resmi" dedikten sonra alt menüden "24-Bit Sürümü" seçerek yeniden kaydedin.
Gerekli dosyalar: TFTLCD.zip
Güzel olmuş.
Teşekkürler