Go Down

Topic: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED] (Read 332338 times) previous topic - next topic

Patrik_Fernandes

#735
Dec 09, 2017, 02:27 pm Last Edit: Apr 08, 2018, 01:59 am by Patrik_Fernandes
I can not understand what's going on with my communication.
It works and then stops and no more comes back to communication.
I've been looking for an answer for two days, but I can not find it.
After the communication drops the first time even I sending another program it does not come back.
can anybody help me?





noiasca

after how many successfull requests does your device stop?
And have you read the manual - they don't recommend software serial for modbus.
DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet

chetanpal

hi everyone
 i am working on a project in which i have to fetch data from LT wl4400 multifunction meter using rs485 and arduino uno R3.i gone through all the previous  posts on this topic. i really need help to find what is the problem in code?
here i am attaching my code ...please help me out ...

#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10
#define TOTAL_NO_OF_REGISTERS 13
#define TxEnablePin 4
enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS
 
};
 
Packet packets[TOTAL_NO_OF_PACKETS];
unsigned int regs[TOTAL_NO_OF_REGISTERS];

/*long previousMillis = 0;
long interval = 1200;
unsigned long currentMillis;
int good_count = 0;*/


void setup()
{
  pinMode(TxEnablePin,OUTPUT);
  Serial.begin(9600);
 
 
  digitalWrite(TxEnablePin,HIGH);
 
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0137,1,10);
//  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0139,1,11);
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0157,1,12);
 
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0 );

 
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
pinMode(TxEnablePin,OUTPUT);

}

void loop()
{
 
  digitalWrite(TxEnablePin,HIGH);

 
  modbus_update();
unsigned long temp;
float voltage, voltage1,voltage2;
//temp = (unsigned long) regs[1] << 16|regs[0];
voltage = regs[10];
voltage = regs[11];
voltage = regs[12];
Serial.print("voltage:");

  Serial.println(voltage);
Serial.print("voltage1:");

  Serial.println(voltage1);
Serial.print("voltage2:");

  Serial.println(voltage2);

delay(1000);
}

noiasca

What do you expect?
What does your code?
Describe clearly what's wrong. We do not have your hardware so we just see some code!

From the code I see:
pinMode in row 45 should do what?

you are declaring in row 11/12 PACKET1, PACKET2

starting with with 35 you try to use
PACKET0,
two times PACKET1
PACKET2

I guess the value at adress 0137 will never find the way into register 10

And check the value of the startadresses, are they really correct. Please provide a datasheet of your device.

in other words: throw away your code and start from scratch.
Take the example and change only the two exisiting packets to your needs as a starting point.
Add only two Serial.prints to print out two registers.

When you get reliable results, enrich the code.


DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet

tamitche

Hi, I have built an Arduino Nano based MODBUS datalogger and I have one remaining strange bug someone might be able to shed some light on.

I am using the SimpleModbusMasterV2rev2 library, an RS485 to TTL adaptor wired to digital pins 0, 1 and 2 (with DE and RE both tied to D2) and a Hitachi  hd44780 16x2 character LCD on pins 3 to 9.  (there is also an SD card interface wired to the SPI inteface (D10-13), some buttons wired between A0 and +5V with series resistors, LEDs  between pins A1-A3 and ground with series resistors and real time clock on the I2C interface (A4-A5), these are still connected but I have created a stripped down version of my code omitting everything except the MODBUS comms and output to the LCD).  I am reading an ABB B21 electric meter and for testing am reading the least signifcant parts of the energy, voltage, current and frequency registers.

I was originally testing with a baud rate of 9600 and 8E1 Data/Parity/Stop Bits.  I was reading 4 holding registers into a unsigned int array regs[], and expected them to be in regs[0] to regs[3], but when I retrieved them they are offset by one, with the result from the register defined in packet[0] returned in regs[1].. packet [2] in regs[3] and packet[3] in regs[0]

Then I started testing other baud rates and Data/Parity/Stop Bit settings and these change the array subscript the values are returned in, e.g. with 9600 and 8O1 the values are in the expected places in the array (regs[0] corresponding to packet[0] etc), with 9600 and 8N2 the result is as for 9600, 8E1

If I only have one packet defined the code always works as expected with regs[0] corresponding to packet[0]  whatever the baud rate and Data/Parity/Stop Bit settings.

Here is my stripped down code.  When I try interrogating different numbers of registers (let's call this n), I am changing
#define TOTAL_NO_OF_REGISTERS n
Commenting out the highest numbered modbus_construct calls as appropriate
Changing the penultimate parameter in the modbus_configure call to n
I am leaving the lcd.print commands and as one would expect they just print garbage when the array subscript exceeds the size of the array.

Further testing shows:
Values returned correctly with odd parity and 1200, 2400, 4800, 9600, 38400 or 5600 baud

Values in wrong order on odd parity with 19200 or 115200 baud, or 9600 to 115200 with even or no parity bit, no values returned at 1200, 2400 or 4800 baud if using even or no parity.  Similar results with 1,3 or 4 packets (=registers) (except obviously if only one packet and register in use can't see the order problem, value is in subscript zero).






//___________________________________

//LIBRARIES
#include <LiquidCrystal.h> //LCD Library
#include <SimpleModbusMaster.h> //Modbus RTU

//DEFINITIONS to insert into code at compile time (so end up in flash memory not RAM)
//LCD Pins
#define pin_RS 8 //arduino pin wired to LCD RS
#define pin_EN 9 //arduino pin wired to LCD EN
#define pin_d4 4 //arduino pin wired to LCD d4
#define pin_d5 5 //arduino pin wired to LCD d5
#define pin_d6 6 //arduino pin wired to LCD d7
#define pin_d7 7 //arduino pin wired to LCD d8
#define pin_BL 3 //arduino pin wired to LCD backlight circuit

//Modbus
#define timeout 1000 //Maximum time for slave to respond (ms)
#define polling 2000 //Maximum scan rate of master to allow slave to return to idle (ms)
#define retry_count 10 //Maximum retries if slave returns response timeout or error
#define TxEnablePin 2 //Pin to set RS485 interface to transmit or receive  (set pin high to Transmit, sets DE and RE on RS485 PCB high. DE must be high to transmit and RE low to receive)

//Misc
#define LongIntMax 4294967295 //Maximum value of a long integer, used in timer check in case value has reset to zero in the interval
#define LCD_UD_Int 900 //LCD Update Interval (ms).  Should happen just over once a second so clock seconds increment nicely

//GLOBAL VARIABLES
unsigned long Prev_LCD_UD = 0; //Timer at last LCD update

#define TOTAL_NO_OF_REGISTERS 4  //Max number of registers to log, used to allocate memory, same as total packets as all packets are sized for one register

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_REGISTERS];

//Create an array to hold returned data in its raw form of unsigned integers
unsigned int holdingRegs[TOTAL_NO_OF_REGISTERS];

//INITIALISE DEVICES
LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7); //Initialise LCD

void setup()
{
   // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
 
  // Initialise backlight
  //BL_Timeout = Def_BL_Timeout; //Backlight timeout to default
  digitalWrite(pin_BL, LOW); //Ensures pullup disabled to avoid damage due to backlight circuit bad design
  pinMode(pin_BL, INPUT); //Set Backlight On

  //Initialise RS485 Pin 
   pinMode(TxEnablePin, OUTPUT);
  digitalWrite(TxEnablePin,LOW);//Receive 485

  //Initialise modbus
  modbus_construct(&packets[0], 6, READ_HOLDING_REGISTERS, 20483, 1, 0); //Energy
  modbus_construct(&packets[1], 6, READ_HOLDING_REGISTERS, 23297, 1, 1);  //Voltage
  modbus_construct(&packets[2], 6, READ_HOLDING_REGISTERS, 23309, 1, 2); //Current
  modbus_construct(&packets[3], 6, READ_HOLDING_REGISTERS, 23340, 1, 3);  //Frequency
  modbus_configure(&Serial, 9600, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, 4 ,holdingRegs); //Changed from max allowable registers (TOTAL_NO_OF_REGISTERS) to actual (x)
}

void loop()
{
  //Poll the MODBUS devices
    modbus_update();

  //Update the LCD periodically
  if(Interval_Check(Prev_LCD_UD, LCD_UD_Int))
  {
    //Clear Display
    lcd.clear(); //In case data not entirely erased by new data

    //Write current values of up to 4 registers
    lcd.setCursor(0,0); //LCD Column (0-15), row (0-1)
    lcd.print(holdingRegs[0]);

    lcd.setCursor(8,0);
    lcd.print(holdingRegs[1]);

    lcd.setCursor(0,1);
    lcd.print(holdingRegs[2]);

    lcd.setCursor(8,1);
    lcd.print(holdingRegs[3]);
   
    //Reset LCD refresh timer
    Prev_LCD_UD=millis();
  }
}
 
byte Interval_Check(unsigned long datum, unsigned long interval) //return 1 if interval has elapsed
{
 unsigned long current_time = millis();
 if ((current_time < datum) && (((LongIntMax - datum) + (current_time)) > interval))
 {
  return 1;
 }
 else if ((current_time < datum) && (((LongIntMax - datum) + (current_time)) <= interval))
 {
   return 0;
 }
 else if ((current_time - datum) > interval)
 {
   return 1;
 }
 else
 {
   return 0;
 }
}

//________________________________________________________________

Any advice welcomed!
Andrew Mitchell
t.a.mitchell@ex.ac.uk

Patrik_Fernandes

#740
Mar 08, 2018, 03:02 am Last Edit: Apr 08, 2018, 01:58 am by Patrik_Fernandes
Good evening,
I am developing a monitoring system through an Arduino Mega master connected to a slave PLC.
Communication OK.
But I noticed in my application that when I used the PACKETS in sequence, the system collapsed, read out, lost connection, I discovered by chance that when I skip the PACKETS the values are read and there are no connection losses.

I ask you whether this is normal or what could be causing this?
The way the system works is to have a delay to carry out the entire reading of at least 20 seconds.
Can I, for example, decrease this time?

noiasca

it might be not the problem you are looking for, but

you've defined
#define TOTAL_NO_OF_REGISTERS 30

but already in PACKET2 you are using

50);//Gerador Tensão


this last number is the register index where the first value will be copied

so check your

unsigned int regs[xx];

best, change it to

unsigned int regs[TOTAL_NO_OF_REGISTERS];



DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet

Andy_ZA

Hi,

I am trying to connect a Schnieder PM5300 power meter to a Mega 2650 using SimpleModbusMaster library.

It seems the data coming from my Mega 2650 UART is inverted. I am using Modscan software as a Modbus master on my PC, and Listen32 on my PC to show the telegrams on the bus.

When my laptop is the master, the telegram to read holding registers looks like this :
01 03 00 00 00 0a c5 cd which works perfectly (asking Modbus slave 01 for function code 03, starting at address 00 00 and a length of 00 0a registers).

When I switch to Arduino as the master, the same telegram comes out like this:
7f 7e ff ff eb 75 65 00. It seems to be inverted.

The address in binary should be 0000 0001
But arduino sends out 0111 1111
This has two problems: the bits are inverted, and also MSB and LSB are reversed. This pattern is true for everything arduino sends out

When it should send 00 it sends ff
0000 0000 is instead 1111 1111

I have tried MAX485 and MAX232 to convert TTL to RS485 or RS232, both with the same results. I even tried to change my Mega2650 for an Uno with the same result.

It all seems to point to a problem with the UART or number format of the library.

Any suggestions?

Here is my sketch:

Code: [Select]
#include <SimpleModbusMaster.h>

// Port Settings
#define baud 19200
#define timeout 400
#define polling 1000
#define retry_count 10

// tggle rx/tx pin on the driver
#define TxEnablePin 2
#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 13

// 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,
 // PACKET3,
 // PACKET4,
 // PACKET5,
 // PACKET6,
 // PACKET7,
 // PACKET8,
  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() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  
  // Initialise packet for Schneider PM5300
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 10, 10);

  //This was used for reg 1123 in PM800
  //modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 1123, 1, 10);

  // Test fot outgoing telegram to check parameters are ok
 // modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 0, 1, 0);
 // modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial2, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
  pinMode(LED, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

    modbus_update();

    float Voltage, Voltage1, Voltage2;
    Voltage = regs[0];
    delay(1000);
    Serial.println("Debug window");
    Serial.print(packets[PACKET1].requests);
    Serial.print("Voltage");
    Serial.print(Voltage);
    Serial.println(" V");
    Serial.print("successful requests: ");
    Serial.println(packets[PACKET1].successful_requests);
    Serial.print("failed requests: ");
    Serial.println(packets[PACKET1].failed_requests);  
        Serial.print("exception errors: ");
    Serial.println(packets[PACKET1].exception_errors);
        Serial.print("connection: ");
    Serial.println(packets[PACKET1].connection);
  
 // regs[0] = analogRead(0); // update data to be written to arduino slave
  
  analogWrite(LED, regs[0]>>2); // constrain adc value from the arduino slave to 255

}






tamitche

It might be worth trying an alternative library to handle the MODBUS comms?  I used https://github.com/charlesbaynham/simple-modbus/ , file SimpleModbusMasterV2rev2.zip which I have tested successfully with a Schneider PM710.  There seem to be a lot of these libraries around which are just slightly different from each other so you may have a rogue one.

As noted in my original post I do get odd behaviour with some Baud rate and parity combinations, I would start with 9600, odd parity (8O1) which works as expected.

Andy_ZA

Thanks Tamitche,

I'm using the same library.. will persevere. Any chance you can post your sketch so I can see how the register addressing comares between the Schneider 710 and 5300?


tamitche

The register list for the Schneider PM710 is available here: http://www.schneider-electric.com/resources/sites/SCHNEIDER_ELECTRIC/content/live/FAQS/212000/FA212631/en_US/PM710_Public_Register_List_v3.150.pdf

These were read with the function parameter set to READ_HOLDING_REGISTERS.  The register number is as in the register list, with one subtracted (e.g. 4109 for hours run, 4120 CT secondary)

I am always reading a single register so have simplified my code as TOTAL_NO_OF_PACKETS will always equal TOTAL_NO_OF_REGISTERS

gunaone

hy all....

i have problem with PM2100 RS485 arduino.

i was try any code, library and i get nothing...

sometime if i change the addres, i get dari anvalid...

help please....

Patrik_Fernandes

#747
Mar 20, 2018, 12:58 pm Last Edit: Apr 08, 2018, 01:58 am by Patrik_Fernandes
Thank you very much, that was the problem. My system is 100% functional and lastly I made an improvement in SRAM consumption. It was fast !!

it might be not the problem you are looking for, but

santhoshrajavels

I will communicate arduino and elmeasure EN8400.The will show trAns and arduino will receive some value .How to get the correct value in arduino

How to change uint16_t to string in arduino

irutechdrive

Hi All,

Is there somebody try to link arduino modbus to other device with included the CRC code ?

Thanks

Go Up