ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于reTerminal DM与Node-RED的工业边缘HMI系统实战部署指南

2026/8/2 11:29:02 拓冰建站 浏览量
基于reTerminal DM与Node-RED的工业边缘HMI系统实战部署指南

1. 项目缘起:当工业边缘计算遇上可视化低代码

最近在折腾一个工厂车间的数据采集与监控项目,客户现场有几台老旧的PLC,通信协议是经典的Modbus TCP,而管理层希望能在车间门口的触摸屏上实时展示产线状态、设备运行参数,甚至能做一些简单的逻辑控制,比如当某个温度传感器超限时自动触发报警灯。这个需求听起来简单,但实操起来有几个痛点:PLC数据需要稳定采集、触摸屏需要友好的可视化界面、中间的逻辑处理要灵活可配置,并且整个系统最好能部署在车间现场一个低功耗、可靠的边缘设备上。

传统的做法可能是写一个C#或Python的采集程序,再搭配一个组态软件或者自己用QT写个界面,开发周期长,后期维护也麻烦。就在我琢磨方案时,一个硬件圈的朋友给我安利了reTerminal DM。这是一款基于树莓派CM4计算模块的工业级HMI(人机界面)设备,自带一块5英寸的触摸屏,接口丰富,支持-20°C到70°C的宽温工作,IP65防护等级,直接扔车间里完全没问题。硬件选型敲定了,软件栈呢?如果还在上面装个完整的桌面环境跑传统软件,总觉得有点“杀鸡用牛刀”,而且资源利用也不够高效。

这时,Node-RED进入了我的视野。它是一个基于Node.js的开源流编程工具,用“连线”的方式就能构建应用,特别适合处理物联网(IoT)数据流。而它庞大的节点库中,正好有node-red-contrib-modbus这个节点,可以轻松连接Modbus TCP设备。一个想法瞬间成型:把reTerminal DM作为硬件载体,运行Node-RED,用它来桥接Modbus TCP设备和前端可视化界面,实现一个一体化的边缘HMI解决方案。这个组合的优势在于,Node-RED的低代码特性极大降低了开发门槛,reTerminal DM的工业设计保证了现场可靠性,而Modbus TCP又是工业领域最通用的协议之一,普适性极强。

接下来,我就把自己从环境搭建、流程设计到实际部署调试的完整过程,以及过程中踩过的坑和总结的经验,详细分享一下。无论你是工业自动化工程师、物联网开发者,还是对边缘计算感兴趣的爱好者,这套方案都值得一试。

2. 核心组件深度解析:为什么是它们三个?

在深入动手之前,我们有必要把这三个核心组件拆开看看,理解它们各自扮演的角色以及组合在一起产生的化学反应。这能帮助我们在后续设计和排错时,心里更有底。

2.1 reTerminal DM:不止于“带屏的树莓派”

reTerminal DM的核心是树莓派Compute Module 4(CM4),这意味着它继承了树莓派庞大的软件生态和社区支持。你可以把它理解为一个“工业强化版”的树莓派。与普通树莓派加个屏幕的方案相比,它的优势非常明显:

  1. 工业级可靠性:宽温设计适应车间冬夏温差,IP65防尘防水能应对粉尘和偶尔的液体溅射,金属外壳和良好的散热设计保障7x24小时稳定运行。这是消费级产品无法比拟的。
  2. 集成化与节省空间:5英寸电容触摸屏、千兆以太网口、RS-485接口(这对Modbus RTU也很有用)、CAN总线接口、USB、GPIO等全部集成在一个紧凑的机身内,无需额外接线和扩展,减少了故障点。
  3. 预装优化的操作系统:官方提供了基于Raspberry Pi OS的定制镜像,对触摸屏、硬件接口做了深度优化,开箱即用,省去了大量驱动调试的时间。

在本次项目中,它承担着“边缘网关”和“人机界面”的双重角色。作为网关,它通过以太网与Modbus TCP设备(PLC)通信;作为HMI,它的屏幕直接运行Node-RED提供的Web可视化界面。

2.2 Node-RED:低代码流编排的核心引擎

Node-RED本质上是一个运行在Node.js环境中的可视化编程工具。它的核心概念是“流”(Flow),由“节点”(Node)通过“连线”(Wire)连接而成。节点可以接收、处理、发送消息。它的强大之处在于:

  • 协议连接器:拥有海量的社区贡献节点,几乎可以连接任何东西,从MQTT、HTTP到Modbus、OPC UA,再到各种数据库和云平台(如AWS IoT, Azure IoT Hub)。node-red-contrib-modbus节点就是专门为Modbus协议设计的。
  • 数据处理与逻辑:内置了函数(Function)节点,可以用JavaScript编写任意处理逻辑;还有切换(Switch)、变更(Change)、延迟(Delay)等节点,能实现复杂的流控制。
  • 可视化与仪表盘node-red-dashboard节点库可以让你通过拖拽,快速创建包含图表、仪表、开关、滑块的控制面板,并自动生成一个Web页面。这正是我们需要的HMI界面。

对于我们的场景,Node-RED完美替代了传统的“采集程序+组态软件”。一个流可以同时完成数据采集(Modbus节点)、逻辑处理(Function节点)和界面展示(Dashboard节点),所有逻辑一目了然,修改起来也极其方便。

2.3 Modbus TCP:工业设备的通用语言

Modbus是一种应用层报文传输协议,位于TCP/IP协议栈之上。它采用主从(Master/Slave)架构,在我们的场景中,Node-RED(通过modbus节点)充当主站(Master),而PLC等设备充当从站(Slave)

理解Modbus TCP,关键要抓住以下几点:

  • 功能码与数据区:主站通过发送包含“功能码”的请求来读写从站的数据。常见功能码如:0x03(读保持寄存器)、0x06(写单个寄存器)、0x10(写多个寄存器)。数据存储在从站的四个不同区域:线圈(Coils)、离散输入(Discrete Inputs)、输入寄存器(Input Registers)、保持寄存器(Holding Registers)。最常用的是保持寄存器,通常用来存储设备的温度、压力、速度等模拟量参数。
  • 地址与映射:这是最容易混淆的地方。Modbus协议中的地址是从0开始的。例如,设备手册上标注的“保持寄存器40001”,在协议报文里使用的地址是0。而很多软件(包括一些PLC编程软件和node-red-contrib-modbus节点)为了兼容习惯,允许你直接输入40001,它在内部会自动做转换。但你必须清楚你用的工具遵循哪种约定,否则读写的地址会完全错误。
  • TCP与RTU的区别:这是网络热词中常被问到的问题。Modbus TCP和RTU是两种不同的传输方式。TCP运行在以太网上,使用标准网络端口(默认502),报文自带MBAP头用于寻址;RTU通常运行在RS-485串行总线上,使用二进制编码,依靠设备地址和报文间隔来区分。TCP更适用于现代网络化车间,布线方便,抗干扰能力强,传输距离远(受网络限制)。reTerminal DM的千兆网口正是为TCP准备的。

理解了这三者的角色,我们的系统架构就清晰了:reTerminal DM作为硬件平台,运行Node-RED服务。Node-RED使用Modbus TCP节点作为主站,主动轮询或读写车间PLC(从站)的数据。然后通过Dashboard节点,将处理后的数据以图表、数值的形式渲染在reTerminal DM的本地浏览器上,形成一个完整的边缘HMI。

3. 实战部署:从零搭建一体化HMI系统

理论清晰后,我们进入实战环节。我会假设你拿到了一台全新的reTerminal DM,带你一步步完成整个系统的搭建。

3.1 reTerminal DM基础系统准备

首先,我们需要为reTerminal DM安装操作系统并进行基础配置。

  1. 烧录系统镜像

    • 前往reTerminal DM的官方Wiki或下载页面,获取最新的预装Raspberry Pi OS的镜像文件(通常是.img格式)。
    • 使用SD卡烧录工具(如Raspberry Pi Imager、BalenaEtcher)将镜像写入一张至少16GB的Micro SD卡中。这里有个关键点:使用Raspberry Pi Imager时,在烧录前可以提前配置主机名、开启SSH、设置Wi-Fi和用户密码,这对于无头(无显示器键盘)启动非常方便。
  2. 首次启动与配置

    • 将烧录好的SD卡插入reTerminal DM,连接网线(或确保Wi-Fi已预先配置好),上电启动。
    • 系统启动后,你可以直接在触摸屏上操作,或者通过SSH远程登录。更推荐后者,因为后续操作多在命令行完成。SSH地址就是你设置的主机名(如reterminaldm.local)或IP地址,用户默认为pi
    • 登录后,首先建议运行sudo raspi-config进行必要设置:
      • 扩展文件系统:确保SD卡所有空间都被利用。
      • 更改密码:修改默认的pi用户密码。
      • 本地化选项:设置时区、区域和键盘布局。
      • 性能选项:酌情分配更多内存给GPU(如果后续需要运行复杂的图形界面),但对我们以Node-RED Web界面为主的应用,默认即可。
    • 最后,执行sudo apt update && sudo apt upgrade -y更新系统到最新状态。

3.2 Node-RED及其关键节点的安装与配置

reTerminal DM的官方镜像可能已经预装了Node.js和Node-RED,但为了确保版本和完整性,我们手动安装一次。

  1. 安装Node.js与Node-RED

    # 安装Node.js(推荐使用NodeSource的版本,比树莓派默认仓库的更新) curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt install -y nodejs # 验证安装 node -v npm -v # 安装Node-RED sudo npm install -g --unsafe-perm node-red

    注意:使用-g参数全局安装。--unsafe-perm参数在树莓派这类环境下有时是必需的,以防权限问题。

  2. 安装必备节点包: 我们需要两个核心节点包:Modbus通讯和Dashboard仪表盘。

    # 进入Node-RED的用户数据目录,通常为~/.node-red cd ~/.node-red # 安装modbus节点 npm install node-red-contrib-modbus # 安装dashboard节点 npm install node-red-dashboard

    安装过程可能需要几分钟。如果遇到网络问题,可以考虑配置npm的国内镜像源。

  3. 配置Node-RED开机自启(作为系统服务): 为了让Node-RED在reTerminal DM开机后自动运行,我们将其设置为systemd服务。

    # 创建服务文件 sudo nano /etc/systemd/system/nodered.service

    将以下内容粘贴进去(注意User=pi要替换为你的用户名):

    [Unit] Description=Node-RED After=syslog.target network.target [Service] ExecStart=/usr/bin/env node-red-pi $NODE_OPTIONS $NODE_RED_OPTIONS # 如果全局安装的node-red命令路径不同,可以用 which node-red 查看 # ExecStart=/usr/local/bin/node-red-pi Restart=on-failure KillSignal=SIGINT SyslogIdentifier=node-red User=pi Group=pi [Install] WantedBy=multi-user.target

    保存退出后,启用并启动服务:

    sudo systemctl daemon-reload sudo systemctl enable nodered.service sudo systemctl start nodered.service # 检查状态 sudo systemctl status nodered.service

    如果状态显示active (running),说明服务已成功启动。默认情况下,Node-RED运行在1880端口。你可以在reTerminal DM本机的浏览器访问http://localhost:1880,或者在同一网络下的其他电脑访问http://<reTerminal DM的IP>:1880,即可看到Node-RED的流编辑器界面。

3.3 构建第一个Modbus TCP数据流

现在,我们打开Node-RED编辑器,开始构建核心的数据流。

  1. 配置Modbus TCP客户端

    • 在左侧节点面板的“网络”分类下,找到“modbus”相关节点。拖拽一个“modbus read”节点到工作区。
    • 双击这个节点进行配置。你需要创建一个新的Modbus客户端。
      • Type:选择TCP
      • Host:填写你的Modbus从站(PLC)的IP地址,例如192.168.1.100
      • Port:默认为502
      • Unit ID:从站设备的单元标识符(Slave ID),通常为1。如果PLC有多个站号,按实际填写。
    • 配置好后,点击“更新”然后“完成”。这个客户端配置可以被多个读写节点共享。
  2. 读取保持寄存器数据

    • 在“modbus read”节点的配置中,设置读取参数:
      • FC:功能码,选择3: Read Holding Registers
      • Address这里需要特别注意!假设我们要读取PLC手册上定义的“温度值1”,地址为40001。在node-red-contrib-modbus节点中,通常直接输入40001即可,节点会自动处理偏移。但为了绝对准确,最好查阅该节点包的文档。我们输入40001
      • Quantity:要读取的寄存器数量。一个寄存器通常是16位(2字节)。如果温度值占用1个寄存器,就填1
      • Poll Rate:轮询频率,例如每2秒读取一次,就填2000ms。
    • 将这个节点的输出连线到一个“debug”节点,并部署流。点击debug节点的标签,在右侧调试窗口查看输出的消息。消息的payload应该是一个数组,包含了读取到的寄存器值。如果看到[0][NaN],或者连接错误,说明地址、从站ID或网络连接可能有问题,这是排查的第一步。
  3. 数据转换与处理: Modbus寄存器读取到的往往是原始整数(INT16, UINT16)或两个寄存器组成的32位浮点数。我们需要将其转换为有意义的工程值。

    • 从左侧面板拖拽一个“function”节点,连接到“modbus read”节点之后。
    • 双击function节点,编写JavaScript代码进行转换。例如,假设PLC中40001地址存储的温度值,实际是放大10倍的整数(即125表示12.5°C),且数据类型为INT16(有符号)。
    // msg.payload 是包含一个元素的数组,如 [125] var rawValue = msg.payload[0]; // 处理有符号整数(INT16),如果最高位是1,则为负数 if (rawValue & 0x8000) { rawValue = rawValue - 0x10000; } // 转换为实际工程值(假设放大了10倍) var realValue = rawValue / 10.0; // 将结果赋值回msg.payload,供后续节点使用 msg.payload = realValue; // 也可以添加一个属性,比如 msg.topic = "temperature1"; return msg;
    • 部署后,再次查看debug输出,应该能看到转换后的浮点数(如12.5)。

3.4 创建Dashboard可视化界面

数据已经能正确读取和转换了,现在把它展示到屏幕上。

  1. 安装并配置Dashboard

    • 确保node-red-dashboard已安装。安装后,左侧节点面板会出现一个“dashboard”分类。
    • 首先,拖拽一个“dashboard”节点(通常是ui_tabui_group)来组织你的界面布局。你可以创建多个标签页(Tab)和分组(Group)来分类显示不同设备或参数。
  2. 添加显示控件

    • 将处理完数据的function节点的输出,连线到一个“gauge”(仪表)节点或“chart”(图表)节点。
    • 配置gauge节点:
      • Group:选择你之前创建的分组。
      • Label:设置为“温度1”。
      • Units:设置为“°C”。
      • Range:根据你的实际值设置,例如0100
    • 同样,你也可以添加“text”节点来显示数值,“button”节点来发送写命令控制PLC。
  3. 访问Dashboard UI

    • 部署整个流。
    • Node-RED Dashboard提供了一个独立的UI地址,默认在1880端口下的/ui路径。在reTerminal DM本机浏览器中访问http://localhost:1880/ui,你就能看到刚刚创建的仪表盘了。
    • 一个优化技巧:为了让reTerminal DM开机后自动全屏显示这个界面,你可以将Chromium浏览器设置为开机启动并全屏打开该URL。编辑自动启动脚本(如~/.config/lxsession/LXDE-pi/autostart),添加一行:
      @chromium-browser --kiosk --incognito http://localhost:1880/ui
      这样,reTerminal DM启动后就会直接进入全屏的监控界面,完全就是一个定制的工业HMI。

4. 进阶配置与深度避坑指南

基础流程跑通只是第一步,要让系统稳定可靠地运行在工业环境,还需要考虑很多细节。下面是我在实际项目中总结的进阶要点和常见坑位。

4.1 Modbus地址映射的“陷阱”与标准化实践

地址问题是Modbus通讯中最常见的错误来源。不同厂商、不同软件对地址的诠释可能不同。

  • “基地址”差异:有些系统认为寄存器40001的地址是0(协议地址),有些则认为就是40001(逻辑地址)。node-red-contrib-modbus节点通常支持直接输入40001,这很方便,但你必须确认你的PLC编程软件或手册使用的是同一套约定。最稳妥的方法是进行小范围测试:先尝试读取一个你知道确切值的寄存器(比如一个设置为0的寄存器),分别用400010去试。
  • 数据类型与字节序
    • 32位浮点数:一个浮点数占用两个连续的16位寄存器。这里涉及字节序(Endian)和字序(Word Order)问题。常见的有“ABCD”(大端序)、“CDAB”(小端序,也称为“字节交换”)、“BADC”(字交换)等。如果读取两个寄存器后转换出的浮点数毫无意义,大概率是字节/字序不对。Function节点中的Buffer对象可以帮助你进行灵活的字节操作。
    • 有符号与无符号:16位整数,需明确是INT16(有符号,范围-32768~32767)还是UINT16(无符号,0~65535)。上文Function节点中的位运算就是处理INT16的方法。
  • 我的标准化建议
    1. 在Node-RED中,为每个数据点建立一个清晰的命名规范。例如,使用msg.topic = "PLC1.Temperature.Tank1"
    2. 将地址、数据类型、转换系数(如放大10倍)、字节序等信息,统一记录在一个JSON配置节点或一个独立的Function节点中,而不是散落在各个Modbus节点里。这样便于管理和修改。

4.2 Node-RED流的稳定性与性能优化

工业现场要求系统长期稳定运行,Node-RED流的设计需要格外注意。

  • 错误处理:Modbus通讯可能因网络抖动、设备忙而失败。node-red-contrib-modbus节点在发生错误时,通常会输出一个包含错误信息的msg。你应该使用“catch”节点来捕获流中任何节点抛出的错误,并将其记录到文件或发送报警通知(例如通过邮件节点或MQTT节点)。不要让错误悄无声息地失败。
    // 在catch节点的function中,可以记录错误 node.error("Modbus读取失败: " + msg.error.message, msg); // 可以在这里将错误信息通过另一个流发送给管理员
  • 避免阻塞:Node-RED是单线程的。如果在Function节点中执行非常耗时的同步操作(如复杂的循环计算、同步文件读写),会阻塞整个事件循环,导致其他流处理延迟。对于耗时操作,应将其异步化,或使用“delay”节点分散压力,甚至考虑拆分成多个子流。
  • 内存管理:长期运行后,注意监控reTerminal DM的内存使用情况(使用free -h命令)。如果流非常复杂,消息对象很大,可能会积累内存。确保流中的消息在不需要后被正确释放(JavaScript的垃圾回收会处理,但要避免全局变量持续引用大对象)。

4.3 reTerminal DM作为生产环境设备的加固措施

将树莓派衍生品用于工业环境,需要做一些加固。

  • 只读文件系统:为了防止突然断电导致SD卡文件系统损坏,可以将根文件系统挂载为只读。但这会使得日志写入、Node-RED节点安装等操作变得复杂。一个折中的方案是,将频繁写的目录(如/var/log,/tmp,~/.node-red中的logs目录)通过tmpfs挂载到内存中,或者符号链接到外部USB存储设备上。
  • 看门狗与自恢复:虽然我们设置了Node-RED为系统服务并自动重启,但还可以启用Linux内核的硬件看门狗(如果硬件支持),并在上层编写一个简单的监控脚本,定期检查Node-RED的Web接口是否存活,如果无响应则强制重启服务。
  • 网络与电源:为reTerminal DM配置静态IP地址,避免因DHCP问题失联。使用优质的工业电源适配器,避免电压波动导致设备重启。如果条件允许,为其配备UPS(不间断电源)。

4.4 从调试到部署:工作流的平滑过渡

在开发阶段,我们频繁地在Node-RED编辑器中修改和部署流。但在生产环境,我们需要一个更稳定、可版本管理的工作流。

  • 项目文件管理:Node-RED的流定义保存在~/.node-red目录下的flows.json文件(或其他你命名的文件)中。定期备份这个文件!你可以使用Git对这个目录进行版本控制,方便回滚和协作。
  • 环境变量:不要在流中硬编码IP地址、端口、密码等敏感信息。使用Node-RED的环境变量功能。你可以在settings.js文件中定义全局变量,或者在流的“环境”标签页中设置。在节点配置中,使用{{env_var_name}}的形式来引用。这样,同一套流可以轻松部署到测试和生产环境,只需改变环境变量即可。
  • “生产”模式部署:当你完成开发并测试无误后,可以在Node-RED的设置中(settings.js)启用“只读”模式,禁用编辑器前端,只保留/ui仪表盘可访问。这样既能防止误操作,也能提高安全性。

通过以上这些步骤和注意事项,reTerminal DM + Node-RED + Modbus TCP的组合就从一个小巧的原型,转变为一个能够胜任实际工业场景的、稳定可靠的边缘HMI解决方案。这个方案的魅力在于其极高的灵活性和可扩展性——未来如果需要接入MQTT上报云平台,或者增加一个SQLite数据库记录历史数据,只需要在Node-RED中拖拽几个新节点并连线即可,无需重写任何底层代码。