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()
沒有留言:
張貼留言