วันอังคาร, 28 ตุลาคม 2568

ให้ ChatGPT เขียนโปรแกรม ESP8266 สั่งจอแสดงผลแบบ TFT ผ่าน WebServer

27 ต.ค. 2025
15

ทำการทดลองฝึกเขียนโปรแกรม ให้ ESP8266 ทำตัวเป็น Web Server สั่งงานการแสดงผลเรียนแบบ LED บนจอ TFT และปรับความสว่างหน้าจอได้ ถ้าเราเขียนโปรแกรมเองน่าจะใช้เวลาหลายวัน แต่ด้วยความสามารถอันทรงพลังของ ChatGPT ทำให้เราแทบไม่ต้องคิดเอง อยากได้อะไรก็ใส่ความต้องการลงไป อึม…ไม่ถึง 10 นาที ก็ได้การทดลองที่เกือบจะสมบูรณ์แบบ สั่งงาน Esp8266 ผ่าน อุปกรณ์แท็ปเลต , Smart Phone ,คอมพิวเตอร์ ได้อย่างเรียบง่าย..จริงๆ

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

// ---------- Wi-Fi ----------
const char* WIFI_SSID = "*****";
const char* WIFI_PASS = "*****";

// ---------- TFT Pin map ----------
#define TFT_CS   D8
#define TFT_RST  D3
#define TFT_DC   D4
#define TFT_SDA  D7   // MOSI
#define TFT_SCL  D5   // SCK
#define TFT_LED  D6   // Backlight (PWM)

// ---------- TFT object ----------
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// จำนวนวงกลม
const int numCircles = 4;

// ตำแหน่งวงกลมเรียงแนวนอน
int circleX[numCircles] = {20, 60, 100, 140};  // ซ้าย -> ขวา
int circleY[numCircles] = {60, 60, 60, 60};    // แถวเดียว
int radius     = 15;

// เก็บสีปัจจุบันของวงแต่ละวง
uint16_t circleColor[numCircles];

// วงกลมที่ active (0-3)
int activeIndex = 0;

// ความสว่าง (0-1023) "ยิ่งมากยิ่งสว่าง" สำหรับผู้ใช้
// แต่จะกลับด้านก่อนเขียนจริง
int brightnessUser = 1023;  // เริ่มสว่างสุด

// ---------- Web Server ----------
ESP8266WebServer server(80);

// ฟังก์ชัน apply brightness -> เขียน PWM ออกไปที่ไฟแบ็คไลต์
void applyBrightness() {
  // บอร์ดคุณตอนนี้เหมือน active-low (0 = สว่างสุด)
  // งั้นเรากลับค่า: 0 (มืด) -> 1023 จริง, 1023 (สว่าง) -> 0 จริง
  int pwmOut = 1023 - brightnessUser;
  analogWrite(TFT_LED, pwmOut);

  Serial.print("Set brightnessUser=");
  Serial.print(brightnessUser);
  Serial.print(" => pwmOut=");
  Serial.println(pwmOut);
}

// วาด IP มุมซ้ายบน
void drawIP(const String& ipText) {
  // เคลียร์พื้นที่หัวแถว
  tft.fillRect(0, 0, 110, 12, ST77XX_BLACK);

  tft.setCursor(0, 2); // ซ้ายบน
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(1);
  tft.print(ipText);
}

// วาดวงกลมทั้งหมดตาม activeIndex
void redrawCircles() {
  for (int i = 0; i < numCircles; i++) {
    uint16_t fillCol = (i == activeIndex) ? ST77XX_GREEN : ST77XX_RED;
    if (circleColor[i] != fillCol) {
      tft.fillCircle(circleX[i], circleY[i], radius, fillCol);
      tft.drawCircle(circleX[i], circleY[i], radius, ST77XX_WHITE);
      circleColor[i] = fillCol;
    }
  }
}

// หน้าเว็บหลัก พร้อมแสดงสถานะ brightness ปัจจุบัน
void handleRoot() {
  String html = F(
    "<!DOCTYPE html><html><head><meta charset='utf-8' />"
    "<meta name='viewport' content='width=device-width,initial-scale=1' />"
    "<title>Circle Control</title>"
    "<style>"
    "body{font-family:sans-serif;background:#111;color:#eee;text-align:center;padding:20px;}"
    "h1{color:#4caf50;font-size:20px;}"
    ".btn{display:inline-block;margin:10px;padding:15px 20px;font-size:18px;"
    "background:#333;color:#fff;border-radius:8px;text-decoration:none;border:2px solid #4caf50;}"
    ".btn:active{background:#4caf50;color:#000;}"
    ".info{margin-top:20px;color:#ccc;font-size:14px;}"
    ".slider{width:80%;margin-top:20px;}"
    "input[type=range]{width:100%;}"
    ".card{background:#222;border:1px solid #444;border-radius:8px;padding:15px;margin-top:20px;}"
    "</style></head><body>"
    "<h1>ESP8266 TFT Circle Control</h1>"

    "<div>"
      "<a class='btn' href='/set?c=0'>วงกลม 1</a>"
      "<a class='btn' href='/set?c=1'>วงกลม 2</a>"
      "<a class='btn' href='/set?c=2'>วงกลม 3</a>"
      "<a class='btn' href='/set?c=3'>วงกลม 4</a>"
    "</div>"

    "<div class='card'>"
    "<div class='info'>วงกลมที่เลือกตอนนี้: "
  );

  html += String(activeIndex + 1);
  html += F("</div>");

  // ส่วนปรับความสว่างด้วย slider
  html += F(
    "<div class='info'>ปรับความสว่างหน้าจอ</div>"
    "<div class='slider'>"
      "<input type='range' min='0' max='1023' step='1' "
      "oninput='valOut.innerText=this.value' "
      "onchange='fetch(`/brightness?val=`+this.value)'>"
      "<div>Brightness: <span id='valOut'>"
  );

  html += String(brightnessUser);
  html += F(
    "</span>/1023</div>"
    "</div>"
    "</div>" // .card
    "</body></html>"
  );

  server.send(200, "text/html", html);
}

// /set?c=N  -> เปลี่ยนวงกลม active
void handleSet() {
  if (server.hasArg("c")) {
    int idx = server.arg("c").toInt();
    if (idx < 0) idx = 0;
    if (idx >= numCircles) idx = numCircles - 1;

    activeIndex = idx;
    redrawCircles();

    Serial.print("Set activeIndex = ");
    Serial.println(activeIndex);
  }

  handleRoot();
}

// /brightness?val=N  -> ปรับค่าความสว่าง
void handleBrightness() {
  if (server.hasArg("val")) {
    int b = server.arg("val").toInt();
    if (b < 0)   b = 0;
    if (b > 1023) b = 1023;

    brightnessUser = b;
    applyBrightness();

    Serial.print("Brightness updated via web: ");
    Serial.println(brightnessUser);
  }

  // ตอบกลับแบบสั้น (JSON เล็ก ๆ ก็ได้)
  String resp = "{ \"brightness\": " + String(brightnessUser) + " }";
  server.send(200, "application/json", resp);
}

void handleNotFound() {
  server.send(404, "text/plain", "Not found");
}

void setup() {
  Serial.begin(115200);


  // --------- จอ TFT ---------
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(3); // แนวนอนที่คุณเลือกใช้แล้ว OK
  tft.fillScreen(ST77XX_BLACK);

  analogWriteRange(1023);
  pinMode(TFT_LED, OUTPUT);
  

  // เริ่มต้นความสว่างตาม brightnessUser
  applyBrightness();

  // บังคับให้วาดครั้งแรก
  for (int i = 0; i < numCircles; i++) {
    circleColor[i] = 0xFFFF;
  }
  redrawCircles();

  // --------- Wi-Fi ---------
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.print("Connecting WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("WiFi connected. IP: ");
  Serial.println(WiFi.localIP());

  // แสดง IP มุมซ้ายบน
  drawIP(WiFi.localIP().toString());

  // --------- Web server ---------
  server.on("/", handleRoot);
  server.on("/set", handleSet);
  server.on("/brightness", handleBrightness);
  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}