Problema Timeout en Comunicación RS485 MODBUS RTU entre ESP32 y sensor RK300-06B

Hola, estoy intentando realizar una comunicación RS485 MODBUS RTU entre un ESP32 (maestro) y el sensor de ruido RK300-06B (esclavo). Para esto el maestro le tiene que mandar una secuencia de bytes hexadecimal al esclavo así este responde con el valor del registro del ruido. El problema es que me salta el error "Tiempo de respuesta agotado" y no lo pude solucionar.


Los 4 cables de la izquierda son del sensor: Rojo (alimentación 5V), Negro (GND), Blanco (A) y Amarillo (B).
Los cables de abajo del ESP32 son alimentación: Rojo (3,3V), Verde (5V) y Azul (GND).
El módulo C25B es un conversor RS485 a TTL con el integrado Max485, el cual está: alimentado con 3,3V, conectado al sensor y conectados a la ESP32, DI al Tx (17), RO al Rx (16) y DE y RE (que estan puenteados por abajo) a un GPIO (22).

#include <ModbusMaster.h>
byte direc[] = {0x01,0x03,0x00,0x06,0x00,0x01,064,0x0B};
ModbusMaster node; // Crear una instancia de la clase ModbusMaster
#define DE_RE 22 // Pines del módulo RS485

void preTransmission() {
  digitalWrite(DE_RE, HIGH);
  delay(10);
}

void postTransmission() {
  digitalWrite(DE_RE, LOW);
  delay(10);
}

void setup() {
  pinMode(DE_RE, OUTPUT); // Configurar el pin DE/RE del módulo RS485 como salida
  digitalWrite(DE_RE, LOW); // Inicializar el pin DE/RE en LOW
  
  Serial.begin(9600); // Inicializar la comunicación serial para depuración
  Serial2.begin(9600, SERIAL_8N1, 16, 17);  // Inicializar la comunicación serial para RS485, RX=16, TX=17
  Serial2.setTimeout(3000);
  node.begin(1, Serial2);  // Iniciar la instancia de ModbusMaster, la dirección del esclavo es 1
  node.preTransmission(preTransmission); // Asignar funciones de pre y post transmisión
  node.postTransmission(postTransmission);
  
  delay(2000); // Pequeña demora para asegurarse de que todo esté listo
}

void loop() {
  uint8_t result = node.readHoldingRegisters(0x0006, 1); // Leer un registro (16 bits) comenzando en la dirección 6
  uint16_t data[16];
  delay(30);
  
  if (result == node.ku8MBSuccess) { // Si la comunicación fue exitosa
    Serial.print("Noise Level: ");
    Serial.print(node.getResponseBuffer(0) / 10.00);
    Serial.println(" dB");
    delay(30);
  } else {
    switch(result) {
      case node.ku8MBIllegalFunction: Serial.println("Error: Función ilegal"); break;
      case node.ku8MBIllegalDataAddress: Serial.println("Error: Dirección de datos ilegal"); break;
      case node.ku8MBIllegalDataValue: Serial.println("Error: Valor de datos ilegal"); break;
      case node.ku8MBSlaveDeviceFailure: Serial.println("Error: Falla del dispositivo esclavo"); break;
      case node.ku8MBInvalidSlaveID: Serial.println("Error: ID de esclavo inválido"); break;
      case node.ku8MBInvalidFunction: Serial.println("Error: Función inválida"); break;
      case node.ku8MBResponseTimedOut: Serial.println("Error: Tiempo de respuesta agotado"); break;
      case node.ku8MBInvalidCRC: Serial.println("Error: CRC inválido"); break;
      default: Serial.println("Error desconocido");
    }
  }
  
  delay(1000);  // Esperar un segundo antes del siguiente ciclo
}

Esto no es correcto, la función debe devolver 0 o 1 (no conozco la librería) si la comunicaci'on es correcta, no tiene sentido compararla con result

Entonces, si eso no es correcto, los ejemplos de la librería están mal... :thinking:

Claro, todos los códigos de esta libreria estan así

Claro, el módulo está mal cableado, te falta conectar el pin RE para poner al Max485 en modo recepción y tal vez modificar el código para declarar el pin que uses.

Me faltó aclarar que estan puenteados por debajo del módulo C25B. Ya lo edité.

Claro, no podía ser la solución fácil... :man_facepalming:t2:

1 Like

Creo que falta algo en el código para habilitar el Serial2 del ESP32.
Prueba agregando

#include <HardwareSerial.h>

Probé y sigue igual

Ok, error mío.
Probaste intercambiando A por B, al ser una señal diferencial no se puede arruinar nada.

Es una locura porque 3 segundos ya es mucho pero ¿si le das un mayor timeout? solo para probar.

¿Tienes la hoja de datos del sensor para ver las conexiones?
Yo no encontré nada útil.

Probé y nada



(en este caso es de 5V y RS485)

Me parece que el problema radica en una conversión en los voltajes niveles y altos. El MAX485 es la versión del transceptor de 5V y lo estas alimentando con los 3.3v del ESP32. Existen versiones del max con apellido 3xxx para trabajar con 3.3v.

Habría que alimentar el max con los 5 voltios del esp32 y usar un adaptador de niveles.

1 Like