Hi guys!
I am trying to read modbus registers through RS485 adapter.
At the beginning it has been used cheap RS485 adapter (Vcc, RX, TX, GND, no DI/DE terminals), it was correctly working in C:
USB-TTL <=> TTL-RS485 <=> device
so all boards were designed without DI/DE terminals.
Now I can’t get code working to correctly read modbus register.
If I manually write tx buffer (reading from Slave #1, FunctionID 04, reading 1 register from address 0x331A):
0x01 0x04 0x33 0x1A 00 01 1F 49
I can see echo received on RX line during transmission request, then (about 6ms later) I can see data from modbus device.
#include <ModbusMaster.h>
#define RS485_SERIAL Serial2
#define RX_PIN 16
#define TX_PIN 17
#define DE_PIN 4
#define SLAVE_ID 1
#define REG_ADDR 13082
#define NUM_REG 1
ModbusMaster node;
void postTransmission()
{
delay(20); // 20 ms di attesa dopo l'invio del frame
}
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.println("Modbus test...Output:");
RS485_SERIAL.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
}
void loop()
{
// Creiamo il frame manualmente per il log
uint8_t frame[16];
int i, n;
i = 0;
frame[i++] = SLAVE_ID; // Slave ID
frame[i++] = 0x04; // Funzione 03 = read holding registers
frame[i++] = (REG_ADDR >> 8) & 0xFF;// High byte indirizzo
frame[i++] = REG_ADDR & 0xFF; // Low byte indirizzo
frame[i++] = 0x00; // High byte numero registri
frame[i++] = NUM_REG; // Low byte numero registri
uint16_t crc = calcCRC(frame, 6);
frame[i++] = crc & 0xFF; // CRC Low
frame[i++] = (crc >> 8) & 0xFF; // CRC High
// Invia tutto il frame
RS485_SERIAL.write(frame, i); // i contiene il numero di byte scritti
RS485_SERIAL.flush(); // aspetta che tutti i byte siano stati trasmessi
// svuota buffer RX e ignora l'eco ricevuta da trasmettitore RS-485 senza gestione
while (RS485_SERIAL.available())
{
RS485_SERIAL.read();
}
delay(20);
n = RS485_SERIAL.available();
Serial.print("ricevuti ");
Serial.print(n);
Serial.println(" bytes...");
while(n>0)
{
uint8_t b = RS485_SERIAL.read();
if (b < 0x10)
Serial.print("0");
Serial.print(b, HEX);
Serial.print(" ");
n--;
}
Serial.println();
delay(5000);
}
Output:
ricevuti 7 bytes...
01 04 02 04 E9 7A 7E
ricevuti 7 bytes...
01 04 02 04 E9 7A 7E
I installed library:
ModbusMaster v2.0.1 (Doc Walker)
How can I manage echo?
I don’t understand if I have to manage it using DI/DE pins, or if I can manage it via sofrware.
#include <ModbusMaster.h>
#define RS485_SERIAL Serial2
#define RX_PIN 16
#define TX_PIN 17
#define DE_PIN 4
#define SLAVE_ID 1
#define REG_ADDR 13082
#define NUM_REG 1
ModbusMaster node;
void postTransmission() {
delay(20); // 20 ms di attesa dopo l'invio del frame
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("ESP32 Modbus RTU Debug completo frame");
// NO DE_PIN AVAILABLE!!!!!!
//pinMode(DE_PIN, OUTPUT);
//digitalWrite(DE_PIN, LOW);
RS485_SERIAL.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
node.begin(SLAVE_ID, RS485_SERIAL);
//node.postTransmission(postTransmission); // assegna la funzione, questo serve per impostare un ritardo di 20ms dalla trasmissione della richiesta alla lettura del buffer seriale per cercare di evitare l'eco
// ERROR: not available!!!
//node.noReceive(20); // <- questa funzione è disponibile solo in alcuni fork
//node.preTransmission(preTransmission);
//node.postTransmission(postTransmission);
}
void loop()
{
// esempio di trasmissione Modbus RTU
// trasmetto richiesta lettura n° 1 registro
// 0x01 0x04 0x33 0x1A 0x00 0x01 0x1F 0x49
//
// risposta:
// 0x01 0x04 0x02 0x04 0xEC 0xBA 0x7D
// lettura Modbus register
uint8_t result = node.readInputRegisters(REG_ADDR, NUM_REG);
// provo a gestire l'eco
while (RS485_SERIAL.available()) RS485_SERIAL.read();
// aspetta che arrivi la vera risposta
// same result using several delay values: always 0.00 V
//delay(20);
//delay(10);
delay(2);
// ora leggi il risultato
result = node.getResponseBuffer(0);
if (result == node.ku8MBSuccess)
{
// Lettura riuscita, estraggo il valore dal buffer
uint16_t value = node.getResponseBuffer(0); // 0 = primo registro letto
Serial.print("Registro ");
Serial.print(REG_ADDR);
Serial.print(" = ");
Serial.println(value);
// conversione in Volt
Serial.print("Tensione = ");
Serial.print(value * 0.01, 2); // due decimali
Serial.println(" V");
}
else
{
Serial.print("Errore Modbus: ");
Serial.println(result);
}
delay(5000);
}
How echo is correctly managed?
Thanks.