Komunikasi Modbus PZEM 003 dengan arduino sebagai master (read input register tanpa library)

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 :

  1. Arduino uno
  2. 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;
}

 

26 thoughts on “Komunikasi Modbus PZEM 003 dengan arduino sebagai master (read input register tanpa library)

  1. gan, bisa enggak komunikasinya tranfer id rfid? yang masternya melakukan registrasi rfid dan slavenya menerima id rfid yg didaftarkan di master dan id rfid tersebut bisa d kases di slavenya?

  2. mas mau nanya
    jika master nya itu terdiri ada arduino + reader rfid kemudian terdapat lebih dari 4 slave yang terdapat juga (arduino + reader rfid), pada master kita melakukan registrasi rfid kemudian master ini mengirimkan id rfidnya ke slave dan di slave bisa mengakses id rfid tersebut. itu bagaimana?

  3. Maaf mas, mau tanya. bagaimana untuk coding menggunakan 2 Arduino 2 RS485 menggunakan Modbus.
    Arudino 1 (Slave) membaca 3 sensor -> RS485 slave -> RS485 Master -> Arduino 2 ( Master) menerima data 3 sensor?.

  4. apa arti dari ” byte *ptr ” , “ptr” digunakan untuk apa mas? dan kenapa “uint16_t crc = 0xFFFF;” apa arti nilai hexa? menyesuaikan alat?.

    Terima Kasih

    1. sesuaikan bagian ini

      byte perintah[] = {0x01, 0x04, 0x00, 0x00, 0x00, 0x08};

      atau

      //alamat register 0x01
      perintah[2] = 0x00
      perintah[3] = 0x01
      //jumlah data 0x02
      perintah[4] = 0x00
      perintah[5] = 0x02
      
    1. pzem punya register2 (data pembacaannya) di alamat tertentu (bisa di lihat di datasheetnya)
      untuk membacanya perlu dikirimkan kode panggil/perintah, dan akan di respon oleh pzem sesuai perintah yang diterimanya

  5. jika mau membuat pembacaan multiple slave, apakah serial pzem yang dipakai hanya 1 atau 2? jika hanya satu pada bagian loopnya menjadi seperti apa ya?
    terima kasih banyak.

Leave a Reply to Andi Falih Cancel reply

Your email address will not be published. Required fields are marked *