Pages: [1]   Go Down
Author Topic: RS485 Master / Slave communication issue  (Read 1034 times)
0 Members and 1 Guest are viewing this topic.
Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
#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:
Code:
#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?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18807
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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:

Code:
Serial.flush ();

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


Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: April 28, 2013, 09:10:21 pm by LegendBR » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!!

Logged

Pages: [1]   Go Up
Jump to: