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?