印刷檢測

客戶需求:使用者會將PDF中的標籤內容印刷到白色的織布上,希望透過視覺檢測可以將印刷不良的情況偵測出來。

我們將計劃使用局部可變形模型來進行標籤內容在織布上的視覺檢測,提供更精細的測試。

局部可變形模型是一種用於視覺檢測的技術,它可以在圖像中尋找局部特定形狀的實例。這種模型具有一定的靈活性,可以應對目標物體在圖像中的變形、旋轉和縮放等情況。

以下是局部可變形模型的一些重要特點和工作原理:

  1. 創建模型:創建局部可變形模型的過程通常包括以下步驟:
    • 選擇目標物體的形狀,可以是點、線、圓等。
    • 從圖像中提取這些形狀的特徵,比如邊緣、角點等。
    • 構建模型,包括特徵點的位置、連接關係和形狀特徵。
  2. 模型搜索:一旦模型被創建,它可以應用於圖像中搜索符合該模型的實例。搜索過程通常包括以下步驟:
    • 在圖像中的每個位置上應用模型,計算模型與圖像的匹配程度。
    • 根據匹配程度選擇最佳的實例,通常使用分數或相似性度量。
    • 如果模型具有變形能力,可以應對目標物體的旋轉、縮放和畸變等變化。


實驗一

我們故意將這張影像上幾處位置,故以把黑色的區域塗白。我們使用了上述的技術將缺瑕檢測出來。

原圖檢出差異處缺瑕圖
原圖檢出差異處QRCode塗白

分類: AOI | 標籤: , | 發佈留言

邏輯斯迴歸

Untitled
分類: 未分類 | 發佈留言

邏輯斯迴歸

Untitled
分類: 未分類 | 發佈留言

Docker Node-RED 影片

分類: Docker, Node-RED | 標籤: , | 發佈留言

Node-RED, OpcUa

OPC UA(開放式連接和訊息架構)是一個開放標準,用於在工業自動化領域中建立跨平台、互操作性的通訊和數據交換。它的出現是為了解決不同廠商的工業自動化設備之間通訊和數據共享的問題。

在過去,許多工業自動化系統都是封閉的,使用各種不同的通訊協定和數據格式。這導致了設備之間的互操作性問題,並且使得數據集成和監控變得困難。為了克服這些問題,OPC UA標準應運而生。

OPC UA提供了一個統一的框架,使得不同廠商的設備和系統能夠輕鬆地進行通訊和數據交換。它支持各種不同的通訊協定,包括Ethernet、TCP/IP和Web服務等,並且提供了豐富的數據模型和安全機制,確保數據的安全性和一致性。

OPC UA被廣泛應用於工業自動化、製造業、能源管理、智慧城市等領域。它可以用於監控和控制工廠設備、收集和分析生產數據、實現製造執行系統(MES)和企業資源計劃(ERP)之間的集成,以及實現設備的遠程監控和維護等功能。總的來說,OPC UA通過提供標準化的通訊和數據交換機制,促進了工業自動化系統的互操作性和智能化水平的提升。

OPC UA的設計目標包括以下幾點:

  1. 跨平台互操作性: OPC UA支持多種不同的平台和操作系統,包括Windows、Linux、嵌入式系統等,並且提供了豐富的通訊協定選擇,使得不同設備之間能夠實現無縫的互操作性。
  2. 豐富的數據模型: OPC UA定義了豐富的數據模型,包括工業設備、生產過程、企業資源等,並且提供了標準化的數據描述和結構,使得不同系統能夠準確地理解和解釋數據。
  3. 安全性和可擴展性: OPC UA提供了多層次的安全機制,包括加密、身份驗證、授權等,確保通訊和數據交換的安全性。同時,它還提供了可擴展的架構,支持大規模系統和高性能需求。
  4. 標準化和開放性: OPC UA是一個開放標準,由國際組織制定,並且得到了廣泛的行業支持和採用。它提供了完整的文檔和規範,使得廠商和開發者能夠自由地實現和使用OPC UA相關的技術。

總的來說,OPC UA通過提供標準化的通訊和數據交換機制,促進了工業自動化和物聯網技術的發展,並且推動了工業4.0和智慧製造等新興應用的應用和發展。

在Modus 範例中我們規劃一個記憶體區塊,使用30個位址。

這裡Demo 使用Python撰寫一個OpcUa Server,內有30個變數,來達到相同的功能。

接下來在Node-Red中安裝下列package.

  • node-red-contrib-opcua

Python OpcUa 30 個變數,可以看到變數的NoeId, DataType, Value, Name

Node-Red 流程規劃:每一秒輪詢OpcUa Server讀取數據更新到LED燈。

Node作用
Inject Node設定每秒觸發一次
OpcUa Item指定數據

NodeID: ns=2,i=3;
DataType: int64;
OpcUa Client連線到OpcUa Server

opc.tcp://opcua-server:4840/freeopcua/server/
指定要執行的指令
READ
function將OpcUa Server讀取的數據指定給GUI

msg.payload = msg.payload[0];return msg;
ui_led接收 funtion 的 msg.payload 顯示紅燈或綠燈
LED Node 外觀LED Node 設定值
  • 紅色區塊:從OpcUa Server讀出數據,指定給GUI Node
  • 緣色區塊:當GUI Node被切換時,會將其值寫入OpcUa Server
Node作用
Inject Node程式開始運行時執行一次
OpcUa Item指定數據

NodeID: ns=2,i=3;
DataType: int64;
OpcUa Client連線到OpcUa Server

opc.tcp://opcua-server:4840/freeopcua/server/
指定要執行的指令
READ
function將OpcUa Server讀取的數據指定給GUI

msg.payload = {    “arrayType”: 0,    “dataType”: 8,    “value”: [        msg.payload[0],        0    ]}return msg;
switch接收 funtion 的 msg.payload 顯示開或關
OpcUa Item接收switch的數據

NodeID: ns=2,i=3;
DataType: int64;
OpcUa Client連線到OpcUa Server

opc.tcp://opcua-server:4840/freeopcua/server/
指定要執行的指令
WRITE
分類: Node-RED, OpcUa | 標籤: | 發佈留言

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 | 標籤: , | 發佈留言

Node-RED 安全性

登入權限控管

路徑/data/setting.js

尋找adminAuth區塊,將註解移除。

新增使用者admin, user 為例

使用node-red-admin hash-pw 指令產生Password, 將產生的password, 填入上方password欄位

Dashboard登入權限控管

尋找httpNodeAuth區塊,將註解移除。

新增使用者peter 為例

http -> https

先產生公私鑰

尋找https區塊,將註解移除。

指定你的公、私鑰的路徑

分類: Node-RED | 標籤: , , | 發佈留言

Node-RED, Use Docker to Replace Xampp

使用Docker快速建構運行環境

1. 軟體容器化: Docker 是一個開源的軟體平台,可以讓開發者將應用程式和其相依的環境(如庫、工具、設定等)一起打包成為一個輕量的容器。這使得應用程式在任何地方都可以快速地運行,而不受環境的限制。

2. 跨平台: Docker 容器可以在任何支援 Docker 的平台上運行,無論是開發人員的筆記本電腦、測試伺服器,還是生產環境中的雲端服務器。這提供了更大的靈活性和可移植性。

3. 簡化配置和管理: Docker 提供了一個統一的平台,開發者可以使用單個 Dockerfile 文件來定義應用程式的配置,以及 Docker Compose 文件來管理多個容器之間的交互和依賴關係。這簡化了應用程式的配置和部署過程。

4. 提高效能和效率: Docker 容器運行在宿主機的核心上,因此可以實現更高的效能和更快的啟動時間。此外,Docker 可以在同一宿主機上運行多個容器,從而實現資源的有效利用和更高的效率。

5. 進行微服務架構: Docker 可以將大型應用程式拆分為多個微服務,每個微服務都運行在獨立的容器中。這使得應用程式更容易擴展、維護和部署,並且可以實現更高的可靠性和彈性。

Docker Desktop下載點

執行Desker Desktop

這是有目前運行的OpenCart, phpadmin, mariadb, Node-RED的環境。

  1. 建立一個資料夾Node-RED
  2. 建立Docker-compose.yml 中所需要的資料夾。nodered-data, image兩個資料夾
  3. 建立一個docker-compose.yml。
  4. 開啟cmd 程式,將路徑切換到Node-RED資料夾
  5. 執行docker-compose up -d,開啟Docker Container node-red 運行OpenCart, phpadmin, mariadb, Node-RED的環境。
  6. 當測試完後,執行docker-compose down 關閉Docker Container node-red.

Docker-compose.yml

version: ‘2’

services:

  node-red:

    container_name: mynodered

    image: nodered/node-red:3.0.2-18

    ports:

      – “1880:1880”

    volumes:

      – ./nodered-data:/data

    restart: unless-stopped

  mariadb:

    image: docker.io/bitnami/mariadb:11.2

    container_name: mariadb

    environment:

      # ALLOW_EMPTY_PASSWORD is recommended only for development.

      – ALLOW_EMPTY_PASSWORD=yes

      #- MARIADB_ROOT_PASSWORD=12345678

      – MARIADB_USER=bn_opencart

        #- MARIADB_PASSWORD=bitnami

      – MARIADB_DATABASE=bitnami_opencart

    ports:

      – “3306:3306”

    volumes:

      # – ./mariadb-data:/bitnami/mariadb

      – ‘mariadb_data:/bitnami/mariadb’

  phpmyadmin:

    image: phpmyadmin/phpmyadmin

    container_name: phpmyadmin

    environment:

      PMA_HOST: mariadb

      PMA_USER: bn_opencart

      #PMA_PASSWORD: 123456

    ports:

      – “8090:80”

    depends_on:

      – mariadb

    restart: unless-stopped

  opencart:

    image: bitnami/opencart:4

    container_name: opencart

    ports:

      – ’80:8080′

      – ‘443:8443’

    environment:

      – OPENCART_HOST=localhost

      – OPENCART_DATABASE_HOST=mariadb

      – OPENCART_DATABASE_PORT_NUMBER=3306

      – OPENCART_DATABASE_USER=bn_opencart

      – OPENCART_DATABASE_NAME=bitnami_opencart

      # ALLOW_EMPTY_PASSWORD is recommended only for development.

      – ALLOW_EMPTY_PASSWORD=yes

      #- OPENCART_DATABASE_PASSWORD=123456

    volumes:

      – ‘opencart_data:/bitnami/opencart’

      – ‘opencart_storage_data:/bitnami/opencart_storage/’

      – ./image:/opt/bitnami/opencart/image/

    depends_on:

      – mariadb

volumes:

  mariadb_data:

    driver: local

  opencart_data:

    driver: local

  opencart_storage_data:

    driver: local

Docker-Compose.yml 段落說明

運行Node-RED

version: ‘2’

services:

  node-red:

    container_name: mynodered

    image: nodered/node-red:3.0.2-18

    ports:

      – “1880:1880”

    volumes:

      – ./nodered-data:/data

    restart: unless-stopped

從遠端Docker Hub下載 nodered/node-red:3.0.2-18 image 到 Docker Host (個人電腦中),再運行 Container 起來. 使用TCP/IP Port 1880. 

運行 mariadb 資料庫

version: ‘2’

services:

  mariadb:

    image: docker.io/bitnami/mariadb:11.2

    container_name: mariadb

    environment:

      # ALLOW_EMPTY_PASSWORD is recommended only for development.

      – ALLOW_EMPTY_PASSWORD=yes

      #- MARIADB_ROOT_PASSWORD=12345678

      – MARIADB_USER=bn_opencart

        #- MARIADB_PASSWORD=bitnami

      – MARIADB_DATABASE=bitnami_opencart

    ports:

      – “3306:3306”

    volumes:

      # – ./mariadb-data:/bitnami/mariadb

      – ‘mariadb_data:/bitnami/mariadb’

從遠端Docker Hub下載 docker.io/bitnami/mariadb:11.2 image 到 Docker Host (個人電腦中),再運行 Container 起來. 使用TCP/IP Port 3306. user: bn_opencart, database: bitnami_opencart

運行 phpmyadmin 資料庫

version: ‘2’

services:

  phpmyadmin:

    image: phpmyadmin/phpmyadmin

    container_name: phpmyadmin

    environment:

      PMA_HOST: mariadb

      PMA_USER: bn_opencart

      #PMA_PASSWORD: 123456

    ports:

      – “8090:80”

    depends_on:

      – mariadb

    restart: unless-stopped

從遠端Docker Hub下載 phpmyadmin/phpmyadmin image 到 Docker Host (個人電腦中),再運行 Container 起來. 使用TCP/IP Port 8090, 連線到mariadb資料庫。

運行 phpmyadmin 資料庫

version: ‘2’

services:

 opencart:

    image: bitnami/opencart:4

    container_name: opencart

    ports:

      – ’80:8080′

      – ‘443:8443’

    environment:

      – OPENCART_HOST=localhost

      – OPENCART_DATABASE_HOST=mariadb

      – OPENCART_DATABASE_PORT_NUMBER=3306

      – OPENCART_DATABASE_USER=bn_opencart

      – OPENCART_DATABASE_NAME=bitnami_opencart

      # ALLOW_EMPTY_PASSWORD is recommended only for development.

      – ALLOW_EMPTY_PASSWORD=yes

      #- OPENCART_DATABASE_PASSWORD=123456

    volumes:

      – ‘opencart_data:/bitnami/opencart’

      – ‘opencart_storage_data:/bitnami/opencart_storage/’

      – ./image:/opt/bitnami/opencart/image/

    depends_on:

      – mariadb

從遠端Docker Hub下載 bitnami/opencart:4 image 到 Docker Host (個人電腦中),再運行 Container 起來. 使用TCP/IP Port 80, 443, 連線到mariadb資料庫。

Node-RED 帳號 http://localhost:1880/

AccountPasswrod
Node-Redadmin123456
Node-Reduser123456
Dashboardpeter123456

phpmyadmin  http://localhost:8090/

opencart  http://localhosthttp://localhost/administration/

分類: Docker, Node-RED | 標籤: , | 發佈留言

Node-RED Modbus

Modbus 的起源:

Modbus 是一種最初由 Modicon 公司於 1979 年開發的通信協議,用於工業控制系統中的數據通信。最初的目的是讓不同品牌的自動化設備能夠互相通信,並且容易地集成到控制系統中。由於其簡單、可靠和廣泛的應用,Modbus 成為了工業領域中最常用的通信協議之一。

Modbus 的實際應用場境及設備:

  1. 工業自動化:Modbus 最常見的應用場境之一是在工業自動化系統中。在工廠設施中,各種自動化設備(如 PLC、傳感器、執行器等)通常使用 Modbus 協議進行通信,從而實現生產過程的監控、控制和數據收集。
  2. 能源管理系統:Modbus 也被廣泛應用於能源管理系統中,用於監控和控制發電廠、能源分配系統、太陽能系統等。透過 Modbus,運營商可以實時監測能源生產和消耗情況,從而進行有效的能源管理和節能措施。
  3. 建築自動化:在大型建築物中,Modbus 通常用於控制 HVAC(暖通空調)、照明系統、安全系統等。通過 Modbus,各種設備可以相互通信並根據需要進行自動調節,從而提高建築的舒適性和節能性。
  4. 遠程監控和控制:Modbus 也被廣泛應用於遠程監控和控制系統中,例如在遠程油氣井監控、水務系統監控、智能農業系統等方面。通過 Modbus,操作員可以遠程監控設備的狀態,並且可以遠程發送控制指令。

總的來說,Modbus 是一種經典且廣泛應用的通信協議,在工業控制和自動化領域中扮演著重要的角色,並且在各種應用場境中都能夠發揮其優勢。

Master vs Slave:

Modbus 是一種工業控制系統中常見的通訊協議,用於在不同裝置之間進行數據傳輸。在 Modbus 通訊中,有兩個主要的角色:Master(主站)和 Slave(從站)。

  1. Master(主站)
    • Master 是控制系統中的主要控制單元,負責發起通訊請求。
    • Master 可以向一個或多個 Slave 裝置發送讀取(Read)或寫入(Write)請求。
    • Master 控制通訊的時序,包括發送請求、接收回應以及處理錯誤等。
  2. Slave(從站)
    • Slave 是控制系統中的被控制單元,被 Master 控制和訪問。
    • Slave 裝置回應 Master 的讀取或寫入請求,並提供所需的數據。
    • 每個 Slave 都有一個唯一的地址,Master 使用該地址來識別和定位特定的從站。

差異

  • 功能:Master 負責控制和調度整個通訊過程,而 Slave 則負責回應 Master 的請求並提供所需的數據。
  • 控制權:Master 擁有主動權,可以隨時發起通訊請求,而 Slave 則被動地回應 Master 的請求。
  • 數量限制:通常一個 Modbus 系統只有一個 Master,但可以有多個 Slave。這是因為 Master 負責控制整個系統的操作,而 Slave 則 passively 等待 Master 的命令。
  • 數據交換:Master 和 Slave 之間通過 Modbus 協議進行數據交換,通常是通過串口(如 RS-232、RS-485)、以太網或其他通訊介質進行連接。

在典型的工業自動化系統中,Master 負責收集各種傳感器和設備的數據,控制執行器的動作,並將數據傳輸到其他系統。而 Slave 裝置則是傳感器、執行器或其他智能設備,負責收集和執行 Master 下發的指令。

電端程式為視覺檢測程式會將工件的檢測結果透過Modbus發送檢測結果給PLC。請問電腦端程式是否為 Mdobus 的Master端,而PLC是否為 Modbus的Slave端?

在這種情況下,電腦端程式是 Modbus 的 Master 端,而 PLC 是 Modbus 的 Slave 端。

這是因為電腦端程式負責發送檢測結果給 PLC,而 PLC 則被動地接收和處理電腦端程式發送的數據。換句話說,電腦端程式具有主動權,它主導通信的發起和控制,因此它是 Master;而 PLC 被動地等待並響應電腦端程式的指令,因此它是 Slave。

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記憶體規劃也取決於具體的應用場景和通信配置。

Modbus 參考網站  https://www.simplymodbus.ca/index.html

Modbus (http://www.simplymodbus.ca/FC01.htm)

兩個表格儲存開/關離散值(線圈),兩個表格儲存數值(暫存器)。線圈和暫存器各有一個只讀表和讀寫表。

每個表有 9999 個值。

每個線圈或觸點都是 1 位,並分配一個 0000 到 270E 之間的資料位址。

每個暫存器為 1 個字 = 16 位元 = 2 個位元組,資料位址在 0000 到 270E 之間。

Coil/Register NumbersData AddressesTypeTable Name
1-99990000 to 270ERead-WriteDiscrete Output Coils
10001-199990000 to 270ERead-OnlyDiscrete Input Contacts
30001-399990000 to 270ERead-OnlyAnalog Input Registers
40001-499990000 to 270ERead-WriteAnalog Output Holding Registers

線圈/暫存器編號可以被視為位置名稱,因為它們不會出現在實際訊息中。資料地址用於訊息中。

例如,第一個保持暫存器(編號為 40001)的資料位址為 0000。這兩個值之間的差值就是偏移量。每個表都有不同的偏移量。 1、10001、30001 和 40001。

Function Code ActionTable NameMemo
01 (01 hex)ReadDiscrete Output CoilsRead Coil Status 
02 (02 hex)ReadDiscrete Input CoilsRead Input Status
03 (03 hex)ReadAnalog Output Holding RegistersRead Holding Registers
04 (04 hex)ReadAnalog Input RegistersRead Input Registers 
05 (05 hex)Write SingleDiscrete Output CoilForce Single Coil 
06 (06 hex)Write SingleAnalog Output Holding RegisterPreset Single Register 
15 (0F hex)Write MultipleDiscrete Output CoilsForce Multiple Coils 
16 (10 hex)Write MultipleAnalog Output Holding RegistersPreset Multiple Registers
Data AddressesReadWrite SingleWrite Multiple
Discrete Output Coils 0xxxxFC01FC05FC15
Discrete Input Contacts 1xxxxFC02NANA
Analog Input Registers 3xxxxFC04NANA
Analog Output Holding Registers 4xxxxFC03FC06FC16

Register 40108 could be defined as any of these 16-bit data types:
    A 16-bit unsigned integer (a whole number between 0 and 65535)
                register 40108 contains AE41 = 44,609 (hex to decimal conversion)

     A 16-bit signed integer (a whole number between -32768 and 32767)
                                                AE41 = -20,927
          (hex to decimal conversion that wraps, if its over 32767 then subtract 65536)

     A two character ASCII string (2 typed letters)
                                                AE41 = ® A

     A discrete on/off value (this works the same as 16-bit integers with a value of 0 or 1.
                                  The hex data would be 0000 or 0001)

Register 40108 could also be combined with 40109 to form any of these 32-bit data types:
    A 32-bit unsigned integer (a number between 0 and 4,294,967,295)
                    40108,40109 = AE41 5652 =  2,923,517,522

     A 32-bit signed integer (a number between -2,147,483,648 and 2,147,483,647)
                                              AE41 5652 = -1,371,449,774

   A 32-bit single precision IEEE floating point number.
  This is a mathematical formula that allows any real number (a number with decimal
  points) to represented by 32 bits with an accuracy of about seven digits.
                                              AE41 5652 = -4.395978 E-11

   Here is a spreadsheet IEEE float calculator for inputs of 4 bytes or 2 words.
  To download a copy, right click and select Save Target As…

     A four character ASCII string (4 typed letters)
                                                AE41 5652 = ® A V R

More registers can be combined to form longer ASCII strings.  Each register being used to store two ASCII characters (two bytes).

Modbus 元件匯入

Modbus Example 匯入

Modbus-Server元件

Modbus-Flex-Write 元件

設定  執行寫入指令 所要連接的  Modebus Server

Modbus-Flex-Getter 元件

設定  執行讀取指令 所要連接的  Modebus Server

練習讀寫數據

Coil/Register NumbersData AddressesTypeTable Name
40001-499990000 to 270ERead-WriteAnalog Output Holding Registers
Data AddressesReadWrite SingleWrite Multiple
Analog Output Holding Registers 4xxxxFC03FC06FC16

從位址0開始,寫入10個數字,數字內容為[1,0,1,0,1,0,1,1,1,1]

從位址0開始,讀取10個Word.

從位址0,寫入數字2345

從位址0,讀取數字

chart

Modbus 

FC6 Write

msg.payload = Math.random() * 100

msg.topic = ‘Power’

msg.payload = { value: msg.payload, ‘fc’: 6, ‘unitid’: 1, ‘address’: 10 , ‘quantity’: 1 };

return msg;

FC3 Read

msg.payload = { input: msg.payload, ‘fc’: 3, ‘unitid’: 1, ‘address’: 10 , ‘quantity’: 1 }

return msg;

var msg1 = {}

msg1.payload = msg.payload.data[0]

msg1.topic = ‘Power’

return msg1

分類: Node-RED | 標籤: , | 發佈留言

Node-RED mariadb setting

資訊庫元件設定

安裝【Manage Pallette】>>【Nodes】>> node-red-node-mysql

查詢待生產的訂單

msg.topic = “select concat(lastname, firstname) as ‘客戶名稱’, order_id as ‘訂單編號’, total as ‘金額’, date_added as ‘下單日期’ from oc_order where order_status_id =1”;

return msg;

var msg1 = {}

msg1.payload = msg.payload

msg1.topic = “select oc_order_product.name as ‘產品名稱’, oc_order_product.quantity as ‘數量’, oc_product_attribute.text as ‘蓋印次數’ \

            from oc_order_product \

            join oc_product_attribute on oc_order_product.product_id = oc_product_attribute.product_id \

            join oc_attribute_description on oc_product_attribute.attribute_id = oc_attribute_description.attribute_id \

            where oc_order_product.order_id = ” + msg.payload[“訂單編號”] + “”

return msg1;

加急

global.set(‘urgent_order_id’, msg.payload[“訂單編號”]);  

msg.topic = “select concat(lastname, firstname) as ‘客戶名稱’, order_id as ‘訂單編號’, total as ‘金額’, date_added as ‘下單日期’ from oc_order where order_status_id =17”;

return msg;

msg.topic = “select concat(lastname, firstname) as ‘客戶名稱’, order_id as ‘訂單編號’, total as ‘金額’, date_added as ‘下單日期’ from oc_order where order_status_id =17”;

return msg;

分類: Node-RED | 標籤: | 發佈留言