RS485 Modbus 通讯

RS485 Modbus Commmunication

我一直在尝试通过 Modbus 通信使用 Arduino 从我的电表获取电气参数。但是我的代码无法从电表中获取数据。在这段代码中,我试图从寄存器地址为 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 或者 0x01 (Illegal Function) 取决于仪表的固件。也许你应该仔细检查波特率。

您可能还需要在设置循环中将节点 ID 设置为 0xAA

node.begin(170, Serial);

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

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

aa 03 0001 003C 0DC0

貌似aa是从机地址,03是上面讨论的功能码,003C是要读取的寄存器个数(60个读取所有数据仪表一次)。最后两个字节 0DC0 应该是 CRC。

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

result = node.readHoldingRegisters(11,2);

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