Modbus multimeter to LCD display with Nano

I want to read one register of a modbus slave multimeter, and display the value in a LCD.
Unfortunately it does not work :frowning:
I am using Arduino Nano, and a module with a MAX485.
I use the ModbusMaster library.
The problem is that in the display I get “V1=65535” instead of “V1=231.4”.
The green LED goes up if “read successful”, it does, so I think the hardware is ok.

It would be nice to see the modbus request that Arduino is sending to the slave. In the serial monitor I get “? ? ? ? ? ? ? ? ?”, while I expected to see something like [xx][xx][xx][xx][xx][xx] that I would then decode. How can I verify if the request is correct?

Also, in this library I didn’t see an option to set 8-N-1 or 8-N-2.

Here is the program, it would be great if you can have a look and tell me how can I make it to work.

// 10-02-2018
//this sketch should read a value from a modbus slave, and siplay in a LCD.
//The slave is a 3-phase multimeter (Electrex FEMTO D4), address 2, baud rate 19200-8-N-1.
//The voltage V1 is at address 220.
// The MAX485CPA is connected to serial 0 (TX, RX are pin 1 and 2 of arduino nano). De/RE are connected to pin D7, of a Arduino nano (Atmega 328P).


// include the library code:
#include <LiquidCrystal.h>
#include <ModbusMaster.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(14, 12,11,10,9,8);

#define MAX485_DE      7
#define MAX485_RE_NEG  7
#define green_led 4

// 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() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);

  // use Serial (port 0); initialize Modbus communication baud rate
  Serial.begin(19200);

  // communicate with Modbus slave ID 2 over Serial (port 0)
  node.begin(2, Serial);
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop() {
  //show that the program is running
  lcd.setCursor(0, 0);
  lcd.print(millis()/1000);
  
  static uint32_t i;
  uint8_t j, result;
  uint16_t data[3]={0,0,0};

  // set word 0 of TX buffer to least-significant word of counter (bits 15..0)
  //node.setTransmitBuffer(0, lowWord(i));
  
  // set word 1 of TX buffer to most-significant word of counter (bits 31..16)
  //node.setTransmitBuffer(1, highWord(i));
  
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on 
  // slave: read (3) 16-bit registers starting at register 220 to RX buffer
  result = node.readHoldingRegisters(220, 3);
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off
  
  // do something with data if read is successful
  if (result == node.ku8MBSuccess){
  //flash green led on success
  digitalWrite(green_led, 1); delay(200); digitalWrite(green_led, 0);
    for (j = 0; j < 3; j++)
    {
      data[j] = node.getResponseBuffer(j);
    }
  }
  //update voltage V1 on the LCD
  lcd.setCursor(0, 1); lcd.print("V1=          ");
  lcd.setCursor(3, 1); lcd.print(data[1]);
  
}

If I disconnect the RS485 bus, the display shows "V1=0" (which is correct).
So, when the connection of the RS485 wires is present, I think that there are data coming back from the multimeter (the program pass trough the "success" test and the green led goes On), however I notice that the RX led on the arduino does not flash (while the TX led yes).

Please post documentation for your multimeter. You're communicating with 8N1 but the ModBus standard says a parity bit is mandatory. There are many devices that say to support ModBus but are not fully standard compliant it's hard for us to check if we have no clue how your device works.

The problem is that in the display I get "V1=65535" instead of "V1=231.4".

You will never get 231.4 with above code. The ModBus standard allows only 16bit integers to be transported. So float values must be converted in some way. The documentation of your device probably tells how to do this but you're hiding it from us.

Hi, the device is a FEMTO D4 energy analyser.
The manual is here http://www.electrex.it/en/products/energy-meters-energy-analyzers/pfa6411-02.html

I managed to read via modbus, but there is a problem with the format of the values (16 or 32 bit).
I opened this: Combine TWO uint16_t in ONE float - Programming Questions - Arduino Forum

The manufacturer say that the value I read from the register 220 is a float (32 bit), but from my understanding of the modbus library it is a unsigned in 16!

The manufacturer say that the value I read from the register 220 is a float (32 bit), but from my understanding of the modbus library it is a unsigned in 16!

The ModBus standard doesn't support the transfer of floats. That means the manufacturer encodes a 32bit float into two 16bit integers. The manual should describe how that is done, otherwise the manual isn't complete.

Here you will find excellent free of charge ModBus tool that may help you.

http://www.baseblock.com/PRODUCTS/comtestpro.htm

Recently it saved me a lot of time.

Data you are trying to read may be fragmented in to a multiple registers so you must do some sort of data joining and conversion after you read it from remote device, but you first must know more about the data format.

Regards...