RS485 Master / Slave communication issue

Hello there.

I'm using Nick Gammon's wonderful library to try to communicate two Arduinos (a Uno and one on a breadboard @ 8 MHz) in a Master / Slave design. After some time I finally got it working, but only one way: the master sends the command just fine to the slave, but I cannot send the feedback from the slave to the master.

I switched the sketches of the Arduinos with each other (the master was now slave, and the slave was now master) to check if there was some problem with the wiring, but they worked fine.

I'm wondering if it has anything to do with timing, but I tried putting delays, using the hardware registers as advised by Nick Gammon himself, but didn't have any success, I cannot send a feedback to the master Arduino.

Here are the codes, modified from Nick's example:

Master:

#include "RS485_protocol.h"
//#include <NewSoftSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 13;
int led;
byte msg[2];

// callback routines

void fWrite (const byte what)
{
  Serial.write (what);  
}

int fAvailable ()
{
  return Serial.available ();  
}

int fRead ()
{
  return Serial.read ();  
}

void setup ()
{
  Serial.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  pinMode (LED_PIN, OUTPUT);  // built-in LED
  led = 0;
}  // end of setup

void loop ()
{

  if (led == 0)
    memcpy (msg, (byte[]){1,1}, sizeof msg);  // device 1, turn on
  else if (led == 1)
    memcpy (msg, (byte[]){2,1}, sizeof msg);  // device 2, turn on
  else if (led == 2)
    memcpy (msg, (byte[]){1,0}, sizeof msg);  // device 1, turn off
  else if (led == 3) {
    memcpy (msg, (byte[]){2,0}, sizeof msg);  // device 2, turn off
    led = -1;
  }

  led++;

  // send to slave  
  digitalWrite (ENABLE_PIN, HIGH);  // enable sending
  sendMsg (fWrite, msg, sizeof msg);

  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);  // disable sending

  // receive response  
  byte buf [10];
  byte received = recvMsg (fAvailable, fRead, buf, sizeof buf);

  digitalWrite (LED_PIN, received == 0);  // turn on LED if error   */ 

  delay (500);

}  // end of loop

Slave 1:

#include "RS485_protocol.h"

const byte ENABLE_PIN = 4;
const byte LED_PIN = 13;
const byte ERROR_PIN = 9;
const byte SLAVE_NUMBER = 1;
const byte GREEN_PIN = 8;

void fWrite (const byte what)
{
  Serial.print (what);  
}
  
int fAvailable ()
{
  return Serial.available ();  
}

int fRead ()
{
  return Serial.read ();  
}
  
void setup()
{
  Serial.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  pinMode (ERROR_PIN, OUTPUT);
  pinMode (GREEN_PIN, OUTPUT);
  pinMode (LED_PIN, OUTPUT);
  digitalWrite (ENABLE_PIN, LOW);
}

void loop()
{
  byte buf [20];
  
  byte received = recvMsg (fAvailable, fRead, buf, sizeof (buf) - 1);
  
  if (received)
    {
    digitalWrite (ERROR_PIN, LOW);
    if (buf [0] != SLAVE_NUMBER) {
      digitalWrite (GREEN_PIN, HIGH);
      return;  // not my device
    }
    digitalWrite (GREEN_PIN, LOW);
    digitalWrite (LED_PIN, buf[1]);  // set light level

    byte msg [] = {
       0,  // device 0 (master)
       3,  // turn light on command received
    };
    
    delay (1);  // give the master a moment to prepare to receive
    digitalWrite (ENABLE_PIN, HIGH);  // enable sending
    sendMsg (fWrite, msg, sizeof msg);
    
    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);  // disable sending
    
    
   }  else { // if nothing received
     digitalWrite (ERROR_PIN, HIGH);
   }  // end receive if
   
}  // end of loop

On the master arduino, the LED is always on. On the slave, the ERROR_PIN lights between the succeed received commands.

Any ideas?

If you are using 1.04 or higher of the IDE, replace:

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

by:

Serial.flush ();

I can't see anything obviously wrong, do you have anything (like a scope or logic analyzer) that can analyze the signals?

I changed that piece of code, but had the same results...

Anyway, I decided to implement my own library using the protocol mentioned here, and now the master sends the command, the slave gets the message, responds, and the master gets the response. Everything is working fine. But thank you, your library helped a lot!

If anyone is interested on the library, feel free to ask for.

Hello LegendBR
I have been trying to accomplish the same thing since a quite some time now with the same issues. This was for a Pan Tilt camera mount i designed for installation at the corner of my house; I wanted it to give me feedback of its angles whenever queried since it keeps scanning the area at a pre-defined speed...
Can you please share this library? I would like to try it out.

Thanks!!