MQTT 教材, Raspberry Pico W 與 ESP32 實作教學

從 MQTT 基本觀念、Broker 架設、Topic 規劃,到 Raspberry Pi Pico W、ESP32 發佈資料,並使用 Python 撰寫 Subscriber 進行接收。

適合 IoT、嵌入式系統、網路通訊與智慧裝置課程。

MQTT Pico W ESP32 Python Subscriber

一、教學目標

  • 理解 MQTT 的通訊模式與用途
  • 了解 Publisher、Subscriber、Broker 的角色
  • 學會架設 Mosquitto Broker
  • 學會讓 Pico W 與 ESP32 發送資料
  • 學會使用 Python 撰寫 Subscriber 接收訊息

二、適用情境

  • 感測器資料上傳
  • 智慧家庭裝置控制
  • 教室 IoT 實驗平台
  • 多設備之間的低頻寬通訊
  • 邊緣運算與雲端橋接
MQTT 的優勢是輕量、簡單、適合資源有限的微控制器。

三、MQTT 基本觀念

1. 三個核心角色

角色 說明
Publisher發送訊息的裝置,例如感測器、ESP32、Pico W
Subscriber接收訊息的裝置或程式,例如 Python 應用程式
Broker負責轉送訊息的中心伺服器,例如 Mosquitto

2. Topic 的概念

MQTT 用 topic 來分類訊息,例如:

iot/classroom/temp
iot/classroom/humidity
iot/pico/led
iot/esp32/status

3. Publish / Subscribe 模式

4. MQTT 常見特色

四、QoS 與 Retain 概念

功能 說明
QoS 0最多傳一次,最快,但不保證一定收到
QoS 1至少傳一次,可能重複收到
QoS 2只傳一次,最可靠但開銷較大
RetainBroker 保留最後一筆訊息,新訂閱者一連上就能收到
教學初期大多使用 QoS 0 或 QoS 1 就夠了。

五、在 Raspberry Pi 上安裝 MQTT Broker, Mosquitto

1. 安裝套件

sudo apt update
sudo apt install -y mosquitto mosquitto-clients

2. 啟動服務

sudo systemctl enable mosquitto
sudo systemctl start mosquitto
sudo systemctl status mosquitto

3. 測試本機 Broker

先開兩個終端機。

終端機 A,訂閱:

mosquitto_sub -h localhost -t test/topic

終端機 B,發送:

mosquitto_pub -h localhost -t test/topic -m "Hello MQTT"
如果終端機 A 收到訊息,代表 Broker 已可正常工作。

六、課堂建議的 Topic 規劃方式

iot/班級/裝置/資料類型

例如:
iot/ece2026/picow/temp
iot/ece2026/picow/humidity
iot/ece2026/esp32/light
iot/ece2026/esp32/status

建議原則

七、使用 Python 撰寫 MQTT Subscriber

1. 安裝 paho-mqtt

python3 -m pip install paho-mqtt

2. subscriber.py

import paho.mqtt.client as mqtt

BROKER_IP = "192.168.1.120"
TOPIC = "iot/ece2026/#"


def on_connect(client, userdata, flags, rc):
    print("Connected with result code", rc)
    client.subscribe(TOPIC)


def on_message(client, userdata, msg):
    print(f"Topic: {msg.topic}")
    print(f"Message: {msg.payload.decode()}")
    print("-" * 40)


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect(BROKER_IP, 1883, 60)
client.loop_forever()

3. 執行

python3 subscriber.py
這個範例會接收 iot/ece2026/ 底下的所有子 topic,非常適合課堂展示。

八、Raspberry Pi Pico W 連線 MQTT 範例

本節採用 MicroPython。請先使用 Thonny 或 mpremote 將 MicroPython 韌體燒錄到 Pico W。

1. 準備檔案

2. Pico W publisher 範例

import network
import time
from umqtt.simple import MQTTClient

SSID = '你的WiFi名稱'
PASSWORD = '你的WiFi密碼'
BROKER = '192.168.1.120'
CLIENT_ID = 'pico_w_01'
TOPIC = b'iot/ece2026/picow/temp'

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

while not wlan.isconnected():
    print('WiFi connecting...')
    time.sleep(1)

print('WiFi connected:', wlan.ifconfig())

client = MQTTClient(CLIENT_ID, BROKER)
client.connect()
print('MQTT connected')

count = 0
while True:
    message = 'Pico W temperature=' + str(25 + count % 5)
    client.publish(TOPIC, message)
    print('Published:', message)
    count += 1
    time.sleep(5)

3. Pico W subscriber 範例

import network
import time
from umqtt.simple import MQTTClient

SSID = '你的WiFi名稱'
PASSWORD = '你的WiFi密碼'
BROKER = '192.168.1.120'
CLIENT_ID = 'pico_w_sub_01'
TOPIC = b'iot/ece2026/picow/led'


def sub_cb(topic, msg):
    print('Received:', topic, msg)

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

while not wlan.isconnected():
    time.sleep(1)

client = MQTTClient(CLIENT_ID, BROKER)
client.set_callback(sub_cb)
client.connect()
client.subscribe(TOPIC)
print('Subscribed to', TOPIC)

while True:
    client.check_msg()
    time.sleep(1)
Pico W 使用 MicroPython 時,函式庫名稱與桌面 Python 不同,不能直接使用 paho-mqtt。

九、ESP32 透過 MicroPython 發送 MQTT 範例

若 ESP32 安裝的是 MicroPython,可直接使用與 Pico W 類似的方式。

import network
import time
from umqtt.simple import MQTTClient

SSID = '你的WiFi名稱'
PASSWORD = '你的WiFi密碼'
BROKER = '192.168.1.120'
CLIENT_ID = 'esp32_01'
TOPIC = b'iot/ece2026/esp32/status'

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

while not wlan.isconnected():
    print('Connecting WiFi...')
    time.sleep(1)

print('WiFi OK:', wlan.ifconfig())

client = MQTTClient(CLIENT_ID, BROKER)
client.connect()
print('MQTT connected')

counter = 0
while True:
    payload = 'ESP32 alive ' + str(counter)
    client.publish(TOPIC, payload)
    print('Published:', payload)
    counter += 1
    time.sleep(3)

十、ESP32 透過 Arduino 框架發送 MQTT 範例

如果課程使用 Arduino IDE,這個版本通常更常見。

1. 安裝函式庫

2. 範例程式

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

const char* ssid = "你的WiFi名稱";
const char* password = "你的WiFi密碼";
const char* mqtt_server = "192.168.1.120";

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("ESP32Client")) {
      client.publish("iot/ece2026/esp32/status", "ESP32 connected");
    } else {
      delay(1000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  client.publish("iot/ece2026/esp32/status", "Hello from ESP32");
  delay(5000);
}

十一、Python 端接收 Pico W 與 ESP32 訊息的整合範例

import paho.mqtt.client as mqtt
import json
from datetime import datetime

BROKER_IP = "192.168.1.120"
TOPICS = [
    ("iot/ece2026/picow/temp", 0),
    ("iot/ece2026/esp32/status", 0),
    ("iot/ece2026/#", 0)
]


def on_connect(client, userdata, flags, rc):
    print("Connected:", rc)
    for topic, qos in TOPICS:
        client.subscribe(topic, qos)
        print("Subscribed:", topic)


def on_message(client, userdata, msg):
    payload = msg.payload.decode()
    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{now}] {msg.topic} -> {payload}")


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER_IP, 1883, 60)
client.loop_forever()
這樣一來,Pico W 與 ESP32 都能發送資料到同一台 Broker,再由 Python 統一接收。

十二、如果要用 Raspberry Pi 上的 Python 當 Publisher

import paho.mqtt.client as mqtt
import time

BROKER_IP = "192.168.1.120"
TOPIC = "iot/ece2026/rpi/message"

client = mqtt.Client()
client.connect(BROKER_IP, 1883, 60)

count = 0
while True:
    msg = f"Hello from Raspberry Pi {count}"
    client.publish(TOPIC, msg)
    print(msg)
    count += 1
    time.sleep(5)

十三、課堂實驗流程建議

  1. 先在 Raspberry Pi 安裝 Mosquitto Broker
  2. 使用 mosquitto_pubmosquitto_sub 做第一個測試
  3. 再讓 Python Subscriber 成功接收訊息
  4. 接著讓 Pico W 發送資料
  5. 再讓 ESP32 發送資料
  6. 最後做多裝置同時上傳與統一監控

十四、常見錯誤與除錯方法

問題 可能原因 解法
連不到 BrokerIP 填錯、Broker 未啟動、防火牆阻擋檢查 systemctl status mosquitto 與 IP 位址
Python 收不到訊息topic 不一致確認 topic 字串完全一致
Pico W 無法連 Wi-FiSSID/密碼錯誤、頻段不支援確認 2.4GHz Wi-Fi 與帳密
ESP32 斷線Wi-Fi 不穩、未做重連加入 reconnect 邏輯
訊息中文亂碼編碼問題統一使用 UTF-8

十五、延伸教學主題

十六、作業與實驗題目建議

  1. 完成 Raspberry Pi 上的 Mosquitto 安裝與測試
  2. 完成 Python Subscriber 程式並接收測試訊息
  3. 讓 Pico W 每 5 秒送出一筆溫度資料
  4. 讓 ESP32 每 3 秒送出狀態訊息
  5. 設計自己的 topic 命名規則
  6. 進階題:以 Python 將收到的資料寫入 CSV 檔案

十七、結語

MQTT 是 IoT 世界中非常重要的通訊協定,觀念清楚之後,學生很快就能把感測器、微控制器、樹莓派、資料庫與網頁儀表板串接起來。

這份教材的重點不是只會執行範例,而是讓學生理解資料如何從裝置經過 Broker,再傳到應用程式端。