2026年8月8日 星期六

Node-RED 寫入到 Do-more PLC

    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):
    1. modbus-write 節點設定
      • FC (Function Code):選擇 FC 5: Write Single Coil
      • Address0(代表 MC0)。
    2. 前段輸入(如 inject 節點)
      • 輸出的 msg.payload 必須是布林值 truefalse(或者是數字 10)。

    情況 B:寫入 16 位元整數(對應 Do-more 的 MHR 暫存器)
    如果要寫入一個 0 ~ 65535 之間的整數值(例如設定溫度、計時器目標值到 MHR0):
    1. modbus-write 節點設定
      • FC (Function Code):選擇 FC 6: Write Single Register
      • Address0(代表 MHR0)。
    2. 前段輸入
      • 輸出的 msg.payload 必須是一個標準整數(如 125)。

    情況 C:寫入 32 位元實數/浮點數(佔用 2 個 MHR 暫存器)
    當你要將一個帶有小數點的數值(如 36.5)從 Node-RED 傳入 Do-more(例如存入 MHR0MHR1)時,因為 Modbus 一個暫存器只能存 16 位元,你必須先用 function 節點將浮點數拆解成兩個 16 位元整數組成的陣列,再進行寫入。
    1. modbus-write 節點設定
      • FC (Function Code):選擇 FC 16: Write Multiple Registers ⚠️ (寫入多個暫存器必選此項)
      • Address0(代表從 MHR0 開始寫)。
      • Quantity2(代表連續寫入 2 個暫存器)。
    2. 前段接一個 function 節點,寫入以下轉換程式碼
    javascript
    // 假設要寫入的浮點數值來自 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)備註 / 對應範例
MC0MC1023Modbus 專用線圈Coils (FC1 / FC5 / FC15)01023MC0 = 位址 0
MI0MI1023Modbus 專用輸入接點Discrete Inputs (FC2)01023MI0 = 位址 0
MHR0MHR2047Modbus 專用保持暫存器Holding Registers (FC3/FC4/FC6/FC16)02047MHR0 = 位址 0
MIR0MIR2047Modbus 專用輸入暫存器Input Registers (FC4)02047MIR0 = 位址 0

Node-RED 寫入到 Do-more PLC

Node-RED 寫入到 Do-more PLC 要將資料從 Node-RED 寫入到 Do-more PLC ,最標準且穩定的做法是讓 Node-RED 扮演 Modbus TCP 客戶端(Client),使用 modbus-write 節點,將資料寫入 Do-more ...