bertmelis / esp32ModbusRTU

modbus RTU client for ESP32
MIT License
70 stars 44 forks source link

error: 0xe0 #44

Closed EmanueleFeola closed 3 years ago

EmanueleFeola commented 3 years ago

Hi, first of all thank you for your useful library. I have encountered this error but I can't understand what it means. error: 0xe0 fc 0x00 address 0x103a

The command that triggers it is: modbus.readHoldingRegisters(SLAVE_ID, STATUS_ADDR, 1);

This command is executed many times before the error is thrown, so for example I can read the status code of the system 100 times and then the error is thrown.

Can anyone please give me an advice on how to tackle this problem? Maybe too many requests in too little time? Thank you in advance

bertmelis commented 3 years ago

It's a timeout. The esp didn't get a response back in time.

Does it recover? Or does the error stay?

EmanueleFeola commented 3 years ago

After the error the ESP32 stop receiving data from the system, like the communication has been terminated. This is a log example: the numbers displayed are the values of the counter that is incremented each time.

10:35:05.200 -> id 0x08; fc 0x03; address 0x103a; len 2: 0x 00 03 STATUS: 0x0003 10:35:05.267 -> 561 10:35:05.301 -> id 0x08; fc 0x10; address 0x27d; len 2: 0x 7d 00 10:35:05.301 -> id 0x08; fc 0x03; address 0x103a; len 2: 0x 00 03 STATUS: 0x0003 10:35:05.369 -> 562 10:35:05.403 -> id 0x08; fc 0x10; address 0x27d; len 2: 0x 7d 00 10:35:05.471 -> 563 10:35:05.575 -> 564 10:35:05.679 -> 565 10:35:05.782 -> 566 10:35:05.886 -> 567 10:35:05.988 -> 568 . . . 10:35:10.093 -> 609 10:35:10.196 -> 610 10:35:10.264 -> 611 10:35:10.366 -> 612 10:35:10.401 -> error: 0xe0 fc 0x00 address 0x103a 10:35:10.435 -> 10:35:10.435 -> id 0x08; fc 0x10; address 0x27d; len 2: 0x 7d 00 10:35:10.469 -> 613 10:35:10.571 -> 614 10:35:10.676 -> 615 10:35:10.780 -> 616 . . . 10:35:15.281 -> 661 10:35:15.383 -> 662 10:35:15.451 -> error: 0xe0 fc 0x00 address 0x103a 10:35:15.451 -> 10:35:15.486 -> id 0x08; fc 0x10; address 0x27d; len 2: 0x 7d 00 10:35:15.486 -> 663 10:35:15.588 -> 664 10:35:15.692 -> 665

EmanueleFeola commented 3 years ago

This is the arduino code, i have simplified to see if the error still occurs, and it does

include

include "defines.h"

esp32ModbusRTU modbus(&Serial1, MODBUS_RTS);

/ Modbus Watchdog / uint8_t modbusWatchdogCounter = 0;

void setup() { Serial.begin(115200); // Serial output Serial1.begin(MODBUS_BAUDRATE, SERIAL_8E1, MODBUS_RX, MODBUS_TX); // Modbus connection

modbus.onData([](uint8_t serverAddress, esp32Modbus::FunctionCode fc, uint16_t address, uint8_t* data, size_t length) { Serial.printf("id 0x%02x; fc 0x%02x; address 0x%02x; len %u: 0x", serverAddress, fc, address, length); for (size_t i = 0; i < length; ++i) { Serial.printf(" %02x", data[i]); }

switch(address){
  case STATUS_ADDR:
  {
    Serial.printf("\t STATUS: %#06x\n", (data[0] << 8) | data[1]);
    break;
  }

  case FW_VERSION_ADDR:
  {
    Serial.printf("\tFirmware Version: %#06x\n", (data[0] << 8) | data[1]);
    break;
  }

  case RPM_ADDR:
  {
    uint16_t rpm = (data[0] << 8) | data[1];

    if((0x80 & data[0])){
      rpm = ~rpm;
      rpm = rpm + 1;
      Serial.printf("\tRPM: %d\n", (~rpm)+1);
    } else {
      Serial.printf("\tRPM: %d\n", rpm);
    }

    break;
  }

  case SERIAL_NUMBER_ADDR:
  {
    uint16_t low = (data[0] << 8) | data[1];
    uint16_t high = (data[2] << 8) | data[3];

    int serialNumber = (high << 16) | low;
    Serial.printf("\tSerial Number: %d\n", serialNumber);

    break;
  }

  case TEMP_ADDR:
  {
    float temp = ((data[0] << 8) | data[1]) / 10.0;
    Serial.printf("\tTemperature: %.1f\n", temp);
    break;
  }

  case TORQUE_SETPOINT_ADDR:
  {
    Serial.println();

    break;
  }

  case K1_GEAR_SELECTION_ADDR:
  {
    break;
  }

  case K1_REVERSE_ADDR:
  {
    modbus.writeSingleHoldingRegister(SLAVE_ID, TORQUE_SETPOINT_ADDR, 1000);
    modbus.writeSingleHoldingRegister(SLAVE_ID, TORQUE_SETPOINT_ADDR, 0);

    break;
  }

  case POT_ADDR:
  {
    Serial.printf("\tPower On Time: %d\n", (data[0] << 8) | data[1]);
    break;
  }

  case ENABLE_ADDR:
  {
    Serial.printf("\tEnabled\\Disable updated\n");
    break;
  }

  case VOLTAGE_ADDR:
  {
    float voltage = ((data[0] << 8) | data[1]) / 10.0;
    Serial.printf("\tVoltage: %.1f\n", voltage);
    break;
  }

  case DRIVE_SIZE_ADDR:
  {
    float driveSize = ((data[0] << 8) | data[1]) / 10.0;
    Serial.printf("\tDrive Size: %.1f\n", driveSize);
    break;
  }

  case POSITION_ADDR:
  {
    uint16_t position = (data[0] << 8) | data[1];

    if((0x80 & data[0])){
      position = ~position;
      position = position + 1;
      Serial.printf("\tPosition: %d\n", (~position)+1);
    } else {
      Serial.printf("\tPosition: %d\n", position);
    }
    break;
  }

  default:
    Serial.printf("\tHas been updated\n");
}

}); modbus.onError([](esp32Modbus::Error error, esp32Modbus::FunctionCode fc, uint16_t address) { Serial.printf("error: 0x%02x fc 0x%02x address 0x%02x\n\n", static_cast(error), fc, address); }); modbus.begin();

delay(1000);

modbus.writeSingleHoldingRegister(SLAVE_ID, ENABLE_ADDR, 0xFF); modbus.readHoldingRegisters(SLAVE_ID, SERIAL_NUMBER_ADDR, 2); modbus.readHoldingRegisters(SLAVE_ID, FW_VERSION_ADDR, 1); modbus.readHoldingRegisters(SLAVE_ID, VOLTAGE_ADDR, 1); modbus.readHoldingRegisters(SLAVE_ID, POSITION_ADDR, 1); modbus.readHoldingRegisters(SLAVE_ID, POT_ADDR, 1);

// modalita esp, azzera velocita, disattiva cruise e metti in prima modbus.writeSingleHoldingRegister(SLAVE_ID, TORQUE_SETPOINT_ADDR, 0); modbus.writeSingleHoldingRegister(SLAVE_ID, K1_GEAR_SELECTION_ADDR, 1); modbus.writeSingleHoldingRegister(SLAVE_ID, K1_MODE_ACTIVATION_ADDR, 0); modbus.writeSingleHoldingRegister(SLAVE_ID, K1_BRAKE_ON_ADDR, 0); modbus.writeSingleHoldingRegister(SLAVE_ID, K1_REVERSE_ADDR, 0); modbus.writeSingleHoldingRegister(SLAVE_ID, K1_BRAKE_ON_ADDR, 0); }

int counter = 0;

void loop() { modbusWatchdogCounter++;

Serial.println(counter);

counter++;

uint8_t buf[4] = {1, counter % 100, 0, modbusWatchdogCounter}; modbus.writeMultHoldingRegisters(SLAVE_ID, TORQUE_SETPOINT_ADDR, 2, buf); modbus.readHoldingRegisters(SLAVE_ID, STATUS_ADDR, 1);

delay(50); }

EmanueleFeola commented 3 years ago

It's all day that I'm running tests and changing parameters. I have noticed that the error is more likely to be thrown when I perform multiple requests in a small amount of time. I have changed the QUEUE_SIZE and TIMEOUT_MS parameters to 100 and 125. With these values the error is less likely to be thrown, but still it appears "randomly" Do you have any advice to give me please?

EmanueleFeola commented 3 years ago

new update: I have noticed that when the system does not stop after the error, all further requests go into error 0xe0 and they look all the same (besides the address). As shown below, the slave id and the function code are both 0 in the response. May this be the source of the error? (The correct slave id is 8)

error: 0xe0 slaveId: 0 fc 0x00 address 0x27e error: 0xe0 slaveId: 0 fc 0x00 address 0x103a

EmanueleFeola commented 3 years ago

Solved (not related to modbus communication)