AltSoftSerial-How to change Parity ( Solved )

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 :wink: There does not seem to be support for anything else than 8N1 in any of the three software serial libraries (SoftwareSeial, AltSoftSerial, NeoSWSerial).

PS
1)
Which board are you using?
2)
I found https://create.arduino.cc/projecthub/luke-j-barker/softwareserial-with-parity-9ede24 after a quick google.

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 ? :wink:

Hacking isn't bad. You learn from it, even if you don't get it right.

@sterretje

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 ?

Use a Mega2560 and change to a hardware serial interface. That supports parity in hardware.

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