Reading data from energy meter using modbus protocols

hello all

Im trying to read data from elmeasure energy meter (model LG+1129) MODBUS RTU in arduino using RS485 to TTL Converter.

I verfiied data communication in MODBUS software using USB to RS485 converter. attaching screenshot of that.

Now im trying to read holding registers value in arduino and display it in serial monitor but in serial monitor the output is always zero.

I used rs485 to TTL converter between arduino and energy meter. when it is connected com led starts bilking while tx and rx happened.
Arduino pin 0 for Ro of Max 485.
Arduino pin 1 for Di of Max 485
Arduino pin 2 for both short of RE&DE of Max 485.

Attaching the code, pls let me know what is wrong in my code.

energy_meter_with_arduino.ino (6.48 KB)

so Serial is Serial Monitor or RS485?

  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

and

 Serial.print("A = ");
  Serial.println(A);
//  Serial.println(A / 77.69624);

  Serial.print("B = ");
    Serial.println(B);

You must not use the same serial interface you attached to the Modbus driver for debugging output. Everything you print there disturbs the Modbus communication.

Then should i have to use software serial?

Then should i have to use software serial?

I never recommend that as it's not a reliable solution. Use an Arduino Leonardo or Mega2560 as they have (at least) one hardware serial available that is not used for the connection to the PC.

As per your instruction i replaced Arduino Uno with Arduino Mega 2560 with RE and DI pins of RS485 to TTL converter connected to pin 0 and 1 of Mega 2560

 modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

&Serial has been changed to &Serial1.

With this change there is no exception error in serial monitor but still the values read from energy meter is 0

reva23:
As per your instruction i replaced Arduino Uno with Arduino Mega 2560 with RE and DI pins of RS485 to TTL converter connected to pin 0 and 1 of Mega 2560

Serial1 pins are labeled RX1 TX1 on Mega

Sorry for typing mistake. I connected RO and DI pins of converter to TX1 and Rx1 pins of mega..

But still serial monitor output is always zero.

But still serial monitor output is always zero.

Unfortunately that means you should change the Modbus library you use. The ModbusMaster library (available in the IDE Library Manager) returns result codes that may show you a bit more what happens behind the curtain.

A few other stuff to check:

  • Is the device ID set to 1 (Parameter 15 in the configuration)?
  • Is the baud rate correct (Parameter 13)?
  • Try other register numbers. The Modbus register number in such documents are often described for PLCs. Try 100 and 101, maybe that gives better results.

pylon:
Unfortunately that means you should change the Modbus library you use. The ModbusMaster library (available in the IDE Library Manager) returns result codes that may show you a bit more what happens behind the curtain.

The Modbus library has been installed through IDE library manager.. ModbusMaster library V2.1.0.

pylon:
A few other stuff to check:

  • Is the device ID set to 1 (Parameter 15 in the configuration)?
  • Is the baud rate correct (Parameter 13)?
  • Try other register numbers. The Modbus register number in such documents are often described for PLCs. Try 100 and 101, maybe that gives better results.

Yes, the device id is set to 1 and FYI in prev post i attached screenshot of modbus comunication with software which gives you clear pic.

The baud rate is 19200 both in program and energy meter.

I tried 100 and 101 still the serial monitor output is zero.

Attached image SCHEME1 is my present hardware configuration.

Does any changes required in hardware side? Whether a grounding is required between energy meter and rest of the circuit attached.

Also i did not use any termination resistors between D+ and D- terminals of energy meter.

The Modbus library has been installed through IDE library manager.. ModbusMaster library V2.1.0.

Please post the sketch you adapted to that other library!

Does any changes required in hardware side? Whether a grounding is required between energy meter and rest of the circuit attached.

It's not strictly necessary but recommended for many situations.

Also i did not use any termination resistors between D+ and D- terminals of energy meter.

The adapter you use is already terminated (most probably, I guess you use that cheap Chinese board available on ebay, Amazon and Ali) and probably the meter is terminated too. As the connection to the PC worked I wouldn't expect a termination problem.

This is the code which i used with Modbusmaster library

#include <ModbusMaster.h>
#define MAX485_DE      2
#define MAX485_RE_NEG  2
// instantiate ModbusMaster object
ModbusMaster node;
void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1);
  digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}
void setup()
{
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
  // Modbus communication runs at 19200 baud
  Serial.begin(19200);
   Serial1.begin(19200, SERIAL_8E1);
  
 
  // Modbus slave ID 1
  node.begin(1, Serial1);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop()
{
  uint8_t result;
  uint16_t data[6];
 
  // Toggle the coil at address 0x0002 (Manual Load Control)
  //result = node.writeSingleCoil(0x0003, state);
  //state = !state;
  // Read 16 registers starting at 0x3900)
  result = node.readHoldingRegisters(133, 30);
  if (result == node.ku8MBSuccess)
  {
    Serial.println("---------------------------------------------");
    Serial.print("L - L Voltage:: ");
    Serial.println(node.getResponseBuffer(33)/100.0f);
    Serial.print("L - N Voltage: ");
    Serial.println((node.getResponseBuffer(41)+node.getResponseBuffer(42))/100.0f);
    Serial.print("V1 - N Voltage: ");
    Serial.println(node.getResponseBuffer(43)/100.0f);
  }
  delay(1000);
}

When I use this code nothing prints on Serial monitor...

This is the code i used with simplemodbusmaster library

#include <SimpleModbusMaster.h>

#define baud 19200
#define timeout 1000
#define polling 2000 // the scan rate
#define retry_count 10


#define TxEnablePin 2

#define TOTAL_NO_OF_REGISTERS 31


enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  //  PACKET6,
  //  PACKET7,
  //  PACKET8,
  //  PACKET9,
  PACKET10,
  PACKET11,
  PACKET12,
  //  PACKET13,
  //  PACKET14,
  //  PACKET15,
  //  PACKETn,

  TOTAL_NO_OF_PACKETS // leave this last entry
};


Packet packets[TOTAL_NO_OF_PACKETS];
//packetPointer packet1 = &packets[PACKET1];
//packetPointer packet2 = &packets[PACKET2];
// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  Serial.begin(19200);
  Serial1.begin(19200);
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //  modbus_construct(&packets[PACKET1], 1(adres PM710 sampai ke n), READ_INPUT_REGISTERS, 4010(adress registry), 1(jenis data), 10(pengurutan data sampai ke n));
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 133, 2, 10); //L-N                  //A8
  modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 0135, 2, 12); //Frekuency            //B
  modbus_construct(&packets[PACKET3], 1, READ_HOLDING_REGISTERS, 40137, 2, 14); //A-N                  //C
  modbus_construct(&packets[PACKET4], 1, READ_HOLDING_REGISTERS, 40107, 2, 16); //B-N                  //D
  modbus_construct(&packets[PACKET5], 1, READ_HOLDING_REGISTERS, 40117, 2, 18); //C-N                  //E
  //
  //    modbus_construct(&packets[PACKET6], 2, READ_INPUT_REGISTERS, 3998, 2, 15); //REAL ENERGY          //F
  //    modbus_construct(&packets[PACKET7], 1, READ_INPUT_REGISTERS, 4005, 1, 16); //REAL POWER           //G
  //    modbus_construct(&packets[PACKET8], 1, READ_INPUT_REGISTERS, 4006, 1, 17); //AMP POWER            //H
  //    modbus_construct(&packets[PACKET9], 1, READ_INPUT_REGISTERS, 4007, 1, 18); //KVAR DAYA REAKTIF    //I
  //
     modbus_construct(&packets[PACKET10], 1, READ_HOLDING_REGISTERS, 40143, 2, 20); //A-B                  //J
     modbus_construct(&packets[PACKET11], 1, READ_HOLDING_REGISTERS, 40145, 2, 22); //B-C                  //K
     modbus_construct(&packets[PACKET12], 1, READ_HOLDING_REGISTERS, 40147, 2, 24); //C-A                  //L
  //
  //    modbus_construct(&packets[PACKET13], 1, READ_INPUT_REGISTERS, 4019, 1, 22); //ARUS A               //M
  //    modbus_construct(&packets[PACKET14], 1, READ_INPUT_REGISTERS, 4020, 1, 23); //ARUS B               //N
  //    modbus_construct(&packets[PACKET15], 1, READ_INPUT_REGISTERS, 4021, 1, 24); //ARUS C               //O
  //
  //modbus_construct(&packets[PACKET2], 3, PRESET_MULTIPLE_REGISTERS, 0, 1, 20);
  /*
  Valid modbus byte formats are:
  SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
  SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
  SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
  */
  // Initialize the Modbus Finite State Machine

/* packet1->id = 2;
  packet1->function = READ_HOLDING_REGISTERS;
  packet1->address = 0;
  packet1->no_of_registers = 3;
  packet1->register_array = regs;*/

  
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
}

void loop()
{
 modbus_update();
  int A, B, C, D, E, F, G, H, I, J, K, L, M, N, O;

  A = regs[10];
  B = regs[12];
  C = regs[14];
  D = regs[16];
  E = regs[18];
  //    F = regs[15];
  //    G = regs[16];
  //    H = regs[17];
  //    I = regs[18];
  J = regs[20];
  K = regs[22];
  L = regs[24];
  //    M = regs[22];
  //    N = regs[23];
  //    O = regs[24];
  //    n = regs[n];

  Serial.print("A = ");
  Serial.println(A);
//Serial.println(A / 77.69624);

  Serial.print("B = ");
    Serial.println(B);
//Serial.println(B / 333.333333);
  //
  Serial.print("C = ");
  Serial.println(C/10);
  //
  Serial.print("D = ");
  Serial.println(D/10);
  //
  Serial.print("E = ");
  Serial.println(E/10);
  //
  //    Serial.print("F = ");
  //    Serial.println(F);
  //
  //    Serial.print("G = ");
  //    Serial.println(G);
  //
  //    Serial.print("H = ");
  //    Serial.println(H);
  //
  //    Serial.print("I = ");
  //    Serial.println(I);
  //
 Serial.print("J = ");
 Serial.println(J);
  //
 Serial.print("K = ");
 Serial.println(K);
  //
  Serial.print("L = ");
  Serial.println(L);
  //
  //    Serial.print("M = ");
  //    Serial.println(M);
  //
  //    Serial.print("N = ");
  //    Serial.println(N);
  //
  //    Serial.print("O = ");
  //    Serial.println(O);
  Serial.println("============================================");
 

  //Voltage2 = regs[12];
  //Serial.print("Voltage L-N : ");
  //Serial.print(Voltage);
  //Serial.println(" V");
  //Serial.println(Voltage1);
  //Serial.println(Voltage2);
  //Serial.println(regs[10]);
  //Serial.println(regs[11]);

  //  Serial.println("DEBUG                     || OUTPUT");
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //  Serial.print("requests: ");
  //  Serial.print(packets[PACKET1].requests);
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //    Serial.print(" || Voltage L-N :");
  //    Serial.println(Voltage);
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //    Serial.print(" || Voltage L-N :");
  //    Serial.print(Voltage/10);
  //    Serial.println("   Volt");
  //    Serial.println("=======================================");
  //    Serial.print(" || Frekuency   :");
  //    Serial.print(F/100);
  //    Serial.println(" Hz");
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  //              Serial.println(" V");
  Serial.print("successful_requests: ");
  Serial.println(packets[PACKET1].successful_requests);
  Serial.println(packets[PACKET10].successful_requests);
  Serial.println(packets[PACKET11].successful_requests);
  Serial.println("                        || ");
  Serial.print("failed_requests: ");
 Serial.print(packets[PACKET1].failed_requests);
  Serial.println("     || ");
  Serial.print("exception_errors: ");
 Serial.print(packets[PACKET1].exception_errors);
  Serial.println("     || ");
  Serial.print("connection: ");
  Serial.print(packets[PACKET1].connection);
  Serial.println("           || ");
  //              Serial.println(" ");
delay(1000);
}

pls let me know what is wrong in above two codes

Still Im not able to read data from energy meter.. Pls help

When I use this code nothing prints on Serial monitor...

Print out the result code you get! Post it here.

  result = node.readHoldingRegisters(133, 30);

Reading registers that doesn't exist might not be the best idea.

BTW, here's a list of registers you meter supports.

pylon:
Print out the result code you get! Post it here.

Serial monitor starts printing if i remove "if (result == node.ku8MBSuccess)" in the code.

  result = node.readHoldingRegisters(133, 30);

Reading registers that doesn't exist might not be the best idea.

pylon:
BTW, here's a list of registers you meter supports.

AS per your advice i changed the register address to 40133 but still serial monitor output is zero. Im attaching serial monitor output screenshot as well as modified code.

 Serial.println(node.getResponseBuffer(33));

If I change the number 33 to 40133 the serial monitor prints 65535 as register value

Pls let me know where I'm going wrong.

test.ino (1.51 KB)

AS per your advice i changed the register address to 40133 but still serial monitor output is zero. Im attaching serial monitor output screenshot as well as modified code.

My advice was not to read 30 consecutive registers beginning at 133 if not all of them exist. I didn't tell you to change the address to 40133.

Serial monitor starts printing if i remove "if (result == node.ku8MBSuccess)" in the code.

I told you to print out the value of the variable "result" and post it here!

pylon:
My advice was not to read 30 consecutive registers beginning at 133 if not all of them exist. I didn't tell you to change the address to 40133.

Please let me know the format for addressing the holding register

pylon:
I told you to print out the value of the variable "result" and post it here!

The value of result is 226

The value of result is 226

In that case the energy meter did not respond at all. You don't have to care about the register address if you don't get any response. Check your hardware! If that's ok, check the configured baudrate, data bits, stop bits, parity, etc. Check the Modbus ID of the meter. Anything in this list is not OK in your setup. Find it! Then we have a look at the correct register number.

The hardware connections is like this

converter ---> Mega 2560

RO ---> RX1(18)
RE & DE ---> Shorted Together and connected to pin 7 in case of Simple Modbus master library.
DI ---> TX1 (19)
VCC ---> 3.3V
GND ---> GND

D+ and D- of energy meter is connected to A(D+) and B(D-) pins respectively.

Communication settings are:

9600, 8 data bits, Even parity, 1 stop bit and device id is 1 and the same is incorporated in program.

Is there any additional hardware connection and communication settings I'm missing? Pls let me know...

P.S: In previous discussions I already mentioned about the RS485 to TTL converter used.