How to Connect PM1200 to Arduino Mega 2560

Please help me. I’m trying to create a power meter data logger using an Arduino Mega 2560, but when I try, the values are always unreadable, and the connection always fails. I tried using Modbus Poll, and the connection works, and the values are readable, but when I try using the Mega 2560, the values are always unreadable.

Wiring diagram:

  • VCC --> Vin 5V Mega2560
  • Tx --> Pin 18 Tx1
  • Rx --> Pin 19 Rx1
  • GND --> GND Mega2560
  • A+ --> A(D1) PM1200
  • B- --> B(D0) PM1200

I am using an RS485 to TTL, Slave ID 1, Baud rate 9600, Parity Even.

#include "SimpleModbusMaster.h"
/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/
//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10
// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 0
#define LED 9
// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 2
// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
//  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};
// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];
// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];
void setup()
{
  Serial.begin(9600);
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 3911, 2, 0);
//  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  pinMode(LED, OUTPUT);
}
void loop()
{
  if (Serial.available()){
     int inByte =Serial1.read();
     Serial.write(inByte);
  }
  modbus_update();
  Serial.println("==================================");
  Serial.print("successful_requests \t : ");
  Serial.println(packets[PACKET1].successful_requests);
  Serial.print("failed_requests \t : ");
  Serial.println(packets[PACKET1].failed_requests);
  Serial.print("exception_errors \t : ");
  Serial.println(packets[PACKET1].exception_errors);
  Serial.print("connection \t\t : ");
  Serial.println(packets[PACKET1].connection);
  Serial.println("==================================");
  delay(1000);
  float A = *(float*)&regs[0]; Serial.print (" F   : "); Serial.println (A);
  
}

Welcome to the forum

Tx --> Pin 18 Tx1
Rx --> Pin 19 Rx1

Looks wrong.

Tx from one device would normally go to Rx of the second device for obvious reasons, but I am not familiar with whatever a PM1200 is

I’ve already tried swapping Tx to Rx and Rx to Tx, but the result is still the same.

EasyLogic PM1200 schenider, PM1200/ Power Meter 1200

I see this in the data sheet for the PM2000

Communication (PM1200)
RS-485 serial channel connection
Industry standard Modbus RTU protocol

Note that the Serial interface is RS-485, not TTL used by the Mega

Have you got any hardware converting from one to the other between the Mata and the PM1200 ?

image

I am using this hardware.

What is that a picture of and how is it connected to the two devices in your project ?

A schematic, even a photo of a hand drawn circuit, is good enough

Wiring diagram:

  • VCC --> Vin 5V Mega2560
  • Tx --> Pin 18 Tx1
  • Rx --> Pin 19 Rx1
  • GND --> GND Mega2560
  • A+ --> A(D1) PM1200
  • B- --> B(D0) PM1200

I tried using Modscan, and it reads correctly.

However, when I run it on the Arduino Mega, it doesn't work, and the connection is not established.

If you check in the modscan32 log ( show traffic option ) you will see that it will use address 3910.
Arduino modbusmaster library, on the contrary, uses the exact address you set ( not sure if simplemodbusmaster does the same )

Tx --> Pin 18 Tx1
Rx --> Pin 19 Rx1

Still looks wrong to me

When the Arduino transmits the other device receives it. Hence Tx on the Arduino needs to connect to Rx on whatever is receiving it

Your RS485 board does not have a TxEnablepin. The software needs that pin.

I’ve already swapped Tx to Rx or Rx to Tx, but it’s the same.

TxEnablepin in my software 0

Do you have pin 0 connected to the enable pin on your RS485 board?

I’m not connecting it to pin 0 on the RS485. Could you please check my code above?

The enable pin is not strictly needed these board generate it on the fly ( the board is always in rx, and switch to tx only when requested, after a short delay reverts to rx ).
From the image on the back of the board the tx pin is 'from tx' and the rx is 'to rx' so your connection is ok
Regarding the library I used modbusmaster so can't help on this but check the 'address-1' as explained above

#define TxEnablePin 0

set to pin 2
connect pin 2 to the TxEnable pin on your RS485 board but your board does not have a Txenable pin

Does 'address-1' mean address 3910?

yes