Problem getting Arduino Mega to communicate with Gavazzi EM340 over Modbus

We are trying to read the "total kWh" register on a Carlo Gavazzi EM340 3-phase meter (Link to manual), using modbus. The Arduino is a Mega 2560, and for the RTU connection we are using this little MAX485 TTL-to-RS485 converter board Link

The cable between the meter and the board is a shielded cable (1m long), with twisted wires, so that should be ok. Ground is connected, see fritz below.

Baudrate on the EM340 is currently set to 9600, but I have tried every single baud value on the EM340 and correspondingly on the Arduino, and still it does not work.

Here is the code, which is based on the ModbusMaster-example:

#include <ModbusMaster.h>

#define MAX485_DE      3
#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);

  Serial.begin(9600);

  // Modbus slave ID 1
  node.begin(1, Serial);
  
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop()
{
  uint8_t result;

  // Read 16 registers starting at 0x3100)
  result = node.readInputRegisters(0x0034, 1);
  Serial.print("Result: ");Serial.println(result);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("kWh: ");
    Serial.println(node.getResponseBuffer(0x00)/100.0f);
  }

  delay(5000);
}

Fritzing drawing:


Yellow: RO
Green: RE
Blue: DE
Orange: DI

No matter what we try, the result is always "226", which means that the Arduino isn't connecting with the EM340.

We also tried applying a separate 5V power supply for the MAX485-board, still a "226" error.

We also tried all different kinds of registers and both holding and input registers. Nothing.

My gut feeling is that this is not a software error, but something to do with the hardware setup.

You can not simultaneously use pins 0 and 1 for communication with the EM340 and use it for printing debugging statements to the Serial Monitor. Move your EM340 connection over to Serial1 (pins 18 & 19)

I also tried that, and the other Serial connections, 2 and 3. Still, response was 226

The MAX(3)485 (MAX3485 is for 3.3V) needs only 3 wires from MCU. RX to RO, TX to DI and one to RE/DE.

To send DE and RE must be high (RE has inverted logic). To receive both must be low. In most cases RE and DE are connected with each other.

This is how I use it with an ATmega32/644 without library.

void sendRs485(String payload) {
  digitalWrite(RS485Out, HIGH); // RS485 in transmit modus
  Serial.println(payload);
  for (uint8_t i = 0; i < delayTijd; i++) {
    _delay_ms(1);
  }
  digitalWrite(RS485Out, LOW); // RS485 back in receive modus
}

For my use delayTijd is 35ms at 19200Bd to send approx 95 bytes. What not effect my program. There aren't other time critical things to do.

For 'sniffing' the RS485/Modbus communication in the Arduino monitor you can use an RS485=>USB converter like this.

Is the code key on the EM340 correct for RS485/Modbus?

What can you see on the EM340 display?


Are there Rx and/or Tx symbols?

Modbus termination correct done like the left figure 8? Connecting B to T?

I've tried a solution where I joined 1 wire from the Mega to both RE and DE, using the breadboard. No change.

As for time delays, I haven't played around with that. I will try it out. Also the modbus-sniffer looks interesting.

Nothing shows up on the display, neither the Rx or Tx symbols. Which can mean either 1) that something was sent, but it wasn't a correctly formatted modbus-command, or 2) that nothing was sent at all. I have a feeling that nothing was sent at all.

I think I will try first to make sure that the RE/DE pins are set to "send" and then I will try out a payload with delays as you mentioned.

Have you read this essential document?

You need to use the modbusRTUClient. The EM340 must be setup (page 9 and 11 from your linked manual) to the same baudrate you use on the arduino, No parity 1 stop bit.

Yep, read the whole thing and the EM340is set up correctly, with the same baud rate as in the code, no parity, 1 stop bit.

Btw, also forgot to mention that B is indeed connected to T.

But your code use

and not

// start the Modbus RTU server, with (slave) id 1
  if (!ModbusRTUServer.begin(1, 9600)) {
    Serial.println("Failed to start Modbus RTU Server!");
    while (1);
  }

I tried this:

#include <ArduinoModbus.h>

int MAX485_TOGGLE_PIN = 4; // controls both RE and DE on MAX485

float kwhTotal;

void setup() {
  pinMode(MAX485_TOGGLE_PIN, OUTPUT);
  
  Serial.begin(9600);
  while (!Serial);

  Serial.println("Starting: Modbus kWh total - EM340");
  // start the Modbus RTU client
  if (!ModbusRTUClient.begin(19200)) {
    Serial.println("Failed to start Modbus RTU Client!");
    while (1);
  }
}

void loop() {
  digitalWrite(MAX485_TOGGLE_PIN, HIGH); // State: send data
  
  Serial.println("Sending request...");
  if (!ModbusRTUClient.requestFrom(1, INPUT_REGISTERS, 0x0034, 1)) {
    Serial.print("failed to read registers! ");
    Serial.println(ModbusRTUClient.lastError());
  } else {
    short kwhTotalRaw = ModbusRTUClient.read();
    kwhTotal = kwhTotalRaw / 10.0;
    Serial.println(kwhTotal);
  }

  digitalWrite(MAX485_TOGGLE_PIN, LOW); // State: send data

  delay(5000);
}

All I get is some weird symbols, followed by "failed to read registers! Connection timed out"

Some unreadable characters is in most cases wrong baudrate.

It is 100% sure the modbus makes a connection.

The default value for the baudrate is 9600.

Have you placed a resistor 120R between A en B on Arduino site?

I tried to add the resistor, same error.

I also tried different baud rates (9600, 19200, 38400, and so forth, right up to 115200, both on the EM340 and the Arduino). Same error.

And, very interestingly, I also tried to unplug the three wires from the EM340 alltogether, and STILL the same error. Could it be a problem with my MAX485-board? And if so, how do I test for hardware errors?

Btw, the TX LED on the mega blinks twice, with the blinks being about 1 second apart. Also when the three modbus wires are disconnected.

There is something in my setup that is wrong. The Rx and Tx cables are connected to the Megas pins 18 and 19. Is that how it's supposed to be?

It also occurs when the standard hardware serial port is being used for Modbus comms at the same time as printing debug information. Looking at your fritzing drawing in post #1, this is what you are doing. This was pointed out back in post #2.

You need to use a different hardware serial port on your MEGA2560 for your Modbus comms. Try TX1 & RX1 instead.

EDIT: I recall reading somewhere that the Modbus library you are using is more suited to the MKR series of devices - due to RAM issued. I could be wrong.

EDIT2: I seem to recall from a previous experiment that if you are using a MEGA2560 and want to use an alternate serial port, then you need to edit the RS485.cpp file that is part of the ArduinoRS485 library.

A quick look at my modified code, and to use serial port 1 on a MEGA2560 I changed:

RS485Class RS485(SERIAL_PORT_HARDWARE, RS485_DEFAULT_TX_PIN, RS485_DEFAULT_DE_PIN, RS485_DEFAULT_RE_PIN);

to

RS485Class RS485(SERIAL_PORT_HARDWARE1, RS485_DEFAULT_TX_PIN, RS485_DEFAULT_DE_PIN, RS485_DEFAULT_RE_PIN);

It also occurs when the standard hardware serial port is being used for Modbus comms at the same time as printing debug information. Looking at your fritzing drawing in post #1, this is what you are doing. This was pointed out back in post #2.

Yes, I moved those to the TX1 and RX1 pins... I guess I should upload a new Fritz-drawing.

A proper Modbus shield for Arduino is on the way and should be here any day now, and I suspect that will work, but it's much more expensive, so I was hoping the little cheap MAX485-board would be enough. We are also looking at other meters with TCP-modbus.

I will try to alter the RS485.cpp file and see what happens.

On another note, is there a simpler way to just check if there is a hole through to the EM340... not necessarily to receive any information, but just to check that there actually is a valid connection through the cable?

Well, changing SERIAL_PORT_HARDWARE to SERIAL_PORT_HARDWARE1 in the RS485.cpp file didn't fix the problem (it still returns "failed to read registers! Connection timed out
"), but the strange symbols disappeared from the response. And the little red LED on the MAX485-board now turns on and off, I'm guessing when the DE/RE toggle receive and send state? I'm using baud rate 9600, but will try out other rates now

Edit: in other posts timing is mentioned as something to look out for. But is that relevant here? I would think the modbus library handles that?

Snif the RS485 line with RS485=>USB stick or logic analyser. See what the arduino is sending. I'm not sure that the library is sending 2 bytes CRC. The EM needs that.

I'm not sure that the library is sending 2 bytes CRC. The EM needs that.

Interesting, I thought that was part of the Modbus standard?

It should work perfectly well with those little RS485 modules.

Yes, that's the job of the Modbus library to take care of all that.

I'd be surprised if there is an issue with the library - but anything is possible.

Yes, you can monitor the RS485 bus with an RS485-USB dongle and see what messages are being sent. You can also do the same using another Arduino and one of those RS485 modules.

From the modbus-rtu.h file

/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
 * RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes
 */
#define MODBUS_RTU_MAX_ADU_LENGTH  256

It seems that must be OK. Sending 256 byte, 2048 bit on 9600Bd = 214ms.

Have you try

#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library

Like in this example.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.