การใช้งานจอ TFT Touch Screen บน ESP32 ด้วยบอร์ด LARB32
จอ TFT Touch screen เป็นการรวมเอาความสามารถในการแสดงผลและการสัมผัสเข้ามาในโปรเจค IoT หรือ Embedded Systems โดยการใช้งานจอ TFT Touch screen นี้สามารถทำได้หลายรูปแบบ เช่น แสดงข้อมูลจากเซ็นเซอร์ต่างๆ ควบคุมอุปกรณ์ไฟฟ้า หรือสร้างอินเทอร์เฟซสำหรับผู้ใช้
คุณสมบัติและข้อดีของจอ TFT Touch screen
- ความละเอียดสูง: จอ TFT มักมีความละเอียดสูง ทำให้สามารถแสดงผลกราฟิกและข้อความได้อย่างชัดเจน
- รองรับการสัมผัส: สามารถรับคำสั่งจากผู้ใช้ผ่านการสัมผัสจอ ซึ่งทำให้สามารถสร้างอินเทอร์เฟซที่ใช้งานง่ายและเป็นมิตรกับผู้ใช้
- การเชื่อมต่อที่ง่าย: จอ TFT มักมีอินเทอร์เฟซการเชื่อมต่อที่ง่ายกับ ESP32 เช่น SPI
- การเขียนโปรแกรมง่าย: มีไลบรารีและโค้ดตัวอย่างที่พร้อมใช้งาน ทำให้การเขียนโปรแกรมเพื่อควบคุมจอ TFT เป็นเรื่องง่าย
ในตัวอย่างนี้เราเลือกใช้ไลบรารี่ TFT eSPI ซึ่งมีการทำงานที่รวดเร็วและใช้งานง่าย แต่ขั้นตอนการติดตั้งจะยุ่งยากแค่ครั้งแรก
อุปกรณ์ที่ใช้ทดลองมีดังนี้
- บอร์ด LARB32
- สายแพและบอร์ดแปลงขาจอ
- จอ TFT ขนาด 2.8 นิ้วหรือใหญ่กว่า รุ่นทัชสกรีนหรือไม่ทัชสกรีนก็ได้ ที่ใช้ไดเวอร์ Ili9341
- (ไม่มีก็ได้) ชิ้นส่วน 3D สำหรับยึดจอ TFT 2.8″ เข้ากับรางปีกนก ดาวน์โหลดไฟล์ 3D ได้ที่ https://www.hs3uka.com/downloads/TFT-ILI9341.stl
วิธีติดตั้งไลบรารี่ TFT_eSPI
ในกรณีที่เครื่องคอมพิวเตอร์ยังไม่เคยติดตั้งไลบรารี่ TFT_eSPI สามารถทำตามวิธีติดตั้งดังนี้
- ติดตั้งผ่าน Library Manager โดยพิมพ์ค้นหาว่า TFT eSPI แล้วเลื่อนหา TFT eSPI by Bodmer
- เมื่อติดตั้งไลบรารี่ TFT eSPI เรียบร้อยแล้วให้ไปที่ File > Preferences
- copy ที่อยู่ของไลบรารี่ จาก Sckethbook location:
- เปิดไปยังที่อยู่ของไลบรารี่ TFT eSPI
- ทำการแก้ไขไฟล์ Uer_Setup.h
- ประมาณบันทัดที่ 167 ให้คอมเม้นการตั้งค่าของบอร์ด ESP8266 ไว้
- ประมาณบันทัดที่ 207 ในส่วนของ ESP32 ให้ตั้งค่าพินใหม่ตามนี้
Pin
GPIO
คำอธิบาย
TFT_MOSI
GPIO23
ส่งข้อมูลจาก Master ไปยัง Slave
TFT_MISO
GPIO19
ส่งข้อมูลจาก Slave ไปยัง Master
TFT_SCLK
GPIO18
สัญญาณนาฬิกา
TFT_DC
GPIO5
ส่งข้อมูลหรือคำสั่งไปยังจอ
TFT_RST
GPIO4
รีเซ็ต
TFT_CS
GPIO15
CS ของจอ TFT
TOUCH_CS
GPIO13
CS ของ Touch Screen
- กดบันทึก
คำสั่งที่ใช้สั่งงานจอ TFT ด้วยไลบรารี่ TFT eSPI
- setRotation(0) หมุน 0° (ค่าเริ่มต้น)
- setRotation(1) หมุน 90°
- setRotation(2) หมุน 180°
- setRotation(3) หมุน 270°
fillScreen(color)
คำสั่งเติมสีทั้งจอภาพ โดยใส่ค่าสีเข้าไปในวงเล็บ เช่น
- fillScreen(TFT_WHITE) สีขาว
- fillScreen(TFT_BLACK) สีดำ
- fillScreen(TFT_GREY) สีเทา
- fillScreen(TFT_NAVY) สีน้ำเงินเข้ม
- fillScreen(TFT_DARKGREEN) สีเขียวเข้ม
- fillScreen(TFT_DARKCYAN) สีฟ้าอมเขียวเข้ม
- fillScreen(TFT_MAROON) สีแดงเข้ม
- fillScreen(TFT_PURPLE) สีม่วง
- fillScreen(TFT_OLIVE) สีเขียวมะกอก
- fillScreen(TFT_LIGHTGREY) สีเทาอ่อน
- fillScreen(TFT_DARKGREY) สีเทาเข้ม
- fillScreen(TFT_BLUE) สีน้ำเงิน
- fillScreen(TFT_CYAN) สีฟ้าอมเขียว
- fillScreen(TFT_RED) สีแดง
- fillScreen(TFT_MAGENTA) สีม่วงแดง
- fillScreen(TFT_YELLOW) สีเหลือง
- fillScreen(TFT_ORANGE) สีส้ม
- fillScreen(TFT_GREENYELLOW) สีเขียวอมเหลือง
- fillScreen(TFT_PINK) สีชมพู
- fillScreen(TFT_BROWN) สีน้ำตาล
- fillScreen(TFT_GOLD) สีทอง
- fillScreen(TFT_SILVER) สีเงิน
- fillScreen(TFT_SKYBLUE) สีฟ้าอ่อน
- fillScreen(TFT_VIOLET) สีม่วงอ่อน
- x คือพิกัดแกน X ของมุมบนซ้ายของสี่เหลี่ยม
- y คือพิกัดแกน Y ของมุมบนซ้ายของสี่เหลี่ยม
- w คือความกว้างของสี่เหลี่ยม
- h คือความสูงของสี่เหลี่ยม
- color คือสีที่ต้องการใช้เติมภายในสี่เหลี่ยม
drawRect(x, y, w, h, color)
เป็นฟังก์ชันที่ใช้ในการวาดกรอบสี่เหลี่ยม (rectangle) บนหน้าจอ TFT โดยฟังก์ชันนี้จะวาดเฉพาะเส้นรอบกรอบของสี่เหลี่ยม โดยไม่มีการเติมสีภายใน
- x คือพิกัดแกน X ของมุมบนซ้ายของสี่เหลี่ยม
- y คือพิกัดแกน Y ของมุมบนซ้ายของสี่เหลี่ยม
- w คือความกว้างของสี่เหลี่ยม
- h คือความสูงของสี่เหลี่ยม
- color คือสีของเส้นรอบกรอบสี่เหลี่ยม
fillTriangle(x0, y0, x1, y1, x2, y2, color)
เป็นฟังก์ชันที่ใช้ในการวาดสามเหลี่ยมและเติมสีภายในสามเหลี่ยมนั้น
- x0, y0 คือพิกัดของจุดแรกของสามเหลี่ยม
- x1, y1 คือพิกัดของจุดที่สองของสามเหลี่ยม
- x2, y2 คือพิกัดของจุดที่สามของสามเหลี่ยม
- color คือสีภายในสามเหลี่ยม
drawTriangle(x0, y0, x1, y1, x2, y2, color)
เป็นฟังก์ชันที่ใช้ในการวาดสามเหลี่ยมบนหน้าจอ TFT โดยฟังก์ชันนี้จะวาดเฉพาะเส้นรอบกรอบของสามเหลี่ยม โดยไม่มีการเติมสีภายใน
- x0, y0 คือพิกัดของจุดแรกของสามเหลี่ยม
- x1, y1 คือพิกัดของจุดที่สองของสามเหลี่ยม
- x2, y2 คือพิกัดของจุดที่สามของสามเหลี่ยม
- color คือสีของเส้นรอบกรอบสามเหลี่ยม
drawLine(x0, y0, x1, y1, color)
ใช้ในการวาดเส้นตรงบนจอ TFT ระหว่างจุดที่กำหนด โดยมีรูปแบบการเรียกใช้งานดังนี้
- x0, y0 คือจุดเริ่มต้นของเส้น
- x1, y1 คือจุดสิ้นสุดของเส้น
drawFastVLine(x, y, h, color)
ใช้สำหรับวาดเส้นตรงแนวตั้งบนจอ TFT โดยมีรูปแบบการเรียกใช้งานดังนี้
- x, y คือพิกัดที่จุดเริ่มต้นของเส้นตรงแนวตั้ง
- h คือความสูงของเส้นตรง (จำนวนพิกเซล)
- color คือสีของเส้นตรง
drawFastHLine(x, y, w, color)
ใช้สำหรับวาดเส้นตรงแนวนอนบนจอ TFT โดยมีรูปแบบการเรียกใช้งานดังนี้
- x, y คือพิกัดที่จุดเริ่มต้นของเส้นตรงแนวนอน
- w คือความกว้างของเส้นตรง (จำนวนพิกเซล)
- color คือสีของเส้นตรง
drawBitmap(x, y, bitmap, w, h, color)
ใช้ในการแสดงภาพ Bitmap บนจอ TFT โดยมีรูปแบบการเรียกใช้งานดังนี้
- (x, y) คือพิกัดที่จุดเริ่มต้นของ Bitmap บนจอ TFT
- bitmap คือตัวแปรที่เก็บข้อมูล Bitmap (ต้องเป็น array ของข้อมูล bitmap)
- w คือความกว้างของ Bitmap ในหน่วยพิกเซล
- h คือความสูงของ Bitmap ในหน่วยพิกเซล
- color (ไม่บังคับ) คือสีที่ใช้สำหรับแสดงภาพ (ใช้ TFT_WHITE เพื่อแสดงในสีขาว และ TFT_BLACK เพื่อแสดงในสีดำ)
invertDisplay(invert)
ใช้ในการกลับสีทั้งหมดบนจอ TFT โดยใช้เพื่อทำให้สีขาวกลายเป็นสีดำ และสีดำกลายเป็นสีขาวบนจอ TFT โดยมีรูปแบบการเรียกใช้งานดังนี้
- true เพื่อกลับสีทั้งหมดบนจอ TFT (สีขาวเป็นดำ และสีดำเป็นขาว)
- false เพื่อยกเลิกการกลับสี
โค้ดตัวอย่างการใช้คำสั่งแสดงผลบนจอ TFT
#include <TFT_eSPI.h> // ไลบรารีสำหรับจอ TFT
#include <SPI.h>
// สร้างออบเจ็กต์สำหรับจอ TFT
TFT_eSPI tft = TFT_eSPI();
// ตัวอย่างข้อมูล Bitmap (24x24 พิกเซล, monochrome)
const unsigned char bitmap_data[] = {
0b00000000, 0b00000000, 0b00000000,
0b00001111, 0b10000111, 0b11000000,
0b00011111, 0b11001111, 0b11100000,
0b00111111, 0b11111111, 0b11110000,
0b01111111, 0b11111111, 0b11111000,
0b01111111, 0b11111111, 0b11111000,
0b01111111, 0b11111111, 0b11111000,
0b00111111, 0b11111111, 0b11110000,
0b00011111, 0b11111111, 0b11100000,
0b00001111, 0b11111111, 0b11000000,
0b00000111, 0b11111111, 0b10000000,
0b00000011, 0b11111111, 0b00000000,
0b00000001, 0b11111110, 0b00000000,
0b00000000, 0b11111100, 0b00000000,
0b00000000, 0b01111000, 0b00000000,
0b00000000, 0b00110000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000
};
void setup() {
tft.init();
tft.setRotation(2); // กำหนดการหมุนของจอ
tft.fillScreen(TFT_BLACK); // ล้างหน้าจอด้วยสีดำ
// ตั้งค่าข้อความ
tft.setTextColor(TFT_WHITE);
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.print("Hello, World!");
tft.setTextFont(2);
tft.setCursor(10, 30);
tft.print("Font 2");
tft.setFreeFont(&FreeSansBold9pt7b);
tft.setCursor(10, 70);
tft.print("Free Font");
// วาดข้อความโดยใช้ drawString
tft.drawString("drawString", 80, 30, 2);
// วาดสี่เหลี่ยมเต็ม
tft.fillRect(10, 80, 50, 30, TFT_RED);
tft.setCursor(70, 90);
tft.setTextFont(1);
tft.print("fillRect");
// วาดสี่เหลี่ยมเปล่า
tft.drawRect(10, 120, 50, 30, TFT_GREEN);
tft.setCursor(70, 130);
tft.print("drawRect");
// วาดสามเหลี่ยมเต็ม
tft.fillTriangle(10, 160, 60, 160, 35, 190, TFT_BLUE);
tft.setCursor(70, 170);
tft.print("fillTriangle");
// วาดสามเหลี่ยมเปล่า
tft.drawTriangle(10, 200, 60, 200, 35, 230, TFT_YELLOW);
tft.setCursor(70, 210);
tft.print("drawTriangle");
// วาดเส้นตรง
tft.drawLine(10, 240, 60, 270, TFT_CYAN);
tft.setCursor(70, 250);
tft.print("drawLine");
// วาด Bitmap
tft.drawBitmap(30, 270, bitmap_data, 24, 24, TFT_RED);
tft.setCursor(70, 280);
tft.print("drawBitmap");
// วาดพิกเซล
tft.drawPixel(10, 300, TFT_WHITE);
tft.setCursor(20, 300);
tft.print("drawPixel");
// วาดเส้นตรงแนวตั้ง
tft.drawFastVLine(230, 10, 200, TFT_WHITE);
tft.setCursor(150, 10);
tft.print("drawFastVLine");
// วาดเส้นตรงแนวนอน
tft.drawFastHLine(100, 310, 135, TFT_WHITE);
tft.setCursor(160, 300);
tft.print("drawFastHLine");
}
void loop() {
delay(3000);
// กลับสีบนจอภาพ
tft.invertDisplay(true);
delay(3000);
// ยกเลิกกลับสีบนจอภาพ
tft.invertDisplay(false);
}
โค้ดโปรแกรมแสดงการใช้คำสั่งต่างๆในการวาดลงบนหน้าจอ TFT จะได้ผลลัพธ์ตามภาพ
คำสั่งที่ใช้สั่งงานจอ TFT ในการใช้งาน Touch screen
- calData อาร์เรย์สำหรับเก็บค่าการปรับเทียบ
- color1 สีของลูกศร
- color2 สีพื้นหลัง
- size ขนาดของพื้นที่สัมผัส
initButton(&tft, x, y, w, h, color1, color2, color3, “Text”, size)
สร้างปุ่มและกำหนดพารามิเตอร์ต่างๆ โดยมีการกำหนดรูปแบบดังนี้
- &tft ตัวชี้ไปยังจอ TFT_eSPI
- x, y พิกัด X, Y ของศูนย์กลางปุ่ม
- w, h ความกว้างและความสูงของปุ่ม
- color1 สีของขอบปุ่ม
- color2 สีของพื้นหลังปุ่ม
- color3 สีของข้อความปุ่ม
- “Text” ข้อความที่จะแสดงบนปุ่ม
- size ขนาดของข้อความ (setTextSize)
setLabelDatum(x, y, datum)
ใช้สำหรับกำหนดตำแหน่งและการจัดวางข้อความบนปุ่ม โดยจะระบุพิกัดและการจัดตำแหน่ง (datum) ของข้อความที่จะแสดงบนปุ่ม
- x ตำแหน่ง X ของจุดอ้างอิง
- y ตำแหน่ง Y ของจุดอ้างอิง
- datum ค่าการจัดตำแหน่งของข้อความ
ตัวเลือกการจัดตำแหน่ง (datum)
- TL_DATUM (0): Top Left
- TC_DATUM (1): Top Center
- TR_DATUM (2): Top Right
- ML_DATUM (3): Middle Left
- MC_DATUM (4): Middle Center
- MR_DATUM (5): Middle Right
- BL_DATUM (6): Bottom Left
- BC_DATUM (7): Bottom Center
- BR_DATUM (8): Bottom Right
setLabelColor(color1, color2)
ใช้สำหรับกำหนดสีของข้อความและสีพื้นหลังของข้อความบนปุ่ม ซึ่งช่วยให้เราสามารถเปลี่ยนสีของข้อความและสีพื้นหลังของข้อความที่แสดงบนปุ่มได้หลังจากที่ initButton ไปแล้ว
- color1 สีข้อความ
- color2 สีพื้นหลัง
drawButton(bool)
คำสั่งวาดปุ่มบนจอหลังจาก initButton แล้ว
- true ปุ่มกดขณะโดนกด
- false ปุ่มกดขณะปล่อย
justPressed()
ตรวจสอบว่าปุ่มถูกกดเพิ่งถูกกดหรือไม่
justReleased()
ตรวจสอบว่าปุ่มเพิ่งถูกปล่อยหรือไม่
press(bool)
ตั้งค่าสถานะปุ่มกด
contains(x,y)
ตรวจสอบว่าพิกัดที่ให้มาอยู่ภายในปุ่มหรือไม่
ตัวอย่างโค้ดการใช้งาน Touch screen
#include <TFT_eSPI.h>
#include <SPI.h>
// สร้างออบเจ็กต์สำหรับจอ TFT
TFT_eSPI tft = TFT_eSPI();
// สร้างออบเจ็กต์สำหรับปุ่ม
TFT_eSPI_Button buttonOn;
TFT_eSPI_Button buttonOff;
// กำหนดพินสำหรับหลอดไฟ
const int ledPin = 2;
void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW); // เริ่มต้นปิดหลอดไฟ
tft.init();
tft.setRotation(2);
tft.fillScreen(TFT_BLACK);
uint16_t calData[5];
tft.calibrateTouch(calData, TFT_WHITE, TFT_RED, 15);
tft.setTouch(calData);
tft.fillScreen(TFT_BLACK);
// กำหนดค่าเริ่มต้นสำหรับปุ่ม ON
buttonOn.initButton(
&tft, // ตัวชี้ไปยังจอ TFT_eSPI
120, 100, // พิกัด X, Y ของศูนย์กลางปุ่ม
100, 50, // ความกว้างและความสูงของปุ่ม
TFT_WHITE, // สีของขอบปุ่ม
TFT_GREEN, // สีของพื้นหลังปุ่ม
TFT_WHITE, // สีของข้อความปุ่ม
"ON", // ข้อความที่จะแสดงบนปุ่ม
2 // ขนาดของข้อความ (setTextSize)
);
// กำหนดค่าเริ่มต้นสำหรับปุ่ม OFF
buttonOff.initButton(
&tft, // ตัวชี้ไปยังจอ TFT_eSPI
120, 200, // พิกัด X, Y ของศูนย์กลางปุ่ม
100, 50, // ความกว้างและความสูงของปุ่ม
TFT_WHITE, // สีของขอบปุ่ม
TFT_RED, // สีของพื้นหลังปุ่ม
TFT_WHITE, // สีของข้อความปุ่ม
"OFF", // ข้อความที่จะแสดงบนปุ่ม
2 // ขนาดของข้อความ (setTextSize)
);
// กำหนดตำแหน่งและการจัดวางข้อความบนปุ่ม ON
buttonOn.setLabelDatum(0, 0, MC_DATUM);
// วาดปุ่ม ON บนจอ
buttonOn.drawButton(false); // 'false' หมายถึงไม่กดปุ่ม
// กำหนดตำแหน่งและการจัดวางข้อความบนปุ่ม OFF
buttonOff.setLabelDatum(0, 0, MC_DATUM);
// วาดปุ่ม OFF บนจอ
buttonOff.drawButton(false); // 'false' หมายถึงไม่กดปุ่ม
}
void loop() {
// รอการสัมผัส
uint16_t x, y;
if (tft.getTouch(&x, &y)) {
if (buttonOn.contains(x, y)) {
buttonOn.press(true); // กดปุ่ม ON
} else {
buttonOn.press(false); // ปล่อยปุ่ม ON
}
if (buttonOff.contains(x, y)) {
buttonOff.press(true); // กดปุ่ม OFF
} else {
buttonOff.press(false); // ปล่อยปุ่ม OFF
}
} else {
buttonOn.press(false); // ปล่อยปุ่ม ON
buttonOff.press(false); // ปล่อยปุ่ม OFF
}
// วาดปุ่มใหม่เมื่อสถานะเปลี่ยนแปลง
if (buttonOn.justPressed()) {
buttonOn.drawButton(true); // 'true' หมายถึงกดปุ่ม ON
digitalWrite(ledPin, HIGH); // เปิดหลอดไฟ
}
if (buttonOn.justReleased()) {
buttonOn.drawButton(false); // 'false' หมายถึงปล่อยปุ่ม ON
}
if (buttonOff.justPressed()) {
buttonOff.drawButton(true); // 'true' หมายถึงกดปุ่ม OFF
digitalWrite(ledPin, LOW); // ปิดหลอดไฟ
}
if (buttonOff.justReleased()) {
buttonOff.drawButton(false); // 'false' หมายถึงปล่อยปุ่ม OFF
}
}
โค้ดตัวอย่างการใช้งาน Touch Screen แสดงผลลัพธ์ตามภาพ