Node-RED, Modbus II

Modbus 協議中的記憶體

Modbus 協議中的記憶體規劃如下:

  1. 線圈(Coils):線圈是一個包含單個位元的可讀寫數據區域,通常用於控制輸出設備(如繼電器、燈光等)。每個線圈的狀態可以是開(ON)關(OFF)
  2. 輸入線圈(Input Coils):輸入線圈是一個包含單個位元的只讀數據區域,通常用於表示輸入信號(如開關狀態、傳感器狀態等)。
  3. 保持寄存器(Holding Registers):保持寄存器是一個包含 16 位元資料的可讀寫數據區域,用於存儲控制器的參數、配置等信息。
  4. 輸入寄存器(Input Registers):輸入寄存器是一個包含 16 位元資料的只讀數據區域,用於表示輸入信號的狀態、測量值等。

這些內存區域的地址範圍從 0 開始,每個區域都有自己的地址空間。通常,線圈和輸入線圈的地址範圍是從 0 到 65535,而保持寄存器和輸入寄存器的地址範圍也是從 0 到 65535。

通過這種內存規劃,Modbus 協議可以簡單而高效地管理不同類型的數據,並提供了對這些數據的讀取和寫入操作。

PLC的實體Input接線端通常對應到Modbus協議中的「輸入線圈(Input Coils)」或「輸入寄存器(Input Registers)」。這取決於PLC和Modbus裝置之間的通信配置和數據交換方式。

  1. 如果PLC的實體Input接線端代表的是開關狀態或二進制信號,則通常對應到Modbus協議中的「輸入線圈(Input Coils)」。這些輸入線圈的狀態可以是開(ON)或關(OFF),並且可以由Modbus Master訪問和讀取。
  2. 如果PLC的實體Input接線端代表的是模擬量(如溫度、壓力等)或其他數值型信號,則通常對應到Modbus協議中的「輸入寄存器(Input Registers)」。這些輸入寄存器中存儲的是16位元的數值資料,可以由Modbus Master訪問和讀取。

因此,PLC的實體Input接線端對應的Modbus記憶體規劃取決於具體的應用場景和通信配置。

PLC的實體Output接線端通常對應到Modbus協議中的「線圈(Coils)」或「保持寄存器(Holding Registers)」。同樣地,這取決於PLC和Modbus裝置之間的通信配置和數據交換方式。

  1. 如果PLC的實體Output接線端用於控制開關類型的設備(如繼電器、閥門等),則通常對應到Modbus協議中的「線圈(Coils)」。這些線圈的狀態可以是開(ON)或關(OFF),並且可以由Modbus Master寫入和控制。
  2. 如果PLC的實體Output接線端用於輸出數值型信號(如控制閥門的開度、調節器的設置值等),則通常對應到Modbus協議中的「保持寄存器(Holding Registers)」。這些保持寄存器中存儲的是16位元的數值資料,可以由Modbus Master寫入和控制。

因此,PLC的實體Output接線端對應的Modbus記憶體規劃也取決於具體的應用場景和通信配置。

Data AddressesReadWrite SingleWrite Multiple
Discrete Output Coils 0xxxx 繼電器FC01FC05FC15
Discrete Input Contacts 1xxxx ON/OFFC02NANA
Analog Input Registers 3xxxx 感測器數值FC04NANA
Analog Output Holding Registers 4xxxxFC03FC06FC16

如果有接硬體的話,一些開關類的裝置會接在PLC的DI處,對應Discrete Input Contacts 1xxxx 記憶體區塊。如果需要推動繼電器等裝置會對應Discrete Output Coils 0xxxx 記憶體區塊。

因為目前情境並沒有實際與硬體接線,故會以讀寫Analog Output Holding Registers 4xxxx來進行模擬。

競賽主題 5.1 機台磨損

Adress作用
15蓋印頭不足燈號
24料件:蓋印頭數量
25蓋印頭警示數量
26蓋印頭剩餘數量

Node-Red 流程可以分為三個區塊:

  1. 輪訊Modbus Memory
  2. 寫入Modubs Memory
  3. 寫入Global Memory
Manual Getter FC3 Node作用
Address指定讀取的開始位址
Quantity指定讀取的長度

如何調整Dashboard UI 元件的Layout?

Function Node作用
global.set(‘address_24’, msg.payload);return msg;程式一執行紿於初始值10, 並將10設定給Global.address_24變數
let val = global.get(‘address_24’);msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 24 , ‘quantity’: 1 };return msg;蓋印頭數量寫回 modbus memory
Function Node作用
global.set(‘address_25’, msg.payload);return msg;程式一執行紿於初始值4, 並將4設定給Global.address_25變數
let val = global.get(‘address_25’);msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 25 , ‘quantity’: 1 };return msg;蓋印頭警示數量寫回 modbus memory
Function Node作用
let val = global.get(‘address_26’);if (val > 0) {    val -= 1;    global.get(‘address_26’, val);}msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 26 , ‘quantity’: 1 };return msg;蓋印頭數量 – 1 後並寫回modbus memory
Function Node作用
let val = global.get(‘address_24’);msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 26 , ‘quantity’: 1 };return msg;將使用者在GUI上設定的蓋印頭數量,寫入modbus中
GUI上的蓋印頭數量是同步設定在Global.address_24變數 
Function Node作用
<div    style=”border: 1px solid black; border-radius: 100%; background-color: {{msg.payload}}; width: 20px; height: 20px;margin:10px auto”></div>這個寫法是網頁的寫法:圓: border-radius: 100%;圓的邊框:border: 1px solid black;圓的顏色:動態指定由前面的Node的回傳值圓的大小:width 20px; height 20px;
if (msg.payload[26] > msg.payload[25]) {    msg.payload = ‘lime’;} else {    msg.payload = ‘red’;}return msg;msg.payload[26] => 印頭的剩餘數量msg.payload[25] => 警示數量
印頭的剩餘數量 > 警示數量  大於: 綠色  小於或等於:紅色
let val = 0;if (msg.payload === ‘red’) {    val = 1;}msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 15, ‘quantity’: 1 };return msg;當數量小於或等於時,就將modbus address 15的設為1
modbus adderss 15:蓋印頭不足燈號
Function Node作用
let max = msg.payload[24];msg.payload = msg.payload[26];  msg.ui_control = { “min”: 0, “max”: max };return msg;max 值為 7msg.payload 值為 6msg.payload[24] => 料件:蓋印頭數量msg.payload[26] => 蓋印頭剩餘數量
源頭的msg是每秒讀出的modbus memory目的端msg是要給Guage Node的值msg.payload = 蓋印頭剩餘數量
msg.ui_control 的寫法是重點,指定Guage Node元件的上、下限。
Adress作用
0待生產數量
2製造時間,秒
5生產數累計
6良品數累計
7不良品數累計

虛擬產線示意圖

  • 紅色區塊:每秒讀Modbus Memory Address 0 ~ 29
  • 藍色區塊:將Modbus Memory值,設定給Glbal變數
  • 綠色區塊:將Modbus Memory的值,更新到GUI
Function Node作用
let in_process = global.get(‘in_process’);if (in_process == false){    let total = msg.payload[5];    let good = msg.payload[6];    msg.payload = Math.floor((good / total) * 100);    return msg;}msg.playload[5] => 已生產數量msg.playload[6] => 良品數量
Math.floor() 函式會回傳小於等於所給數字的最大整數。console.log(Math.floor(5.95));// Expected output: 5
console.log(Math.floor(5.05));// Expected output: 5
console.log(Math.floor(5));// Expected output: 5
console.log(Math.floor(-5.05));// Expected output: -6

將 text node 所要顯示的值指定為  msg.payload[0], 讀取address 0的值料。

  • 紅色區塊:初始化Text Input Node及Global.address_0變數
  • 綠色區塊:將Global.address_0變數的值寫入Modbus Memory Address 0
  1. 紅色區塊:開始累計加工時間
  2. 綠色區塊:更新待生產數量及生產數量
Function Node作用
let val = global.get(‘address_0’);if (val > 0) {    global.set(‘in_process’, true);    return msg;} else {    global.set(‘in_process’, false);    return null;}判斷待生產數是否 > 0  是: 設定生產中  否:設定未產產
Function Node作用
拫據Switch Node的開關,設定Global.AOI變數,並更新GUI。if (msg.payload) {    msg.payload = ‘良品’;    global.set(‘aoi’, true);} else {    msg.payload = ‘不良品’;    global.set(‘aoi’, false);}return msg;使用者切換檢測判定結果的Switch,並將Switch的值寫入Global.aoi變數中。
Function Node作用
let val = global.get(‘in_process’);if (val) {    return msg;} else {    return null;}判斷是否在生產中,如果不是就跳開。
回傳 null 就是跳開後面的邏輯。
global.set(‘break_timer’, 1);global.set(‘in_process’, false);return msg;停止累計加工時間的變數設為1
生產中的變數設為False
let aoi = global.get(‘aoi’);if (aoi) {    let val = global.get(“address_6”);    val += 1    msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 6, ‘quantity’: 1 };} else {    let val = global.get(“address_7”);    val += 1    msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 7, ‘quantity’: 1 };}return msg;依據 檢測結果
aoi == True, 良品, address 6, +1
aoi == False, 不良品, address 7, +1
Function Node作用
msg.payload = { value: 0, ‘fc’: 6, ‘unitid’: 1, ‘address’: 0, ‘quantity’: 1 };return msg;address 0:待生產數量
msg.payload = { value: 0, ‘fc’: 6, ‘unitid’: 1, ‘address’: 2, ‘quantity’: 1 };return msg;address 2: 加工累計時間
let val = [0, 0, 0];msg.payload = { value: val, ‘fc’: 16, ‘unitid’: 1, ‘address’: 5, ‘quantity’: 3 };return msg;address 5, 6, 7: 生產累計、良品累計、不良品累計
Function Node作用
msg.payload = msg.payload[1];return msg;依address_1為例,其它的作法一樣將modbus address 1的值指定給GUI LED Node
LED Node 外觀LED Node 設定值
  • 紅色區塊:從Modbus Memory讀出數據,指定給GUI Node
  • 緣色區塊:當GUI Node被切換時,會將其值寫入Modbus Memory
Function Node作用
msg.payload = msg.payload[1];return msg;依address_1為例,其它的作法一樣將modbus address 1的值指定給GUI LED Node
let val = msg.payload;msg.payload = { value: val, ‘fc’: 6, ‘unitid’: 1, ‘address’: 1, ‘quantity’: 1 };return msg;這段是將GUI Node的值指定給val
let val = msg.payload; 
將val值寫入modbus memory
分類: Node-RED,標籤: , 。這篇內容的永久連結

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *