I have a project with 2 arduino mega and Nextion touch panel. Connection diagram below.
I need to transfer a message 48-50 characters from Arduino Mega #2 to Arduino Mega #1. Both boards communicate on 115200 baud. I am on communication testing stage. I want to present on the screen one of the messages transfered from Mega #2 to Mega#1. I'm facing with an issue that messages are lossing own boundaries and instead of receving a formatted messages as commented below for Mega#2 I'm receving scrumbled message.
Board #2 generates and sends the messages in batches. Not sure that it's correct way, but I don't know how to stay in buffer size:
//A01011100
//B0101
//C110
//D01010101010101011
//E11110000
message = "C";
message.concat(counter); //where counter is 3 digits int value
Serial1.println("A01011100");
Serial1.println("B0101");
Serial1.println(message);
Serial1.println("D01010101010101011");
Serial1.println("E11110000");
Mega #1 code below. Code is a bit not organized, 'cuz I on communication testing stage. As I understand I have an issue with buffer size but I can't figure out how to fix it. Any help is appreciated!
The very first thing I would do is begin to debug the program by putting in serial.Print() lines to track the logic and display the value being read. As things are right now, you do not know where to look or where to change anything.
You can make a connection from the transmitting Arduino to the Receiving Arduino and let the receiving processor tell the transmitter when to start and stop. Have it stop when the buffer is about 80% full or fuller and start again when it is 30% or less.
For example one function writes string while checking for terminating null to buffer by calling another function which pushes chars to buffer without checking for terminating char.
void Write_String_To_Buffer(const char* const STR_PTR)
{
tByte i = 0;
while (STR_PTR[i] != '\0') {
Write_Char_To_Buffer(STR_PTR[i]);
i++;
}}
And then when buffer is ready(its up to you when and under what conditions determine its ready) to be sent function is sending ready to send request to receiving side and waiting for ready to accept response and then is sending. Rs232 is using lsb first method btw.
So u kinda r implementing xon and xoff method. When receiving side cant keep up with processing its sending xon to sender side and if its ok to accept sending xoff. I would increase both senders and receivers buffers maximum possible value. And aso would decrease baudrate to 9600 to be within error rate of 2.5% just in case then slowly increase it to 115 or even higher.
Your readDataFromReceiver will read a completely random number of characters, with no guarantee you read a complete message. Serial data takes TIME to arrive, but you can process characters MUCH faster than they arrive. Problem is, you stop reading characters as soon a available() returns false, which can, and WILL, occur between characters, in the middle of a message. You then, effectively, process whatever fragment of a message you have received, then discard it, even though it was likely NOT a complete message.
You need to either wait, in readDataFromReceiver for an entire message to arrive, or, MUCH better, receive and buffer as many characters as are available, then return, SAVING those characters, and adding to the buffer on subsequent calls to readDataFromReceiver until you have an entire message buffered. Only then do you process the buffered message.
As result I start receiving:
A = A01011100
B = B11100010D0101001
C = C193C193
D = D01
E = E11110000101010101101
A = A01011100C327
B = B0101A0101110
C = C
D = D101
E = E1101
It's what I thought. But how I can wait for an entire message to arrive? What do you mean to read as much characters as are available? How can I check how many characters are available for me?
Do you have any examples of code that I try to modify and apply into my scenario?
I'm still thinking is it right way to send the data from transmitter unit using multiple Serial1.println methods. Or I need to combine all parts into a 1 giant message and then send.
Buffer length DOESN'T MATTER, provided you process the message as it comes in, but you need to either buffer it again until it's complete, or process it in chunks as it's received.
Software can read and process the bytes much faster than they are received, if designed properly. However, throwing delay() into the mix almost guarantees you'll overrun your serial buffer sooner or later.
and learn the RIGHT way to handle communications data. Whether youe messages are long or short makes no difference. What you're doing now WILL fail. Do it properly as shown in that link, and you'll never have a problem. And, you won't be wasting tens of billions of CPU cycles doing nothing useful.
That is part of the software you have to write. There may be some libraries for this but I am not familiar with them. Try this link: SerialTransfer - Arduino Reference I used this search term "Arduino data transfer library" and got a lot of hits. Try it you might find something you like.
I will try to dig a little bit deeper into this question. But so far it works. In the beginning when I had connected only 2 arduino boards the code was working fine, but when I added 3rd component into the circuit, then it star giving me an issues.
As RayLivingston mentioned in his reply, they recevier trying to read whatever is available for him. Message can be present without head or without tail. It actually what was happening, the system was saving available data into char array, unfortunately Serial.available() doesn't tell that message is ready, it just tells that I have stuff in my buffer and if I want I can work with it.
I read couple times again about Arduino- Serial and simple examples from Robin2Serial Input Basics - updated . Everything looks simple until you are adding more stuff into the systmtem. Then it makes my understanding of Serial to fall apart. I wish it was that easy as TCP/UDP.
No one has commented on this yet, but this will likely cause issues around the time millis() wraps around (after about 49.7 days). The "canonical" and only correct way to run a periodic task using millis() is by subtracting the previous time that a task ran from millis(), like this: