SoftwareSerial TTL MAX RS-485 Master and Multi-Slaves

Hello friends I’m using Serial Software in Master and Serial Hardware in Slave to make a communication

Master asks all Slaves to send data.

Everything works perfectly without data loss when delay(2000);

When the delay is less than 2000 the data does not arrive correctly

I wonder if there is any way to fix this down so that communication becomes faster without data loss

I’m using:

1 - Arduino MEGA 2560 ( Master )
10 - Arduino UNO ( Slave )
12 - TTL MAX RS-485

Master Code:

/*
RS485
18/10/19
*/
#include<SoftwareSerial.h> 

#define MAX_PIN 2  //MAX485 control pin

SoftwareSerial RS485(11,12);

String id_sensor_t;
char tipo_t;
char status_vaga_t;

void setup(){
  RS485.begin(9600);
  Serial.begin(9600);
  pinMode(MAX_PIN, OUTPUT);
}

void loop(){
  SendRequest();
  CheckMsg();
}
  

void CheckMsg(){
  if(RS485.available() > 0){
  String received = RS485.readString();
  int size_msg = received.length();
  Serial.println(received); 
  }
}

void SendRequest(){
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("001");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);
  
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("002");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);
  
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("003");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);
  
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("004");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("005");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);
  
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("006");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("007");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);
  
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("008");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("009");
  digitalWrite(MAX_PIN,LOW);
  delay(2000);
  
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("010");
  digitalWrite(MAX_PIN,LOW);
  //delay(2000);
}

Slave Code:

/*
RS485
18/10/19
*/
#define MAX_PIN 2  //MAX485 control pin

#define trig 10
#define echo 11


String id = "001";
char type = '0';
char status_device = '0';
    
String msg;

    
void setup(){
  Serial.begin(9600);
  pinMode(MAX_PIN, OUTPUT);

  //ULTRASONICO
  pinMode(trig, OUTPUT);
  pinMode(trig, LOW);
  pinMode(echo, INPUT);
}
    
void loop(){
  ReceiveMsg();
}      

void ReceiveMsg(){
  if(Serial.available() > 0){
    String received = Serial.readString();
    int size_msg = received.length();

    // Se receber o id então envia o status
    if (received == id){
      SendMsg();
    }
  }
}

void SendMsg(){
  int size_msg = id.length();
  char char_array[size_msg];
  id.toCharArray(char_array, size_msg);
  char msg[10] = {'[',id[0],id[1],id[2],'.',type,'.',status_device,']'};

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 transmission
  Serial.write(msg);  
  delay(200);
  digitalWrite(MAX_PIN,LOW);    //Disable max485 transmission mode
  delay(500);
}

Can someone help me? Thank you all !!

Your slave receive code needs 700 ms to send a reply, therefore the master needs to leave a big gap between sending each message.

There are many problems with this code. Did you write it?

mikb55:
Your slave receive code needs 700 ms to send a reply, therefore the master needs to leave a big gap between sending each message.

There are many problems with this code. Did you write it?

Yes, i am new in arduino this code was written by me
what improvements do you suggest?

Is there any possibility of getting faster?

DJMatrix-HU3:
Yes, i am new in arduino this code was written by me
what improvements do you suggest?

Is there any possibility of getting faster?

How long does it take the slave to send a 10 byte message?
It's definitely less than 200 milliseconds. You can do the calculations.

What is the purpose of the 500 millisecond delay at the end of SendMsg()?

Before the master sends each message it should check to see if any data has been received as a response to the previous message. This will empty the receive buffer so there is always room for the next message.

When the master does a RS485.write() you cannot immediately pull the MAX_PIN LOW, you have to wait for the amount of time it takes to send 3 characters, then pull it low. You need to calculate the delay time required.

You could simplify the slave code by using a single character identifier for each slave and using char instead of the String class.

thanks for the tips i implemented some improvements

mikb55:
How long does it take the slave to send a 10 byte message?
It’s definitely less than 200 milliseconds. You can do the calculations.

What is the purpose of the 500 millisecond delay at the end of SendMsg()?

500 ms of delay really was unnecessary has been removed from code

mikb55:
Before the master sends each message it should check to see if any data has been received as a response to the previous message. This will empty the receive buffer so there is always room for the next message.

CheckMsg() has been removed from Loop() and pasted below each slave request

mikb55:
When the master does a RS485.write() you cannot immediately pull the MAX_PIN LOW, you have to wait for the amount of time it takes to send 3 characters, then pull it low. You need to calculate the delay time required.

time worked correctly with delay(50);

but it is not possible to decrease the time 950ms after digitalWrite(MAX_PIN,LOW);

mikb55:
You could simplify the slave code by using a single character identifier for each slave and using char instead of the String class.

Maybe not possible because my goal is to use up to 150 slaves

Master:

/*
RS485
18/10/19
*/
#include<SoftwareSerial.h> 

#define MAX_PIN 2  //MAX485 control pin

SoftwareSerial RS485(11,12);

String id_sensor;
char type;
char status_device;

void setup(){
  RS485.begin(9600);
  Serial.begin(9600);
  pinMode(MAX_PIN, OUTPUT);
}

void loop(){
  SendRequest();
}
  

void CheckMsg(){
  if(RS485.available() > 0){
  String received = RS485.readString();
  int size_msg = received.length();
  Serial.println(received); 
  }
}

void SendRequest(){
  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("001");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("002");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("003");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("004");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("005");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("006");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("007");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("008");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("009");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 MAX_PIN
  RS485.write("010");
  delay(50);
  digitalWrite(MAX_PIN,LOW);
  delay(950);
  CheckMsg();
}

Slave:

/*
RS485
18/10/19
*/
#define MAX_PIN 2  //MAX485 control pin

#define trig 10
#define echo 11


String id = "002";
char type = '0';
char status_device = '0';
    
String msg;

    
void setup(){
  Serial.begin(9600);
  pinMode(MAX_PIN, OUTPUT);

  //ULTRASONICO
  pinMode(trig, OUTPUT);
  pinMode(trig, LOW);
  pinMode(echo, INPUT);
}
    
void loop(){
  ReceiveMsg();
}      

void ReceiveMsg(){
  if(Serial.available() > 0){
    String received = Serial.readString();
    int size_msg = received.length();

    // Se receber o id então envia o status
    if (received == id){
      SendMsg();
    }
  }
}

void SendMsg(){
  int size_msg = id.length();
  char char_array[size_msg];
  id.toCharArray(char_array, size_msg);
  char msg[10] = {'[',id[0],id[1],id[2],'.',type,'.',status_device,']'};

  digitalWrite(MAX_PIN, HIGH);  //Enable max485 transmission
  Serial.write(msg);  
  delay(50);
  digitalWrite(MAX_PIN,LOW);    //Disable max485 transmission mode
}

Monitor Serial:

03:17:36 -> [001.0.0]
03:17:38 -> [002.0.0]
03:17:40 -> [003.0.0]
03:17:42 -> [004.0.0]
03:18:44 -> [005.0.0]
03:18:46 -> [006.0.0]
03:18:48 -> [007.0.0]
03:18:50 -> [008.0.0]
03:18:52 -> [009.0.0]
03:18:54 -> [010.0.0]

There was not much difference in the total receiving time of all slaves, but the receiving separated was already a great advance.

Is it still possible to make it faster than that?

Look at the data sheet for the Max485. It can only do 32 nodes on a single bus.

My recommendation is that you should abandon your current effort and use a standard communications library such as Modbus.

mikb55:
Look at the data sheet for the Max485. It can only do 32 nodes on a single bus.

My recommendation is that you should abandon your current effort and use a standard communications library such as Modbus.

mikb55 I tried to implement modBus in several ways but I was unsuccessful ...

Serial.print when receiving slave data using modBus, but there is no such example

I don't know if it's due to my bad english but I have a hard time understanding a modbus library

already tried to use all these and to no avail

The readString() function may be blocking for 1 second. Apparently this is by design. See Arduino readString(); code runs slow - Stack Overflow

The fix is to change the default timeout value. This should work for the hardware serial, but I don't know if software serial behaves the same. Try the following code changes.

In the master code, after the line
RS485.begin(9600);
RS485.setTimeout(100);

In the slave code , after the line
Serial.begin(9600);
Serial.setTimeout(100);

The readString function is strange. I don't know why it uses a timeout.

The issue of 32 nodes using Max485 chips still remains. There is no software fix for this limitation. I doubt that you will be able to find any kind of driver chip that can do 150 devices. You'll need to use multiple buses.

mikb55:
The readString() function may be blocking for 1 second. Apparently this is by design. See Arduino readString(); code runs slow - Stack Overflow

The fix is to change the default timeout value. This should work for the hardware serial, but I don't know if software serial behaves the same. Try the following code changes.

In the master code, after the line
RS485.begin(9600);
RS485.setTimeout(100);

In the slave code , after the line
Serial.begin(9600);
Serial.setTimeout(100);

The readString function is strange. I don't know why it uses a timeout.

The issue of 32 nodes using Max485 chips still remains. There is no software fix for this limitation. I doubt that you will be able to find any kind of driver chip that can do 150 devices. You'll need to use multiple buses.

mikb55 thank you are you right

RS485.setTimeout (100); it worked perfectly without data loss .. the speed of it is amazing !!

I really need to use different buses for 32 more nodes

Thank you for your help

01:04:52.634 -> [001.0.0]
01:04:52.978 -> [002.0.0]
01:04:53.354 -> [003.0.0]
01:04:53.699 -> [004.0.0]
01:04:54.042 -> [005.0.0]
01:04:54.417 -> [006.0.0]
01:04:54.759 -> [007.0.0]
01:04:55.132 -> [008.0.0]
01:04:55.474 -> [009.0.0]
01:04:55.849 -> [010.0.0]