RS485 Modbus 通讯

问题描述

我一直在尝试使用 Arduino 通过 Modbus 通信从我的电能表获取电气参数。但是我的代码无法从仪表中获取数据。在这代码中,我试图从寄存器地址为 12 的电能表中获取相电压值。

  #include<ModbusMaster.h>
  #define MAX485_DE      3
  #define MAX485_RE_NEG  2
  ModbusMaster node;

  void preTransmission()
  {
    digitalWrite(MAX485_RE_NEG,1);
    digitalWrite(MAX485_DE,1);
  }

  void postTransmission()
  {
    digitalWrite(MAX485_RE_NEG,0);
    digitalWrite(MAX485_DE,0);
  }

  void setup() {
    pinMode(MAX485_RE_NEG,OUTPUT);
    pinMode(MAX485_DE,OUTPUT);
    // Init in receive mode 
    digitalWrite(MAX485_RE_NEG,0);  
    digitalWrite(MAX485_DE,0);  
  
    Serial.begin(9600);  
    //slave ID 1  
    node.begin(1,Serial);  

    Serial.println("Starting Modbus Transaction:");  
    node.preTransmission(preTransmission);  
    node.postTransmission(postTransmission);  
  }

  void loop() {
    static uint32_t i;
    uint8_t j,result;
    uint16_t data[10];

    i++;

    result = node.readInputRegisters(0x30012,2);

    Serial.println("");
  
    if (result == node.ku8MBSuccess) {
      Serial.print("Success,Received data: ");
      for (j = 0; j < 2; j++) {
        data[j] = node.getResponseBuffer(j);
        Serial.print(data[j],HEX);
        Serial.print(" ");
      }
      Serial.println("");
    } else {
      Serial.print("Failed,Response Code: ");
      Serial.print(result,HEX);
      Serial.println("");
      delay(5000); 
    }
    delay(1000);
  }

解决方法

您使用了错误的 Modbus 功能。您应该使用函数 0x03 readHoldingRegisters(注意页面底部框架开头的 0x03)。

只需更改这一行:

result = node.readInputRegisters(0x30012,2);

到:

result = node.readHoldingRegisters(12,2);

顺便说一句,您的设置肯定有其他问题,因为您得到的错误代码是 0xE2 而您应该得到 0x02 的意思是 Ilegal Data Address 或者 {{1 }} (0x01) 取决于仪表的固件。也许你应该仔细检查一下波特率。

您可能还需要在设置循环中将节点的 ID 设置为 Illegal Function

0xAA

正如上面有人评论的那样。文档不是很好...

如果您查看底部的示例数据命令:

node.begin(170,Serial);

看起来 aa 03 0001 003C 0DC0 是从地址,aa 是上面讨论的功能代码,03 是要读取的寄存器数量(60 从仪表读取所有数据一气呵成)。最后两个字节 003C 应该是 CRC。

如果这是正确的,那么如果您想获得相电压,您应该考虑读取寄存器 11 和 12 而不是 12-13:

0DC0

再说一次,这只是我填补文档空白的最佳猜测。