Modbus 服务器
modbus_server 组件创建一条 RS485 连接,让你的 ESPHome 节点充当 Modbus 服务器,从而允许 ModBUS 客户端从你的 ESPHome 节点读取数据(如传感器值)。
你必须将 Modbus 的 role 属性设置为 server。
你需要一个 RS485 收发器模块:
有关更多细节,请参阅 stackexchange 上的这个 RS485 模块是如何工作的?。
收发器连接到 MCU 的 UART。对于 ESP32,默认将引脚 16 连接到 TXD、引脚 17 连接到 RXD,但也可以使用任何其他引脚。将 3.3V 连接到 VCC,当然还有 GND 连接到 GND。
在总线侧,根据 Modbus 标准,你需要在总线电缆的两端各放置一个 120 欧姆的终端电阻。有些收发器已经将其焊接到板上,而一些从站设备可能通过跳线或 DIP 开关提供。
NOTE
如果你使用的是 ESP8266,串行日志记录可能会导致从 UART 读取出现问题。为获得最佳效果,建议使用硬件串行。如果其他组件在 loop() 中花费大量时间,软件串行可能无法读取所有接收到的数据。
对于硬件串行,只能使用一组有限的引脚。使用 tx_pin: GPIO1 和 rx_pin: GPIO3,或 tx_pin: GPIO15 和 rx_pin: GPIO13。
使用硬件 UART 的缺点是不能再使用串行日志记录,因为串行日志会被发送到 Modbus 设备(们),从而导致错误。
可以通过设置 baud_rate: 0 来禁用串行日志记录。
参见 Logger 了解更多细节。
logger: level: <level> baud_rate: 0-
modbus_id (可选, ID): 手动指定
modbushub 的 ID。 -
address (必选, integer): 服务器设备的 Modbus 地址。
-
courtesy_response (可选): 配置块,用于在设备充当 Modbus 服务器时启用友好响应(courtesy response)功能。
- enabled (可选, boolean): 是否启用友好响应功能。
默认为
false。 - register_last_address (可选, integer): 最高的 Modbus 寄存器地址(含),在该范围内允许读取未定义的寄存器,并将用默认值填充。
任何包含此范围内的未定义寄存器的读取请求都将返回
register_value指定的值,而不是触发异常。 默认为65535。 - register_value (可选, integer): 在
register_last_address定义的地址范围内,为未定义寄存器返回的 16 位值(范围:0–65535)。 默认为0。
- enabled (可选, boolean): 是否启用友好响应功能。
默认为
-
registers (可选): 充当服务器时响应的寄存器列表。
-
address (必选, integer): 一个范围内第一个寄存器的起始地址。
-
value_type (可选): mod_bus 寄存器数据的数据类型。ModBUS 的默认数据类型是 big endian(网络字节序,最高字节在前)格式的 16 位整数。
U_WORD:无符号 16 位整数,1 个寄存器,uint16_tS_WORD:有符号 16 位整数,1 个寄存器,int16_tU_DWORD:无符号 32 位整数,2 个寄存器,uint32_tS_DWORD:有符号 32 位整数,2 个寄存器,int32_tU_DWORD_R:little endian 无符号 32 位整数,2 个寄存器,uint32_tS_DWORD_R:little endian 有符号 32 位整数,2 个寄存器,int32_tU_QWORD:无符号 64 位整数,4 个寄存器,uint64_tS_QWORD:有符号 64 位整数,4 个寄存器,int64_tU_QWORD_R:little endian 无符号 64 位整数,4 个寄存器,uint64_tS_QWORD_R:little endian 有符号 64 位整数,4 个寄存器,int64_tFP32:32 位 IEEE 754 浮点数,2 个寄存器,floatFP32_R:little endian 32 位 IEEE 754 浮点数,2 个寄存器,float
默认为
U_WORD。 -
read_lambda (必选, lambda): 返回此寄存器值的 Lambda。
-
write_lambda (可选, lambda): 设置此寄存器值的 Lambda。系统会提供一个适当类型(
uint16_t、int32_t等,见上文)的变量x作为值, 同时还提供包含此寄存器地址的address变量。如果操作成功,你必须返回true,否则返回false; 返回false时,将向客户端发送 ModBUS 异常码4。 -
allow_partial_read (可选, boolean): 对于多寄存器值类型 (
U_DWORD、S_QWORD、FP32等),允许读取请求仅覆盖 该值的部分范围——从中间开始或在其结束前停止——并且 只返回所请求的寄存器。当为false时,该值被视为 原子的,任何未覆盖整个值的读取都会以ILLEGAL_DATA_ADDRESS异常被拒绝。对单寄存器类型 (U_WORD/S_WORD)没有影响。默认为false。NOTE
即使启用了
allow_partial_read,read_lambda仍然 每个请求计算一次,因此单个请求内返回的寄存器 始终彼此一致。在分开的请求中读取某个值的各个部分 的客户端,可能会观察到值在两次读取之间发生了变化——这是按寄存器逐项访问 Modbus 所固有的特性。此选项仅影响读取。写入始终是原子的:写入必须 覆盖整个值,因为无法为
write_lambda重构部分值。
-
NOTE
每个寄存器条目根据其 value_type 占据多个连续的地址
(*_WORD 占 1 个,*_DWORD/FP32 占 2 个,*_QWORD 占 4 个)。
同一个 modbus_server 内的寄存器地址范围不得重叠,
且必须适合 16 位地址空间(0x0000–0xFFFF);
否则配置将被拒绝。
以下代码允许 ModBUS 客户端从你的 ESPHome 节点读取传感器值,而该节点本身是从某个本地传感器读取的。
uart: - id: uart_modbus_server tx_pin: 25 rx_pin: 35
modbus: - uart_id: uart_modbus_server id: modbus_server role: server
modbus_server: - modbus_id: modbus_server address: 0x4 registers: - address: 0x0002 value_type: U_DWORD_R read_lambda: |- return id(uptime_sens).state;
sensor: - platform: uptime id: uptime_sens