組態(tài)王通過Modbus TCP與ESP32通訊
組態(tài)王
組態(tài)王在工控領(lǐng)域被廣泛應(yīng)用。作為人機(jī)界面可以開發(fā)多種應(yīng)用。與ESP8266通過無線網(wǎng)通訊沒有太多的文章介紹,這里介紹通過使用modbus TCP協(xié)議實(shí)現(xiàn)數(shù)據(jù)上傳和命令下發(fā)。
組態(tài)王的通訊設(shè)置
組態(tài)王可以通過板卡或串口來建立一個(gè)通訊路徑。
這個(gè)畫面中,選擇設(shè)備-新建出現(xiàn)新建設(shè)備畫面。
選擇莫迪康(Modicon)作為生產(chǎn)廠家,就是我們要通訊設(shè)備的生產(chǎn)廠家(大名鼎鼎的Modicon,以前也叫過歌德,中國的煉鋼廠當(dāng)時(shí)用得都是這個(gè)廠家得PLC)。通訊協(xié)議選擇是ModbusTCP。這個(gè)協(xié)議是在Modbus串口通訊協(xié)議發(fā)展而來得。
給這個(gè)設(shè)備起一個(gè)名稱。這個(gè)是可以隨意取。
這里要選擇一個(gè)串口,因?yàn)樵诔绦蛑幸獎(jiǎng)?chuàng)建Socket,不知道為啥非要選串口。選一個(gè)不能用到得串口,我選擇了COM21。
在這里需要注意,上面設(shè)置是按如下得格式設(shè)置得:
192.168.4.81 是要通訊的主機(jī)(Server)的IP地址。
:6600 是通訊服務(wù)器的端口號
5 是ModbusTCP的地址
/50 是超時(shí)時(shí)間
后面就是一路確定到:
組態(tài)王變量設(shè)置
Modbus的通訊可以是離散量輸入,離散量輸出,模擬量輸入和模擬量輸出。離散量是一個(gè)位,用modbus就是10001或者00001,10001表示輸入,即數(shù)字輸入點(diǎn),00001表示輸出,即數(shù)字量輸出點(diǎn)。模擬量輸入采用30001,十六位的輸入,模擬量輸出是40001,16位數(shù)字表示一個(gè)輸出值。在這里我們設(shè)置一個(gè)16位寄存器值,40101.
這里選擇的連接設(shè)備時(shí)WTGSimuPLC。寄存器是40101. 數(shù)據(jù)類型是無符號整數(shù)。通訊頻率為1000ms。有了這個(gè)變量可以在圖形中做可視化就可以讀取這個(gè)變量值了。
變量顯示
在畫面中展示做一個(gè)數(shù)字,然后和變量進(jìn)行連接就可以實(shí)現(xiàn)這個(gè)變量的顯示了。
動(dòng)畫連接,選擇模擬量輸出:
在畫面上可以展示這個(gè)輸出了。
ESP8266編程
需要在ESP8266中編程,我還是選擇了Arduino IDE進(jìn)行編程。方法是當(dāng)接受到信息時(shí),接受這些信息,檢查信息是否是發(fā)送給自己的,如果是的話,接受信息,然后按規(guī)約的要求發(fā)送信息到發(fā)送方。在編制程序時(shí)不需要添加一些頭文件。
#include <ESP8266WiFi.h> #include <WiFiClient.h> WiFiClient client; IPAddress loIP(192, 168, 4, 61); IPAddress snIP(255, 255, 255, 0); IPAddress gwIP(192, 168, 4, 1); IPAddress mbTCP(192, 168, 4, 51); WiFiServer server(6600); // 服務(wù)器,server void wifiSetup() { if (!WiFi.config(loIP, gwIP, snIP)) { Serial.println("Satation配置不成功"); delay(3000); } WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); } void sMBTCP(uint8_t* buff, int16_t iLength) { int iTemp; int rAdd; if ( bDebug ) { Serial.println("The length = " + String(iLength)); for(int i = 0; i < iLength; i++) Serial.printf("The buff[%d] = 0x%02X\n", i, (uint8_t)buff[i]); } if (buff[6] != 0x05) // modbus TCP address return; switch ( buff[7] ) { case 3: // read hold register rAdd = (buff[8] << 8) + buff[9]; // register address if ( bDebug4 ) { Serial.println("The rAdd = " + String(rAdd)); } buff[5] = ((buff[10] << 8) + buff[11]) * 2 + 3; // reply bytes buff[8] = ((buff[10] << 8) + buff[11]) * 2; iTemp = 9 + buff[8]; // total bytes send if ( rAdd == 0) { for (int i = 0; i < buff[8]/2; i++) { buff[9 + (i * 2)] = hreg40001[i] >> 8; buff[10 + (i * 2)] = hreg40001[i]; } } if ( bDebug ) { for ( int i = 0; i < iTemp; i++) { Serial.printf("buff[%d] = 0x%02X\n", i, (uint8_t)buff[i]); } } client.write(buff, iTemp); break; case 6: break; case 16: break; default: break; } if ( bDebug ) { for (int i = 0; i < iTemp; i++) Serial.printf("The buff[%d] = 0x%02X\n", i, (uint8_t)buff[i]); } } void setup() { Serial.begin(115200); // 調(diào)試助手 delay(1000); // pasue 1 second wifiSetup(); // setup wifi hot AP server.begin(); // 服務(wù)器運(yùn)行 } void loop() { if (server.hasClient()) // 這個(gè)是當(dāng)有新的client與Server連接時(shí) { client = server.available(); Serial.println("client connected"); } if ( client && client.connected()) { int i = 0; while (client.available()) { char c = client.read(); if (client.available() == 0) mbLength = i + 1; mdTCPbuff[i] = c; i++; } if ( i > 0 ) { sMBTCP(mdTCPbuff, i); } } }
上面的程序可以完成modbusTCP通訊了。場景是固定的IP地址,發(fā)送讀取命令,然后應(yīng)答讀取。
總結(jié)
用組態(tài)王做一個(gè)人機(jī)界面在工控領(lǐng)域比較流行。ESP8266可以通過Wifi作為一個(gè)服務(wù)器為HMI提供服務(wù)。