Pada pengembangan sistem dengan komunikasi Modbus RTU dengan RS485, kadang-kadang kita perlu memonitor pertukaran data di kabel RS-485 untuk memantau apakah komunikasi data berjalan dengan benar. Pada artikel ini diuraikan secara ringkas pembuatan perangkat untuk memantau dan merekam trafik data di komunikasi RS-485 tersebut.
Berikut ini skema rangkaiannya secara sederhana
Penjelasan cara kerja rangkaian
Komponen utama sistem adalah sebagai berikut
- MAX485 berfungsi untuk mengubah level tegangan RS-485 menjadi TTL 5 volt.
- Level converter berfungsi mengubah tegangan TTL 5 volt dari MAX485 menjadi TTL dengan tegangan 3 volt.
- Mikrokontroler ESP32 berfungsi merekam data serial dan mengirimnya menggunakan kabel USB ke komputer.
- Komputer untuk merekam data serial dari ESP32
- Power supply 5 volt untuk MAX485
Berikut ini foto rangkaian dengan breadboard
Alat untuk merekam sinyal Modbus RTU di RS485 dengan mikrokontroler ESP32
#esp32-freertos-rs485-analyzer
/**
analisis data RS485
*/
#define LED_BUILTIN 22
#define RXD1 17
#define TXD1 5
#define RXD2 18
#define TXD2 23
void setup() {
Serial.begin(115200);
Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
Serial.println("Serial Txd 0 is on pin: " + String(TX));
Serial.println("Serial Rxd 0 is on pin: " + String(RX));
Serial.println("Serial Txd 1 is on pin: " + String(TXD1));
Serial.println("Serial Rxd 1 is on pin: " + String(RXD1));
Serial.println("Serial Txd 2 is on pin: " + String(TXD2));
Serial.println("Serial Rxd 2 is on pin: " + String(RXD2));
pinMode(LED_BUILTIN, OUTPUT);
if (1)
xTaskCreate(
TaskBlinker, /* Task function. */
"TaskBlinker", /* String with name of task. */
1000, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the task */
1, /* Priority of the task. */
NULL); /* Task handle. */
xTaskCreate(
TaskSerial1, /* Task function. */
"TaskSerial1", /* String with name of task. */
2000, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the task */
1, /* Priority of the task. */
NULL); /* Task handle. */
}
// the loop function runs over and over again forever
void loop() {
delay(10000);
}
void TaskBlinker(void *parameter) {
int counter = 0;
TickType_t xLastWakeTime;
const TickType_t xPeriod = 500 ;
xLastWakeTime = xTaskGetTickCount();
// dht.begin(); // aktifkan sensor DHT22
while (1) {
digitalWrite(LED_BUILTIN, HIGH);
vTaskDelayUntil(&xLastWakeTime, xPeriod);
digitalWrite(LED_BUILTIN, LOW);
vTaskDelayUntil(&xLastWakeTime, xPeriod);
// Serial.print("Counter:");
// Serial.println(counter);
counter++;
}
}
#define BUFFER_MAX 200
void TaskSerial1(void *parameter) {
int interframe_timer_max = 0;
int interframe_timer = 0; // untuk mengukur waktu antar frame
char buffer_data[BUFFER_MAX];
int buffer_idx = 0;
TickType_t xLastWakeTime;
const TickType_t xPeriod = 1 ;
xLastWakeTime = xTaskGetTickCount();
while (1) {
int incomingByte;
if (Serial1.available() > 0) {
interframe_timer = 0;
} else {
interframe_timer++;
}
while (Serial1.available() > 0) {
// read the incoming byte:
incomingByte = Serial1.read();
buffer_data[buffer_idx] = incomingByte ;
buffer_idx++;
if (buffer_idx > BUFFER_MAX) {
buffer_idx = BUFFER_MAX; // buffer overflow protection
}
}
//Serial.print(incomingByte, HEX);
//Serial.print(" ");
if (interframe_timer > interframe_timer_max) {
interframe_timer_max = interframe_timer;
Serial.print("interframe_max ");
Serial.println(interframe_timer_max);
}
if (interframe_timer > 6 && buffer_idx > 0) {
// cetak semua data di buffer
for (int i = 0; i < buffer_idx; i++) {
Serial.print(buffer_data[i], HEX);
Serial.print(" ");
}
Serial.println();
buffer_idx = 0; // empty buffer
}
vTaskDelayUntil(&xLastWakeTime, xPeriod);
}
}