Hi There,
I have just been getting familiar with Arduino's software serial port, and sending text messages through the port between two Arduino UNO's. I also printed these messages through the serial monitor so I could see what I had written, and received and acknowledgement from the receiver once they received a sent message.
From there I have shifted to RS-485, and initially I was hoping to do the same thing. I understand it gains complexity through the implementation of protocols, however I just wanted to be able to send text messaging between UNO's as I had done over UART just at the moment, before I read more into using protocols.
I have adapted the initial code I had for the UART communications to include definitions for RO, DI, DE and RE, with digital write high and low in areas I wish to send and receive messages.
I know typically that the master sends out an addressed message to the slave devices, however as mentioned I am just wanting to communicate freely between master and slave at this point, so I have not set this part of it up.
When I send a message from the master, I see what I have printed to the serial monitor, and I also see the slave receive the sent message as it also prints it to the serial monitor. Yes I have two serial monitors open to see the communications between Arduino UNO's.
The issue I have, is it seems as if the slave does not write the Ack: (Received Message) back to the master. I cannot figure out why this is the case, as I have checked the contents of the buffer with the message I wish to write back and it is there so I am unsure what is going on.
Would it be possible to look at the code and provide me with some advice on the next steps I should try?
Below I have copied the Master and Slave sketches.
MASTER RS-485
#include <SoftwareSerial.h>
// Defining the digital IO pins to align with RS-485 definitions.
#define RO 10
#define DI 11
#define DE_RE 12
SoftwareSerial swSerial_MasterNode(RO,DI);
// Char array variables to store the serial data/message.
char buffer1_size[32];
char buffer2_size[32];
char ack[6] = "Ack: ";
char CR[3] = {'\n'};
char buffer3_size[39];
// Integer variables.
int bytesRead1;
int bytesRead2;
int charCheck;
int ackFlag;
int txFlag;
void setup()
{
// Open serial port and wait for connection.
Serial.begin(9600);
while(!Serial)
{
// Wait for the serial port to connect - needed for native USB port.
}
// Set data rate for the software serial port.
swSerial_MasterNode.begin(9600);
// Define DE_RE as an output.
pinMode(DE_RE, OUTPUT);
// Master sets this pin to high to begin transmission.
digitalWrite(DE_RE, HIGH);
}
void loop()
{
// If there is no serial data/message available, perform the following.
if(swSerial_MasterNode.available() == 0)
{
// If there is data/message written in the serial monitor, perform the following.
if(Serial.available() > 0)
{
// Read the serial port and store data in the integer variable until either a newline character (ENTER KEY) is read, or the byte limit is reached.
bytesRead1 = Serial.readBytesUntil('\n',buffer1_size,32);
// Add a null character to the array to terminate the string.
buffer1_size[bytesRead1] = '\0';
// Print the data/message to the serial monitor.
Serial.print("Transmit message: ");
Serial.println(buffer1_size);
// Set write conditions and write data/message to the port.
digitalWrite(DE_RE, HIGH);
swSerial_MasterNode.write(buffer1_size);
digitalWrite(DE_RE, LOW);
txFlag = 1;
delay(50);
swSerial_MasterNode.flush();
}
}
// If there is a serial data/message available, perform the following.
if(swSerial_MasterNode.available() > 0)
{
bytesRead2 = swSerial_MasterNode.readBytesUntil('\n',buffer2_size,32);
buffer2_size[bytesRead2] = '\0';
// String variable to hold the data/message in the buffer.
String buffer2_String(buffer2_size);
// Index through the buffer string and store the integer value in charCheck when the colon is found (':'). This will determine if the data/message is an acknowledgement or not.
charCheck = buffer2_String.indexOf(':');
// This nested logic checks if the character is not in the data/message. Received the data/message from the sender, print what is received to the serial monitor.
if(charCheck != 3)
{
// Print the data/message to the serial monitor and set the acknowledgement flag.
Serial.print("Receive message: ");
Serial.println(buffer2_size);
ackFlag = 1;
// This nested logic checks if the acknowledgement and transmit flag states are as expected.
if((ackFlag == 1) && (txFlag == 0));
{
// Using the sprintf function to compile the strings to the char array buffer3_size.
sprintf(buffer3_size, "%s%s%s", ack, buffer2_size, CR);
buffer3_size[0] = '\0';
// Copy into buffer and append further strings.
strcpy(buffer3_size, ack);
strcat(buffer3_size, buffer2_size);
strcat(buffer3_size, CR);
// Set the control pin high for RS-485 data transmission and write Ack: <Message> back to sender.
digitalWrite(DE_RE, HIGH);
swSerial_MasterNode.write(buffer3_size);
digitalWrite(DE_RE, LOW);
txFlag = 1;
delay(50);
swSerial_MasterNode.flush();
}
}
// Other logic condition which checks if the character (':') is in the data/message. Received acknowledgement from slave print to serial monitor.
else if(charCheck == 3)
{
Serial.println(buffer2_size);
ackFlag = 0;
}
}
}
SLAVE RS-485
#include <SoftwareSerial.h>
// Defining the digital IO pins to align with RS-485 definitions.
#define RO 10
#define DI 11
#define DE_RE 12
SoftwareSerial swSerial_SlaveNode(RO,DI);
// Char arrays required to store the serial data/message.
char buffer1_size[32];
char buffer2_size[32];
char ack[6] = "Ack: ";
char CR[3] = {'\n'};
char buffer3_size[39];
// Integer variables.
int bytesRead1;
int bytesRead2;
int charCheck;
int ackFlag;
int txFlag;
void setup()
{
// Open serial port and wait for connection.
Serial.begin(9600);
while(!Serial)
{
// Wait for the serial port to connect.
}
// Set data rate for the software serial port.
swSerial_SlaveNode.begin(9600);
// Define DE_RE as an output.
pinMode(DE_RE, OUTPUT);
// Slave sets this pin to low to receive transmission.
digitalWrite(DE_RE, LOW);
}
void loop()
{
// If there is no serial data/message available, perform the following.
if(swSerial_SlaveNode.available() == 0)
{
// If there is data/message written in the serial monitor, perform the following.
if(Serial.available() > 0)
{
// Read the serial port and store data in the integer variable until either a newline character (ENTER KEY) is read, or the byte limit is reached.
bytesRead1 = Serial.readBytesUntil('\n',buffer1_size,32);
// Add a null character to the array to terminate the string.
buffer1_size[bytesRead1] = '\0';
// Print the data/message to the serial monitor.
Serial.print("Transmit message: ");
Serial.println(buffer1_size);
// Set write conditions and write data/message to the port.
digitalWrite(DE_RE, HIGH);
swSerial_SlaveNode.write(buffer1_size);
digitalWrite(DE_RE, LOW);
txFlag = 1;
delay(50);
swSerial_SlaveNode.flush();
}
}
// If there is a serial data/message available, perform the following.
if(swSerial_SlaveNode.available() > 0)
{
bytesRead2 = swSerial_SlaveNode.readBytesUntil('\n',buffer2_size,32);
buffer2_size[bytesRead2] = '\0';
// String variable to hold the data/message in the buffer.
String buffer2_String(buffer2_size);
// Index through the buffer string and store the integer value in charCheck when the colon is found (':'). This will determine if the data/message is an acknowledgement or not.
charCheck = buffer2_String.indexOf(':');
// This nested logic checks if the character is not in the data/message. Received the data/message from the sender, print what is received to the serial monitor.
if(charCheck != 3)
{
// Print the data/message to the serial monitor and set the acknowledgement flag.
Serial.print("Receive message: ");
Serial.println(buffer2_size);
ackFlag = 1;
// This nested logic checks if the acknowledgement and transmit flag states are as expected.
if((ackFlag == 1) && (txFlag == 0));
{
// Using the sprintf function to compile the strings to the char array buffer3_size.
sprintf(buffer3_size, "%s%s%s", ack, buffer2_size, CR);
buffer3_size[0] = '\0';
// Copy into buffer and append further strings.
strcpy(buffer3_size, ack);
strcat(buffer3_size, buffer2_size);
strcat(buffer3_size, CR);
// Set the control pin high for RS-485 data transmission and write Ack: <Message> back to sender.
digitalWrite(DE_RE, HIGH);
swSerial_SlaveNode.write(buffer3_size);
digitalWrite(DE_RE, LOW);
txFlag = 1;
delay(50);
swSerial_SlaveNode.flush();
}
}
// Other logic condition which checks if the character (':') is in the data/message. Received acknowledgement from master print to serial monitor.
else if(charCheck == 3)
{
Serial.println(buffer2_size);
ackFlag = 0;
}
}
}