Modbus adalah sebuah protokol komunikasi antar perangkat. Modbus tergolong sebagai komunikasi serial dengan kelebihan mampu berkomunikasi dalam bus data (lalu lintas data), jadi dalam sebuah jaringan modbus bisa menghubungkan lebih dari 2 alat (hingga 254 alat/perangkat). Contoh penggunaan protokol modbus adalah programmable logic controllers (PLCs) serta supervisory control and data acquisition (SCADA).
Dalam protokol modbus terdapat fungsi-fungsi diantaranya :
- Coils (1 bit) baca/tulis
- Discrete Inputs: (1 bit) hanya baca
- Input Registers: (2 byte) hanya baca
- Holding Registers: (2 byte) baca/tulis
Komunikasi antara perangkat dalam jaringan modbus digambarkan dalam diagram berikut :
RS485
rs485 adalah perangkat elektronika pengirim dan penerima data (serial) umumnya menggunakan dua kabel dengan karakteristik sinyal yang seimbang. rs485 juga mampu menghubungkan lebih dari 2 perangkat komunikasi (multipoint).
rs485 sering dimanfaatkan sebagai perangkat tambahan dalam komunikasi modbus.
Pembacaan modul PZEM modbus dengan arduino sebagai master
modul pzem dikenal sebagai modul pembaca tegangan, arus, daya, energi, frekuensi dari listrik. beberapa diantaranya mendukung protokol modbus. dalam contoh ini digunakan modul pzem 003 yaitu modul pengukuran dc.
skema komunikasi modbus berbasis arduino:
komponen yang digunakan :
- Arduino uno
- modul serial rs485
sketch/program arduino untuk pembacaan sensor pzem :
#define pinModBusTX 4 #include <SoftwareSerial.h> SoftwareSerial pzem(2, 3); // RX, TX byte perintah[] = {0x01, 0x04, 0x00, 0x00, 0x00, 0x08};//readInputRegisters byte bufferDataModbus[100]; byte *ptr; void setup() { pinMode(pinModBusTX, OUTPUT); Serial.begin(9600); Serial.println(F("Komunikasi Modbus dengan arduino sebagai master (read input register tanpa library)")); Serial.println(F("https://www.project.semesin.com")); Serial.println(); pzem.begin(9600); ptr = bufferDataModbus; } void loop() { uint16_t crc = calcCRC(perintah, sizeof(perintah)); digitalWrite(pinModBusTX, HIGH); delay(1); pzem.write(perintah, sizeof(perintah)); pzem.write(lowByte(crc)); pzem.write(highByte(crc)); delay(10); digitalWrite(pinModBusTX, LOW); long millisResponModbus = millis() + 1000; while (!pzem.available()) { if (millisResponModbus < millis()) { break;//timeout } } while (pzem.available()) { byte b = pzem.read(); *ptr++ = b; delay(2); } if (memcmp(bufferDataModbus, perintah, 2) == 0) { ptr = bufferDataModbus; float tegangan = ((ptr[0 + 3] << 8) + ptr[1 + 3]) * 0.01; float arus = ((ptr[2 + 3] << 8) + ptr[3 + 3]) * 0.01; float daya = (((uint32_t)ptr[6 + 3] << 24) + ((uint32_t)ptr[7 + 3] << 16) + (ptr[4 + 3] << 8) + ptr[5 + 3]) * 0.1; float energi = (((uint32_t)ptr[10 + 3] << 24) + ((uint32_t)ptr[11 + 3] << 16) + (ptr[8 + 3] << 8) + ptr[9 + 3]); uint16_t alarmHigh = ((ptr[12 + 3] << 8) + ptr[13 + 3]); uint16_t alarmLow = ((ptr[14 + 3] << 8) + ptr[15 + 3]); memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); Serial.println("=========="); Serial.print("tegangan = "); Serial.println(tegangan); Serial.print("arus = "); Serial.println(arus); Serial.print("daya = "); Serial.println(daya); Serial.print("energi = "); Serial.println(energi); Serial.print("alarmHigh = "); Serial.println(alarmHigh); Serial.print("alarmLow = "); Serial.println(alarmLow); } Serial.println(); delay(1000); } uint16_t calcCRC(byte *data, byte panjang) { int i; uint16_t crc = 0xFFFF; for (byte p = 0; p < panjang; p++) { crc ^= data[p]; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; else crc = (crc >> 1); } } return crc; }