ESP32 - MAX485 Modbus RTU communication

I need help with my ESP project. I'm trying to read data using a MAX485 module, but apparently, it's not receiving any information from the slave device. I'm not sure if the issue is with the code or the hardware wiring. I’d really appreciate it if someone could check it with me, please!


#define BLYNK_TEMPLATE_ID "TMPL2csTY2CJO"
#define BLYNK_TEMPLATE_NAME "pfehazar"
#define BLYNK_AUTH_TOKEN "HD_q6hRUbTNAOP8Ic-RIyrl6yz2IBIHp" 

#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <ModbusMaster.h>         // Bibliothèque Wi-Fi pour ESP32
#include <HTTPClient.h>        // Bibliothèque pour les requêtes HTTP
#include <Wire.h>              // Bibliothèque pour la communication I2C
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <ModbusRTU.h>

const int pinDE = 5;
const int pinRE = 4;

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

ModbusRTU modbus;     // Objet Modbus maître

#define ID_ESCLAVE { 1 , 2 }

// Fonction de callback pour afficher le résultat des opérations Modbus
bool callback(Modbus::ResultCode code, uint16_t idTransaction, void* donnees) {
    activerReception();  // Mettre DE=0, RE=0 après émission
    Serial.print("Code retour Modbus : ");
    Serial.println(code);
    return true;
}

LiquidCrystal_I2C lcd(0x27, 20, 4); // single LCD at I2C address 0x27

// Paramètres Wi-Fi
char auth[] = "HD_q6hRUbTNAOP8Ic-RIyrl6yz2IBIHp"; // token
char ssid[] = "TOPNETTT";         // Your Wi-Fi SSID
char pass[] = "26011967";                    // Your Wi-Fi password

// Fonction pour envoyer les données via Wi-Fi
void sendToBlynk(float temperature, float humidity, uint16_t freq, uint16_t faultcode, String machineStatus, unsigned long runTime, int Pi,int TRS,int NR, int index) {
  Blynk.virtualWrite(V0 , temperature);       // V0 for VFD1, V10 for VFD2
  Blynk.virtualWrite(V1 , humidity);
  Blynk.virtualWrite(V2 + index * 10, freq);
  Blynk.virtualWrite(V3 + index * 10, faultcode);
  Blynk.virtualWrite(V4 + index * 10, machineStatus);
  Blynk.virtualWrite(V5 + index * 10, runTime);
  Blynk.virtualWrite(V6 , Pi);
  Blynk.virtualWrite(V7 + index * 10, TRS);
  Blynk.virtualWrite(V8 , NR);

}
// Fonction pour activer la transmission
void activerTransmission() {
  digitalWrite(pinDE, HIGH);  // Active la transmission (DE = HIGH)
  digitalWrite(pinRE, HIGH);  // Désactive la réception (RE = HIGH)
}

// Fonction pour désactiver la transmission et activer la réception
void activerReception() {
  digitalWrite(pinDE, LOW);   // Désactive la transmission (DE = LOW)
  digitalWrite(pinRE, LOW);   // Active la réception (RE = LOW)
}
int machineStatusFlag[3] ;
unsigned long startTime[2] ;     // Store the start time for each VFD
unsigned long runTime[2] ;       // Store the accumulated run time for each VFD
bool isRunning[2] ;              // To track whether the machine is running or not
unsigned long Hours[2] ;
unsigned long Minutes[2] ;
float TRS [2] ;

void setup() {
  Serial.begin(115200);  // Initialisation de la liaison série avec le PC
  Serial2.begin(9600, SERIAL_8N1,   16, 17);  // Communication série avec l'esclave
  
  modbus.begin(&Serial2);  // Donne le contrôle du DE/RE à la lib
  modbus.master();  // Ajoute ceci si tu ne l'as pas fait
 
  pinMode(pinDE, OUTPUT);  // Définir les broches en sortie
  pinMode(pinRE, OUTPUT);  // Définir les broches en sortie

  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  } 

  Serial.println("Wi-Fi connected");

  Blynk.config(auth);  // Configure Blynk avec le token
  Serial.println("Connecting to Blynk...");

  while (!Blynk.connected()) {
    Blynk.run();  // Essayer de se connecter à Blynk
    delay(100);
  }
  Serial.println("Connected to Blynk!");



  Wire.begin(21, 22);  // SDA = GPIO21, SCL = GPIO22
  lcd.begin(20,4);
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("VFD 1 : Demarrage");
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0); lcd.print("Freq: ");
  lcd.setCursor(0, 1); lcd.print("Fault: ");
  lcd.setCursor(0, 2); lcd.print("Etat: ");
  lcd.setCursor(0, 3); lcd.print("RunTime: ");

}

void loop() {
  Blynk.run();      // Required for Blynk to work

   // Lire les valeur humidité température 
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

 /*  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  } */

  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print("°C  |  Humidity: ");
  Serial.print(humidity);
  Serial.println("%");

  int VFDADDRESSES[] = ID_ESCLAVE;
  uint16_t frequency[2];   // Stocke la fréquence réelle
  uint16_t faultCode[2];   // Stocke le code de faute
  uint16_t runStop[2];     // Stocke l'état RUN/STOP  

  for (int i = 0; i < 2; i++ ){
    activerTransmission();
    // Lecture du registre 1
    if (!modbus.slave()) {
      Serial.println("active1");
      modbus.readHreg(VFDADDRESSES[i], 1, &frequency[i], 1, callback);
      Serial.println("active2");
      while (modbus.slave()) {
        Serial.println("active3");
        modbus.task();  // This is the correct function to process communication
      }
      Serial.println("active4");
       
      lcd.setCursor(16, 0);
      lcd.print(String(frequency[i])+"   ");
      Serial.print("Frequence VFD " + String(i + 1) + ": " + String(frequency[i]));
    } else {
      Serial.print("Erreur lecture fréquence VFD ");
      Serial.println(i + 1);
     
    }

    delay(100);  // Pause d'une seconde entre chaque lecture

    // Lecture du registre 5
    if (!modbus.slave()) {
      modbus.readHreg(VFDADDRESSES[i], 5, &faultCode[i], 1, callback);

        // Attente de la réponse de l'esclave
      while (modbus.slave()) {
        modbus.task();  // This is the correct function to process communication

      }
        
      lcd.setCursor(13, 1);
      lcd.print("   ");  // 3 espaces pour effacer les anciens chiffres
      lcd.setCursor(13, 1);
      lcd.print(faultCode[i]);
      Serial.print("Faute VFD " + String(i + 1)+ ": " + faultCode[i]);

    } else {
        Serial.print("Erreur lecture code de faute VFD ");
        Serial.println(i + 1);
     
    }

    delay(100);  // Pause d'une seconde entre chaque lecture

    // Lecture du registre 8
    if (!modbus.slave()) {
      modbus.readHreg(VFDADDRESSES[i], 40001, &runStop[i], 1, callback);

        // Attente de la réponse de l'esclave
      while (modbus.slave()) {
        modbus.task();  // This is the correct function to process communication
      }
      uint16_t status= runStop[i] & 0x03;  // Masking to keep only last 2 bits
      if (faultCode[i] != 0) {
        machineStatusFlag[i] = 1;  // Fault
      } else if (status == 0) {
        machineStatusFlag[i] = 2;  // RUN
      } else {
        machineStatusFlag[i] = 3;  // STOP
      }

      lcd.setCursor(13, 2);
      if (machineStatusFlag[i] == 2) {
        lcd.print("RUN   ");
      } else if (machineStatusFlag[i] == 3) {
        lcd.print("STOP ");
      } else {
        lcd.print("Fault");
      }

    // Print status to the serial monitor
      Serial.print("Etat VFD " + String(i + 1) + ": ");
      if (machineStatusFlag[i] == 2) {
        Serial.println("RUN");
      } else if (machineStatusFlag[i] == 3) {
        Serial.println("STOP");
      } else {
        Serial.println("Fault");
      }
        
    } else {
        Serial.print("Erreur lecture état RUN/STOP VFD ");
        Serial.println(i + 1);
    }

    // Handle time accumulation and live display based on the RUN/STOP status
    unsigned long currentTime = millis();

    if (machineStatusFlag[i] == 2) {  // Machine is RUNNING
      if (!isRunning[i]) {
        // Machine just started a new cycle
        isRunning[i] = true;
        startTime[i] = currentTime;
        runTime[i] = 0;  // Reset for a new cycle
      }

    // While running, calculate the current cycle's duration
     unsigned long currentRunTime = currentTime - startTime[i];

    // Convert to hours and minutes
     Hours[i] = currentRunTime / 3600000;
     Minutes[i] = (currentRunTime % 3600000) / 60000;

    // Display on LCD
      lcd.setCursor(12, 3);
      lcd.print(String(Hours[i]) + "H" + String(Minutes[i]) + "M");

    } else if (machineStatusFlag[i] == 3 && isRunning[i]) {
    // Machine just stopped, finalize this cycle's time
    isRunning[i] = false;
    runTime[i] = currentTime - startTime[i];

    Hours[i] = runTime[i] / 3600000;
    Minutes[i] = (runTime[i] % 3600000) / 60000;

    // Display final time on LCD
    lcd.setCursor(12, 3);
    lcd.print(String(Hours[i]) + "H" + String(Minutes[i]) + "M");
    }

    if ((runTime[i] / 60000.0) > 0 && frequency[i] > 0) {
      TRS[i] = (((runTime[i] / 60000.0) / 480.0) * ((1420.0 / 60.0) / (float)frequency[i])) * 100.0;
    } else {
     TRS[i] = 0;
    }

  int Pi = ((1420 * frequency[0]) / 60) * (runTime[0] / 60000.0) * 0.05;
  int NR = Pi/ 120 ; 

  sendToBlynk(temperature, humidity, frequency[i], faultCode[i], (machineStatusFlag[i] == 2 ? "RUN " : (machineStatusFlag[i] == 3 ? "STOP" : "Fault")), (runTime[i] / 3600000.0), Pi,TRS[i],NR, i);
    delay(100);  // Pause d'une seconde entre chaque itération
  }
}

I moved your topic to an appropriate forum category @nieoma.

In the future, when creating a topic please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

May I suggest you to test your RS485 setup without rest of the setup, especially Blynk.
When you have everything working add them there.
Post your hardware details.

1 Like

I tried with this code, and it returned 228 as the Modbus communication code.

#include <ModbusRTU.h>
const int DE_RE_PIN = 15;
ModbusRTU mb;
uint16_t res[2]; 

bool cb(Modbus::ResultCode event, uint16_t, void*) {
  Serial.print("Modbus result: ");
  Serial.println(event);
  return true;
}

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8E1);

  mb.begin(&Serial2,DE_RE_PIN);  
  mb.master();      

  mb.readHreg(1, 5, res, 2, cb);
}

void loop() {
  mb.task();
}

Try with this library:

You find it from IDE library manager.
Also post your wiring and tell what device you are dealing with..