Hi, i am currently trying to create a simple SofwareSerial communication between 2 arduinos (Uno and Pro Micro), to send bytes of data one by one using the mySerial.write() function. So, the connection does work, but after two or three successful transmission of a byte, only -1 values appear on my serial monitor, which do not correspond to the value that was sent by the other arduino. I had this problem a lot of times while trying to receive bytes of data with the SoftwareSerial, unless the sending module uses the mySerial.print() (instead of write) function, or if i directly print the received byte on the computer without transferring it to a variable first.
Here are simple sending and receiving programs where this issue still exists :
Sending :
#include <SoftwareSerial.h>
SoftwareSerial Micro (10, 13);
int data = 0;
void setup()
{
Serial.begin(9600);
Micro.begin(9600);
while (!Serial)
delay(500);
Serial.println("Ready");
}
void loop()
{
data = random(0, 254);
Micro.write(0xFF); Micro.write(data);
delay(1000);
}
Receiving :
#include <SoftwareSerial.h>
SoftwareSerial Uno (16, 15);
int data = 0;
void setup()
{
Serial.begin(9600);
Uno.begin(9600);
while (!Serial)
delay(500);
Serial.println("Ready");
}
void loop()
{
if (Uno.available())
{
if (Uno.read() == 0xFF)
{
data = Uno.read();
Serial.println(data);
}
}
}
In this case, valid numbers arrive on my computer about 2 times before everything i receive becomes -1's.
So, thanks in advance for any suggestions about this issue.
Have a nice day
You are off to the races when just one character has arrived. You win the race because you are faster than the second character.
Use available to check if one character is ready, and only read a character if one is. Waiting for you, "available"… each character, every read.
available()
Get the number of bytes (characters) available for reading from a software serial port. This is data that has already arrived and stored in the serial receive buffer.
If you have not understood the comment of post #2@anon73444976 , then try the following codes in UNO to get things clearer on how FIFO-type serial buffer works.
#include <SoftwareSerial.h>
SoftwareSerial Uno (16, 15);
int data = 0;
void setup()
{
Serial.begin(9600);
Uno.begin(9600);
while (!Serial)
delay(500);
Serial.println("Ready");
}
void loop()
{
byte n = Uno.available();
if (n == 2)
{
if (Uno.read() == 0xFF)
{
Serial.println(Uno.read());
}
}
}
Ok, so basically i'm asking it to read a byte that has not arrived yet. I simply added a delay between the two reads to test it out, and it works. Thanks !
Now it would be best to write it so you could tolerate a longer or shorter delay between the first character and second. Or one character and the next.
Just configure your logic so you never read a character you don't know for sure is fully arrived and wait in the buffer.
The looping nature of loop() means you might ask thousands of times if that second character is here yet, doing nothing but looping while waiting on its availability.
Let us study, with the help of the following conceptual diagram (Fig-1), the working principle of the FIFO type (first-in first-out) buffer of the UART Port and the role of Serial.available() instruction in order to establish that the delay you added is not justified.
Figure-1:
1. You send A at Bd = 9600. The frame ((START bit (1), character bit (8), STOP bit (1)) will take about 41 us (+ transmission/propagation delay that depends on cable type and length) time to reach at the destination.
2. The frame arrives at the destination UNO which strips out the START and STOP bits and then the 8-bit character code is automatically saved into Location-0 of the FIFO Buffer.
3. As the character takes some times to arrive at the destination, let us keep checking that the buffer has indeed received the character before we attempt to read the character from the buffer. In this process, the instruction code (byte n = Serial.available()) is just assuring that at least one character has arrived and been accumulated in the buffer.
4. Execution of Serial.read() instruction will bring out the character A from the buffer very fast (<<41 us) ; the buffer is empty now. The next character B will arrive after 41+ us later. If you make another Serial.read() operation, you will get nothing as the buffer is empty. In fact, you get 0xFF indicating buffer emptiness, which when printed shows -1.
5. You waited for a while with a hope that the next character will arrive after the inserted time delay; but, it may not arrive due to two perturbing factors (cable type and length). So, the trick should be not to insert time delay; rather, check again that the buffer has received a character/data byte.
6. In post #5, before reading data from buffer, it has been ensured that the buffer contains at least two data bytes.