RS-485 與 Modbus 實戰:MD02 溫濕度感測器程式解說 (1/3)

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 多工器,透過 S0S1 兩個腳位來控制並切換不同的通訊裝置。我們透過巨集定義 (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)         
【插圖說明:UART 多工器硬體切換邏輯】
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; // 儲存溫濕度原始數值的變數
【插圖說明:Modbus 資料結構與流程預覽】

在上方的程式中,我們宣告了 telegram 這個陣列,它的作用就像是我們準備發送給感測器的「兩張包裹單」:
📦 telegram[0]:準備打包「讀取溫度」的指令參數。
📦 telegram[1]:準備打包「讀取濕度」的指令參數。
當感測器回傳資料後,我們預先準備的 au16data 陣列就會作為「收件箱」,負責接收並暫存這些 16 位元的十六進位數據。

第一段總結:到這裡,我們已經完成了所有硬體腳位切換準備、網路參數設定,以及 Modbus 核心物件與緩衝區的宣告。下一段我們將進入 setup() 函式,解析硬體初始化的過程以及確保網路穩定的 WiFi 防呆重連機制!