ESP32 with MAX485 sending HEX only - Really need help

I have an ESP32 that I would like to use to read MODBUS data from a digital controller via a MAX485.

I am using the Basic example from the ModbusRtu.h library and am receiving data back from the controller. The data received is however not correct. (Checked against the settings on the device as well as via PC)

If I send the following to the controller : 0103039300017463
Address : 01
Function : 03
Read Register : 0393
Num Elements Read : 0001
Checksum : 7463

I expect to receive : 01030202A6395E
Address : 01
Function : 03
Not too sure about this : 02
HEX Value of Register : 02A6
Checksum : 395E

I am receiving : 010301fffd01541c

The address and function values are correct however the rest of the response makes no sense :frowning:

Is there and easier way to send and receive a large number of queries to a MODBUS device by using the HEX sequences directly?

Below is the code I am using

#include <ModbusRtu.h>

uint16_t au16data[16]; //!< data array for modbus network sharing

uint8_t u8state; //!< machine state

uint8_t u8query; //!< pointer to message query

/**

 *  Modbus object declaration

 *  u8id : node id = 0 for master, = 1..247 for slave

 *  port : serial port

 *  u8txenpin : 0 for RS-232 and USB-FTDI 

 *               or any pin number > 1 for RS-485

 */

Modbus master(0,Serial,23); // this is master and RS-232 or USB-FTDI

/**

 * This is an structe which contains a query to an slave device

 */

modbus_t telegram[23];

unsigned long u32wait;

void setup() {

  // telegram 0: read registers

  telegram[0].u8id = 1; // slave address

  telegram[0].u8fct = 3; // function code (this one is registers read)

  telegram[0].u16RegAdd = 393; // start address in slave

  telegram[0].u16CoilsNo = 1; // number of elements (coils or registers) to read

  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino

  // telegram 1: write a single register

  //telegram[1].u8id = 1; // slave address

  //telegram[1].u8fct = 6; // function code (this one is write a single register)

  //telegram[1].u16RegAdd = 4; // start address in slave

  //telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read

  //telegram[1].au16reg = au16data+4; // pointer to a memory array in the Arduino

  Serial.begin( 9600 ); // baud-rate at 9600

  master.start();

  master.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over

  u32wait = millis() + 1000;

  u8state = u8query = 0; 

}

void loop() {

  switch( u8state ) {

  case 0: 

    if (millis() > u32wait) u8state++; // wait state

    break;

  case 1: 

    master.query( telegram[u8query] ); // send query (only once)

    u8state++;

  u8query++;

  if (u8query > 2) u8query = 0;

    break;

  case 2:

    master.poll(); // check incoming messages

    if (master.getState() == COM_IDLE) {

      u8state = 0;

      u32wait = millis() + 1000; 

    }

    break;

  }

  au16data[4] = analogRead( 0 );

  

}

Any help would be appreciated.

Still stuck....

Is your ESP32 a 3V3 system?

I'm not sure if the MAX485 device is rated to work below 5V supply. Maybe someone else can clarify as I may have missed it in the datasheet.

A quick play with the online CRC calculator for Modbus indicates that the checksum in the received message is not correct for the data that is in the message. Assuming that the device you are talking to understood the message, and responded with a valid modbus message, then that may suggest that the MAX485 is struggling if powered from 3V3.

I think that is correct as it is the number of bytes in the data section of the response message.

I may be wrong here, but, if you are the controller device, then as long as you have a pause between messages (>3.5x the time it takes to send a byte at the chosen baud rate - I think!), you can format up your own byte array of address, function, data & CRC and simply send that to a UART for transmission and wait for the reply.

I'm not familiar with the ESP32, so I don't know how many hardware serial ports it has. You may have to use a software serial port implementation.

Have a look at this discussion - and post #16 onwards for some basic code. It's for a different modbus device but shows how to talk to one without using the modbus library.