# ModBus 持續學習中,如有錯誤歡迎留言賜教 ## 說明 https://home.gamer.com.tw/creationDetail.php?sn=3854794 https://makerpro.cc/author/ryanhu/ https://www.ni.com/zh-tw/innovations/white-papers/14/the-modbus-protocol-in-depth.html https://dotblogs.com.tw/Leo_CodeSpace/2018/12/26/185411 https://www.youtube.com/watch?v=txi2p5_OjKU&feature=emb_title 是一種工業上常用的通訊協定 主要分為3種通訊方式 - ModBus ASCII - ModBus RTU ( remote terminal uint ) - ModBus TCP 其中 ModBus ASCII 是一開始設計出來時使用的編碼方式,現在已經很好人使用了,現在主要是使 ModBus RTU 為大宗,可以搭配 RS-232,RS-422,RS-485使用,ModBus TCP某種意義上可以說是 ModBus RTU 為了能在網路上傳輸訊息的變種,在架構上可以是 點對點 或是主從關係,由使用者做決定 以 RTU 方式所傳出的資料格式 ![](https://i.imgur.com/fQkDTJ8.png) Device Address 是指定要傳輸 Slave 裝置 Function Code 是參照下方的指令表跟記憶體位址選擇要執行的命令 ![](https://i.imgur.com/q3dFWhB.png) ![](https://i.imgur.com/9gN14C0.png) 上圖四種記憶體分別是 - Coils 數位輸出 - Discrete Inputs 數位輸入 - Input Regusters 類比輸入 - Holding Registers 類比輸出 Type prefix 可以當成對其記憶體種類的編號,在使用上依據函式庫要求填上編號 下方為 Function code ![](https://i.imgur.com/87v3f8f.png) 在使用時,須結合兩張表的資訊,選擇函式引數 在傳輸時,ModBus 通常以使用者角度看是以 PDU 為單位做傳送,但在實際傳輸時,會依不同的通訊協定加上不同的標頭跟結尾變成一個應用資料單元 ( Application Data Unit APU )做傳輸,在特殊狀況下可以依需求以人工方式將 ADU 做拆分,但通常其況下這部分會交由函式庫做處理。 ## 比較 https://stackoverflow.com/questions/17081442/python-modbus-library ## 規格書 https://modbus.org/docs/MBConformanceTestSpec_v3.0.pdf https://modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf ## pymodbus ### github https://github.com/riptideio/pymodbus https://pymodbus.readthedocs.io/en/latest/readme.html https://pythonhosted.org/pymodbus/examples/index.html ## 工具 ### modbustool https://www.modbustools.com/download.html ### nmap https://www.raspberrypi.org/documentation/remote-access/ip-address.md ## pyModbus function: - write_coils( start_address, value(true or false), **kwargs(slave address) ) : write a single coil_register ( digital out ) - write_coils( start_address, value(can input array), **kwargs(slave address) ) write multi coil_registers by array ( digital out ) - write_register(start_address, value, **kwargs(slave address) ) write a single holding_register - write_registers(address, values, **kwargs(slave address) ) write multi holding_registers by array - read_coils(start_address, count=1(how many), **kwargs(slave address) ) read coil_registers return a deferred response handle use .bits to show the boolean array - read_holding_registers(start_address, count=1(how many), **kwargs(slave address) ) read holding_registers return a deferred response handle use . registers to show the number array - read_discrete_inputs(address, count=1(how many), **kwargs) read discrete_registers (digital input) use .bits to show the boolean array - close() closes the underlying socket connection