Node-RED 寫入到 Do-more PLC
要將資料從 Node-RED 寫入到 Do-more PLC,最標準且穩定的做法是讓 Node-RED 扮演 Modbus TCP 客戶端(Client),使用 modbus-write 節點,將資料寫入 Do-more 內建的 Modbus 專用暫存器(如線圈 MC 或保持暫存器 MHR)。
以下為您整理完整的設定步驟與不同資料型態(開關、16位元整數、32位元浮點數)的寫入方法。
1. 基礎節點設定 (Modbus Write)
在 Node-RED 中,拖曳 modbus-write 節點到畫布上,雙擊開啟並進行以下基礎設定:
- Server:選擇您先前建立好的 Do-more 連線(確認 IP 正確、Port 為
502)。 - Unit ID:輸入
1(或依 PLC 設定,通常預設為 1)。 - Address:輸入 0-based 的相對位址(例如欲寫入
MHR0,此處請填 0)。
2. 三種常見資料型態的寫入實作
情況 A:寫入開關/布林值(對應 Do-more 的 MC 線圈)
如果要控制 PLC 內部的某個開關接點(例如 MC0):
modbus-write 節點設定:- FC (Function Code):選擇
FC 5: Write Single Coil。 - Address:
0(代表 MC0)。
- 前段輸入(如
inject 節點):- 輸出的
msg.payload 必須是布林值 true 或 false(或者是數字 1 或 0)。
情況 B:寫入 16 位元整數(對應 Do-more 的 MHR 暫存器)
如果要寫入一個 0 ~ 65535 之間的整數值(例如設定溫度、計時器目標值到 MHR0):
modbus-write 節點設定:- FC (Function Code):選擇
FC 6: Write Single Register。 - Address:
0(代表 MHR0)。
- 前段輸入:
- 輸出的
msg.payload 必須是一個標準整數(如 125)。
情況 C:寫入 32 位元實數/浮點數(佔用 2 個 MHR 暫存器)
當你要將一個帶有小數點的數值(如 36.5)從 Node-RED 傳入 Do-more(例如存入 MHR0 與 MHR1)時,因為 Modbus 一個暫存器只能存 16 位元,你必須先用 function 節點將浮點數拆解成兩個 16 位元整數組成的陣列,再進行寫入。
modbus-write 節點設定:- FC (Function Code):選擇
FC 16: Write Multiple Registers ⚠️ (寫入多個暫存器必選此項)。 - Address:
0(代表從 MHR0 開始寫)。 - Quantity:
2(代表連續寫入 2 個暫存器)。
- 前段接一個
function 節點,寫入以下轉換程式碼:
// 假設要寫入的浮點數值來自 msg.payload (例如 36.5)
let floatValue = Number(msg.payload);
// 建立一個 4 內容值的 Buffer 區塊 (32 bits)
const buf = Buffer.alloc(4);
// 將浮點數以 Big-Endian 格式寫入 Buffer
buf.writeFloatBE(floatValue, 0);
// 將 4 個 Bytes 拆解組合成 2 個 16 位元的無正負號整數 (UInt16)
let word1 = buf.readUInt16BE(0); // 高位字組 (High Word)
let word2 = buf.readUInt16BE(2); // 低位字組 (Low Word)
// 將準備好的陣列賦值給 msg.payload 輸出給 modbus-write 節點
msg.payload = [word1, word2];
return msg;
- 。
[{"id":"281052bfc8430391","type":"modbus-read","z":"940df9f68ff5f5f7","name":"","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"255","dataType":"Coil","adr":"0","quantity":"8","rate":"3000","rateUnit":"ms","delayOnStart":false,"enableDeformedMessages":false,"startDelayTime":"","server":"03e72e7fd9537ba2","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":390,"y":440,"wires":[["01a0a871b0013f8d"],[]]},{"id":"01a0a871b0013f8d","type":"debug","z":"940df9f68ff5f5f7","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":380,"wires":[]},{"id":"72834d90122f8f0c","type":"modbus-read","z":"940df9f68ff5f5f7","name":"","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"255","dataType":"HoldingRegister","adr":"0","quantity":"8","rate":"3000","rateUnit":"ms","delayOnStart":false,"enableDeformedMessages":false,"startDelayTime":"","server":"03e72e7fd9537ba2","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":390,"y":320,"wires":[["01a0a871b0013f8d"],[]]},{"id":"02ac9ac5b37299ac","type":"modbus-write","z":"940df9f68ff5f5f7","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"255","dataType":"Coil","adr":"8","quantity":"1","server":"03e72e7fd9537ba2","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":540,"y":520,"wires":[["c23cc8f3685a03c3"],[]]},{"id":"8fa3a624ea874c80","type":"inject","z":"940df9f68ff5f5f7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":350,"y":520,"wires":[["02ac9ac5b37299ac"]]},{"id":"c23cc8f3685a03c3","type":"debug","z":"940df9f68ff5f5f7","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":720,"y":480,"wires":[]},{"id":"e8ec656f015766b6","type":"modbus-write","z":"940df9f68ff5f5f7","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"255","dataType":"HoldingRegister","adr":"2","quantity":"1","server":"03e72e7fd9537ba2","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":540,"y":620,"wires":[["c23cc8f3685a03c3"],[]]},{"id":"c85e74ca4374c2bb","type":"inject","z":"940df9f68ff5f5f7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"127","payloadType":"num","x":350,"y":620,"wires":[["e8ec656f015766b6"]]},{"id":"03e72e7fd9537ba2","type":"modbus-client","name":"modbus-Do-more","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":502,"tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":9600,"serialDatabits":8,"serialStopbits":1,"serialParity":"none","serialConnectionDelay":100,"serialAsciiResponseStartDelimiter":"0x3A","unit_id":255,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showErrors":false,"showWarnings":true,"showLogs":true},{"id":"207b905784147db1","type":"global-config","env":[],"modules":{"node-red-contrib-modbus":"5.60.1"}}]
Do-more 轉 Modbus 記憶體對應表
在 Node-RED 的 Modbus 節點設定中,Address(位址) 通常採用 0 起始(0-based) 的相對位址(即協定內定址)。
| Do-more 記憶體類型 | 說明 | Modbus 類型 / 功能碼 (FC) | Node-RED 位址 (0-based) | 備註 / 對應範例 |
|---|
MC0 – MC1023 | Modbus 專用線圈 | Coils (FC1 / FC5 / FC15) | 0 – 1023 | MC0 = 位址 0 |
MI0 – MI1023 | Modbus 專用輸入接點 | Discrete Inputs (FC2) | 0 – 1023 | MI0 = 位址 0 |
MHR0 – MHR2047 | Modbus 專用保持暫存器 | Holding Registers (FC3/FC4/FC6/FC16) | 0 – 2047 | MHR0 = 位址 0 |
MIR0 – MIR2047 | Modbus 專用輸入暫存器 | Input Registers (FC4) | 0 – 2047 | MIR0 = 位址 0 |