You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP8266通过Modbus/TCP读取EEM-MA370浮点值问题咨询

ESP8266 ModbusIP 正确读取EEM-MA370浮点数方案

你当前读取值异常的核心原因有两点:

  • 单次仅读取了1个16位保持寄存器,而EEM-MA370的U12等瞬时电参量为32位IEEE754格式浮点数,需要占用2个连续的保持寄存器,单寄存器返回值只是浮点数的半段数据,自然会出现60664这类无意义数值。
  • 未处理Modbus设备的字节序(大小端)差异,即便读够2个寄存器,拼接顺序错误也会得到异常结果。

EEM-MA370 HMI瞬时测量值界面

参考拼接代码逻辑说明

那段示例代码的逻辑非常简单:

  • 把第一个16位无符号变量左移16位,移动到32位存储空间的高16位位置
  • 加上第二个16位无符号变量(放在32位存储空间的低16位),组合成完整的32位原始值

注意:这段代码仅演示32位整型的拼接逻辑,不能直接用于浮点数转换,且两个变量的先后顺序完全由从站设备的寄存器字节序决定,没有固定取值。

可直接运行的实现代码

ModbusIP库的readHreg支持指定读取寄存器的数量,不需要手动分两次读单个寄存器。注意该库是异步实现,必须在loop中持续调用mb.task()处理收发帧,不要发完请求立刻转换值。

#include <ModbusIP_ESP8266.h>
#include <stdint.h>

ModbusIP mb;
IPAddress remote(10, 30, 21, 75);
const uint16_t U12_START_REG = 32768; // U12对应的起始保持寄存器地址
uint16_t regBuffer[2]; // 缓存2个连续寄存器的返回值
float u12Val = 0;
unsigned long lastReadTs = 0;
const long READ_INTERVAL = 1000; // 读间隔设为1秒,避免频繁请求堵死总线

// 用共用体做32位原始值到浮点数的转换,避免类型转换的未定义行为
union FloatCast {
  uint32_t raw32Bit;
  float floatResult;
};

void setup() {
  Serial.begin(115200);
  mb.client(); // 初始化Modbus主站模式
}

void loop() {
  mb.task(); // 必须常驻调用,处理ModbusTCP的帧收发

  // 未连接时持续重连
  if (!mb.isConnected(remote)) {
    mb.connect(remote);
    Serial.println("Connecting to EEM-MA370...");
    delay(200);
    return;
  }

  // 定时发起读请求,一次读2个寄存器
  if (millis() - lastReadTs >= READ_INTERVAL) {
    lastReadTs = millis();
    mb.readHreg(remote, U12_START_REG, regBuffer, 2);
  }

  FloatCast converter;
  // EEM-MA370默认采用大端字序:低地址寄存器存32位值的高16位,高地址寄存器存低16位
  converter.raw32Bit = (uint32_t)regBuffer[0] << 16 | regBuffer[1];
  // 如果读出来的值和HMI显示不符,把上面一行换成下面这行,颠倒两个寄存器顺序即可
  // converter.raw32Bit = (uint32_t)regBuffer[1] << 16 | regBuffer[0];
  u12Val = converter.floatResult;

  Serial.print("U12 measurement value: ");
  Serial.println(u12Val, 2); // 打印2位小数

  delay(100);
}

异常排查要点

  • 若返回值仍不符合预期,先通过串口打印regBuffer[0]和regBuffer[1]的16进制值,对照HMI显示的实际值反推字节序:比如HMI显示U12为380V时,对应的IEEE754浮点数16进制为0x43BE0000,如果regBuffer[0]打印为0x43BE、regBuffer[1]为0x0000,就用第一种拼接顺序,反之调换顺序即可。
  • 部分厂商提供的Modbus寄存器地址是协议偏移地址,实际请求时需要偏移1位,如果上述地址读不到正确值,可以把U12_START_REG的值加1或者减1尝试。
  • 不要把读请求的间隔设得太短,EEM-MA370的Modbus网关响应需要时间,建议间隔不小于500ms。

内容的提问来源于stack exchange,提问作者yilopa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:27:25