Node-RED与Modbus

点击链接加入群聊【Node-RED与IoT开发交流】https://jq.qq.com/?_wv=1027&k=5owlJfm
新创立的群,欢迎加入!


微信ID: Van1sh1ngAct

Node-RED Tutorial Home

介绍
Node-RED编程基础
建立你的第一个流
基础节点和流
核心节点


例子:
使用Node-RED搭建一个天气预报面板
基于 SIMATIC IOT2040 的 Node-RED S7 通信


[提醒] 由于技术有限,错误在所难免,如有错误,希望您不吝赐教,指出文章错误。

Modbus

Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。
通俗的讲,Modbus的本质就是通过寄存器、线圈与其它设备交换数据。

Modbus与Modbus TCP 、Modbus RTU、Modbus ASCII

Modbus是一簇协议,包含RTU、TCP、ASCII,Modbus并没有规定物理层。标准的Modicon控制器使用RS232C实现串行的Modbus协议。ASCII与RTU协议规定了信息、数据的结构、命令和应答的方式,采用Master/Slave方式,即Master端发出数据请求信息,Slave端接收到正确信息后就可以发送数据到Master端以响应请求;Master端也可以直接发送信息修改Slave端的数据,实现双向读写。
Modbus协议会对数据数据进行校验,ASCII采用LRC校验,RTU采用16位CRC校验,TCP由于可靠传输无需校验。
这三者的具体实现也有会所不同,TCP与RTU方式差别较小,具体参照详细
总的来说Modbus TCP/RTU/ASCII这三者是Modbus协议的具体实现。最显而易见的就是,TCP通过以太网传输,RTU通过RS232C或RS422/RS485传输。

Modbus功能码

功能码 名词 作用
01 读线圈状态 取得一组逻辑线圈的当前状态(ON/OFF)
02 读取输入状态 取得一组开关输入的当前状态(ON/OFF)
03 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值
04 读取输入寄存器 在一个或多个输入寄存器中取得当前的二进制值
05 强置单线圈 强制一个逻辑线圈的通断状态
06 预置单寄存器 把具体二进制值装入一个保持寄存器
07 读取异常状态 取得8个内部线圈的通断状态,这8个线圈的地址由控制器决定
08 回送诊断检验 把诊断检验报文送从机,以对通信处理进行评估
09 编程 (只用于484) 使主机模拟编程器作用,修改PC从机逻辑
10 控询(只用于484) 可使主机与一台正在执行长程序任务从机通信,探询该从机是够已完成其操作任务,仅在含有功能码9的报文发送后,本功能码才发送
11 读取事件计数 可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时
12 读取通信事件记录 可使主机检索每台从机的Modbus事务处理通信事件记录。如果某项事务处理完成,记录会给出相关错误。
13 编程(184/384/484/584) 可使主机模拟编程器功能修改PC从机逻辑
14 探询(184/384/484/584) 可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能码13的报文发送后,本功能才得发送
15 强置多线圈 强置一串连续逻辑线圈的通断
16 预置多寄存器 把具体的二进制值装入一串连续的保持寄存器
17 报告从机标识 可使主机判断编址从机的类型及该从机运行指示灯的状态
18 (884和Micro84) 可使主机模拟编程功能,修改PC的状态逻辑
19 重置通信链路 发生非可修改错误后,使从机复位于已知状态,可重置顺序字节
20 读取通用参数(584L) 显示拓展存储器文件中的数据信息
21 写入通用参数(584L) 把通用参数写入拓展存储文件,或修改之
22 ~ 64 保留以备用户功能所用 留作用户功能的拓展编码
73 ~ 191 非法功能
120 ~ 121 保留 留作内部使用
128 ~ 255 保留 用于异常应答

注:
常用的为1、2、3、4、15、16. 这6个功能即可实现对下位机数字量、模拟量的读写操作。

Node-RED中的Modbus

Flow

手头没有设备 暂时通过模拟演示
往常编写上位机程序可能需要手工根据数据格式构造数据封包,但目前有多别人造好的轮子装上就可以直接跑,何乐而不为?

安装Modbus节点

安装node-red-contrib-modbus

在Node-RED上模拟Modbus通讯

Modbus Server在本地127.0.0.1:10502以Modbus-TCP的方式模拟了一个Modbus Server。
其它设备可以直接通过Modbus-TCP直接连接该服务器。

Modbus Server

Server

端口尽量不要改动,如要改动要切换到管理员权限。

Modbus Client

Client

端口与Server保持一致,0.0.0.0localhost可以认为是一样的
TypeTCP,Serial,Serial Expert三个可选项。
Modbus TCP选择TCP(本例中使用此选项), Modbus RTU选择Serial(串口, 未尝试).

读操作

本例读取0~9号寄存器中的值
首先通过inject间断触发当前流,达到轮询效果。
function中, 写入如下代码,fc为功能码,unitid为设备ID,address为地址,如读取多个寄存器为起始地址,quantity为数量,读取单个为1.

msg.payload = {
    'fc': 3,
    'unitid': 1,
    'address': 0,
    'quantity': 10
};
return msg;

其次,在function节点后添加Modbus Flex Getter节点,选择上一步添加的Client,该节点有两个输出,1号输出为读取的寄存器的值,可继续进行处理, 2号输出作为响应输入。

写操作

本例中随机生成10个int组成数组,写入0~10号寄存器
大致流程与读操作类似,function有一点不同

msg.payload = {
    'value': msg.payload,
    'fc': 16,
    'unitid': 1,
    'address': 0,
    'quantity': 10
};
return msg;

总体示例,导入的话,要添加Random节点

[{"id":"58a754a5.a3698c","type":"modbus-flex-getter","z":"788c6c48.cf2004","name":"","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"eaee2849.d0bd78","useIOFile":false,"ioFile":"","useIOForPayload":false,"x":465.5,"y":233,"wires":[["51569d6a.edb564"],["4c92ea01.f4acb4"]]},{"id":"f3754a33.823048","type":"modbus-flex-write","z":"788c6c48.cf2004","name":"","showStatusActivities":false,"showErrors":false,"server":"eaee2849.d0bd78","x":815.5,"y":297,"wires":[[],["d9df3e32.64265"]]},{"id":"2c9dfede.6b1562","type":"function","z":"788c6c48.cf2004","name":"fc3 1[0~9]","func":"msg.payload = {\n    'fc': 3,\n    'unitid': 1,\n    'address': 0,\n    'quantity': 10\n};\nreturn msg;","outputs":1,"noerr":0,"x":275.5,"y":233,"wires":[["58a754a5.a3698c"]]},{"id":"d6897fbf.b68c7","type":"inject","z":"788c6c48.cf2004","name":"","topic":"","payload":"","payloadType":"date","repeat":"0.5","crontab":"","once":false,"onceDelay":0.1,"x":110.5,"y":233,"wires":[["2c9dfede.6b1562"]]},{"id":"4c92ea01.f4acb4","type":"modbus-response","z":"788c6c48.cf2004","name":"","registerShowMax":20,"x":695.5,"y":239,"wires":[]},{"id":"1556b7fb.0614d8","type":"random","z":"788c6c48.cf2004","name":"","low":"0","high":"30","inte":"true","property":"payload","x":277.5,"y":299,"wires":[["ae9ce461.982f78"]]},{"id":"45cd92a5.68a16c","type":"function","z":"788c6c48.cf2004","name":"fc16 1[0~9]","func":"msg.payload = {\n    'value': msg.payload,\n    'fc': 16,\n    'unitid': 1,\n    'address': 0,\n    'quantity': 10\n};\nreturn msg;","outputs":1,"noerr":0,"x":607,"y":297,"wires":[["f3754a33.823048"]]},{"id":"ae9ce461.982f78","type":"join","z":"788c6c48.cf2004","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"10","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":425.5,"y":298,"wires":[["45cd92a5.68a16c"]]},{"id":"1c34ff31.4684f1","type":"inject","z":"788c6c48.cf2004","name":"","topic":"","payload":"","payloadType":"date","repeat":"0.1","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":299,"wires":[["1556b7fb.0614d8"]]},{"id":"c9f27f2d.b30f3","type":"inject","z":"788c6c48.cf2004","name":"","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":97.5,"y":152,"wires":[["3317a601.2c860a"]]},{"id":"51569d6a.edb564","type":"debug","z":"788c6c48.cf2004","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":620.5,"y":150,"wires":[]},{"id":"3317a601.2c860a","type":"modbus-server","z":"788c6c48.cf2004","name":"","logEnabled":false,"hostname":"0.0.0.0","serverPort":10502,"responseDelay":100,"delayUnit":"ms","coilsBufferSize":10000,"holdingBufferSize":10000,"inputBufferSize":10000,"discreteBufferSize":10000,"showErrors":false,"x":336.5,"y":150,"wires":[["51569d6a.edb564"],["51569d6a.edb564"],["51569d6a.edb564"],["51569d6a.edb564"]]},{"id":"d9df3e32.64265","type":"modbus-response","z":"788c6c48.cf2004","name":"","registerShowMax":20,"x":1008.5,"y":344,"wires":[]},{"id":"eaee2849.d0bd78","type":"modbus-client","z":"788c6c48.cf2004","name":"","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"tcpHost":"localhost","tcpPort":"10502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectTimeout":2000}]

通过Modbus Slave在局域网模拟Modbus通信

在Modbus Slave中按F3配置连接,使用Modbus TCP/IP, 端口设置为502。


Connection Setup

建立多个 Slave以模拟不同的功能。


Modbus Slave

在Node-RED上配置客户端。
Modbus Client

按下述方式连接。function与上例相同。


Modbus连接

某个时间点,Node-RED上读取的信息如下
Node-RED 数据

Modbus Slave数据如下
Modbus Slave

其中数据是由Node-RED中的Inject节点与Random节点配合随机生成,由此可见以实现Node-RED
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容