RS 485 half duplex communication problem

I am a novice to Arduino. I came across an article on rs 485 and currently trying to implement the same between 2 arduino unos. I copied code from internet which is pretty simple but I am unable to make communication work properly. Here is the code for master arduino with explanation of what I am trying to do.

 **Master Arduino Code** 
/* master will send a message I1LF where I shows start of master message by master.
 *  1 shows the slave device No. from whom data is to be fetched and L 
 *  shows that master wants to read slave's sensor data 
 *  and F indicates finish of message by master. 
 *  slave will respond by sending Serial.println(i1) where i is slave no and 1 is to let master know that 
 *  correct slave is sending data. then slave would send sensor_value and then f indicates end of slave message. 
 *  master will display data read from rs 485 bus. 
 */

#include<LiquidCrystal.h>                    //Library for LCD display function  
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable =  2;  
int value1=0;
void setup() 
{ 
  Serial.begin(9600);
  pinMode(Enable, OUTPUT);   
  digitalWrite(Enable, HIGH);  // put master arduino into transmission mode.  
  lcd.begin(16,2);
  lcd.clear();
}
void loop() 
{  
  Serial.print('I');  // I indicates master has started communication.  
  Serial.print('1');  // this is the address of slave from whom data is to be fetched. 
  Serial.print('L');  // this means master wants to read sensor data. 
  Serial.print('F');  // this means end of message. 
  Serial.flush();    // wiat untill all data has been pushed to the serial. 
  
  digitalWrite(Enable, LOW); // put master into receiving mode. 
  if(Serial.find('i'))    // i will be sent (to indicate start of slave message) by the slave that was 
                               // prompted by master to answer. 
  {                       // indicating master wants to read slave's sensor data.  
                   
      int slave1 = Serial.parseInt();   // check which slave is sending data.   
      value1 = Serial.parseInt();       
      if(Serial.read() == 'f' && slave1 == 1)   // f indicates end of message sent by slave and 1 
                                                                      //is the address of the slave sent by 
                                                    // the slave so that master can recognize which slave is this. 
      { 
        lcd.setCursor(0,0);
        lcd.print("Slave 1:      ");
        lcd.setCursor(11,0);
        lcd.print(value1);
      }
 }
      digitalWrite(Enable, HIGH);
      delay(300);
}

````Preformatted text`

Slave Code

#include<LiquidCrystal.h>               
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable =  2; 
const int SlaveNumber = 1;
void setup() 
{ 
  Serial.begin(9600);  
  pinMode(Enable, OUTPUT);
  digitalWrite(Enable, LOW);   // initially put slave in receiving mode
  pinMode(A0, INPUT);
  lcd.begin(16,2);
  lcd.clear();
} 
void loop() 
{ 
  if(Serial.available())
  { 
    if(Serial.read()=='I')  // all slaves will detect I on rs 485 bus which means master has started commmunication. 
    {    
        int Slave = Serial.parseInt();  // read next character on rs 485 bus which would definitely be a digit 
                                        //indicating slave no to whom master wishes to communicate.     
        if(Slave == SlaveNumber)    // check if master wants to commnucate with you. 
        {   
            char command = Serial.read();       // read next character in serial buffer which would be command L 
             delay(100);
             if(command == 'L')                  
             {   
                if(Serial.read()=='F')    // if master's message has finished. 
                 { 
                   int AnalogValue = analogRead(0);  // read sensor 
                   digitalWrite(Enable, HIGH);    // put slave in transmission mode. 
                   Serial.print("i");             // i indicates start of slave message 
                   Serial.println(SlaveNumber);   // send slave no so that master can identify 
                                                                   //which slave he is receiving data from.  
                   Serial.print(AnalogValue);    
                   Serial.print("f");     // indicates end of message by the slave. 
                   Serial.flush(); 
                   digitalWrite(Enable, LOW);           // put slave in listening ( receivig ) mode 
                 }
             }
             
        }
    }

  }
}
This is screen shot of proteous simulation showing Master unable to read slave1's sensor data 


https://drive.google.com/file/d/1QDYk4NMfvtLyZ-UyQsluTd0WxQgf5Tiv/view?usp=sharing


I assessed that problem arose because of master and slave both being in transmission mode so I attached a not gate between master's enable pin and slave's enable pin and then master is working fine. but practically attaching a not gate wont be possible. that's why I want to know how to ensure that enable of both master and slave is not high simultaneously. I have tried a couple of strategies and introduced delays at different locations in the code but nothing seems to work. by hit and trial it starts to work sometimes but I want to know the correct way of doing so. 

This is screen shot of proteous simulation which shows master reading correctly slave1 data only after I attach a not gate between master Enable pin and Slave's Enable pin.
Code for both master and slave and circuit is exactly the same as before. only a not gate has been used between master's enable pin and slave's enable pin. 

[proteous circuit of rs 485 working ](https://drive.google.com/file/d/1L1NsiTzgcBSSYoXa8uVOMnY0Uhg5vBDQ/view?usp=sharing)

Hi, @eengr152
Welcome to the forum.

It will show you how to post your code.

Have to actually built your project or are you running a simulation only?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:
PS, About to go to bed, 1:50am here in Australia.. :sleeping: :sleeping: :sleeping:

Thanks Tom,
I am running Proteous simulation. I dont know why i am not able to upload screen shot of the simulation as that would have made picture clearer. I have been running proteous simulations before and those worked quiet OK but i am now stuck at RS 485. Problem is not with Proteous or circuit problem is basically with both Arduinos going in transmission mode simultaneously.

Browse web for "madleech rs485 library". Works flawlessly with auto485, another library. Ignore that it's for model RRs, that's irrelevant.

This will wait for the last character brought on the road from the buffer, but then cuts the line before that character has been transferred. You have to wait one more character transmission time before turning off the sender.

You also can enable the receiver during transmission of the last character(s) and wait until all is received.

Hi,
Can I suggest you forget your code for the moment.
WRITE some simple code, just to get the two 485 units communicating.

Google;

arduino rs485 tutorial

This will help, get back to basics and learn how the system works.

This should help you by testing your hardware, you will gather an understanding of the code necessary to accomplish your quest.

I suggest you also get some hardware and experiment in real life.

Thanks.. Tom.. :coffee: :smiley: :+1: :coffee: :australia:

tried with madleech rs485 library but still having same problem.

one way communication works fine. master sends data seamlessly to slave but when slave tries to send data back to master then problem arises.

Thanks for the suggestion. Unfortunately even adding a dealy of 5ms before digitalWrite(Enable, LOW); doesnt work.

Please show your actual master code.

Thanks for your response.

/* master will send a message I1LF where I shows start of master message 
 *  1 shows the slave device no from whom data is to be fetched and L 
 *  shows that master wants to read slave's sensor data 
 *  and F indicates finish of message by master. 
 *  slave will respond by sending Serial.println(i1) where i is slave no and 1 is to let master know that 
 *  correct slave is sending data. then slave would send sensor_value and then f indicates end of slave message. 
 *  master will display data read from rs 485 bus. 
 */
#include<LiquidCrystal.h>                    //Library for LCD display function  
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable =  2;  
int value1=0;
void setup() 
{ 
  Serial.begin(38400);
  pinMode(Enable, OUTPUT);   
  digitalWrite(Enable, HIGH);  // put master arduino into transmission mode.  
  lcd.begin(16,2);
  lcd.clear();
}
void loop() 
{  
  Serial.print('I');  // I indicates master has started communication.  
  Serial.print('1');  // this is the address of slave from whom data is to be fetched. 
  Serial.print('L');  // this means master wants to read sensor data. 
  Serial.print('F');  // this means end of message. 
  Serial.flush();    // wiat untill all data has been pushed to the serial. 
  delay(5);
  digitalWrite(Enable, LOW); // put master into receiving mode.
  while (!Serial.available()); 
  if(Serial.find('i'))    // i will be sent (to indicate start of slave message) by the slave that was // prompted by master to answer. 
  {                       // indicating master wants to read slave's sensor data.  
                   
      int slave1 = Serial.parseInt();   // check which slave is sending data.   
      value1 = Serial.parseInt();
      while  (!Serial.available()){};       
      if(Serial.read() == 'f' && slave1 == 1)   // f indicates end of message sent by slave and 1 // is the address of the slave sent by 
                                                // the slave so that master can recognize which slave is this. 
      { 
        lcd.setCursor(0,0);
        lcd.print("Slave 1:      ");
        lcd.setCursor(11,0);
        lcd.print(value1);
      }
 }
      digitalWrite(Enable, HIGH);
      delay(300);
}

Please read what Serial.flush() does! It puts all waiting characters into the UART but does not wait for the transmission of the last character.

You have to split the transmitter/receiver enable. The receiver can always be ON if you check the echo of all outgoing characters.

I think one problem lies in your master code you posted (post #11).

You should put the RS485 transceiver into Rx mode in setup.

You should only put the master into Tx mode when the master wants to transmit something. The rest of the time it should be in Rx mode, otherwise the slave(s) cannot take control of the RS485 bus to respond.

i added delay of 5ms after Serial.flush() in both master and slave codes but it still does not work. if slave stays in receiving mode only then the system works fine.

if master is only sending data to slave i.e. one way communication works fine.

I understand that you don't understand what I wrote. I'm out.

You are right basically problem arises when both master and slave try to take control of the bus simultaneously. But adding delays and making slave only respond when master is demanding data is also not working. I think i would rather have to go for full duplex communication. I did what you suggested and modified the code such that master remains in receiving mode except for the time it is to send data. but still problem is appearing in exactly the same fashion.

Not sure what you're doing wrong, because the madleech code I referred you to is straightforward. However, I'm no fan of simulation/emulation, I prefer to actually connect devices, so I can't tell you where your problem lies there.
If nothing else, you should tear apart the madleech and Auto485 implementations to figure it out - they're both open source, so you should be able to figure it out.

That situation shouldn't occur. If you have a command response setup, then the slave(s) should only transmit in response to a message to themselves from the master.

I'm with @camsysca here. I prefer to work things out on real hardware. In my opinion, a simulation only gets you so far. You can also run into problems with the speed (or lack of) if you are interacting with real hardware.

This tells me the problem is in your code, I think. Why doesn't it work, if the master requests something and the slave then responds? That works, absolutely, no problem, with madleech and Auto485. Since the madleech approach is all about a specific bus implementation, I get it that you can't use it for your job, but it does work, so should provide a starting point. the Auto485 code it's built upon should do what you want.