This is a simple code to read the Frequency register of a EM6436H power meter which sends the Frequency as a 32 bit float via two 16 bit registers starting at address hex 3110.
I am right now getting 0.0 instead of 50.00 and one possible reason is the config of the Serial stream. The instrument is set for 9600-8E1 ( This cannot be changed as its locked ) . But I think the AltSoftSerial is for 9600-8N1
Is there anyway I can have this parity of 8N1 changed to 8E1 ?
#include <ModbusMaster.h>
#include <AltSoftSerial.h>
AltSoftSerial softSerial(2, 3); //Software Serial port For Arduino Uno
ModbusMaster node;
union X
{
float f;
unsigned int i[2];
} unX;
void setup()
{
Serial.begin(9600); //Baud rate is 9600 8N1
softSerial.begin(9600); //Modbus Baud rate is 9600 8N1
node.begin(softSerial); // communicate with Modbus slave ID 1 over softSerial
}
void loop()
{
uint8_t j, result;
int data[2];
result = node.readHoldingRegisters(1,3110, 2); // Read (2) 16-bit registers starting at register 3110 to RX buffer
if (result == node.ku8MBSuccess)
{
for (j = 0; j < 2; j++)
{
unX.i[j] = node.getResponseBuffer(j);
}
}
Serial.println(unX.f, 2);
delay(2000);
}
You can hack the library There does not seem to be support for anything else than 8N1 in any of the three software serial libraries (SoftwareSeial, AltSoftSerial, NeoSWSerial).
AltSoftSerial softSerial(2, 3); //Software Serial port For Arduino Uno
The AltSoftSerial library doesn't allow to select the pins it runs on. It seems you're using a non-standard version of the library but you failed to provide a link to it.
@sterretje . Thanks . Looks to be the exact library that I need . Most times a Google search on Arduino topics yields more relevant pages than the Forum Search engine. This is one such. IT has compiled fine - let me check with hardware tomorrow.
@Pylon . Its the same AltSoftSerial library that you pointed out. Thanks for the correction on pin assignment. Missed it. . In any case this library is not OK for me as it does not have a facility to change parity. ( hacking is beyond me and anyway isnt it bad ?
Could check out the SoftwareSerialParity library. Oddly I get a "nan" when I set the Parity to EVEN which is what the instrument is set for. And "0.00" if I set the parity to either ODD or NONE.
( But in these instruments if you set the parity to NONE then you must increase the number of STOP bits to 2. So it will be 8N2. Another issue with MCU setups )
Any other point to check ? Somehow this Arduino with Modbus has been a issue all along for me. Any better shield or other hardware to link up with Modbus using Mega 2560 / Teensy 3.5 etc ?
Consider using the hardware serial port of any Arduino to interface with the device, as it supports parity, and use software serial to report the results.
@jremington and @pylon. Thanks. That cleared the issue and once I chose to use the HW serial it worked the first time. That parity cannot be changed in any Software Serial ( as is without hacking ) is the big learning.
The code that works is below :
/*
02 Aug 2020
ModBus_EM6400_read.ino
Code to read the Modbus register of EM6436H power meter using a UNO.
Not working .... tried with many Software libraries and Parity changes. Getting zero as result most times
06 Aug 2020
Parity cannot be set in any Software Serial. So will need to use a Hardware serial and then set it. Thus
UNO cannot be used for this.
Use the Serial1 HW Serial of the Adafruit 32u4 and the problem is solved !!
*/
#include <ModbusMaster.h>
ModbusMaster node;
union X // Create a Union to hold the data types in line with the Modbus register being read..
{
float f; // 32 bit float
uint16_t i[2]; // Array of 16bit word
} unX;
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
void setup()
{
Serial.begin(9600, SERIAL_8N1); //Baud rate is 9600 / 8N1
Serial1.begin(19200, SERIAL_8E1); //Modbus Baud rate is 9600/ 8E1
Serial.println(" Beginning Modbus master !" );
node.begin(Serial1); // Communicate with Modbus slave ID 1 over Hardware Serial
}
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
void loop()
{
uint8_t j, result;
uint16_t data[2];
// Read 2 nos 16-bit registers starting at register 3110 to RX buffer.
// Modbus address starts at 1 while MCU index starts with 0.
result = node.readHoldingRegisters(1,3109, 2);
if (result == node.ku8MBSuccess)
{
for (j = 0; j < 2; j++)
{
data[j] = node.getResponseBuffer(j);
Serial.println(unX.i[j], HEX);
}
}
unX.i[1] = data[0]; // Rearrange the received data to get the float ...
unX.i[0] = data[1];
Serial.println(unX.f, 2);
delay(2000);
}
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO