Go Down

Topic: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED] (Read 258913 times) previous topic - next topic

Esakki

Hello everyone....

i'm newbie to arduino

i'm having an ELMEASURE LG+1129 meter , i have been trying for several days to read the register values..

My Hardware: Arduino uno, RS-485

My Firmware: Arduino ide 1.8.3, simplemodbusmaster v2rev2 DUE

Can you please guide me how to read the register value from the ELMEASURE using arduino uno

My library:

https://drive.google.com/drive/folders/0B0B286tJkafVYnBhNGo4N3poQ2c

below here attached my connection dig, elmeasure lg 1129 datasheet

Patrik_Fernandes

Hello
I'm having trouble with the arduino Mega with the delay in reading modbus.
After some modifications I discovered that the delay is related to the number of packages.
Is there any way to read more than one value in a single package, as it should be.
This my code will increase twice, today to only update these values ​​below, delay 3 minutes
Code: [Select]
#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

long previousMillis = 0;
long interval = 1000;

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 10

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 23

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  READ_FROM_SLAVE_1,       // Letter 0
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  PACKET7,
  PACKET8,
  PACKET9,
  PACKET10,
  PACKET11,
  PACKET12,
  PACKET13,
  PACKET14,
  PACKET15,
  PACKET16,
  PACKET17,
  PACKET18,
  PACKET19,
  PACKET20,
  PACKET21,
  PACKET22,
  PACKET23,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];
unsigned int readRegs[1];
unsigned long currentMillis;

void setup()
{
  Serial.begin(9600);
  // Initialize each packet


  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
  modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 1, 1, 1);
  modbus_construct(&packets[PACKET3], 1, READ_HOLDING_REGISTERS, 2, 1, 2);
  modbus_construct(&packets[PACKET4], 1, READ_HOLDING_REGISTERS, 3, 1, 3);
  modbus_construct(&packets[PACKET5], 1, READ_HOLDING_REGISTERS, 4, 1, 4);
  modbus_construct(&packets[PACKET6], 1, READ_HOLDING_REGISTERS, 5, 2, 5);
  modbus_construct(&packets[PACKET7], 1, READ_HOLDING_REGISTERS, 6, 2, 6);
  modbus_construct(&packets[PACKET8], 1, READ_HOLDING_REGISTERS, 7, 2, 7);
  modbus_construct(&packets[PACKET9], 1, READ_HOLDING_REGISTERS, 8, 1, 8);
  modbus_construct(&packets[PACKET10], 1,READ_INPUT_REGISTERS, 29, 1, 9); // Frequencia Rede
  modbus_construct(&packets[PACKET11], 1,READ_INPUT_REGISTERS, 700, 4,10); // Tensão Rede R+N
  modbus_construct(&packets[PACKET12], 1,READ_INPUT_REGISTERS, 702, 4, 11); // Tensão Rede S+N
  modbus_construct(&packets[PACKET13], 1,READ_INPUT_REGISTERS, 704, 4, 12); // Tensão Rede T+N
  modbus_construct(&packets[PACKET14], 1,READ_INPUT_REGISTERS, 28, 1, 13); // Frequencia Gerador
  modbus_construct(&packets[PACKET15], 1,READ_INPUT_REGISTERS, 708, 1, 14); // Tensão Gerador R+N
  modbus_construct(&packets[PACKET16], 1,READ_INPUT_REGISTERS, 710, 1, 15); // Tensão Gerador S+N
  modbus_construct(&packets[PACKET17], 1,READ_INPUT_REGISTERS, 712, 1, 16); // Tensão Gerador T+N
  modbus_construct(&packets[PACKET18], 1,READ_INPUT_REGISTERS, 72, 1, 17); // Tensão Bateria;
  modbus_construct(&packets[PACKET19], 1,READ_INPUT_REGISTERS, 70, 1, 18); // Horas Funcionamento Motor
  modbus_construct(&packets[PACKET20], 1,READ_INPUT_REGISTERS, 131, 1, 19); // Estado Motor
  modbus_construct(&packets[PACKET21], 1,READ_INPUT_REGISTERS, 720, 1, 20); // Horas manutenção
  modbus_construct(&packets[PACKET22], 1,READ_INPUT_REGISTERS, 120, 1, 21); // Modo de Operação
  modbus_construct(&packets[PACKET23], 1,READ_INPUT_REGISTERS, 130, 1, 22); // Alarme Status
 
  // Initialize the Modbus Finite State Machine
modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
   modbus_update();
float Power;
  unsigned long temp = (unsigned long)regs[0] << 16 | regs[1];
  Power = *(float*)&temp;
 
   currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {

    Serial.print("Exception errors: ");
    Serial.println(packets[PACKET1].exception_errors);

    Serial.print("Failed requests: ");
    Serial.println(packets[PACKET1].failed_requests);
   
    Serial.print("Successful requests: ");
    Serial.println(packets[PACKET1].successful_requests);
    Serial.print("Low byte: ");
    Serial.println(regs[0]);
    Serial.print("High byte: ");
    Serial.println(regs[1]);
    Serial.print("Power ");
    Serial.print(Power);
    Serial.println("----------");
  }
 
  Serial.print("Horário = ");
  Serial.print(regs[2]);
  Serial.print(":");
  Serial.print(regs[1]);
  Serial.print(":");
  Serial.print(regs[0]);
  Serial.println();
  /////////////////////////////////////////////////////////////////////
 Serial.print("Data = ");
  Serial.print(regs[3]);
  Serial.print("/");
  Serial.print(regs[5]);
  Serial.print("/");
  Serial.println(regs[6]);
  Serial.println();
  /////////////////////////////////////////////////////////////////////
  Serial.print("Frequência da Rede = ");
  Serial.print(regs[9]/255);
  Serial.print("Hz");
  Serial.println();
  /////////////////////////////////////////////////////////////////////
  Serial.print("Tensão da Rede = ");
  Serial.print("RN:");
  Serial.print(regs[10]/256);
  Serial.print("V, ");
  Serial.print("SN:");
  Serial.print(regs[11]/256);
  Serial.print("V, ");
  Serial.print("TN:");
  Serial.print(regs[12]/256);
  Serial.print("V");
  Serial.println();
  /////////////////////////////////////////////////////////////////////
  Serial.print("Frequência do Gerador = ");
  Serial.print(regs[13]/255);
  Serial.print("Hz");
  Serial.println();
  /////////////////////////////////////////////////////////////////////
  Serial.print("Tensão do Gerador = ");
  Serial.print("RN:");
  Serial.print(regs[14]/256);
  Serial.print("V, ");
  Serial.print("SN:");
  Serial.print(regs[15]/256);
  Serial.print("V, ");
  Serial.print("TN:");
  Serial.print(regs[16]/256);
  Serial.print("V");
  Serial.println();
  /////////////////////////////////////////////////////////////////////
  Serial.print("Tensão da Bateria = ");
  Serial.print(regs[17]/256);
  Serial.print("VCC");
  Serial.println();
  /////////////////////////////////////////////////////////////////////
  Serial.print("Horas Funcionamento = ");
  Serial.print(regs[18]);
  Serial.print("h");
  Serial.println();
  /////////////////////////////////////////////////////////////////////
 Serial.print("Status = ");
  if (regs[19] == 0)
{
  Serial.print("Parando");
}
  if (regs[19] == 1)
{
  Serial.print("Abortar Parada");
}
  if (regs[19] == 2)
{
  Serial.print("Parado");
}
  if (regs[19] == 3)
{
  Serial.print("Falha na Parada");
}
Serial.println();
/////////////////////////////////////////////////////////////////////
Serial.print("Manutenção = ");
Serial.print(regs[20]);
Serial.print("h");
Serial.println();
/////////////////////////////////////////////////////////////////////
Serial.print("Modo = ");
  if (regs[21] == 0)
{
  Serial.print("OFF");
}
  if (regs[21] == 1)
{
  Serial.print("MANUAL");
}
  if (regs[21] == 2)
{
  Serial.print("AUTOMÁTICO");
}
  if (regs[21] == 3)
{
  Serial.print("TEST");
}
  if (regs[21] == 4)
{
  Serial.print("REMOTE START");
}
Serial.println();
/////////////////////////////////////////////////////////////////////
  delay(100);
}

noiasca

you can read more than one byte per packet. This will spare at least your first 6 Packets from your current example.
I follow this logic

modbus_construct(&packets[PACKET0], 1, READ_INPUT_REGISTERS, 0xStartadress, BytesToReads, FirstRegisterIndex);

in your case
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 5, 0);
will do the same like your first 5 rows.

This makes no sense for me
Code: [Select]

modbus_construct(&packets[PACKET6], 1, READ_HOLDING_REGISTERS, 5, 2, 5);
modbus_construct(&packets[PACKET7], 1, READ_HOLDING_REGISTERS, 6, 2, 6);
modbus_construct(&packets[PACKET8], 1, READ_HOLDING_REGISTERS, 7, 2, 7);


PACKET6 will write in data and sets Register 5 and 6, because you are requesting 2 bytes.
PACKET7 will read again data and sets Register 6 and 7 ...
PACKET8 will read data and sets Register 7 and 8

so you are reading byte 6 and 7 two times.

try to reduce the packets but without exceeding the internal buffers.

Patrik_Fernandes


Thank you,
It worked correctly.
I tried several ways but I could not.

I need more help:
What better method to read and write a value in BIT, since the reading is DECIMAL.
Example:

Bit00 Alarm
Bit01 Shutdow
Bit02 Reset
.
.
Exemple supervisory Set  Driver1.Tag1.Bit02 = true.


In the arduino how would it be?

noiasca

google is your friend: https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit


noiasca

has anyone an idea to insert a "delay" between each full cycle of packet requests? I don't want to exceed the MODBUS_POLLING because this increases the intervall between the packets. I would like to have all packets read (fast), one by one, and then let the modbus silent for i.e. 30 seconds.

rockwallaby

I do not see that being a problem for a Modbus master.

In the past I have used this technique in a GNU/Linux based program I developed using Libmodbus library, where multiple slaves were polled on different communications channels at user defined rates. The master would go out to poll the slave for all packets in sequence with short inter packet polling delays and then wait for the user defined period before starting the packet sequence again.

You should be able to do the same with Arduino based libraries to I imagine.
____________
Paul - VK7KPA

noiasca


I'm pretty shure it can be done, but the question is, if it was already done by someone with that particular library. Yes I can stop the requests by something like

Code: [Select]
packets[i].connection = false;

but i would like to know what's the best solution to disconnect after one (sucessfull) cycle and reconnect all packets again after a certain periode of time...

jhbower

My project involves controlling actuators and reading position data from them. I am using SMBmaster and SMBslave on Mega 2560's. I am using Linksprite RS485 shields that I have modified in order to easily route the hardware TX and RX pins to SERIAL1 pins (18 and 19) on the Mega 2560. From a hardware and software perspective, I have things up and running pretty well. So this isn't a request for how to get one thing or another working. The following may sound like a stupid question, but I will risk it.

In operation, the master controls a device with position pots and motors. The master (remote controller) polls the slave to get current position data, which it then displays for the user. The user then changes the positioning on slave device, the new position is shown on the display prior to the "move" command being transmitted from the master to the display. When the modbus_update() is executed, two packets go out (position readout update request, and the move command) and the position is read by the slave and transmitted back to the master, before the move command has completed. As a result, the display might read 10.0 inches (the new position specified), then flash to 7.1 inches, 9.9 inches and then settle on 10.0. I've developed a work around, but..

The question is: can packets be "suppressed", or once enumerated and constructed, all packets go out with every modbus_update()?

In reading the 100's of posts in this thread, I've not seen this discussed, though I might have missed it. Given the PLC roots of modbus, I would think a PLC controls its modbus requests as it sees fit. Is it possible to reconfigure a "constructed" packet on the fly? I can see several ways around this, but I am wondering if I am missing something obvious.

Thanks, John
 

VarunNelakanti

Hey ModBus Experts,

I just have one question. I keep getting exception errors when i try to communicate with my ELMeasure LG+ 5310 series energy meter. The communication light blinks as many times as i given the retry count. But I get no reply. If anyone has any answer, it will be highly appreciated. :D

I'm pasting the code here.

Code: [Select]


#include <SimpleModbusMaster.h>



//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 500 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 2

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{

 // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 40101, 2, 0);
 Serial.begin(9600);
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8E2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
}

void loop()
{

    modbus_update();
    Serial.print(packets[PACKET1].requests);
    Serial.print(";successful_requests: "); 
    Serial.print(packets[PACKET1].successful_requests);
    Serial.print(";failed_requests: "); 
    Serial.print(packets[PACKET1].failed_requests); 
    Serial.print(";exception_errors: "); 
    Serial.print(packets[PACKET1].exception_errors);
    Serial.println(regs[0]);
    Serial.println(regs[1]);
}







If anyone wants to see the register map, its here Register Map


Thank you much.

noiasca

@John, you can try following:

Code: [Select]
packets[i].connection = false;


where i is the the packet to deactivat

I use it vice versa: I try to reconnect each slave every hour just in case it was deactived, so the other way round should work also ...

noiasca

@VarunNelakanti

I assume you have got a wrong adress:

Code: [Select]
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 40101, 2, 0);

Read the very good manual of the library and see how to start counting with READ_HOLDING_REGISTERS.
I assume 40101 is to high as you should just use a offest to the start where RED_HOLDING_REGISTERS usually start, but that should be found in the manual.

Just as a hint, I'm using READ_INPUT_REGISTERS, and have only to add 0x3100 ... so 40101 looks very high to me:
Code: [Select]
modbus_construct(&packets[PACKET0], 1, READ_INPUT_REGISTERS, 0x3100, 8, 0);

jhbower

From page 28 of the product manual:
4. If RS-485 communication does not work:
a) Check that the baud rate of the host computer/PLC is the same as Meter.
b) Check that the device ID of the meter are unique and should not replicate.
c) Check all communications wiring is complete.
d) Check that the number of data bits is set to 8, with one stop bit and even
parity.

Also Page 8 tells you where the display value of the device ID

You are not showing your resulting printout, which might be helpful. And it is not clear that you have checked other aspects of your setup, such as match the slave ID to what you have declared in your program.

jhbower

@John, you can try following:

Code: [Select]
packets[i].connection = false;


where i is the the packet to deactivat

I use it vice versa: I try to reconnect each slave every hour just in case it was deactived, so the other way round should work also ...

Noiasca,

Thank you very much, that does the trick.

-John

jhbower

Following up on what noiasca stated, I think that "READ_HOLDING_REGISTERS" automatically generates the 40001  "base address", therefore you don't need to state it explicitly, I think that replacing the the 40101 with either 100 or 101 gets you to that address on the device.

Code: [Select]
// Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 40101, 2, 0);
 Serial.begin(9600);
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8E2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
}

Go Up