after 2 weekends of being busy with this modbus stuff, my wife is getting fed up with me. Because I haven't got a place to store my Arduino stuff and work on it at the same time, the living is becoming a mess. So please help my wife (and me).
I have tried lots of different libraries and code but I ended up with the code writtten down below. This code gives an error in the output monitor that says:
Exception errors: 0
Failed requests: 9
Successful requests: 0
Low byte: 0
High byte: 516
Voltage 0.00
Exception errors: 0
Failed requests: 11
Successful requests: 0
Low byte: 0
High byte: 516
Voltage 0.00
The Energy meter, you might not be able to see on the picture, gives the communication blink (com) but sadly doesn't give the output I was hoping for on the PC.
I cannot find an obvious error in your code, except that you're requesting two registers but provide space for only one (this doesn't pose a problem yet because the connection fails anyway).
But I recommend not to use SimpleModbusMaster but ModbusMaster instead as it provides return codes that tells you what kind of error occured and is usually easier to use in the end.
Once you've done that, post the return code you got (error code) as well as your changed code!
Check the Modbus ID, baud rate and parity on the meter as well as the polarity of the RS485 connection.
I've been busy selfteaching me this part of arduino... and finally (with the help of this forum) I got it working
First, I have changed the parity in the meter from "even" to "none" (which is the default in ModbusMaster)
the code that I've used is as following
#include <ModbusMaster.h>
/*!
*
*
*
*
This program is made to read data from a "Inepro PRO1-Mod energy meter" (EAN 08717438668840)
it's a 45amp single phase energy meter
https://ineprometering.com/pro1/#Types
documentation:
https://ineprometering.com/wp-content/uploads/2018/09/PRO1-user-manual-V2.18.pdf
I'm using a MAX485-compatible RS485 Transceiver.
https://opencircuit.nl/Product/MAX485-TTL-to-RS485-module
and a mega 2560
Rx/Tx is hooked up to the hardware serial port at 'Serial3' which is port 14 and 15.
The Data Enable and Receiver Enable pins are hooked up as follows:
*/
#define MAX485_DE 3 // I do not use this port since I only receive data
#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 9600 baud
Serial.begin(9600);
Serial3.begin(9600); // standard config = 8N1 (8 bits, none parity, 1 stopbit) if else: 8E1 (8 bits, even parity, 1 stopbit) Serial3.begin(9600, SERIAL_8E1)
// Serial3 is port 14 & 15 @ mega 2560
// Modbus slave ID 1
node.begin(1, Serial3);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
bool state = true;
void loop()
{
uint16_t result;
// Read 2 registers starting at 0x4003)
// for the INEPRO mod1 energy meter, these registers are data typed as: Signed
result = node.readHoldingRegisters(0x4003, 2);
if (result == node.ku8MBSuccess)
{
Serial.print("Modbus ID: "); //modbus id
Serial.println(node.getResponseBuffer(0x00)); // read register 4003
Serial.print("Baud rate: "); // baud rate
Serial.println(node.getResponseBuffer(0x01)); // read register 4004
}
// Read 1 register starting at 0x400B)
// for the INEPRO mod1 energy meter, these registers are data typed as: Signed
result = node.readHoldingRegisters(0x400B, 1);
if (result == node.ku8MBSuccess)
{
Serial.print("Meter Amps: "); // max ampere of this meter
Serial.println(node.getResponseBuffer(0x00)); // read register 400B
}
// Read 2 registers starting at 0x5000)
// for the INEPRO mod1 energy meter, these registers are data typed as: float ABCD
// register length of 0x5000 is 2 so this is 2 times 16 bit = 32 bit
// so we are receiving 32-bit data in two parts of 16 bit via data[0] and data[1]
// the data is part of the 32-bit binary32 (IEEE-754) standard
// to get the decimal number, we need to construct the data
// decimalvalue = data[0] << 16 | data[1] example: 0x43680000 + 0xD747 = 0x4368D747
result = node.readHoldingRegisters(0x5000, 2);
if (result == node.ku8MBSuccess)
{
Serial.println(node.getResponseBuffer(0x00));
Serial.println(node.getResponseBuffer(0x01));
}
result = node.readHoldingRegisters(0x5000, 2);
if (result == node.ku8MBSuccess)
{
float x;
unsigned long *p;
p = (unsigned long*)&x;
*p = (unsigned long)node.getResponseBuffer(0x00) <<16 | node.getResponseBuffer(0x01);
Serial.print("Voltage: "); //voltage of the grid
Serial.println(x, 1); // 1 decimal (x, 2)= x with 2 decimal
}
result = node.readHoldingRegisters(0x6000, 2);
if (result == node.ku8MBSuccess)
{
float x;
unsigned long *p;
p = (unsigned long*)&x;
*p = (unsigned long)node.getResponseBuffer(0x00) <<16 | node.getResponseBuffer(0x01);
Serial.print("Current: "); //total usage of kWh
Serial.print(x, 5);
Serial.println(" kWh");
}
result = node.readHoldingRegisters(0x5012, 2);
if (result == node.ku8MBSuccess)
{
float x;
unsigned long *p;
p = (unsigned long*)&x;
*p = (unsigned long)node.getResponseBuffer(0x00) <<16 | node.getResponseBuffer(0x01);
Serial.print("Active Power: "); // kW used at this moment
Serial.print(x, 5);
Serial.println(" kW");
}
node.clearResponseBuffer();
delay(1000);
}