Bu projemizde, Arduino Uno ve dokunmatik TFT LCD ekran modülünü bir üst seviyeye taşıyarak bir "Aktivite Merkezi" tasarlıyoruz. Durum makinesi (State Machine) mimarisiyle yazılan bu gelişmiş proje; dinamik bir ana menü, renk paletli ve fırça boyutlu bir resim çizim atölyesi, Arduino'ya karşı oynayabileceğiniz yapay zeka algoritmalı bir XOX (Tic-Tac-Toe) oyunu ve ekran sapmalarını sıfırlayan EEPROM kayıtlı 5 noktalı hassas kalibrasyon menüsünü tek bir kod içinde birleştiriyor.

Görsel: TFT LCD Ekran Üzerinde Ana Menü ve Alt Uygulama Arayüzleri
Proje, ekran verimliliğini ve kullanıcı deneyimini artırmak için nesne yönelimli mantıkla tasarlanmış 4 ana modülden oluşur:
enum EkranDurumu yapısı sayesinde Arduino o an hangi ekranda olduğunu bilir. Menü butonlarına dokunulduğunda klik efekti (görsel geri bildirim) tetiklenir ve ilgili mod sorunsuz bir şekilde başlatılır.Kritik Bilgi: TFT LCD ekranların kontrol pinleri ile dokunmatik panelin okuma pinleri (A1, A2, 6, 7 nolu pinler) donanımsal olarak ortaktır. Dokunmatik panelden veri okunduktan sonra ekranın düzgün çizim yapabilmesi için pinlerin tekrar çıkış (OUTPUT) yapılması ve HIGH seviyesine çekilmesi gerekir. Kod yapımız bu döngüyü otomatik olarak yöneterek ekranın kilitlenmesini engeller.
#include "TFTLCD.h"
#include "TouchScreen.h"
#include <EEPROM.h>
// Dokunmatik Ekran Donanımsal Pinleri
#define YP A1
#define XM A2
#define YM 7
#define XP 6
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
// TFT LCD Kontrol Pinleri
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4
// 16-bit Gelişmiş Renk Paleti (RGB565 formatı)
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define WHITE 0xFFFF
#define YELLOW 0xFFE0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define GRAY 0x7BEF
#define DARK_GRAY 0x31A6
TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// Kalibrasyon Katsayıları
float tsA = 0.3117, tsB = 0.0, tsC = -46.75;
float tsD = 0.0, tsE = -0.39, tsF = 366.8;
struct CalibData {
byte magic; // Kalibrasyon geçerlilik imzası (0xCD)
float A; float B; float C;
float D; float E; float F;
};
// Durum Makinesi (State Machine) Tanımları
enum EkranDurumu { MENU, PAINT, GAME, CALIB };
EkranDurumu mevcutDurum = MENU;
// Resim Atölyesi Değişkenleri
uint16_t cizimRengi = GREEN;
int fircaBoyutu = 3;
// XOX Oyunu Değişkenleri
char xoxTahta[3][3];
char siraKimde = 'X'; // Oyuncu = 'X', Arduino = 'O'
int oyuncuSkor = 0;
int arduinoSkor = 0;
bool oyunBitti = false;
String oyunSonucMesaji = "";
#define MINPRESSURE 10
#define MAXPRESSURE 1000
void setup(void) {
Serial.begin(9600);
tft.reset();
tft.initDisplay();
tft.setRotation(0); // Dikey Ekran Yönü (240x320)
// EEPROM'dan kalibrasyon değerlerini yükle
eepromYukle();
// Ana Menüyü Çiz
anaMenuyuCiz();
}
void loop() {
TSPoint p = ts.getPoint();
// Paylaşımlı pinlerin ekran kontrolü için çıkış yapılması
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
digitalWrite(XM, HIGH);
digitalWrite(YP, HIGH);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
// Kalibre edilmiş hassas koordinatlar
int x = tsA * p.x + tsB * p.y + tsC;
int y = tsD * p.x + tsE * p.y + tsF;
x = constrain(x, 0, tft.width() - 1);
y = constrain(y, 0, tft.height() - 1);
// Mevcut duruma göre dokunma işlemlerini yürüt
switch (mevcutDurum) {
case MENU:
anaMenuDokunmaYonet(x, y);
break;
case PAINT:
resimAtolyesiDokunmaYonet(x, y);
break;
case GAME:
xoxOyunuDokunmaYonet(x, y);
break;
case CALIB:
// Kalibrasyon kendi iç döngüsünü yönetir
break;
}
}
}
void anaMenuyuCiz() {
mevcutDurum = MENU;
tft.fillScreen(BLACK);
// Başlık Şeridi
tft.fillRect(0, 2, tft.width(), 45, BLUE);
tft.drawString(3, 16, "TFT AKTIVITE MERKEZI", WHITE, 2);
// Buton 1: Resim Atölyesi
tft.fillRect(15, 75, 210, 55, DARK_GRAY);
tft.drawRect(15, 75, 210, 55, WHITE);
tft.drawString(45, 93, "RESIM ATOLYESI", GREEN, 2);
// Buton 2: XOX Oyunu
tft.fillRect(15, 150, 210, 55, DARK_GRAY);
tft.drawRect(15, 150, 210, 55, WHITE);
tft.drawString(65, 168, "XOX OYUNU", CYAN, 2);
// Buton 3: Kalibrasyon
tft.fillRect(15, 225, 210, 55, DARK_GRAY);
tft.drawRect(15, 225, 210, 55, WHITE);
tft.drawString(45, 243, "EKRAN AYARLARI", YELLOW, 2);
// Alt Bilgi
tft.drawString(30, 300, "Secmek icin ekrana dokunun.", GRAY, 1);
}
void anaMenuDokunmaYonet(int x, int y) {
// Resim Atölyesi Seçimi
if (x > 15 && x < 225 && y > 75 && y < 130) {
butonGeriBildirimEfekti(15, 75, 210, 55);
resimAtolyesiniBaslat();
}
// XOX Oyunu Seçimi
else if (x > 15 && x < 225 && y > 150 && y < 205) {
butonGeriBildirimEfekti(15, 150, 210, 55);
xoxOyununuBaslat();
}
// Kalibrasyon Seçimi
else if (x > 15 && x < 225 && y > 225 && y < 280) {
butonGeriBildirimEfekti(15, 225, 210, 55);
mevcutDurum = CALIB;
kalibrasyonYonetimi();
}
}
void resimAtolyesiniBaslat() {
mevcutDurum = PAINT;
tft.fillScreen(BLACK);
// Çizim Alanı Sınırları (Üst ve alt menüler hariç)
tft.drawRect(0, 50, 240, 220, GRAY);
// Üst Menü: Renk Paletleri
// Renk kutuları (X: 5'ten başlayarak 35px genişlik, 35px yükseklik, 10px boşluk)
uint16_t renkler[] = {RED, GREEN, BLUE, YELLOW, WHITE};
for (int i = 0; i < 5; i++) {
tft.fillRect(5 + (i * 45), 5, 35, 35, renkler[i]);
tft.drawRect(5 + (i * 45), 5, 35, 35, GRAY);
}
// Silgi Butonu (En sağda)
tft.fillRect(230, 5, 10, 35, BLACK);
tft.drawRect(230, 5, 10, 35, WHITE);
// Alt Menü Kontrolleri
// "TEMIZLE" Butonu
tft.fillRect(5, 280, 80, 35, RED);
tft.drawString(12, 290, "TEMIZLE", WHITE, 1);
// Fırça Boyutu Butonu
tft.fillRect(95, 280, 60, 35, DARK_GRAY);
tft.drawString(102, 290, "FIRCA: M", WHITE, 1);
// "GERI" Butonu
tft.fillRect(165, 280, 70, 35, BLUE);
tft.drawString(185, 290, "GERI", WHITE, 1);
cizimRengi = GREEN;
fircaBoyutu = 3;
}
void resimAtolyesiDokunmaYonet(int x, int y) {
// Üst Palet Seçimleri (Y: 5 - 40)
if (y > 5 && y < 40) {
for (int i = 0; i < 5; i++) {
int btnX = 5 + (i * 45);
if (x > btnX && x < (btnX + 35)) {
uint16_t renkler[] = {RED, GREEN, BLUE, YELLOW, WHITE};
cizimRengi = renkler[i];
return;
}
}
// Silgi seçimi (En sağdaki küçük alan)
if (x > 225) {
cizimRengi = BLACK;
}
}
// Alt Buton Alanları (Y: 280 - 315)
else if (y > 280 && y < 315) {
// TEMIZLE Butonu
if (x > 5 && x < 85) {
tft.fillRect(1, 51, 238, 218, BLACK);
delay(150);
}
// FIRCA BOYUTU Butonu
else if (x > 95 && x < 155) {
if (fircaBoyutu == 1) {
fircaBoyutu = 3;
tft.fillRect(95, 280, 60, 35, DARK_GRAY);
tft.drawString(102, 290, "FIRCA: M", WHITE, 1);
} else if (fircaBoyutu == 3) {
fircaBoyutu = 6;
tft.fillRect(95, 280, 60, 35, DARK_GRAY);
tft.drawString(102, 290, "FIRCA: L", WHITE, 1);
} else {
fircaBoyutu = 1;
tft.fillRect(95, 280, 60, 35, DARK_GRAY);
tft.drawString(102, 290, "FIRCA: S", WHITE, 1);
}
delay(200);
}
// GERI Butonu
else if (x > 165 && x < 235) {
anaMenuyuCiz();
delay(200);
}
}
// Çizim Alanı İçinde Kalınma Durumu (Y: 52 - 268)
else if (y > (50 + fircaBoyutu) && y < (270 - fircaBoyutu) && x > fircaBoyutu && x < (240 - fircaBoyutu)) {
tft.fillCircle(x, y, fircaBoyutu, cizimRengi);
}
}
void xoxOyununuBaslat() {
mevcutDurum = GAME;
tft.fillScreen(BLACK);
// Üst Bar (Skorlar ve Geri Butonu)
tft.fillRect(0, 2, tft.width(), 40, BLUE);
tft.drawString(10, 15, "SKOR: OYUNCU ", WHITE, 1);
tft.drawString(100, 15, String(oyuncuSkor).c_str(), GREEN, 1);
tft.drawString(120, 15, " - ", WHITE, 1);
tft.drawString(140, 15, String(arduinoSkor).c_str(), RED, 1);
tft.drawString(155, 15, " ARDUINO", WHITE, 1);
// "GERI" Menü Butonu (Sağ Üstte)
tft.fillRect(200, 7, 35, 30, RED);
tft.drawString(208, 18, "<", WHITE, 1);
// Oyun Tahtasını Sıfırla
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
xoxTahta[i][j] = ' ';
}
}
oyunBitti = false;
siraKimde = 'X';
oyunSonucMesaji = "";
xoxGridCiz();
}
void xoxGridCiz() {
tft.fillRect(30, 70, 180, 180, BLACK);
tft.drawRect(30, 70, 180, 180, WHITE);
// Dikey Çizgiler
tft.drawLine(90, 70, 90, 250, WHITE);
tft.drawLine(150, 70, 150, 250, WHITE);
// Yatay Çizgiler
tft.drawLine(30, 130, 210, 130, WHITE);
tft.drawLine(30, 190, 210, 190, WHITE);
// Alt Durum Bilgisi Alanı
tft.fillRect(10, 260, 220, 55, BLACK);
if (!oyunBitti) {
tft.drawString(45, 275, "SIRA SIZDE (X)", CYAN, 2);
}
}
void xoxOyunuDokunmaYonet(int x, int y) {
if (x > 200 && x < 235 && y > 7 && y < 37) {
anaMenuyuCiz();
delay(200);
return;
}
if (oyunBitti) {
xoxOyununuBaslat();
delay(250);
return;
}
if (siraKimde == 'X') {
if (x >= 30 && x <= 210 && y >= 70 && y <= 250) {
int sutun = (x - 30) / 60;
int satir = (y - 70) / 60;
if (xoxTahta[satir][sutun] == ' ') {
xoxTahta[satir][sutun] = 'X';
sembolCiz(satir, sutun, 'X');
if (xoxDurumKontrol()) {
oyunSonlandir();
} else {
siraKimde = 'O';
tft.fillRect(10, 260, 220, 55, BLACK);
tft.drawString(30, 275, "ARDUINO DUSUNUYOR...", RED, 1);
delay(800);
arduinoHamlesiYap();
}
}
}
}
}
void arduinoHamlesiYap() {
if (oyunBitti) return;
int secilenSatir = -1;
int secilenSutun = -1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (xoxTahta[i][j] == ' ') {
xoxTahta[i][j] = 'O';
if (kontrolKazanma('O')) {
secilenSatir = i;
secilenSutun = j;
xoxTahta[i][j] = ' ';
break;
}
xoxTahta[i][j] = ' ';
}
}
if (secilenSatir != -1) break;
}
if (secilenSatir == -1) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (xoxTahta[i][j] == ' ') {
xoxTahta[i][j] = 'X';
if (kontrolKazanma('X')) {
secilenSatir = i;
secilenSutun = j;
xoxTahta[i][j] = ' ';
break;
}
xoxTahta[i][j] = ' ';
}
}
if (secilenSatir != -1) break;
}
}
if (secilenSatir == -1) {
if (xoxTahta[1][1] == ' ') {
secilenSatir = 1;
secilenSutun = 1;
}
}
if (secilenSatir == -1) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (xoxTahta[i][j] == ' ') {
secilenSatir = i;
secilenSutun = j;
break;
}
}
if (secilenSatir != -1) break;
}
}
if (secilenSatir != -1 && secilenSutun != -1) {
xoxTahta[secilenSatir][secilenSutun] = 'O';
sembolCiz(secilenSatir, secilenSutun, 'O');
if (xoxDurumKontrol()) {
oyunSonlandir();
} else {
siraKimde = 'X';
tft.fillRect(10, 260, 220, 55, BLACK);
tft.drawString(45, 275, "SIRA SIZDE (X)", CYAN, 2);
}
}
}
void sembolCiz(int satir, int sutun, char tur) {
int merkezX = 30 + (sutun * 60) + 30;
int merkezY = 70 + (satir * 60) + 30;
if (tur == 'X') {
tft.drawLine(merkezX - 15, merkezY - 15, merkezX + 15, merkezY + 15, CYAN);
tft.drawLine(merkezX + 15, merkezY - 15, merkezX - 15, merkezY + 15, CYAN);
} else {
tft.drawCircle(merkezX, merkezY, 15, RED);
}
}
bool kontrolKazanma(char oyuncu) {
for (int i = 0; i < 3; i++) {
if (xoxTahta[i][0] == oyuncu && xoxTahta[i][1] == oyuncu && xoxTahta[i][2] == oyuncu) return true;
}
for (int j = 0; j < 3; j++) {
if (xoxTahta[0][j] == oyuncu && xoxTahta[1][j] == oyuncu && xoxTahta[2][j] == oyuncu) return true;
}
if (xoxTahta[0][0] == oyuncu && xoxTahta[1][1] == oyuncu && xoxTahta[2][2] == oyuncu) return true;
if (xoxTahta[0][2] == oyuncu && xoxTahta[1][1] == oyuncu && xoxTahta[2][0] == oyuncu) return true;
return false;
}
bool xoxDurumKontrol() {
if (kontrolKazanma('X')) {
oyunSonucMesaji = "KAZANDINIZ! :)";
oyuncuSkor++;
oyunBitti = true;
return true;
}
if (kontrolKazanma('O')) {
oyunSonucMesaji = "ARDUINO KAZANDI! :(";
arduinoSkor++;
oyunBitti = true;
return true;
}
bool tahtaDolu = true;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (xoxTahta[i][j] == ' ') tahtaDolu = false;
}
}
if (tahtaDolu) {
oyunSonucMesaji = "BERABERE BITTID!";
oyunBitti = true;
return true;
}
return false;
}
void oyunSonlandir() {
tft.fillRect(10, 260, 220, 55, BLACK);
tft.drawString(15, 270, oyunSonucMesaji.c_str(), YELLOW, 2);
tft.drawString(30, 295, "Yeni Oyun icin Dokun", WHITE, 1);
siraKimde = 'X';
}
void kalibrasyonYonetimi() {
tft.fillScreen(BLACK);
tft.fillRect(0, 2, tft.width(), 38, BLUE);
tft.drawString(35, 14, "EKRAN AYARLARI", WHITE, 2);
tft.drawString(15, 60, "Ekraninizi kalibre", WHITE, 2);
tft.drawString(15, 85, "etmek ister misiniz?", WHITE, 2);
tft.fillRect(15, 140, 210, 45, GREEN);
tft.drawRect(15, 140, 210, 45, WHITE);
tft.drawString(55, 154, "KALIBRE ET", BLACK, 2);
tft.fillRect(15, 205, 210, 45, RED);
tft.drawRect(15, 205, 210, 45, WHITE);
tft.drawString(75, 219, "VAZGEC", WHITE, 2);
while (true) {
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
digitalWrite(XM, HIGH);
digitalWrite(YP, HIGH);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
int tx = tsA * p.x + tsB * p.y + tsC;
int ty = tsD * p.x + tsE * p.y + tsF;
tx = constrain(tx, 0, tft.width() - 1);
ty = constrain(ty, 0, tft.height() - 1);
if (tx > 15 && tx < 225 && ty > 140 && ty < 185) {
dokunmaBirakilanaKadarBekle();
kalibrasyonYap5Nokta();
break;
}
if (tx > 15 && tx < 225 && ty > 205 && ty < 250) {
dokunmaBirakilanaKadarBekle();
anaMenuyuCiz();
break;
}
}
delay(50);
}
}
void kalibrasyonYap5Nokta() {
tft.fillScreen(BLACK);
tft.drawString(30, 100, "5-NOKTALI HASSAS", CYAN, 2);
tft.drawString(30, 130, "KALIBRASYON", CYAN, 2);
tft.drawString(30, 160, "BASLIYOR...", WHITE, 2);
delay(1500);
long tX[5] = {30, 210, 30, 210, 120};
long tY[5] = {40, 40, 280, 280, 160};
long rX[5] = {0, 0, 0, 0, 0};
long rY[5] = {0, 0, 0, 0, 0};
const char* adimIsimleri[5] = {
"1/5: SOL-UST HEDEF",
"2/5: SAG-UST HEDEF",
"3/5: SOL-ALT HEDEF",
"4/5: SAG-ALT HEDEF",
"5/5: ORTA HEDEF"
};
for (int i = 0; i < 5; i++) {
hedefCiz(tX[i], tY[i], adimIsimleri[i]);
long rawXSum = 0;
long rawYSum = 0;
int basariliOkuma = 0;
while (true) {
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
digitalWrite(XM, HIGH);
digitalWrite(YP, HIGH);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
delay(100);
break;
}
}
for (int numSamples = 0; numSamples < 16; numSamples++) {
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
digitalWrite(XM, HIGH);
digitalWrite(YP, HIGH);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
rawXSum += p.x;
rawYSum += p.y;
basariliOkuma++;
}
delay(15);
}
rX[i] = rawXSum / basariliOkuma;
rY[i] = rawYSum / basariliOkuma;
dokunmaBirakilanaKadarBekle();
}
float nA, nB, nC, nD, nE, nF;
if (calculateLeastSquares(rX, rY, tX, tY, nA, nB, nC, nD, nE, nF)) {
dogrulamaVeTestEkrani(nA, nB, nC, nD, nE, nF);
} else {
tft.fillScreen(BLACK);
tft.drawString(20, 120, "HATA: KALIBRASYON", RED, 2);
tft.drawString(20, 150, "BASARISIZ OLDU!", RED, 2);
delay(2000);
kalibrasyonYap5Nokta();
}
}
bool calculateLeastSquares(long rx[], long ry[], long tx[], long ty[], float &outA, float &outB, float &outC, float &outD, float &outE, float &outF) {
double Sxx = 0, Sxy = 0, Sx = 0, Syy = 0, Sy = 0;
double Vx0 = 0, Vx1 = 0, Vx2 = 0;
double Vy0 = 0, Vy1 = 0, Vy2 = 0;
for (int i = 0; i < 5; i++) {
double x = rx[i];
double y = ry[i];
double X = tx[i];
double Y = ty[i];
Sxx += x * x;
Sxy += x * y;
Sx += x;
Syy += y * y;
Sy += y;
Vx0 += x * X;
Vx1 += y * X;
Vx2 += X;
Vy0 += x * Y;
Vy1 += y * Y;
Vy2 += Y;
}
double a = Sxx; double b = Sxy; double c = Sx;
double e = Syy; double f = Sy; double k = 5.0;
double det = a * (e * k - f * f) - b * (b * k - c * f) + c * (b * f - c * e);
if (abs(det) < 0.0001) {
return false;
}
double m00 = e * k - f * f;
double m01 = c * f - b * k;
double m02 = b * f - c * e;
double m11 = a * k - c * c;
double m12 = b * c - a * f;
double m22 = a * e - b * b;
outA = (m00 * Vx0 + m01 * Vx1 + m02 * Vx2) / det;
outB = (m01 * Vx0 + m11 * Vx1 + m12 * Vx2) / det;
outC = (m02 * Vx0 + m12 * Vx1 + m22 * Vx2) / det;
outD = (m00 * Vy0 + m01 * Vy1 + m02 * Vy2) / det;
outE = (m01 * Vy0 + m11 * Vy1 + m12 * Vy2) / det;
outF = (m02 * Vy0 + m12 * Vy1 + m22 * Vy2) / det;
return true;
}
void hedefCiz(int x, int y, const char* baslik) {
tft.fillScreen(BLACK);
tft.drawString(10, 10, baslik, CYAN, 2);
tft.drawLine(x - 20, y, x + 20, y, RED);
tft.drawLine(x, y - 20, x, y + 20, RED);
tft.drawCircle(x, y, 6, WHITE);
tft.drawCircle(x, y, 12, BLUE);
tft.drawCircle(x, y, 18, WHITE);
tft.drawString(15, 140, "Kalem ucuyla tam", WHITE, 2);
tft.drawString(15, 170, "merkeze dokunup", WHITE, 2);
tft.drawString(15, 200, "bekleyin.", WHITE, 2);
}
void dogrulamaVeTestEkrani(float nA, float nB, float nC, float nD, float nE, float nF) {
tft.fillScreen(BLACK);
tft.drawRect(5, 5, 230, 220, GRAY);
tft.drawString(10, 15, "TEST ALANI: Ekrana", CYAN, 1);
tft.drawString(10, 30, "dokunarak cizgi cizin.", CYAN, 1);
tft.fillRect(10, 240, 105, 50, GREEN);
tft.drawRect(10, 240, 105, 50, WHITE);
tft.drawString(25, 258, "KAYDET", BLACK, 2);
tft.fillRect(125, 240, 105, 50, RED);
tft.drawRect(125, 240, 105, 50, WHITE);
tft.drawString(135, 258, "YENIDEN", WHITE, 2);
bool kararVerildi = false;
while (!kararVerildi) {
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
digitalWrite(XM, HIGH);
digitalWrite(YP, HIGH);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
int testX = nA * p.x + nB * p.y + nC;
int testY = nD * p.x + nE * p.y + nF;
testX = constrain(testX, 0, tft.width() - 1);
testY = constrain(testY, 0, tft.height() - 1);
if (testX > 8 && testX < 228 && testY > 8 && testY < 220) {
tft.fillCircle(testX, testY, 2, GREEN);
}
if (testX > 10 && testX < 115 && testY > 240 && testY < 290) {
dokunmaBirakilanaKadarBekle();
tsA = nA; tsB = nB; tsC = nC;
tsD = nD; tsE = nE; tsF = nF;
CalibData data;
data.magic = 0xCD;
data.A = tsA; data.B = tsB; data.C = tsC;
data.D = tsD; data.E = tsE; data.F = tsF;
EEPROM.put(0, data);
tft.fillScreen(BLACK);
tft.drawString(30, 120, "KALIBRASYON", GREEN, 2);
tft.drawString(30, 150, "KAYDEDILDI!", GREEN, 2);
delay(1500);
kararVerildi = true;
anaMenuyuCiz();
}
if (testX > 125 && testX < 230 && testY > 240 && testY < 290) {
dokunmaBirakilanaKadarBekle();
kalibrasyonYap5Nokta();
kararVerildi = true;
}
}
}
}
void eepromYukle() {
CalibData data;
EEPROM.get(0, data);
if (data.magic == 0xCD) {
tsA = data.A; tsB = data.B; tsC = data.C;
tsD = data.D; tsE = data.E; tsF = data.F;
Serial.println("Kayitli kalibrasyon verileri yuklendi.");
} else {
tsA = 0.3117; tsB = 0.0; tsC = -46.75;
tsD = 0.0; tsE = -0.39; tsF = 366.8;
Serial.println("Gecerli kalibrasyon yok! Varsayilan yuklendi.");
}
}
void dokunmaBirakilanaKadarBekle() {
delay(100);
bool basili = true;
while (basili) {
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
digitalWrite(XM, HIGH);
digitalWrite(YP, HIGH);
if (p.z < MINPRESSURE || p.z > MAXPRESSURE) {
basili = false;
}
delay(30);
}
delay(100);
}
void butonGeriBildirimEfekti(int bx, int by, int bw, int bh) {
tft.drawRect(bx, by, bw, bh, GREEN);
delay(120);
tft.drawRect(bx, by, bw, bh, WHITE);
}
Bu proje, gömülü sistemlerde GUI (Grafik Kullanıcı Arayüzü) geliştirmenin ve çoklu görev yönetiminin mantığını anlamak adına eksiksiz bir kütüphanedir. Eğer projeyi daha da büyütmek isterseniz, EEPROM yapısını genişleterek XOX oyunundaki skorları kalıcı hafızaya kaydedebilir ya da Aktivite Merkezi'ne yeni bir durum (state) ekleyerek basit bir dijital saat veya alarm modülü entegre edebilirsiniz.
Henüz yorum yapılmamış. İlk yorumu siz yapın!