I am working on a project with Arduino MEGA (2560) and HMI touch display. Everything was fine until my last firmware programming to Arduino. Many of my subroutines finish with Arduino reset instead of return to where they were called from. In fact I can't even make it jump from void setup() to void loop(). I already ruled out watchdog as I have some subroutines that wait for user input and Arduino does not reset while waiting. There is no electrical issue either. If I explicitly add loop(); at the end of void setup() for example it goes to void loop() which makes it very strange. I thought of the call stack and that I might be going too deep with subroutines, but that is not the case with setup() and loop(). I checked the failing subroutines and they are executed to the very end, but they don't return, they reset Arduino. Tested this with serial print to the debug port (USB) at the end of the subroutines. I also thought something might have happened to my Arduino board so I programmed another one, but I got the same result. I get no error or warning during compilation either. I have ran out of ideas and I have to solve this soon. I would appreciate any idea that might point me in the right direction.
This is from my main code:
#include "Definitions.h"
#include "CommonFunc.h"
#include "RW_BBS_COM.h"
#include "RW_HMI_COM.h"
#ifdef DEBUG
#include "DEBUG.h"
#endif // DEBUG
void setup() {
unsigned int btn = 0; // Variable for pressed button ID
// Connect serial ports
#ifdef DEBUG
ConnectToPC();
#endif // DEBUG
BBS_Serial.begin(BBSBaud); // default at 8bits data, no parity check, 1 stop bit
BBS_Serial.setTimeout(25); // Set timeout for reading bytes from BBSxx
HMI_Serial.begin(HMIBaud); // default at 8bits data, no parity check, 1 stop bit
HMI_Serial.setTimeout(7); // Set timeout for reading bytes from HMI
InitHMI(); // Initialize HMI
if (ConnectBBS()){ // Try connecting to BBSxx
GenData = ReadGEN(); // Read General Information form BBS
ReadBBSProfile(); // Read full profile and store in ActiveProfile
#ifdef DEBUG
PrintGENData();
Debug_Serial.println("Wait HMI input? y/n:");
#endif // DEBUG
// Wait for user to press OK on the HMI and go to main loop
while (btn != BtnOK_p1){ // Wait until OK button pressed on page 1
// Wait for input from HMI
while (!HMI_Serial.available()){
delay(100); // Wait for user response
#ifdef DEBUG // In Debug mode respond to user command to stop waiting on HMI response
char UserInput;
if (Debug_Serial.available()){
UserInput = Debug_Serial.read();
if (UserInput == 'n')
break; // Break the HMI waiting loop and go to main loop
}
#endif // DEBUG
}
HMI_Serial.readBytes(HMIinput, sizeof(HMIinput)); // Get HMI report
btn = ReadBtn(); // Read button ID
#ifdef DEBUG
btn = BtnOK_p1; // Don't wait more in DEBGUG
#endif // DEBUG
}
ShowImage(ImgMainMenu); // After user reads the startup info and presses OK, show the main menu
AdvProfileNum = 0; // No advanced profile loaded yet so set it to 0
}
else{
// Display message on HMI that connection failed and ask for reset
// Add function to write with white font with no background and no refresh as on this screen we have no Status bar
#ifdef DEBUG
Debug_Serial.println("BBS connect error. Restart!");
#endif // DEBUG
while (true) // Loop here until user decides to restart the system
{}
}
loop(); // >>>>>>>>> IF THIS IS NOT HERE INSTEAD OF GOING TO loop() ARDUINO RESETS AND START OVER
}
void loop() {
unsigned int btn = 0; // Variable for pressed button
#ifdef DEBUG
/*DebugCycle:
Debug_Serial.println("Reading profile...");
ReadBBSProfile();
PrintProfile();
Debug_Serial.println("Write back? y/n:");
while (!Debug_Serial.available())
delay(100); // Wait for response
if (Debug_Serial.read() == 'y'){
Debug_Serial.println("Writing profile...");
WriteBBSProfile();
PrintBBSerr();
Debug_Serial.println();
Debug_Serial.println("<<< Write end >>>");
Debug_Serial.println();
}
Debug_Serial.println("Repeat? y/n:");
while (!Debug_Serial.available())
delay(100); // Wait for response
if (Debug_Serial.read() == 'y')
goto DebugCycle; // Repeat if requested */
#endif // DEBUG
#ifdef DEBUG
CheckHMI: // HMI interaction loop start (used in Debug mode only to skip profile read/write repetition)
#endif // DEBUG
while (!HMI_Serial.available()){delay(100);} // Wait for user interaction
btn = 0; // Clear button variable
HMI_Serial.readBytes(HMIinput, sizeof(HMIinput)); // Get HMI report
btn = ReadBtn(); // Read button ID
#ifdef DEBUG
Debug_Serial.println(btn, DEC); // Print the data from HMI
#endif // DEBUG
switch (btn){
// Main Menu page
// >>>FOLLOWING FUNCTION RETURNS CORRECTLY TO loop()
case BtnGEN_p2: {ShowGENinfo(); break;} // Display General Info page and update indicators
// >>>FOLLOWING FUNCTION ENDS WITH RESETS
case BtnBeginner_p2: {ShowBeginner(); break;} // Display Beginner Mode page and update indicators
// >>>FOLLOWING FUNCTION ENDS WITH RESETS
case BtnAdvanced_p2: {ShowAdvanced(advBAS); break;} // Display Advanced Mode page (Basic Settings) and update indicators
// >>>FOLLOWING FUNCTION RETURNS CORRECTLY TO loop()
case BtnAdvProf_p2: {ShowAdvProf(); break;} // Display Advanced Profiles page and update indicators
default: break; // Communication error or button unsupported by this firmware
}
#ifdef DEBUG
goto CheckHMI; // If in Debug mode don't go back to profile read/write test after HMI interaction
#endif // DEBUG
}