Dual Arduino Communication using Mega and Nano behaving strangely

I have setup a pretty large Project, which includes 128 WS2811 LED´s, a temperature Sensor, a Clock Module and an IR-Receiver which Communicates with an IR-Remote. Since WS2811 disables all Interrupts, using the IR-Remote is quite a pain. I was able to provide a fix, where around 90% of the Time a Button-Click on the Remote is recognized, but i decided to try to use a second board to handle IR-Communication (Nano). I made this decision because I want to add a WiFi Module as well to controll the LED´s from my Phone/PC using WiFi, which would be very hard on the Mega.

The Problem I am facing is that the Mega stops reading the Data send from the Nano after a seemingly random amount of time and/or commands. I changed the baud rate of both Serials from 9600 to 115200 which caused this random failure to happen later (more time and/or commands). After this happens the Communication fails completelöy and the mega does not receive any more data.

I am somewhat new to Arduinos and all this is a learn by doing experience, but i did not find a similar Issue which helped me fix this Problem.

My Guess would be, that the buffer of the Mega is maybe overflowing, but this should only losse data and not totally block the input of the Megas Serial, i think! Might be wrong there.

Also maybe the SRAM is overflowing since I am using a lot of variables etc.

I also tried to upload a skecth on the Mega which only reads the bytes of the SerialTransfer, converts them into a unsigned long value and print that onto the Serial Monitor. This seemed to work. Hence there is probably something wrong with my Code, so I decided to include the whole Code. I am Happy for any suggestions to what might lead to this fail.

Thanks in advance!!!

Here is the Code which is uploaded to the Nano.

#include<SerialTransfer.h>
#include<IRremote.h>

#define RECV_PIN 7
#define HZ_OF_SERIAL 5

IRrecv irrecv(RECV_PIN);
decode_results results;
SerialTransfer myTransfer;

int sendingPeriod = 1000 / HZ_OF_SERIAL;
int lastMillis = 0;


void setup() {
  Serial.begin(115200);
  irrecv.enableIRIn();
  myTransfer.begin(Serial);
  
}

void loop() {
  // if(millis() > (lastMillis + sendingPeriod)) { // Tried to Time Sending the Data, which didnt really help
    if(irrecv.decode(&results)) {
    
      myTransfer.txBuff[0] = 0; // Processing Mode on Mega
      // Unsigned Long represented by 4 Bits
      myTransfer.txBuff[1] = results.value & 0xFF;
      myTransfer.txBuff[2] = (results.value >> 8) & 0xFF;
      myTransfer.txBuff[3] = (results.value >> 16) & 0xFF;
      myTransfer.txBuff[4] = (results.value >> 24) & 0xFF;

      myTransfer.sendData(5);

      // Serial.print(results.value);

      irrecv.resume();

      // lastMillis = millis();
    }
  // }
}

Full Code of the Mega can be found in the Attachments, since it is very long.

full_sketch_git.ino (20 KB)

Really an impressive project and good work, being "somewhat new".
So Your current setup includes one Nano and one Mega?
What does the compiler report say about memory usage? 50%? Above 75 might start to be thrilling. Using strings? That can cause thrashing, memory fragmentation and problems.

Thanks for the reply, both the Nano and the Mega are below 50%. The Mega espacially is only around 21%. I did not read the memory descritions correctly. I thought SRAM was different from the dynamic memory, but according to the Memory reference on the Arduino page its not, so SRAM can not be the Problem. I wondern why changing the baud rate has changed the behaviour. I will probably test different baud rates tommorow and test how long the sketch runs, when i keep one Button on the IR-Remote pressed.

Also I figured i can stop the Nano from sending Data if a Button is pressed multiple times since the code does not change and i dont use any functions which support button holding. This might improve the functionality further. I still want to find the error :C

A higher baudrate transports data faster. For a transmitting device it means a lot. For the receiver, not the same inportance.
However! From other topics there is some basics to know! The loop of the receiver needs to run faster than the loop of the transmitter. Else the receiver buffer will overflow and data will be lost, mishmashed, corrupted.

Limiting the transmitted data to only happend when something has changed is a good way to awoid buffer filling and receiver efforts to decode "nothing new".

Railroader:
However! From other topics there is some basics to know! The loop of the receiver needs to run faster than the loop of the transmitter. Else the receiver buffer will overflow and data will be lost, mishmashed, corrupted.

Would this lead to a permanent block of the receiving decives serial communication? since that is what is hapenning, The loop of the Receiver is definitively running slower, i can just change the timing in the Nano and wait for a specific time of millis to pass before sending. I will try that sometime today. I hope this fixes it :D.

Thanks fr the advice!

You are right. An overload of data for the receiver should not cause a total hanging but maybe corrupted data causes the logic to lock up.
Maybe You could install some short, very short, test printouts, to Serial Monitor, inside the receiver code gossiping what part of code is executed.

Didnt have time today, but will try tomorrow. Also I will try different baud rates and measure the time until it stops receiving the data. I hope i can find the error, so thi whole thing works out. This tiny detail would be such a pain in the ass if it didnt work.

I have continued to search through Forums, do you have any Information on Serial behaving strangely when interrupts are blcoked. I know that FastLED in Combination with a WS2811 LED blocks all other Interrupts. Can this lead to the Serial port getting blocked totally. I tried some different tweaks to my sketches and it seems that eventhough the Nano is sending continously when i keep a Button pressed on the IR-Remote the Mega just receives Data in a “stuttering” manner. This doesnt change even when i ensure that the Nano is sending Data slower than the Mega receiving Data.

Just wondering if Serial Communication doesnt work properly when interrupts are blocked.

Statements about Interrupts and FastLED: Possible Conflict with IRRemote · Issue #198 · FastLED/FastLED · GitHub

How are the circuits built up? Do You use breadboards? They are quite sencitive to vibrations, shocks. Quite small bumps, pushes, tends to make a short intermittent contact and hanging is a fact.

There are better knowing guys than me to tell about the possible interrupt trouble You describe.

Can You make a test run and, in the code, cut away (cooment out the calls) to FastLED or WS2811 LED and verify Your theory?

I'm fairly certain hardware UARTs/USARTs don't rely on interrupts (could be wrong, but I highly doubt it), so the LED lib shouldn't ruin the comms portion of the project. That being said, it would be a good idea to try seeing if removing the fastLED library and seeing if the communication portion of the code becomes "fixed".

What is more likely to be the issue is timing. Delays in the receiver code should be removed so that overflow can be more easily avoided. The transmitter code should be limited to send data no faster than the receiver can read/handle the data.

Side notes:

  • This library makes implementing software timers much easier
  • You can use "myTransfer.txObj()" and "myTransfer.rxObj()" to help send and receive multi-byte objects without having to manually bit shift (example sketch)
  • "magic numbers" should be avoided - you can make global const variables to replace them all

I am currently using breadboards, yeha. This allows me to add more sonsors etc. I do not think this is a problem tbh, since after simply rebooting the System the Serial works again without rewiring or similar activity. Commenting out FastLED basically changes the whole sketch to a simple Test Sketch for Serial Communication since 90% of the Code is FastLED related. I could write a test sketch with the rest of the sensors working and look if that would work. I also just found out a student colleague of mine knows someone who works a lot with arduinos. I will just ask him about interrupts etc. He might have an Idea what causes this problem.

Thanks for the Help regardless if I can fix this or not!

You can use "myTransfer.txObj()" and "myTransfer.rxObj()" to help send and receive multi-byte objects without having to manually bit shift (example sketch)

Didn´t know that, thanks for the advice. It will simplify later Code using a Wifi module by a lot.

This library makes implementing software timers much easier

I dont know if i have the patience to work in this library, but i will try if i find the time, since it seems very beneficial. Thanks a lot!

I try to avoid "Magic Numbers" as much as possible, but i tend to not use constant when im in a rush. I always take time to revisit code and change such things, but thanks for remindign me, might be time again :smiley:

I dont know if i have the patience to work in this library, but i will try if i find the time, since it seems very beneficial. Thanks a lot!

Semms to be very easy and fast :smiley:

You can use "myTransfer.txObj()" and "myTransfer.rxObj()" to help send and receive multi-byte objects without having to manually bit shift (example sketch)

I have a question regarding this Method. I would need a struct to represent the command i want to send. As for now i have Ideas for multiple Objects/structs to send. As an example i want to be able to send an unsigned long which corrosponds to a command of the IR-Remote. Moreover i would like to be able to send an array of 128 bytes which represent the hue value of each led, so i can basiclly "draw" a picture on my Phone using and app i need to code and the WIFI Module. Therefore i would need two different types of variables i would send in an object.

My way to got here would be to create a struct which holds all of these variables and determine which to process based on a simple byte (0-255) for the different modes of processing. Is there a smarter way to do this using struct? I am new to c coding and dont really know good practices.

Help would be appreciated :smiley:

The Arduino HardwareSerial makes use of interrupts to move received data to a software buffer (from where PowerBroker's SerialTransfer library reads it). You can receive 3 bytes (328P datasheet) before loosing data if the data is not read from the UART because interrupts are disabled.

I however experienced similar problems in combination with WS2812 strips (420 leds in my project). The only way that I'm aware of that will work reliable is to send a byte from the Nano, wait till the byte is echoed back by the Mega, send the next byte, wait till it's echoed back and so on. Based on the previous paragraph, you should be able to send 3, wait for all three to be echoed and next continue but it might be more complicated.

Note
FastLed.show() for 128 LEDS takes approx. 4 milliseconds.

everything i tried so far just made the transfer more unreliable, meaning signals get lost earlier or a lot faster in general.

I however experienced similar problems in combination with WS2812 strips (420 leds in my project). The only way that I'm aware of that will work reliable is to send a byte from the Nano, wait till the byte is echoed back by the Mega, send the next byte, wait till it's echoed back and so on. Based on the previous paragraph, you should be able to send 3, wait for all three to be echoed and next continue but it might be more complicated.

So basically I would need to introduce a custom protocol which sends the package i want to send in smaller packages and reessambles them on the mega? How long would a transfer of such data need to be processed, since the delay between pressing a button on the ir remote and the Leds receiving the corresponding command shouldnt be very long.

EDIT: Even limiting the SerialTransfer to outclude the signal for a button being hold over a longer time, seems to quicken and worse the problems I am facing. At this point im completely clueless why this is happening :C

Another Side Note: Increasing the RX Buffer size does notchange anything either, so i doubt that this is the Problem. I changed the Buffer Sizze to 256 and confirmed this by printing SERIAL_RX_BUFFER_SIZE to the Serial Monitor.

Okay, I decided to just stay with one Arduino and just work with what I have working.
Thank you for helping me out.