2026年1月20日 星期二

Python 控制 WOKWI ESP32 10個LED 閃爍

 Python 控制 WOKWI ESP32 10個LED 閃爍

分為兩個部分:ESP32 接收端程式(負責接收指令並執行 LED 跑馬燈)以及 Python Tkinter 控制端程式(負責發送指令)。

1. ESP32 端程式碼 (Wokwi)

這段程式會連線到 MQTT Broker 並訂閱 alex9ufo/LEDcommand 主題。當收到數字指令時,會切換對應的 LED 效果。

2. Python Tkinter 控制端程式碼

這支程式提供按鈕來發送 1~6 的指令,並顯示 MQTT 連線狀態。




#include <WiFi.h>
#include <PubSubClient.h>

// --- 設定區 ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "mqtt-dashboard.com";
const char* mqtt_topic = "alex9ufo/LEDcommand";

// LED 接腳定義
int ledPins[] = {19, 18, 5, 4, 2, 27, 26, 25, 33, 32};
int numLeds = 10;
int currentMode = 0; // 目前的模式編號

WiFiClient espClient;
PubSubClient client(espClient);

void allOff() {
  for (int i = 0; i < numLeds; i++) digitalWrite(ledPins[i], LOW);
}

// MQTT 接收回調函式
void callback(char* topic, byte* payload, unsigned int length) {
  String message = "";
  for (int i = 0; i < length; i++) message += (char)payload[i];
 
  Serial.print("收到指令: ");
  Serial.println(message);
 
  // 更新模式編號
  currentMode = message.toInt();
  allOff(); // 切換模式時先全滅
}

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Connected");
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32_LED_Client")) {
      Serial.println("connected");
      client.subscribe(mqtt_topic);
    } else {
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < numLeds; i++) pinMode(ledPins[i], OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void runMode(int mode) {
  switch (mode) {
    case 1: // 從上到下
      for (int i = 0; i < numLeds; i++) { allOff(); digitalWrite(ledPins[i], HIGH); delay(100); client.loop(); if(currentMode != 1) return; }
      break;
    case 2: // 從下到上
      for (int i = numLeds - 1; i >= 0; i--) { allOff(); digitalWrite(ledPins[i], HIGH); delay(100); client.loop(); if(currentMode != 2) return; }
      break;
    case 3: // 上下來回
      for (int i = 0; i < numLeds; i++) { allOff(); digitalWrite(ledPins[i], HIGH); delay(70); client.loop(); }
      for (int i = numLeds - 2; i > 0; i--) { allOff(); digitalWrite(ledPins[i], HIGH); delay(70); client.loop(); }
      break;
    case 4: // 1,3,5,7,9 亮
      allOff();
      for (int i = 0; i < numLeds; i += 2) digitalWrite(ledPins[i], HIGH);
      break;
    case 5: // 2,4,6,8,10 亮
      allOff();
      for (int i = 1; i < numLeds; i += 2) digitalWrite(ledPins[i], HIGH);
      break;
    case 6: // 奇偶交替
      allOff();
      for (int i = 0; i < numLeds; i += 2) digitalWrite(ledPins[i], HIGH);
      delay(300); client.loop();
      allOff();
      for (int i = 1; i < numLeds; i += 2) digitalWrite(ledPins[i], HIGH);
      delay(300);
      break;
  }
}

void loop() {
  if (!client.connected()) reconnect();
  client.loop();
  if (currentMode != 0) runMode(currentMode);
}





import tkinter as tk

import paho.mqtt.client as mqtt


# --- 設定區 ---

MQTT_SERVER = "mqtt-dashboard.com"

MQTT_TOPIC = "alex9ufo/LEDcommand"


class LEDController:

    def __init__(self, root):

        self.root = root

        self.root.title("ESP32 LED 遠端控制")

        self.root.geometry("300x450")


        # 連線狀態

        self.status_label = tk.Label(root, text="MQTT 狀態: 正在連線...", fg="orange", font=("Arial", 10))

        self.status_label.pack(pady=10)


        # 按鈕標題

        tk.Label(root, text="選擇 LED 模式", font=("Arial", 12, "bold")).pack(pady=5)


        # 模式按鈕定義

        modes = [

            ("1. 從上到下", "1"),

            ("2. 從下到上", "2"),

            ("3. 上下來回", "3"),

            ("4. 1,3,5,7,9 亮", "4"),

            ("5. 2,4,6,8,10 亮", "5"),

            ("6. 奇偶交替閃爍", "6"),

            ("全部熄滅", "0")

        ]


        for text, cmd in modes:

            btn = tk.Button(root, text=text, width=20, height=2, 

                            command=lambda c=cmd: self.send_command(c))

            btn.pack(pady=5)


        # MQTT 初始化

        self.client = mqtt.Client()

        self.client.on_connect = self.on_connect

        try:

            self.client.connect(MQTT_SERVER, 1883, 60)

            self.client.loop_start()

        except:

            self.status_label.config(text="MQTT 狀態: 連線失敗", fg="red")


    def on_connect(self, client, userdata, flags, rc):

        if rc == 0:

            self.status_label.config(text="MQTT 狀態: 已連線", fg="green")

        else:

            self.status_label.config(text=f"MQTT 狀態: 錯誤({rc})", fg="red")


    def send_command(self, cmd):

        self.client.publish(MQTT_TOPIC, cmd)

        print(f"發送指令: {cmd}")


if __name__ == "__main__":

    root = tk.Tk()

    app = LEDController(root)

    root.mainloop()


沒有留言:

張貼留言

經由MQTT協定的2個WOKWI ESP32 雙向通訊 (ESP32 to ESP32 MQTT Communication )

 經由MQTT協定的2個WOKWI ESP32 雙向通訊  (ESP32  to ESP32 MQTT Communication ) 使用兩個 ESP32 建立一個遠端控制系統。 MQTT Broker: mqtt-dashboard.com Topic (主題): ale...