一文搞懂物联网Modbus通讯协议
簡介:?一般來說,常見的物聯網通訊協議眾多,如藍牙、Zigbee、WiFi、ModBus、PROFINET、EtherCAT、蜂窩等。而在眾多的物聯網通訊協議中,Modbus是當前非常流行的一種通訊協議。它一種串行通信協議,是Modicon公司于1979年為使用可編程邏輯控制器(PLC)通信而制定的,可以說,它已經成為工業領域通信協議的業界標準。
1 概述
隨著IT技術的快速發展,當前已經步入了智能化時代,其中的物聯網技術將在未來占據越來越重要的地位。根據百度百科的定義,物聯網(Internet of things,簡稱IOT )即“萬物相連的互聯網”,是互聯網基礎上的延伸和擴展的網絡,物聯網將各種信息有機的結合起來,實現任何時間、任何地點,人、機、物的互聯互通。物聯網從技術上來說,很重要的核心是通訊協議,即如何按約定的通訊協議,把機、物和人與互聯網相連接,進行信息通信,以實現對人、機和物的智能化識別、定位、跟蹤、監控和管理的一種網絡。
一般來說,常見的物聯網通訊協議眾多,如藍牙、Zigbee、WiFi、ModBus、PROFINET、EtherCAT、蜂窩等。而在眾多的物聯網通訊協議中,Modbus是當前非常流行的一種通訊協議。它一種串行通信協議,是Modicon公司于1979年為使用可編程邏輯控制器(PLC)通信而制定的,可以說,它已經成為工業領域通信協議的業界標準。其優勢如下:
- 免費無版稅限制
- 容易部署
- 靈活限制少
2 ModBus協議概述
Modbus通訊協議使用請求-應答機制在主(Master)(客戶端Client)和從(Slave)(服務器Server)之間交換信息。Client-Server原理是通信協議的模型,其中一個主設備控制多個從設備。這里需要注意的是:Modbus通訊協議當中的Master對應Client,而Slave對應Server。Modbus通訊協議的官網為www.modbus.org。目前官網組織已經建議將Master-Slave替換為Client-Server。從協議類型上可以分為:Modbus-RTU(ASCII)、Modbus-TCP和Modbus-Plus。本文主要介紹Modbus-RTU(ASCII)的通訊協議原理。標準的Modbus協議物理層接口有RS232、RS422、RS485和以太網接口。
通訊示意圖如下:
? 一般來說,Modbus通信協議原理具備如下的特征:
- 一次只有一個主機(Master)連接到網絡
- 只有主設備(Master)可以啟動通信并向從設備(Slave)發送請求
- 主設備(Master)可以使用其特定地址單獨尋址每個從設備(Slave),也可以使用地址0(廣播)同時尋址所有從設備(Slave)
- 從設備(Slave)只能向主設備(Master)發送回復
- 從設備(Slave)無法啟動與主設備(Master)或其他從設備(Slave)的通信
? ? Modbus協議可使用2種通信模式交換信息:
- 單播模式
- 廣播模式
? ? 不管是請求報文還是答復報文,數據結構如下:
即報文(幀數據)由4部分構成:地址(Slave Number)+功能碼(Function Codes)+數據(Data)+校驗(Check) 。其中的地址代表從設備的ID地址,作為尋址的信息。功能碼表示當前的請求執行具體什么操作,比如讀還是寫。數據代表需要通訊的業務數據,可以根據實際情況來確定。最后一個校驗則是驗證數據是否有誤。其中的功能碼說明如下:
比如功能碼為03代表讀取當前寄存器內一個或多個二進制值,而06代表將二進制值寫入單一寄存器。為了模擬Modbus通訊協議過程,這里可以借助模擬軟件:
- Modbus Poll(Master)
- Modbus Slave
具體的安裝過程這里不再贅述。首先這里需要模擬一個物聯網傳感器設備,這里用Modbus Slave來定義,首先打開此軟件,并定義一個ID為1的設備:
此功能碼為03。另外,設置連接參數,示例界面如下:
下面再用Modbus Poll軟件來模擬主機,來獲取從設備的數據。首先定義一個讀寫報文。
然后再定義一個連接信息:
注意:兩個COM口要使用不同的名稱。
成功建立通訊后,通信的報文格式如下:
Tx代表請求報文,而Rx代表答復報文。
3 ModBus Java實現
下面介紹一下如何用Java來實現一個Modbus TCP通信。這里Java框架采用Spring Boot,首先需要引入Modbus4j庫。Maven依賴庫的pom.xml定義如下:
<dependency><groupId>com.infiniteautomation</groupId><artifactId>modbus4j</artifactId><version>3.0.3</version> </dependency> <dependency><groupId>org.rxtx</groupId><artifactId>rxtx</artifactId><version>2.1.7</version> </dependency>其中的modbus4j庫可能在Maven中無法正常下載,可以手動下載后放于項目中,并添加到項目庫中。如下圖所示:
注意:首次實用串口時,需要進行安裝,否則會報 no rxtxSerial in java.library.path的錯誤。
訪問RXTX for Java 下載對應操作系統的庫文件,解壓后安裝如下指導進行拷貝后安裝。
For a JDK installation: Copy RXTXcomm.jar ---> <JAVA_HOME>\jre\lib\ext Copy rxtxSerial.dll ---> <JAVA_HOME>\jre\bin Copy rxtxParallel.dll ---> <JAVA_HOME>\jre\bin另外,需要注意,這里還需要串口支持,這里可以用虛擬串口軟件來解決。
下面給出Java核心代碼片段。
public static SerialPort open(String portName, Integer baudRate, Integer dataBits,Integer stopBits, Integer parity) {SerialPort result = null;try {CommPortIdentifier identifier = CommPortIdentifier.getPortIdentifier(portName);// 打開端口CommPort commPort = identifier.open(portName, 2000);// 判斷是不是串口if (commPort instanceof SerialPort) {result = (SerialPort) commPort;// 設置串口的參數result.setSerialPortParams(baudRate, dataBits, stopBits, parity);log.info("打開串口{}成功", portName);}else{log.info("{}不是串口", portName);}} catch (Exception e) {log.error("打開串口{}錯誤", portName, e);}return result;}首先需要啟動Modbus RTU Slave程序,核心代碼片段如下:
public static void createRtuSlave(){// 串口是COM3,波特率是9600SerialPortWrapperImpl wrapper = new SerialPortWrapperImpl("COM3", 9600,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, 0, 0);ModbusFactory modbusFactory = new ModbusFactory();創建RTU Slavefinal ModbusSlaveSet slave = modbusFactory.createRtuSlave(wrapper);// 寄存器里可以設置線圈狀態、離散輸入狀態、保持寄存器和輸入寄存器//從站設備ID是1BasicProcessImage processImage = new BasicProcessImage(1);processImage.setInvalidAddressValue(Short.MIN_VALUE);slave.addProcessImage(processImage);// 添加監聽器,監聽slave線圈狀態和保持寄存器的寫入processImage.addListener(new MyProcessImageListener());//設置數據setCoil(processImage);setInput(processImage);setHoldingRegister(processImage);setInputRegister(processImage);// 開啟線程啟動new Thread(() -> {try {slave.start();}catch (ModbusInitException e) {e.printStackTrace();}}).start();}而Modbus RTU Master程序,核心代碼片段如下:
private static void createRtuMaster() throws Exception{//串口是COM4,波特率是9600SerialPortWrapperImpl wrapper = new SerialPortWrapperImpl("COM4", 9600,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, 0, 0);ModbusFactory modbusFactory = new ModbusFactory();//RTU MasterModbusMaster master = modbusFactory.createRtuMaster(wrapper);master.init();// 從站設備ID是1int slaveId = 1;// 讀取保持寄存器readHoldingRegisters(master, slaveId, 0, 3);// 將地址為0的保持寄存器數據修改為0writeRegister(master, slaveId, 0, 0);// 再讀取保持寄存器readHoldingRegisters(master, slaveId, 0, 3);}啟動后輸出如下所示:
//Slave [Thread-1] INFO cn.wu.demo.modbus4j.util.SerialPortUtils - 打開串口COM3成功 保持寄存器地址=0,舊值=8,新值=0 //Master // [main] INFO cn.wu.demo.modbus4j.util.SerialPortUtils - 打開串口COM4成功 讀取保持寄存器=[8, 56, 0] 寫保持寄存器成功 讀取保持寄存器=[0, 56, 0]參考開源項目:GitHub - wu-boy/modbus4j: modbus4j demo
原文鏈接
本文為阿里云原創內容,未經允許不得轉載。?
總結
以上是生活随笔為你收集整理的一文搞懂物联网Modbus通讯协议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HBase读链路分析
- 下一篇: 无接触式智能服务 用“减法”重塑企业前台