Modbus giving crc errors

I am trying to get a simple modbus controller working, but it produces continuous crc errors. Looking at the log it seems like a lot of random data is read all the time.

Some things I have noticed and tried

  • The moment I disconnect the tx pin everything stops.
  • Also if I remove the modbus configuration from the yaml nothing is happening on the uart.
  • The moment I add only the modbus config, the noise starts again on the uart
  • If I load custom firmware on the same device it works perfectly so I know there is nothing wrong with the physical setup and wiring.

I am using an esp32 dev board with a max 485 module. I tried a different board with the same results and also working with custom firmware.

Here is my yaml


uart:
  id: uart_bus
  rx_pin: GPIO17 #GPIO20
  tx_pin: GPIO16 #GPIO21
  baud_rate: 9600
  debug:

modbus:
  flow_control_pin: GPIO32
  id: modbus1
  uart_id: uart_bus
  send_wait_time: 200ms

modbus_controller:
  - id: river_modbus
    address: 0x1   ## address of the Modbus slave device on the bus
    modbus_id: modbus1
    setup_priority: -10
    command_throttle: 100ms

Small snippet of my log files,

19:25:29][W][modbus:108]: Modbus CRC Check failed! 1030!=EA03
[19:25:29][W][modbus:108]: Modbus CRC Check failed! 47F4!=F4F4
[19:25:29][W][modbus:108]: Modbus CRC Check failed! 7577!=F4D0
[19:25:29][W][modbus:108]: Modbus CRC Check failed! 7577!=F0F4
[19:25:29][W][modbus:108]: Modbus CRC Check failed! AD76!=F4D4
[19:25:29][W][modbus:108]: Modbus CRC Check failed! B570!=F4FC
[19:25:29][D][uart_debug:114]: <<< 54:00:00:03:EA:F8:50:54:54:54:50:50:50:50:54:54:02:5A:FA:FE:FA:FA:FC:FC:FC:F0:FC:FE:FC:FC:FC:FC:FC:FC:FC:F4:C0:FC:FC:F4:F4:F4:F4:F0:D0:F4:FC:F4:F4:F4:F4:F4:F4:FC:F4:D4:D0:F4:F4:F4:F4:F4:F4:F4:D4:D4:F4:F4:F4:F0:F4:F4:F4:F4:F4:D4:FC:F4:F4:F4:F4:F4:F4:F4:F4:F4:D4:FC:F0:F4:F4:F4:F4:F4:F4:F4:F4:D0:F4:F4:F4:F4:F4:F0:F4:F4:D4:D4:F4:F4:FC:F4:FC:F4:50:54:54:54:54:55
[19:25:29][W][modbus:108]: Modbus CRC Check failed! F117!=F4F4
[19:25:29][W][modbus:108]: Modbus CRC Check failed! 7671!=F4F4
[19:25:29][W][modbus:108]: Modbus CRC Check failed! BC6E!=F4FC

Can you explain this better.

So instead of using ESPhome and HA. I have a small c program in PIO that uses SoftwareSerial to send the commands including crc, I load this onto the espboard and everything works as expected. I can switch the device(VFD) on and off. I can read registers. But when I load the Esphome firmware with the modbus config it goes crazy without having the mod_controller or any sensors/switches configured.

Here is some part of the code that I think might be of importance

#include <SoftwareSerial.h>

#include "Web.h"

// RS485 setup with ESp32

#define RE 19 // Connect RE terminal with 32 of ESP

#define DE 19 // Connect DE terminal with 33 of ESP

#define byte unsigned char

SoftwareSerial mod(20, 21); // RX=26 , TX =27

void setup()
{
 mod.begin(9600); // modbus configuration
}

Once the crc is appended to a buffer with the command, I set the DE,RE pins high(this use to be 2 different pins but since ESPhome only has one I just connected them together) and write it to mod serial. Set pins low and wait for the response.

Sounds correct. Did you control that you wired to your hardware serial2 pins on the actual board (16,17)?

The code above doesn’t include any modbus requests

Yes I use 16 and 17 on ESP32 and 20,21 on ESP-C3. The code has a webserver as well, I use that to make testing easier, you can enter a command in the browser that will send that over the serial and then display the return result.

But here is the writing and reading to the Serial

yte ModbusData(byte data[], int len, byte out[], bool &success, int &retryCnt)
{

  AddCheckSum(data, len);
  byte i;
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  int cnt = 0;
  if (mod.write(data, len+2) == len+2)
  {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);

    cnt = Read(&mod, out);
    
    Serial.printf("Received(%i) :", cnt);
    success = false; 
    if(cnt >2)
    {
      unsigned int chk = crc_chk_value(out, cnt-2);
      unsigned int* vl = (unsigned int*)&out[cnt-2]; // Suppose to work!!
      unsigned int chkR = out[cnt-1] << 8 |  out[cnt-2]; //Only solution, pointing an int to this buffer yield weird resutls
      success = (chk == chkR);
      Serial.printf("%i - Checksum Calculated: %u, Received: %u, Direct: %u\r\n", success, chk,chkR,*vl);
    }
   }
  if(!success && retryCnt>0)
  {
    Serial.println("Serail CRC failed Retrying...");// on retrycnt: %i. Retrying\r\n", retryCnt);
    retryCnt--;
    return ModbusData(data, len, out, success, retryCnt);
  }
  Serial.println("ModBusDone");
  return cnt;
}

Reading the return

int Read(SoftwareSerial *ser, byte data[], int max = 200, int initTimeout = 100, int betweenTimeout= 100) 
 {
   int cnt = 0;
   unsigned long st = millis();
   unsigned long lr = 0;
   bool hasTimeout = false;
   int fc =-1;
   int lb = -1;
   int tt = -1; 
  
   while(!hasTimeout && cnt< max)
   {
      if(cnt == 0)
      {
        if(millis()-st > initTimeout) 
        {
          hasTimeout = true;
          //Serial.printf("init timeout:%i\r\n", (millis()-st));
        }
      }
      else
      {
        if(millis() - lr > betweenTimeout ) 
        {
          hasTimeout = true;
          //Serial.printf("Between timeout:%i\r\n", (millis()-lr));
        }
      }
      
      if(hasTimeout) break;

      if(ser->available()>0)
      {
        if(fc == -1 )
        {
           fc = millis()-st;
        }
        else
        {
          int tlr = millis() - lr;
          if(tlr> lb) lb = tlr;
        }
        lr = millis();
         
        data[cnt] = ser->read();
        cnt++;
      }
   }
   tt = millis()-st;
   //tt = cnt > 0? lr - st: millis()-st;
   //Serial.printf("cnt: %i, fc: %i, st: %lu, lr: %lu, now:%lu\r\n", cnt,fc,st,lr, millis());
   Serial.printf("Read: Bytes: %i, Initial: %i, Between: %i, Total: %i \r\n", cnt, fc, lb, tt);
         
  return cnt;
 }

Reading the data took me some time to figure out how long to wait, which is clear from above code that I measured almost everything.
But it works well, no libraries used.
Command I will send through in the data parameter will be something like

01 06 20 00 00 01 // Switch on the VFD
01 06 20 00 00 05 // Stop the VFD
01 03 10 00 00 14 // Read all the stats(About 24 registers)

Is this modbus rtu or… ?

If yes, I would read this: slave address 1, read holding regs, first register 10, number of registers 0