MODBUS RTU (RS485)

I am trying to receive some data out of an modbus slave, the TX and RX pin on the RS485 are blinking while connected. If not connected TX blinks 10 times, and stops (as programmed). So i am guessing i do got an connection towards the slave. Only not being able to make some data visible.

i've tried the scenario where the information is 32 bits and not 16 bits. Only still didn't got relevant data, i got things like a8/a8 (HEX). What am i doing wrong, or how can read information out of the (array) register? As i'm assuming i should do that, only didn't figured out how.

For monitoring i used an TTL to usb converter with labview watching.

  mySerial.write("slave data");

code:

#include <SimpleModbusMaster.h>
#include <SoftwareSerial.h>

//////////////////// Port information ///////////////////
#define baud 57600
#define timeout 2000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2 

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

// 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];

SoftwareSerial mySerial(10, 11); // RX, TX

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

//Timers
unsigned long previoustime = 0;
const long interval = 250;     // interval logging
unsigned long currenttime;


void setup()
{
 mySerial.begin(57600);
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 0, 7, 0);
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
}

void loop()
{
   unsigned long currenttime = millis ();
   
  if (currenttime - previoustime >= interval)  {
  previoustime = currenttime; 
  modbus_update();

  long temps = (long)regs[235];
  //mySerial.write("hello");
  mySerial.write(temps);
  }
}
#define TOTAL_NO_OF_REGISTERS 29

unsigned int regs[TOTAL_NO_OF_REGISTERS];

  long temps = (long)regs[235];

  mySerial.write(temps);

Sniff? Sniff? Something doesn't pass the sniff test here.

Why are you debugging using SoftwareSerial? Get that device off the Serial instance, and onto a SoftwareSerial instance, so you can use Serial for debugging.

PaulS:

#define TOTAL_NO_OF_REGISTERS 29

unsigned int regs[TOTAL_NO_OF_REGISTERS];

long temps = (long)regs[235];

mySerial.write(temps);



Sniff? Sniff? Something doesn't pass the sniff test here.

Why are you debugging using SoftwareSerial? Get that device off the Serial instance, and onto a SoftwareSerial instance, so you can use Serial for debugging.

I used this because i though the Serial (usb) connection would interrupt with the serial rs485 shield that is using pin 0 and 1. So i though ohw well i can use an serial TTL converter to make the data visible, who properly is interrupting with the serial connection.

Only i can't use the Serial monitor cause the serial line is used for the rs485 (modbus) shield, right?

How should i make the data visible? For debugging etc?

Using Serial.print(); ?
Or is there another way to do this?

Which shield are you using? No decent shield forces you to give up Serial.

PaulS:
Which shield are you using? No decent shield forces you to give up Serial.

For the RS485 shield i use the JOY-IT RS485 shield, and later i will be using an W5100 Ethernet shield for TCP connection.

Gert-Jan_Snik:
For the RS485 shield i use the JOY-IT RS485 shield, and later i will be using an W5100 Ethernet shield for TCP connection.

I clicked on the link to the shield you are using. Nothing happened.

PaulS:
I clicked on the link to the shield you are using. Nothing happened.

Uhm i didn't included a link of the shield. So it would be weird if something would happend.

He're is a link of the shield i use: Buy Joy-it Serielle Schnittstelle für Arduini RS485 Shield | Conrad Electronic

So where do you have the jumpers set? Details please.

ohw sorry, my bad.

i'm using 5 V.
i'm using TX_ctrl.
For TX i use D1.
For RX i use D0.

If i forgot something please let me know.

Cause i can't use an ttl converter because the serial port, (led's keep blinking while connected and receiving some data from the arduino like hello (no modbus data))
While using the Serial monitor the leds stop blinking because i guess the serial port of the chip is used, as i expected.

Do you think reading element 235 of a 29 element array is going to work?

MarkT:
Do you think reading element 235 of a 29 element array is going to work?

Uhm nope, only it was try and error. And while ttl printing (regs) i received an HEX value that was exual to 235. Worth the try right? And that was the latest option i tried before uploading the code to this post. So that's the reason why.

On a plc i receive the data of a few NTC on Aray 0,1,2,3,4,5,6,7. I've tried those regs, only without succes, also with combining two regs incase the data is 32 bits.

Not worth the try. If anything is writing outside your array bounds all sorts of confusing symptoms can
happen - I'd make sure that cannot happen in the first instance (make array longer?).

MarkT:
Not worth the try. If anything is writing outside your array bounds all sorts of confusing symptoms can
happen - I'd make sure that cannot happen in the first instance (make array longer?).

Yeah make sense it wasn't working.

Uhm what do you mean?

The regs array? Cause according to the manual i included below with function 4 for reading the input register there is a limit of 29 registers.

The slave? What should i change than, and how?

SimpleModbusMasterManual.pdf (275 KB)

Gert-Jan_Snik:
ohw sorry, my bad.

i'm using 5 V.
i'm using TX_ctrl.
For TX i use D1.
For RX i use D0.

If i forgot something please let me know.

Cause i can't use an ttl converter because the serial port, (led's keep blinking while connected and receiving some data from the arduino like hello (no modbus data))
While using the Serial monitor the leds stop blinking because i guess the serial port of the chip is used, as i expected.

Based on the post so far, you have SoftwareSerial running on pins 0/1 along with the serial monitor running by means of the hardware serial. Please use pins 0 and 1 for one purpose, either hardware or software and either RS-485 or Serial monitor. (I suggest since you insist on using SoftwareSerial to go ahead and use pins 2 and 3 for RS-485 via Software Serial. We are also assuming you are speaking of an Arduino UNO. Assuming because you have not said otherwise.

adwsystems:
Based on the post so far, you have SoftwareSerial running on pins 0/1 along with the serial monitor running by means of the hardware serial. Please use pins 0 and 1 for one purpose, either hardware or software and either RS-485 or Serial monitor. (I suggest since you insist on using SoftwareSerial to go ahead and use pins 2 and 3 for RS-485 via Software Serial. We are also assuming you are speaking of an Arduino UNO. Assuming because you have not said otherwise.

It's correct that i am using an arduino uno, sorry i didn't said that.

The RS485 shield was running on pin 0 and 1, and while serial monitoring it bugs because usb serial also used these pins. So that make sense.

The Softwareserial (TTL to usb) was running on pin 10 and 11. The reason i reached for this is because i knew that the usb uses pin 0 and 1 for serial connection, and as far as i know i can't change the TX and RX pin within the modbus librairy without tweaking the librairy itself.

Is what i was doing so far right and possible? or can the uno chip only have one serial interface active?

All the chips (or at least the ones I'm aware of), including the UNO can only have one pin do one thing. You can't run SoftwareSerial on a pin that is also being used for hardware serial. Nor can you use the serial monitor and transmit RS-485 at the same time. The other similar shield to the one you have chosen, has a switch to toggle from the USB connection to the RS-485 connection. I wonder why that would be?

You can have SoftwareSerial (one instance based on other limitations) active while also using hardware serial on pins 0/1. That is perfectly legit. You can't have them overlap, in way way. One thing at a time.

What TTL to USB did you have running on pins 10/11? There has not been mention of this.

adwsystems:
All the chips (or at least the ones I'm aware of), including the UNO can only have one pin do one thing. You can't run SoftwareSerial on a pin that is also being used for hardware serial. Nor can you use the serial monitor and transmit RS-485 at the same time. The other similar shield to the one you have chosen, has a switch to toggle from the USB connection to the RS-485 connection. I wonder why that would be?

You can have SoftwareSerial (one instance based on other limitations) active while also using hardware serial on pins 0/1. That is perfectly legit. You can't have them overlap, in way way. One thing at a time.

What TTL to USB did you have running on pins 10/11? There has not been mention of this.

I'm currently not at the office, where i have the arduino and TTL to usb. So furter information about the hardware i can't give you right now.

Uhm yeah idk why other shield would have an toggle, maybe so you can switch the usage of a pin for more options, like using it for serial monitoring and the rs485 shield?

So using an SoftwareSerial on other pins than 0 and 1 is possible?

So next question, how can i make the slave data viewable on the SoftwareSerial?

Gert-Jan_Snik:
So using an SoftwareSerial on other pins than 0 and 1 is possible?

Possible Yes. Must Yes. It's like swallowing and breathing. You can only do one at a time. Choose one.

Gert-Jan_Snik:
So next question, how can i make the slave data viewable on the SoftwareSerial?

Whenever you receive data from the RS-485 serial port, write it to the hardware serial to USB to Serial Monitor.

adwsystems:
Possible Yes. Must Yes. It's like swallowing and breathing. You can only do one at a time. Choose one.

Whenever you receive data from the RS-485 serial port, write it to the hardware serial to USB to Serial Monitor.

Uhm while using the usb Serial monitor the tx and rx pins don't blink, so i guess that this is interrupting with the serial connection on the rs-485 shield witch is using pin 0 and 1. This makes sense because the serial port on 1 and 0 is used on two connection, and only connect on one.

I figured out an way of making the correct data visible. Through an lcd screen.

#include <SimpleModbusMaster.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,4,5,6,7);

//////////////////// Port information ///////////////////
#define baud 57600
#define timeout 2000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2 

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

// 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];

//Timers
unsigned long previoustime = 0;
const long interval = 250;     // interval logging
unsigned long currenttime;

// modbus data
long T01;
long T02;
long T03;
long T04;


void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 0, 7, 0);
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

  lcd.begin(16,2);
}

void loop()
{
   unsigned long currenttime = millis ();
   
  if (currenttime - previoustime >= interval)  {
  previoustime = currenttime; 
  modbus_update();

  long T01 = regs[0];
  long T02 = regs[1];
  long T03 = regs[2];
  long T04 = regs[3];

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("T1:");
  lcd.print(T01);
  
  lcd.setCursor(0,1);
  lcd.print("T2:");
  lcd.print(T02);

  lcd.setCursor(8,0);
  lcd.print("T3:");
  lcd.print(T03);

  lcd.setCursor(8,1);
  lcd.print("T4:");
  lcd.print(T04);

  }
}

Only i wanne use more slave, i could set the local start addres of the register to an higher number. Only got an limitation of 29 regs, and i will be using 6 regs per slave. So there is an limitation of almost 5 slaves.

Is there an way i can use an if statement, and in that statement i can use the slave address or packet that will be used. Where the register will be overwritten, and if there is the correct packet or slave address the modbus data will be stored in a long on the arduino. Or any other thoughts on this?