RS-485 與 Modbus 實戰:MD02 溫濕度感測器程式解說 (1/3)
為了幫助大家更清楚地理解如何透過程式碼控制硬體,我們將 RTL8720DF (Realtek Ameba) Datalogger IoT 開發板讀取 RS485-MD-02 溫濕度感測器的範例程式分為三段來解說。本篇為第一段,主要聚焦於「程式庫引入、硬體腳位定義與通訊物件宣告」,也就是在 setup() 之前的全域準備工作。
一、 引入必要程式庫與基礎設定
在程式的開頭,我們需要引入三個關鍵的程式庫,分別負責 Modbus 主從通訊、軟體序列埠以及 WiFi 網路連線。
#include <ModbusRtu.h> // Modbus RTU 主從通訊程式庫 #include <SoftwareSerial.h> // 軟體序列埠程式庫 #include <WiFi.h> // WiFi 連線程式庫
二、 UART 多工器 (Multiplexer) 腳位切換
Datalogger IoT 開發板上整合了多種通訊介面,因此設計了 UART 多工器,透過 S0 與 S1 兩個腳位來控制並切換不同的通訊裝置。我們透過巨集定義 (Macro) 的方式,讓後續程式可以輕鬆切換到 RS-485 模式。
#define S0 1 // 多工器選擇腳位 0
#define S1 0 // 多工器選擇腳位 1
// 選擇 RS-485 裝置 (當 S0=HIGH, S1=LOW 時)
#define USE_RS485() do{ digitalWrite(S0, HIGH); digitalWrite(S1, LOW); } while(0)
| S1 狀態 | S0 狀態 | 對應啟用的實體裝置 |
|---|---|---|
| LOW (0) | LOW (0) | PMS5003 空氣品質感測器 |
| LOW (0) | HIGH (1) | RS-485 (Modbus 裝置) |
| HIGH (1) | LOW (0) | GPS 模組 |
| HIGH (1) | HIGH (1) | 外部 UART 裝置 |
(透過 S0 與 S1 的高低電位組合,開發板即可將單一共用通訊線路導向指定的硬體介面)
三、 網路連線與雲端平台設定
這段程式除了讀取感測器,還身兼將數據上傳至 ThingSpeak 雲端平台的任務,因此需要設定 WiFi SSID、密碼以及 ThingSpeak 的 API 金鑰與伺服器位址。同時,為了控管上傳與斷線重連的頻率,設定了幾個非阻塞計時器變數。
// WiFi 與 ThingSpeak 設定 char ssid[] = "your_ssid"; char pass[] = "your_password"; char server[] = "api.thingspeak.com"; const String api_key = "your_api_key"; // 計時器設定 (利用 millis() 實現非阻塞延遲) unsigned long CurrentTime, preTime; const int intervalSwitch = 1000 * 60 * 1; // 資料上傳間隔: 1 分鐘 unsigned long reTryConnTime, reTryConnPreTime; const int reTryConnIntervalSwitch = 1000 * 10; // WiFi 重連檢查間隔: 10 秒
四、 Modbus 通訊物件與變數宣告
這部分是 Modbus 通訊的核心準備工作。我們宣告了儲存資料的陣列 au16data、狀態機變數 u8state,並利用腳位 2 和 3 建立軟體序列埠 mySerial。最後,將軟體序列埠綁定到 Modbus 主站 (Master) 物件上,並宣告了具有 2 個元素的 telegram 陣列,準備分別用於儲存讀取溫度與濕度的查詢結構。
uint16_t au16data; // 用於儲存從 slave 讀取的暫存器數據 uint8_t u8state; // 狀態機目前狀態 (0: 等待, 1: 發送查詢, 2: 輪詢回應) uint8_t u8Query; // 目前執行的查詢編號 (0: 溫度, 1: 濕度) SoftwareSerial mySerial(2, 3); // 軟體序列埠: RX=Pin2, TX=Pin3 Modbus master(0, mySerial); // 建立 Modbus 主站,使用軟體序列埠 (參數 0 表示為 Master 主機) modbus_t telegram[2]; // 宣告 2 組 Modbus 查詢結構 unsigned long u32wait; // Modbus 查詢間隔等待計時器 uint16_t temperature, humdidity; // 儲存溫濕度原始數值的變數
在上方的程式中,我們宣告了 telegram 這個陣列,它的作用就像是我們準備發送給感測器的「兩張包裹單」:
📦 telegram[0]:準備打包「讀取溫度」的指令參數。
📦 telegram[1]:準備打包「讀取濕度」的指令參數。
當感測器回傳資料後,我們預先準備的 au16data 陣列就會作為「收件箱」,負責接收並暫存這些 16 位元的十六進位數據。
第一段總結:到這裡,我們已經完成了所有硬體腳位切換準備、網路參數設定,以及 Modbus 核心物件與緩衝區的宣告。下一段我們將進入 setup() 函式,解析硬體初始化的過程以及確保網路穩定的 WiFi 防呆重連機制!