วันนี้ได้จอสี lcd แบบ 1.8 นิ้ว ST7735 สื่อสารแบบ SPI มาลองเล่น ซึ่งข้อมูลหาง่ายมาก พี่ๆในกลุ่มก็ใช้กัน บ้านใกล้เรือนเคียงก็เล่นกันแบบสนุกสนาน
เลือกใช้ esp8266เนื่องจากไม่ต้องการความแรงมาก ราคาไม่แพง ต่อ wifi ได้ ทำการประกอบจอ+esp8266 เสร็จเรียบร้อย เริ่มทดลองอะไรดีละ!! เอาแบบง่ายๆเลย ดึงค่าวัน เดือน ปี และเวลา จากเวป มาแสดงผลบนจอ lcd
งานนี้ใช้ Ai นาม Gemini ใส่คีย์เวิร์ดเสร็จ Gemini เขียนโปรแกรมให้เลย อุ๊ย!! เขียนออกมาได้ด้วย นึกว่าหมูแล้ว… สั่ง run ทำไม!! เวลาตัวเลขเปลี่ยน จอกระพริบเหมือนเจ้าเข้าเลย ถาม Gemini ต่อ ไม่อยากให้ตัวเลขกระพริบทำอย่างไร คำตอบชัดเจนจอกระพริบเพราะ Ai เขียนโปรแกรมแบบง่าย พอข้อมูลใหม่มาจะสั่งเคลียร์หน้าจอทั้งหมด กว่าจะใส่สีทีละ pixel ช้า ตาเราเลยเห็นว่าเกิดการกระพริบ
Ai รู้ปัญหา บอกวิธีแก้ (อ่าวแล้วทำไมไม่ทำให้ครั้งแรกเลย) ให้ใช้คำสั่ง tft.fillRect ลบตำแหน่งตัวเลขที่มีการเปลี่ยนแปลงเท่านั้น ดีเลย การกระพริบเหลือน้อยมาก ตามองการเปลี่ยนแปลงเพียงเล็กน้อย รับได้
กว่าจะคุยกับ Geminiให้เข้าใจ และเขียนโปรแกรมให้เราได้ตามความต้องการ ใช้เวลาพิมพ์คุยเกือบ 10 นาที โปรแกรมที่แปะไว้ Gemini เขียนให้ทั้งหมด ทำงานได้คอมพายผ่าน แก้ไขแค่ชื่อ wifi และ รหัส ถ้าผิดพลาดประการใดให้โทษ Gemini นะครับ


#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h> // For SPI communication
#include <time.h> // For struct tm, localtime
// — Wi-Fi Credentials —
const char *ssid = “wifi”;
const char *password = “pass”;
// — NTP Client Setup —
WiFiUDP ntpUDP;
// Set offset time in seconds to adjust for your timezone (GMT+7 = 25200 seconds)
NTPClient timeClient(ntpUDP, “pool.ntp.org“, 25200);
// — ST7735S LCD Pin Definitions (matching your specified pins) —
// NodeMCU D-pins to GPIO mapping:
// D0 = GPIO16
// D1 = GPIO5
// D2 = GPIO4
// D3 = GPIO0
// D4 = GPIO2
// D5 = GPIO14 (SCK)
// D6 = GPIO12 (MISO)
// D7 = GPIO13 (MOSI)
// D8 = GPIO15 (CS)
#define TFT_CS 15 // Chip select (GPIO15 / D8 on NodeMCU)
#define TFT_DC 2 // Data/command (GPIO2 / D4 on NodeMCU)
#define TFT_RST -1 // Reset pin. Set to -1 if not connected or handled externally.
// *** IMPORTANT: If -1, physically connect RST pin of display to 3.3V ***
// Create ST7735S LCD object
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// Week Days (Used for Serial Monitor, not directly on LCD in this example)
String weekDays[7]={“Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”};
// Month names (Thai – for Serial Monitor or if you want to use them elsewhere)
String months[12]={“มกราคม”, “กุมภาพันธ์”, “มีนาคม”, “เมษายน”, “พฤษภาคม”, “มิถุนายน”,
“กรกฎาคม”, “สิงหาคม”, “กันยายน”, “ตุลาคม”, “พฤศจิกายน”, “ธันวาคม”};
// — Variables to store previous time/date for flicker-free updates —
int prevSecond = -1;
int prevMinute = -1;
int prevHour = -1;
int prevMonthDay = -1;
int prevMonth = -1;
int prevYear = -1;
int indexa = 1;
// — Setup Function: Runs once at the beginning —
void setup() {
// Regarding D0 (GPIO16) and analogWrite(D0, 0);
// As mentioned, GPIO16 on NodeMCU (D0 pin) does not support analogWrite (PWM).
// This line will effectively just set GPIO16 to a LOW state (0V).
// If you intend to control a backlight connected to D0 (GPIO16) and want it OFF, this is okay.
// If you want it ON, you’d need `digitalWrite(D0, HIGH);`
// If you need PWM brightness control, connect backlight to a PWM-capable pin (e.g., D3/GPIO0, D4/GPIO2).
pinMode(D0, OUTPUT);
analogWrite(D0, 0);
Serial.begin(115200);
Serial.println(“\nกำลังเชื่อมต่อ Wi-Fi…”);
// 1. Initialize LCD
tft.initR(INITR_18GREENTAB); // For 1.8″ green tab (most common)
tft.setRotation(3); // Adjust rotation (0-3) to fit your project orientation (160×128 pixels)
tft.fillScreen(ST7735_BLACK); // Clear screen to black
tft.setTextWrap(false); // Prevent text from wrapping automatically
// Display initial message on LCD
tft.setCursor(10, 50);
tft.setTextColor(ST7735_YELLOW);
tft.setTextSize(1);
tft.println(“Connecting to WiFi…”);
// 2. Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
tft.print(“.”); // Display dots on screen while connecting
}
Serial.println(“\nWi-Fi Connected!”);
Serial.print(“IP Address: “);
Serial.println(WiFi.localIP());
tft.fillScreen(ST7735_BLACK); // Clear screen after Wi-Fi connection
tft.setCursor(10, 50);
tft.setTextColor(ST7735_GREEN);
tft.println(“WiFi Connected!”);
delay(1000); // Pause to show message
// 3. Initialize NTP Client
timeClient.begin();
// — Draw static elements once in setup —
tft.fillScreen(ST7735_BLACK); // Clear screen completely before drawing static elements
// Display Title (Static)
tft.setCursor(5, 5);
tft.setTextColor(ST7735_WHITE);
tft.setTextSize(1);
tft.println(“Current Date & Time:”);
timeClient.update();
}
// — Loop Function: Runs repeatedly —
void loop() {
// Update time from NTP
/*
if (!timeClient.update()) {
Serial.println(“Failed to update time. Retrying…”);
tft.fillScreen(ST7735_BLACK); // Clear and show error if time update fails
tft.setCursor(5, 50);
tft.setTextColor(ST7735_RED);
tft.setTextSize(1);
tft.println(“Failed to get time!”);
delay(5000); // Wait longer if time update fails
return; // Exit current loop iteration to try again
}
*/
// — Get Date and Time Components —
time_t epochTime = timeClient.getEpochTime(); // Unix timestamp
struct tm *ptm = localtime((time_t *)&epochTime); // Convert to local time structure (adjusted by NTPClient’s offset)
// Extract components for LCD display
int currentYear = ptm->tm_year + 1900;
int currentMonth = ptm->tm_mon + 1; // 1-12
int monthDay = ptm->tm_mday;
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
int currentSecond = timeClient.getSeconds();
// — Print to Serial Monitor (for debugging) —
Serial.print(“Epoch Time: “); Serial.println(epochTime);
Serial.print(“Formatted Time: “); Serial.println(timeClient.getFormattedTime());
Serial.print(“Hour: “); Serial.println(currentHour);
Serial.print(“Minutes: “); Serial.println(currentMinute);
Serial.print(“Seconds: “); Serial.println(currentSecond);
Serial.print(“Week Day: “); Serial.println(weekDays[timeClient.getDay()]);
Serial.print(“Month day: “); Serial.println(monthDay);
Serial.print(“Month: “); Serial.println(currentMonth);
Serial.print(“Month name: “); Serial.println(months[ptm->tm_mon]); // Use original month name array for serial
Serial.print(“Year: “); Serial.println(currentYear);
Serial.println(“”);
// — Display on LCD (Flicker-free updates) —
// Check if Date has changed (updates once per day)
if (monthDay != prevMonthDay || currentMonth != prevMonth || currentYear != prevYear) {
// Clear old date area: X=5, Y=25, Width=120px (10 chars * 12px), Height=16px (2 lines * 8px)
tft.fillRect(5, 25, 120, 16, ST7735_BLACK);
// Display Date (DD-MM-YYYY Buddhist)
tft.setCursor(5, 25);
tft.setTextColor(ST7735_YELLOW);
tft.setTextSize(2); // Larger text for date
tft.print(monthDay);
tft.print(“-“);
if (currentMonth < 10) tft.print(“0”); // Add leading zero for month
tft.print(currentMonth);
tft.print(“-“);
tft.println(currentYear + 543); // Add 543 for Buddhist calendar year
// Update previous date values
prevMonthDay = monthDay;
prevMonth = currentMonth;
prevYear = currentYear;
}
// — Time Display (HH:MM:SS) —
// Only update parts that change
// If Hour changes
if (currentHour != prevHour) {
// Clear and redraw HH and first colon
tft.fillRect(5, 60, 36 + 18, 24, ST7735_BLACK); // X, Y, Width for HH + :, Height
tft.setCursor(5, 60);
tft.setTextColor(ST7735_CYAN);
tft.setTextSize(3);
if (currentHour < 10) tft.print(“0”);
tft.print(currentHour);
tft.print(“:”);
prevHour = currentHour;
}
// If Minute changes
if (currentMinute != prevMinute) {
// Clear and redraw MM and second colon
// X position for minutes: 5 (start) + (2 chars * 18px/char for HH) + (1 char * 18px/char for = 5 + 36 + 18 = 59
tft.fillRect(59, 60, 36 + 18, 24, ST7735_BLACK); // X, Y, Width for MM + :, Height
tft.setCursor(59, 60);
tft.setTextColor(ST7735_CYAN);
tft.setTextSize(3);
if (currentMinute < 10) tft.print(“0”);
tft.print(currentMinute);
tft.print(“:”);
prevMinute = currentMinute;
}
// If Second changes (always redraws seconds)
if (currentSecond != prevSecond) {
// Clear and redraw SS
// X position for seconds: 5 (start) + (2*18 for HH) + (1*18 for + (2*18 for MM) + (1*18 for
= 5 + 36 + 18 + 36 + 18 = 113
tft.fillRect(113, 60, 36, 24, ST7735_BLACK); // X, Y, Width for SS, Height
tft.setCursor(113, 60);
tft.setTextColor(ST7735_CYAN);
tft.setTextSize(3);
if (currentSecond < 10) tft.print(“0”);
tft.print(currentSecond);
prevSecond = currentSecond;
}
delay(1000); // Small delay to allow other tasks or just loop faste
}