RS485: Full duplex?

In a RS485 communication channel, if both arduinos are sending as well as receiving, then will I have to connect 680 ohm resistors on both sides of the channel or only on one side as shown in the link?What exactly is the function of the resistors? Please go to this link, scroll down to Electrical Connections.

The resistors should exist only once per bus but you're free to choose where they are.

But that's completely unrelated to the subject of this thread. Why did you write "Full duplex" there?

The function of the resistors is to define a state on the bus if none of the nodes has the driver active, so none is sending.

Actually , I am working on a mechanism in which arduino1 sends a request to arduino2 for data via rs485. Arduino2 receives the request and is supposed to send data over to 1. But arduino1 is receiving nothing.
I thought it had something to do with the resistors.
Now, I am beginning to wonder where I have gone wrong. I put in hard-coded delays to make arduino 1 wait for the data. Is that causing problems?

Please post both codes and a wiring diagram of your setup.

Delays are a bad idea in most situations but I can tell you more if I see the code.

//Code for arduino 2

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

byte request[10];
byte requestreceived=recvMsg(fAvailable,fRead,request,sizeof(request));

if(requestreceived){
  Serial.println("Wakey Wakey");
  int i;
  for(i=0;i<3;i++){
    Serial.println(request[i]);
  }
  delay(1500);   //Change wait time accordingly during presentation

  byte jumbo[]={0,65,135}; //address,lower range,higher range -set accordingly
  digitalWrite(ENABLE_PIN,HIGH);
  sendMsg(fWrite,jumbo,sizeof(jumbo));
  delayMicroseconds(660);
   /*while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
     UCSR0A |= 1 << TXC0;  // mark transmission not complete
   while (!(UCSR0A & (1 << TXC0))); */  // Wait for the transmission to complete

  digitalWrite(ENABLE_PIN,LOW); 
  Serial.println("Reciprocated");
}
}

//Code for arduino 1

   //only relevant part posted
byte request[]={0,1,0};
    if(speeddatareceived==true){
      digitalWrite(ENABLE_PIN,HIGH);
      sendMsg(fWrite,request,sizeof (request));
      delayMicroseconds(660);
       
      /* while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
      UCSR0A |= 1 << TXC0;  // mark transmission not complete
      while (!(UCSR0A & (1 << TXC0)));*/   // Wait for the transmission to complete

      digitalWrite(ENABLE_PIN,LOW);
      Serial.println("Message sent");
      delay(2500); //fix delaytime so that no message is missed out
      
    }

    //receive response
    byte message[10];
    byte received=recvMsg(fAvailable,fRead,message,sizeof(message));
    if((received)&&(speeddatareceived==true)){
      // put in main response
        Serial.println("Action");
}

Arduino 1 successfully prints "Message sent".
Arduino 2 successfully prints
Wakey Wakey
0
1
0
Reciprocated

But arduino1 does not receive jumbo[].
Wiring: Same as the figure on Gammon forum, resistors connected on arduino 1 side.

As you do not state exactly what you have in terms of hardware we will assume okay.

So, if you have two standard Arduino UNO's each with a single hardware asynchronous communications port and connect them together using TIA-485 drivers, why on Earth are you then doing serial.prints to the computer, assuming your computer is connected to the Arduino via USB ?

You only have 'one' serial port, so use it in either TIA-485 mode or via USB but not both.
People so often fail to see this point and wonder why their code does not function.


Paul - VK7KPA

I am not using the inbuilt serial port for rs485. Rather I am using the softwareserial library.

Because you do not explain that in words or in code how are we supposed to know that, by guessing and making assumptions as we always seem to have to do here.

If you need help, then spend time in writing, detailing exactly in clear and understandable terms what you have and what you need to achieve.

Otherwise we will go around and around in circles guessing.

In your code you have, albeit commented out the following, which lead me to 'assume' you were using a hardware communications port:

/* while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
UCSR0A |= 1 << TXC0;  // mark transmission not complete
while (!(UCSR0A & (1 << TXC0)));*/   // Wait for the transmission to complete

Do you see how that might be confusing for people ?


Paul - VK7KPA

Extremely sorry if I have misled you in anyway. But now, what do I do?

If I were doing this I would get rid of software serial altogether and make the two Arduinos communicate via their hardware asynchronous ports.

You need to think laterally and use that stuff between your ears more.

You need to research and learn about software serial library and its limitations and to know that it can not and will not do full duplex as your topic title states.

When you write:

Wiring: Same as the figure on Gammon forum, resistors connected on arduino 1 side.

Again, you are making a total assumption that everyone knows what and where to find that figure. I would guess that only 1 out of every 1000 people here on this forum would know what you are talking about, maybe even less. So, I hope my point is made clear by now, provide links and concise information.


Paul - VK7KPA

For your kind information, the link has been provided at the very beginning of the post. I think, you should go through the entire post properly before making irrelevant comments.

I have removed the hard-coded delays from the code and modified it quite a bit. Still, the last communication is not happening. I have posted both the codes.

//Code for arduino 2

#include <SoftwareSerial.h>
#include <RS485_non_blocking.h>
#include <RS485_protocol.h>

SoftwareSerial rs485(10,11); //receive pin,transmit pin

//variable definitions
const int ENABLE_PIN=12; //RS485 communication control pin

void setup() {
  // put your setup code here, to run once:
rs485.begin(28800);
pinMode(ENABLE_PIN,OUTPUT);
Serial.begin(9600);
}

//RS485 protocol
void fWrite(const byte what){
  rs485.write(what);
 }
 int fAvailable(){
  return rs485.available();
 }
int fRead(){
  return rs485.read(); 
}
//RS485 protocol ends

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

byte jumbo[]={0,65,135}; //address,lower range,higher range -set accordingly
byte request[10];
byte requestreceived=recvMsg(fAvailable,fRead,request,sizeof(request));

if(requestreceived){
  Serial.println("Wakey Wakey");
  int i;
  for(i=0;i<3;i++){
    Serial.println(request[i]);
  }
  delay(1);   //Change wait time accordingly during presentation

  
  
  digitalWrite(ENABLE_PIN,HIGH);
  sendMsg(fWrite,jumbo,sizeof(jumbo));
  delayMicroseconds(660);
  digitalWrite(ENABLE_PIN,LOW); 
  Serial.println("Reciprocated");
}
}

//code for arduino 1

#include <RS485_non_blocking.h>
#include <RS485_protocol.h>
#include <SoftwareSerial.h>

//Pin Initialisation
SoftwareSerial rs485(10,11); //receive pin, transmit pin
SoftwareSerial mySerial(8,9);

//variable definitions
const int ENABLE_PIN=12;  // RS485 communication control pin
const int Triggerpin=3;
const int redpin=4;
const int greenpin=5;
boolean speeddatareceived=false;
volatile boolean triggered=false;
boolean communicationon=false;
int speeddata;
unsigned long int timeon;
unsigned long int interval;

//Rs485 protocol begins
void fWrite(const byte what){
  rs485.write(what);
}
int fAvailable(){
  return rs485.available();
}
int fRead(){
  return rs485.read();
}
//RS485 protocol ends

//wait function
void wait(int interval){
  unsigned long previousmillis=millis();
  unsigned long currentmillis;
  while(1>0){
    currentmillis=millis();
    if((currentmillis-previousmillis)>=interval)break;
  }
  return;
}

void timeout(){
  triggered=false;
  communicationon=false;
  speeddatareceived=false;
  Serial.println("Assimilator not responding.Communication aborted");
  delay(100);
}

//ISR
void trigger(){
  triggered=true;
}

void setup() {
  // put your setup code here, to run once:
rs485.begin(28800);
pinMode(ENABLE_PIN,OUTPUT);
pinMode(redpin,OUTPUT);
pinMode(greenpin,OUTPUT);
Serial.begin(9600);
mySerial.begin(28800);
//pinMode(Triggerpin,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(3),trigger,FALLING); //check both high and rising to see which one works
}


void loop() {
  // put your main code here, to run repeatedly:
if((triggered==true)&&(communicationon==false)){
    Serial.println("Ready");
    //delay(100);  //wait for 100 ms for first arduino to process
    if(mySerial.available()>0){
      speeddata=mySerial.read();
      Serial.println(speeddata);
      //delay(100);
      if(speeddata>0)speeddatareceived=true;
    }
    else {Serial.println("False alarm");
          triggered=false;
          speeddatareceived=false;
          }
    
    //time to request geophone assimilator for data
    byte request[]={0,1,0};
    if(speeddatareceived==true){
      
      digitalWrite(ENABLE_PIN,HIGH);
      sendMsg(fWrite,request,sizeof (request));
      delayMicroseconds(660);
      digitalWrite(ENABLE_PIN,LOW);
      Serial.println("Message sent");
      
      communicationon=true; //flag variable
      timeon=millis();
    }
}

//receive response
    byte message[10];
    byte received=recvMsg(fAvailable,fRead,message,sizeof(message));
  
    
if((received)&&(communicationon==true)){
        // put in main response
        Serial.println("Action");
triggered=false;
        speeddatareceived=false;
        communicationon=false;
    }

   if((communicationon==true)&&(received==0)){
    unsigned long int timenow=millis();
    interval= timenow-timeon;
    if(interval>=10000)timeout();    //wait for 10 seconds for assimilator to respond, otherwise terminate communication
   }
   
    
}

Anybody?

rs485.begin(28800);

I've seldom seen SoftwareSerial work at 9600 baud, I never saw a reliable communication with that software at such high data rates. Try at 4800, increase only if it works reliably. Use the highest data rate that worked for you over a longer period.

You don't need the delays before lowering the driver enable pin because SoftwareSerial does not work in the background, the write method does not return before the last bit was sent and no interrupt is handled in that time too.

Please learn to format code, these sketches look horrible. How can keep control over program flow with such a formatting? Do you know the auto-formatter of the IDE (Control-T)?

#include <RS485_non_blocking.h>
#include <RS485_protocol.h>

What do these files contain?

Your wait() function does the same as the standard delay(), are you aware of that?

sen_diptangshu writes:

For your kind information, the link has been provided at the very beginning of the post. I think, you should go through the entire post properly before making irrelevant comments.

I always inform myself with each thread, starting from the first post and carefully reading through it all to get some understanding of what the topic is about.

My comment was completely relevant about providing detailed information and links to subjects mentioned.
Maybe you can highlight where the link is that you say is there ?

I will help you and provide the link here as I know the link myself:
Nick Gammon's post on RS485 Communications
And I will make an assumption, again, that the wiring connection you have is according to the first diagram in this link, is that correct ?

Pylon, those two files are from Nick Gammon and can be obtained at the link I provided.
If sen_diptangshu was clear and concise from the very start then all the above posts might have been avoided and some progress might have been made.


Paul - VK7KPA

Still not working at 4800 baud! Now what? No clue what to do!!!! :frowning:

Read again the first part of my post# 9, or try the example from Nick Gammon's site, where there is plenty of examples.


Paul - VK7KPA

Not even working with hardwareserial. I fail to understand why the last bit of communication is failing to take place!! Everything else works fine.

  1. Arduino1 is triggered successfully .
  2. Arduino1 receives speeddata successfully over softwareserial and sends request to arduino2.
    3)Arduino 2 receives successfully, prints out the request format successfully and also prints "Reciprocated",implying that it runs through the sending code.

But, arduino1 does not receive anything. It waits for 10 seconds before declaring a timeout.

Serial on arduino1 shows:

Ready
20
Message sent
(After some time)
Assimilator not responding.Communication aborted.

Serial on arduino2 shows:

Wakey Wakey
0
1
0
Reciprocated

Anybody? This problem is really getting on my nerves!

You have two instances of SoftwareSerial active. Only one can be receiving at any given point in time. It's the last which's listen() method got called, in you case mySerial (in the begin() method call). I have no clue why think you need two instances of a class you should never, never use.

I'm almost sure you never tried with the hardware serial as it probably would have worked with that.