Panduan Lengkap Komunikasi Modbus RS485 ESP32: Wiring, Firmware C++, hingga Web SCADA Dashboard
Bagi Anda yang berprofesi sebagai Automation Engineer, IoT Developer, atau Maintenance Technician di lantai produksi, menguasai komunikasi industri berbasis Modbus RS485 ESP32 adalah sebuah keharusan. Meskipun teknologi transmisi nirkabel terus berkembang, bus fisik serial RS485 tetap menjadi tulang punggung otomasi pabrik karena keandalannya terhadap imunitas electrical noise (akibat VFD atau motor induksi) serta jangkauan kabel yang sanggup mencapai hingga 1.200 meter.
Dalam tutorial teknis hands-on yang disusun oleh tim R&D PT Sayuswa Multi Teknologi ini, kita akan membahas arsitektur lengkap mulai dari anatomi paket data Modbus RTU, skematik pengkabelan modul transceiver MAX485 ke ESP32, teknik konversi floating point IEEE 754, hingga pengiriman telemetri via MQTT ke Web SCADA / Node-RED Dashboard.
1. Memahami Protokol Modbus RTU & Struktur Frame Data
Modbus RTU mentransmisikan data dalam format biner murni (raw binary frame) tanpa karakter pembatas ASCII. Komunikasi berjalan dengan metode Half-Duplex Master-Slave, di mana ESP32 bertindak sebagai Master yang mengirim perintah request, lalu sensor bertindak sebagai Slave yang mengembalikan response.
+-----------------------------------------------------------------------------------+
| ANATOMI FRAME MODBUS RTU |
+---------------+-------------------+----------------------+------------------------+
| Address (1B) | Function Code(1B) | Data Payload (N-Byte)| CRC16 Checksum (2-Byte)|
+---------------+-------------------+----------------------+------------------------+
| Slave ID 0x01 | 0x03 (Read Hold) | Start Register & Qty | Low Byte & High Byte |
+---------------+-------------------+----------------------+------------------------+
Komponen Utama Paket Data Modbus:
-
Slave Address (1 Byte): Alamat node target (nilai 1 hingga 247). Alamat 0 dicadangkan untuk siaran global (broadcast).
-
Function Code (1 Byte): Jenis instruksi kerja:
-
0x03: Read Holding Registers (baca register konfigurasi/data terukur). -
0x04: Read Input Registers (baca data analog read-only). -
0x06: Write Single Register (menulis 1 alamat register). -
0x10(FC16): Write Multiple Registers (menulis beberapa register sekaligus).
-
-
Data Field (N Byte): Berisi parameter alamat register awal (Starting Address) dan kuantitas register (Register Quantity).
-
CRC16 Checksum (2 Byte): Algoritma validasi integritas frame. Jika kalkulasi CRC penerima tidak cocok dengan paket kiriman, data otomatis dibuang (frame error).
2. Algoritma Kalkulasi Manual CRC16 Checksum (C/C++)
Jika Anda sedang membangun driver bare-metal tanpa dependensi library eksternal, implementasikan fungsi standar polinomial Modbus (0xA001) berikut ke dalam firmware mikrokontroler Anda:
// Fungsi Kalkulasi CRC16 Modbus RTU (Polynomial 0xA001)
uint16_t calculate_modbus_crc16(const uint8_t *buffer, uint16_t length) {
uint16_t crc = 0xFFFF;
for (uint16_t pos = 0; pos < length; pos++) {
crc ^= (uint16_t)buffer[pos]; // XOR byte data ke byte rendah CRC
for (int i = 8; i != 0; i--) {
if ((crc & 0x0001) != 0) { // Jika LSB bernilai 1
crc >>= 1;
crc ^= 0xA001; // Polinomial Modbus
} else {
crc >>= 1;
}
}
}
// Nilai CRC16 dihasilkan: Low Byte ditransmisikan lebih dulu
return crc;
}
3. Bill of Materials (BOM) & Kebutuhan Alat
Sebelum merangkai sirkuit, pastikan komponen berikut telah tersedia di meja kerja:
| Komponen Hardware | Spesifikasi Rekomendasi | Fungsi |
| Edge Gateway / MCU | ESP32 DevKit V1 / Sayuswa Smart Controller | Mengolah polling Modbus & gateway data |
| Sensor Slave | Power Meter Listrik (Eastron SDM / PZEM / Selec) | Menyediakan data voltase, arus, dan daya |
| Transceiver Serial | Modul MAX485 atau SP3485 (3.3V kompatibel) | Mengonversi sinyal TTL UART ke diferensial RS485 |
| Resistor Terminator | 120 $\Omega$ Metal Film 1/4 Watt | Mencegah pantulan sinyal (signal reflection) |
| Kabel Transmisi | Shielded Twisted Pair (STP Cat5e / Belden) | Menjaga integritas data dari gangguan EMI |
| Power Supply | Catu Daya Switching 24VDC & 5VDC DIN-Rail | Suplai daya industri untuk sensor & board |
4. Skematik Wiring Fisik RS485: Pinout ESP32 ke MAX485
Karakteristik utama RS485 adalah pensinyalan diferensial dua kawat ($A$ dan $B$). Gunakan kabel Shielded Twisted Pair (STP) di mana lilitan sepasang kawat berfungsi meniadakan interferensi elektromagnetik, dan pasang pelindung (shield) ke sistem Earth Ground.
[ESP32 Gateway] [Modul MAX485 TTL] [Sensor Modbus Slave]
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé 3.3V / 5V Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓû║Γöé VCC Γöé Γöé 24VDC Power Source Γöé
Γöé GND Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓû║Γöé GND Γöé Γöé GND Power Source Γöé
Γöé GPIO16(RX2)Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓû║Γöé RO (Receiver Out)Γöé Γöé Γöé
Γöé GPIO17(TX2)Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓû║Γöé DI (Data In) Γöé Γöé Γöé
Γöé GPIO4 Γö£ΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓû║Γöé DE (Driver En) Γöé Γöé Γöé
Γöé Γöé ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓû║Γöé RE (Read En Bar) Γöé Γöé Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ Γöé ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
Γöé Γöé Γöé
Γöé Γö£ΓöÇΓöÇΓöÇ Terminal A (D+) ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ Terminal A (D+)
Γöé Γöé [R 120 Ohm] Γöé
Γöé ΓööΓöÇΓöÇΓöÇ Terminal B (D-) ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ Terminal B (D-)
Γöé Γöé
Control Direction Ground Shield
Prosedur Penting Pemasangan:
-
Pin Direction Control (DE/RE): Hubungkan pin DE dan pin $\overline{\text{RE}}$ secara paralel ke GPIO4. Logika
HIGHmengaktifkan modul untuk transmisi (Transmit Mode), dan logikaLOWmengubah modul ke mode siap terima (Receive Mode). -
Resistor Terminator: Pasang resistor 120 $\Omega$ secara paralel di terminal A-B pada ujung pertama (gateway) dan ujung akhir jalur fisik (slave terjauh).
5. Peta Register Modbus RTU Slave (Datasheet Sample)
Sensor membaca parameter kelistrikan melalui Holding Register 16-bit atau 32-bit. Berikut adalah konfigurasi umum dari Power Meter:
| Parameter Ukur | Register Address (Hex/Dec) | Function Code | Tipe Data | Standar Satuan |
| Tegangan (Voltage) | 0x0000 (Dec: 0) |
FC03 | 32-bit Float | IEEE 754 (Volt) |
| Arus (Current) | 0x0008 (Dec: 8) |
FC03 | 32-bit Float | IEEE 754 (Ampere) |
| Daya Aktif (Active Power) | 0x0012 (Dec: 18) |
FC03 | 32-bit Float | IEEE 754 (Watt) |
| Frekuensi (Frequency) | 0x0036 (Dec: 54) |
FC03 | 32-bit Float | IEEE 754 (Hz) |
Konfigurasi Default Serial: Slave ID = 1, Baudrate = 9600 bps, Data Bit = 8, Parity = None, Stop Bit = 1 (8N1).
6. Firmware ESP32: FreeRTOS Task & Library ModbusMaster
Untuk mencegah polling Modbus memblokir proses komunikasi Wi-Fi atau MQTT, kita memisahkan eksekusi program ke dalam arsitektur FreeRTOS Dual-Core:
[Core 0 ESP32: Task Modbus Polling (Prioritas Tinggi)] ΓöÇΓöÇΓû║ Polling RS485 tiap 100ms
Γöé
Γû╝
[Core 1 ESP32: Task Telemetri MQTT (Prioritas Standar)] ΓöÇΓöÇΓû║ Publish JSON via Wi-Fi
Pasang pustaka ModbusMaster oleh DocWalker melalui Library Manager di VS Code (PlatformIO) atau Arduino IDE, lalu masukkan kode berikut:
#include <Arduino.h>
#include <ModbusMaster.h>
#define RXD2_PIN 16
#define TXD2_PIN 17
#define MAX485_DE_RE_PIN 4
ModbusMaster node;
// Fungsi Transmit/Receive Control
void preTransmission() {
digitalWrite(MAX485_DE_RE_PIN, HIGH);
}
void postTransmission() {
digitalWrite(MAX485_DE_RE_PIN, LOW);
}
// Konversi 2 Register 16-bit ke 32-bit Float IEEE 754
float registersToFloat(uint16_t reg0, uint16_t reg1) {
uint32_t combined = ((uint32_t)reg0 << 16) | reg1;
float result;
memcpy(&result, &combined, sizeof(result));
return result;
}
// Task Polling Sensor di Core 0
void TaskModbusPolling(void *pvParameters) {
for (;;) {
uint8_t result = node.readHoldingRegisters(0x0000, 2);
if (result == node.ku8MBSuccess) {
uint16_t reg0 = node.getResponseBuffer(0);
uint16_t reg1 = node.getResponseBuffer(1);
float voltage = registersToFloat(reg0, reg1);
Serial.print(">> Pembacaan Sukses! Tegangan Listrik: ");
Serial.print(voltage, 2);
Serial.println(" VAC");
} else {
Serial.print(">> Modbus Error Code: 0x");
Serial.println(result, HEX);
}
vTaskDelay(pdMS_TO_TICKS(2000)); // Delay non-blocking 2 detik
}
}
void setup() {
Serial.begin(115200);
pinMode(MAX485_DE_RE_PIN, OUTPUT);
digitalWrite(MAX485_DE_RE_PIN, LOW);
// Inisialisasi UART2 ESP32
Serial2.begin(9600, SERIAL_8N1, RXD2_PIN, TXD2_PIN);
// Inisialisasi Modbus Master untuk Slave ID 1
node.begin(1, Serial2);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
// Jalankan Task Modbus pada Core 0
xTaskCreatePinnedToCore(
TaskModbusPolling,
"ModbusTask",
4096,
NULL,
2,
NULL,
0
);
}
void loop() {
// Core 1 bebas menangani komunikasi MQTT / HTTP / Web Server
vTaskDelay(pdMS_TO_TICKS(1000));
}
7. Penulisan Register Modbus (Write Function Code 06 & 16)
Selain membaca data (Read Holding Registers), sistem otomasi sering membutuhkan kontrol balik (Write Single/Multiple Registers) untuk menyalakan relay atau mengatur setpoint mesin:
// Menulis Single Register (FC06) ke Alamat Tertentu
bool writeSingleRegister(uint8_t slaveID, uint16_t regAddress, uint16_t regValue) {
node.begin(slaveID, Serial2);
uint8_t result = node.writeSingleRegister(regAddress, regValue);
return (result == node.ku8MBSuccess);
}
// Menulis Data Float 32-bit ke 2 Buah Register (FC16 / 0x10)
bool writeFloatRegister(uint8_t slaveID, uint16_t startReg, float floatValue) {
uint32_t rawBits;
memcpy(&rawBits, &floatValue, sizeof(floatValue));
// Memecah Float 32-bit menjadi 2 Word (16-bit)
uint16_t reg0 = (uint16_t)(rawBits >> 16); // High Word
uint16_t reg1 = (uint16_t)(rawBits & 0xFFFF); // Low Word
node.begin(slaveID, Serial2);
node.setTransmitBuffer(0, reg0);
node.setTransmitBuffer(1, reg1);
uint8_t result = node.writeMultipleRegisters(startReg, 2);
return (result == node.ku8MBSuccess);
}
8. Memahami Byte Swapping & Urutan Endianness Float
Tipe data float 32-bit terdiri dari 4 byte ($B_0, B_1, B_2, B_3$). Karena Modbus bekerja berbasis register 16-bit (2 byte), setiap pabrikan instrumen menerapkan standar susunan byte yang berbeda:
-
Big-Endian (ABCD): Format standar industri internasional (misal: Schneider, Eastron).
-
Little-Endian (DCBA): Pembalikan total susunan byte.
-
Mid-Big Endian (CDAB / Byte Swap): Byte internal register ditukar (contoh: sensor modul PZEM).
-
Mid-Little Endian (BADC / Word Swap): Word 16-bit ditukar posisi.
Tips Engineer: Jika nilai voltase Anda terbaca eksponensial tidak wajar (misal:
1.45e-38), sesuaikan susunan byte pada fungsiregistersToFloatdengan menukar posisireg0danreg1.
9. Skrip Alternatif Modbus RTU pada Python & Industrial PC
Bagi Anda yang menggunakan Industrial PC atau Gateway berbasis Linux (seperti Raspberry Pi), bahasa pemrograman Python menawarkan kemudahan pembacaan register:
Menggunakan Pustaka PyModbus
from pymodbus.client import ModbusSerialClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
client = ModbusSerialClient(
port='/dev/ttyUSB0',
baudrate=9600,
parity='N',
stopbits=1,
bytesize=8,
timeout=1
)
if client.connect():
result = client.read_holding_registers(address=0x0000, count=2, slave=1)
if not result.isError():
decoder = BinaryPayloadDecoder.fromRegisters(
result.registers,
byteorder=Endian.BIG,
wordorder=Endian.BIG
)
voltage = decoder.decode_32bit_float()
print(f"[DATA SUKSES] Tegangan: {voltage:.2f} VAC")
client.close()
10. Integrasi IoT: Pengiriman MQTT & Visualisasi Node-RED
Setelah data parameter listrik diperoleh, gateway membungkus informasi tersebut ke format JSON dan mengirimkannya ke MQTT Broker:
{
"gateway_id": "SAYUSWA-GW-01",
"timestamp": 1726800000,
"telemetry": {
"voltage_vac": 224.75,
"current_amp": 12.30,
"active_power_w": 2764.40,
"frequency_hz": 50.02
}
}
Konfigurasi Flow Node-RED SCADA:
-
Pasang node
mqtt indan arahkan ke topiksayuswa/factory1/power_meter. -
Gunakan node
json parseruntuk mengekstrak atribut payload. -
Hubungkan keluaran parsing ke widget UI Gauge (skala 0ΓÇô300 V) dan Chart untuk melihat tren grafik real-time.
11. Pengukuran Fisik Sinyal Diferensial RS485 dengan Multimeter
Jika komunikasi gagal total dan Anda tidak membawa osiloskop ke lapangan, gunakan Multimeter Digital pada mode DC Voltage untuk memeriksa kondisi bus RS485 saat idle:
-
Ukur Jalur A ke Ground: Kondisi normal saat idle berkisar antara +2.5V hingga +3.3V DC.
-
Ukur Jalur B ke Ground: Kondisi normal saat idle berkisar antara +1.1V hingga +2.2V DC.
-
Ukur Beda Potensial ($V_{A-B} = V_A – V_B$): Beda potensial pin A terhadap pin B wajib bernilai positif antara +0.2V hingga +1.5V DC. Apabila $V_{A-B} < 0.2\text{ V}$, transceiver tidak dapat mengenali logika biner transmisi.
12. Tabel Troubleshooting Error Modbus RS485
| Gejala Error | Kemungkinan Penyebab | Langkah Solusi Lapangan |
Response Timeout (0xE2) |
Polaritas kabel A & B terbalik, atau Slave ID salah | Balik posisi sambungan A dan B; cek ulang Slave ID di datasheet. |
Invalid Response (0xE0) |
Baudrate, Parity, atau Stop Bit tidak sinkron | Samakan pengaturan serial port master dengan sensor (misal: 9600 8N1). |
| Nilai Pembacaan Kacau (Garbage Data) | Format Endianness byte tidak sesuai | Balik urutan register Word (Word Swap) di kode firmware Anda. |
| Koneksi Drop Saat Inverter/Motor Hidup | Interferensi induksi gelombang elektromagnetik | Gunakan kabel STP berpelindung logam dan pasang grounding shield di 1 sisi panel. |
13. FAQ Seputar Implementasi Modbus RS485
Q1: Mengapa kabel RS485 tidak boleh disambung menggunakan topologi Bintang (Star Topology)?
Jawab: Topologi bintang memicu banyak cabang liar (spur) yang memantulkan gelombang elektromagnetik kembali ke transmitter (signal reflection). Pantulan ini merusak bentuk gelombang kotak biner. Selalu gunakan metode rantai daisy (Daisy-Chain Topology).
Q2: Berapa banyak sensor slave yang dapat dipasang dalam satu jalur bus?
Jawab: Standar RS485 menetapkan batasan beban listrik sebesar 32 Unit Load (UL) per segmen kabel. Jika menggunakan transceiver hemat beban seperti 1/8 UL, Anda dapat memasang hingga 256 node perangkat tanpa memerlukan repeater tambahan.
Q3: Mengapa pelindung kabel (Shield) hanya boleh di-grounding pada SATU titik saja?
Jawab: Jika kedua ujung pelindung kabel dihubungkan ke tanah (ground), akan terjadi Ground Loop Current akibat perbedaan resistansi potensial bumi antar-panel. Aliran arus bocor ini justru menginduksikan gangguan sinyal liar (noise) ke jalur data.
Bangun Solusi Otomasi & IoT Industri Anda Bersama Sayuswa Teknologi
Mengembangkan gateway industri yang andal memerlukan rancangan hardware berstandar proteksi tinggi dan arsitektur firmware yang tangguh.
PT Sayuswa Multi Teknologi menyediakan solusi lengkap perangkat keras dan integrasi sistem SCADA/IoT industri:
-
Data Logger & IoT Gateways: Modul Industrial Edge Gateway siap pakai dengan Web GUI konfigurasi dan auto-polling Modbus terintegrasi.
-
Sensors & Instrumentation: Sensor transmiter industri (Power Meter, Flow Meter, Suhu, & Tekanan) bersertifikasi.
-
Panel Listrik & PLC Otomasi: Pembuatan panel kontrol terstandarisasi, lengkap dengan pengaman lonjakan petir (Surge Arrester) dan filter suplai daya.
Butuh konsultasi arsitektur SCADA atau pengadaan perangkat otomasi untuk pabrik Anda?
Hubungi Tim Engineering PT Sayuswa Multi Teknologi sekarang untuk mendapatkan konsultasi teknis dan solusi tepat guna!