Arduino freezes, memory issues?

Hello everyone,

I am trying to do the following: Read a serial string and inputting it into a char array, then using if conditions on charArray to light some LEDs.

My full code is:

#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

//Screen color definition
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

//Variable definition
char input[13] = "0000000000W0";
int CPUtemp = 0;
int GPUtemp = 0;
char inputChar;
int index = 0;

//Custom character for LCD screen from: http://maxpromer.github.io/LCD-Character-Creator/
byte tempChar[8] = {0x8, 0xf4, 0x8, 0x43, 0x4, 0x4, 0x43, 0x0};
byte startF[8] = {0x1F, 0x10, 0x17, 0x17, 0x17, 0x17, 0x10, 0x1F};
byte midF[8] = {0x1F, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x1F};
byte midE[8] = {0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F};
byte endE[8] = {0x1F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F};
byte endF[8] = {0x1F, 0x01, 0x1D, 0x1D, 0x1D, 0x1D, 0x01, 0x1F};

byte firstP[] = {0x1F, 0x10, 0x17, 0x15, 0x17, 0x14, 0x10, 0x1F};
//byte middleU[] = {0x1F, 0x00, 0x0A, 0x0A, 0x0A, 0x0E, 0x00, 0x1F};
byte middleM[] = {0x1F, 0x00, 0x0A, 0x15, 0x15, 0x15, 0x00, 0x1F};
byte lastP[] = {0x1F, 0x00, 0x1C, 0x14, 0x1C, 0x10, 0x00, 0x1F};

void setup()
{
  Serial.begin(115200);
  lcd.begin(16, 2);

  //Create custom characters
  lcd.createChar(1, startF);
  lcd.createChar(3, midF);
  lcd.createChar(2, midE);
  lcd.createChar(4, endE);
  lcd.createChar(5, endF);
  lcd.createChar(7, firstP);
  //lcd.createChar(0, middleU);
  lcd.createChar(0, middleM);
  lcd.createChar(6, lastP);

  lcd.setBacklight(WHITE);
  lcd.setCursor(0, 0);
  lcd.print("Hardware Monitor");
  lcd.setCursor(0, 1);
  lcd.print("waiting for port");
  delay(1000);
}

void loop()
{
  while (Serial.available() > 0)
  {
    if (index < 12) // One less than the size of the array
    {
      //lcd.setCursor(3, 1);  DEBUG to see if it hangs during the read phase
      //lcd.print(";");       There was an issue of ending the connection while the arduino was trying to read, possible fix: close connection button changes a char and the send timer sends only if the char is on open
      inputChar = Serial.read(); // Read a character
      input[index] = inputChar; // Store it
      index++; // Increment where to write next
      input[index] = '\0'; // Null terminate the string
      delay(20);
    }
  }
  index = 0;
  if (input[11] == 'C') // devided into two work modes
  {
    lcd.setCursor(0, 0);
    lcd.print("CPU:");
    lcd.setCursor(0, 1);
    lcd.print("GPU:");
    //CPU temp value
    lcd.setCursor(4, 0);
    lcd.print(input[0]);
    lcd.setCursor(5, 0);
    lcd.print(input[1]);
    lcd.setCursor(6, 0);
    lcd.print((char)223);
    lcd.setCursor(7, 0);
    lcd.print(" ");
    //CPU load value
    lcd.setCursor(8, 0);
    lcd.print(input[2]);
    lcd.setCursor(9, 0);
    lcd.print(input[3]);
    lcd.setCursor(10, 0);
    lcd.print("% ");
    //CPU Fan value
    if (input[4] == 'P')
    {
      lcd.setCursor(12, 0);
      lcd.print((char)7);
      lcd.setCursor(13, 0);
      lcd.print((char)0);
      lcd.setCursor(14, 0);
      lcd.print((char)6);
      lcd.setCursor(15, 0);
      lcd.print((char)4);
    }
    if (input[4] == '1')
    {
      lcd.setCursor(12, 0);
      lcd.print((char)1);
      lcd.setCursor(13, 0);
      lcd.print((char)2);
      lcd.setCursor(14, 0);
      lcd.print((char)2);
      lcd.setCursor(15, 0);
      lcd.print((char)4);
    }
    if (input[4] == '2')
    {
      lcd.setCursor(12, 0);
      lcd.print((char)1);
      lcd.setCursor(13, 0);
      lcd.print((char)3);
      lcd.setCursor(14, 0);
      lcd.print((char)2);
      lcd.setCursor(15, 0);
      lcd.print((char)4);
    }
    if (input[4] == '3')
    {
      lcd.setCursor(12, 0);
      lcd.print((char)1);
      lcd.setCursor(13, 0);
      lcd.print((char)3);
      lcd.setCursor(14, 0);
      lcd.print((char)3);
      lcd.setCursor(15, 0);
      lcd.print((char)4);
    }
    if (input[4] == '4')
    {
      lcd.setCursor(12, 0);
      lcd.print((char)1);
      lcd.setCursor(13, 0);
      lcd.print((char)3);
      lcd.setCursor(14, 0);
      lcd.print((char)3);
      lcd.setCursor(15, 0);
      lcd.print((char)5);
    }
    //GPU temp value
    lcd.setCursor(4, 1);
    lcd.print(input[5]);
    lcd.setCursor(5, 1);
    lcd.print(input[6]);
    lcd.setCursor(6, 1);
    lcd.print((char)223);
    lcd.setCursor(7, 1);
    lcd.print(" ");
    //GPU load value
    lcd.setCursor(8, 1);
    lcd.print(input[7]);
    lcd.setCursor(9, 1);
    lcd.print(input[8]);
    lcd.setCursor(10, 1);
    lcd.print("% ");
    //GPU Fan value
    if (input[9] == 'P')
    {
      lcd.setCursor(12, 1);
      lcd.print((char)7);
      lcd.setCursor(13, 1);
      lcd.print((char)0);
      lcd.setCursor(14, 1);
      lcd.print((char)6);
      lcd.setCursor(15, 1);
      lcd.print((char)4);
    }
    if (input[9] == '1')
    {
      lcd.setCursor(12, 1);
      lcd.print((char)1);
      lcd.setCursor(13, 1);
      lcd.print((char)2);
      lcd.setCursor(14, 1);
      lcd.print((char)2);
      lcd.setCursor(15, 1);
      lcd.print((char)4);
    }
    if (input[9] == '2')
    {
      lcd.setCursor(12, 1);
      lcd.print((char)1);
      lcd.setCursor(13, 1);
      lcd.print((char)3);
      lcd.setCursor(14, 1);
      lcd.print((char)2);
      lcd.setCursor(15, 1);
      lcd.print((char)4);
    }
    if (input[9] == '3')
    {
      lcd.setCursor(12, 1);
      lcd.print((char)1);
      lcd.setCursor(13, 1);
      lcd.print((char)3);
      lcd.setCursor(14, 1);
      lcd.print((char)3);
      lcd.setCursor(15, 1);
      lcd.print((char)4);
    }
    if (input[9] == '4')
    {
      lcd.setCursor(12, 1);
      lcd.print((char)1);
      lcd.setCursor(13, 1);
      lcd.print((char)3);
      lcd.setCursor(14, 1);
      lcd.print((char)3);
      lcd.setCursor(15, 1);
      lcd.print((char)5);
    }
    if (input[10] == 'W')
    {
      lcd.setBacklight(WHITE);
    }
    if (input[10] == 'D')
    {
      lcd.setBacklight(LOW);
    }
    if (input[10] == 'R')
    {
      lcd.setBacklight(RED);
    }
    if (input[10] == 'G')
    {
      lcd.setBacklight(GREEN);
    }
    if (input[10] == 'B')
    {
      lcd.setBacklight(BLUE);
    }
    if (input[10] == 'Y')
    {
      lcd.setBacklight(YELLOW);
    }
    if (input[10] == 'V')
    {
      lcd.setBacklight(VIOLET);
    }
    if (input[10] == 'T')
    {
      lcd.setBacklight(TEAL);
    }
  }
  if (input[11] == 'D')
  {
    lcd.setBacklight(RED);
    lcd.setCursor(0, 0);
    lcd.print("   Connection   ");
    lcd.setCursor(0, 1);
    lcd.print("   Terminated   ");
  }
  if (input[11] == 'X')
  {
    lcd.setBacklight(RED);
    lcd.setCursor(0, 0);
    lcd.print("    Software    ");
    lcd.setCursor(0, 1);
    lcd.print("   Terminated   ");
  }
}

Everything is working fine, my LCD shows what it needs to show, but after a while it just freezes. The serial signal is still transmitting (debugged in serial monitor), but the arduino is just stuck and only disconnecting and reconnecting it does anything.

Can this be a memory issue? I am clueless.

Edit: (I have updated the code to its full version) After testing for a full night it did not run into any issues, but while my PC is stressed it sometimes hangs and just gets stuck without updating.

It happens on my computer but not on another, I have no idea what can cause that. Any further help appreciated!

  if (input[10] == 'D')
  {
   lcd.setBacklight(LOW);
  }

even though you are reading at a high baud rate, it i possible that you empty the buffer before you are done parsing the whole message… then when you arrive here, you may see unexpected results.

you could try:

adding a small delay in the while loop, or
block until the message is complete (look for end marker)
or use a method that isn’t holding in a while loop

I went for the simpler solution and added a delay(10); in the while, I will run it for the next few hours and see if it hangs. Thanks a lot!

It's never going to run properly past 10 received characters, because after you've received 10 characters you're writing beyond the end of the array, and corrupting memory you don't own...

Regards,
Ray L.

Why would that happen? Isn't my array long enough? Or can arduino only recieve up to 10 chars at once?

You have two very obvious problems:

  1. You never reset index - you simply continue adding new characters to the end of whatever was already there.

  2. Once you've received 12 characters, you completely stop even reading characters, and your loop never exits, so the program simply stops doing anything at all useful.

Regards,
Ray L.

RayLivingston:
You have two very obvious problems:

  1. You never reset index - you simply continue adding new characters to the end of whatever was already there.

  2. Once you've received 12 characters, you completely stop even reading characters, and your loop never exits, so the program simply stops doing anything at all useful.

Regards,
Ray L.

Good catch but sadly I did have an index reset, I just did not paste it here, ill edit the original code.
Right aftet the while I reset the index to 0. But the arduino freezes after a about an hour of working fine with the strings.

"Good catch but sadly I did have an index reset, I just did not paste it here, ill edit the original code."

Please always give us the whole code so you don't waste our time with stuff like that. Even the parts you think aren't important. If you want to make something shorter to post then go ahead but make sure it is still a complete program that will compile and shows the problem. That means you shorten it and then compile and test it.

Delta_G:
"Good catch but sadly I did have an index reset, I just did not paste it here, ill edit the original code."

Please always give us the whole code so you don't waste our time with stuff like that. Even the parts you think aren't important. If you want to make something shorter to post then go ahead but make sure it is still a complete program that will compile and shows the problem. That means you shorten it and then compile and test it.

I was posting from my tablet so I guess my fingers failed me, but thanks for taking the time to review my code!

Other than the index issue, is there anywhere where I am having memory issues? Or anything that would cause an arduino uno to hang?

After letting it run all night, it seems to be working without any issues, the delay made then all go away. Thanks!

Updated the original post and added the full code after still running into some issues. The problem still exists..

I also tested the integrity of the serial string that is being sent (it is sent from a c# program that I also wrote) and it seems to be fine too. If you want to see the code of that too I can post it on pastebin or something since it is much longer.

menkes:
Edit: (I have updated the code to its full version) After testing for a full night it did not run into any issues, but while my PC is stressed it sometimes hangs and just gets stuck without updating.

It happens on my computer but not on another, I have no idea what can cause that. Any further help appreciated!

what does this mean, PC stressed?

BulldogLowell:
what does this mean, PC stressed?

Well, while running all night my CPU and GPU usage was almost non-existent, but when it gets "stuck" it's always when I have high GPU usage and my CPU is working quite hard too.

I noticed this happens only when the PC has lots of things running, a game, many chrome tabs and other things running in the background.

start here and make sure you have a robust method to parse the serial stream

Post your current code. Relying on delay to sort out your problem is eventually going to bite you - it seems unlikely, but it sounds like your PC when heavily loaded is not emitting the serial data rapidly enough. In any event, as already advised, you need better serial handling on the Arduino - without using delay.

BulldogLowell:
start here and make sure you have a robust method to parse the serial stream

I will check that out ASAP.

wildbill:
Post your current code. Relying on delay to sort out your problem is eventually going to bite you - it seems unlikely, but it sounds like your PC when heavily loaded is not emitting the serial data rapidly enough. In any event, as already advised, you need better serial handling on the Arduino - without using delay.

That is a bit above my current skill level, I will give it a try!

Is it weird that it happens only on one PC? (which happens to be the strongest)

menkes:
Is it weird that it happens only on one PC? (which happens to be the strongest)

so just make the interface tolerant of the not-so-reliable sender.

Plus: you will be surprised how much simpler your code looks/is using functions!

Is there any way to check the validity of the string received? Or add some protection to the string itself in the arduino code? I tired adding some overflow protection to the while loop:

while (Serial.available() > 0)
  {
    if (index < 12) // One less than the size of the array
    {
      //lcd.setCursor(3, 1);  DEBUG to see if it hangs during the read phase
      //lcd.print(";");       There was an issue of ending the connection while the arduino was trying to read, possible fix: close connection button changes a char and the send timer sends only if the char is on open
      inputChar = Serial.read(); // Read a character
      input[index] = inputChar; // Store it
      index++; // Increment where to write next
      //input[index] = '\0'; // Null terminate the string
      delay(20);
    }
    /*
    if (index > 13)
    {
      for (int i = 0; i < 13; i++)
      {
        input[i] = '0';
      }
      input[13] = '\0';
      break;
    }
    */
  }

But that too did not work… I am not logging this and I do not care if some string are corrupted (data-wise) I just need it to work constantly, is there a way to check if the data received is bad and just wait for the next serial?

menkes:
But that too did not work.. I am not logging this and I do not care if some string are corrupted (data-wise) I just need it to work constantly, is there a way to check if the data received is bad and just wait for the next serial?

are you in control of the format of the string you are sending?

if so, what does is it look like?

BulldogLowell:
are you in control of the format of the string you are sending?

if so, what does is it look like?

3404P69304GC

Was the last string I sent over serial for example