Arduino Locking up

Hello all,

I am having another issue where the Arduino locks up after executing a piece of code. The locking up occurs right after the section posted here on a Serial.println function call. I am not sure what could be causing this issue and have been running around in circles for the last few hours here. Could someone take a look at the function that I have posted here and see if there is anything glaring obvious that is an issue? Please let me know. Best

Note: I know that I should not use String but there were a few instances where I needed something easier to manipulate then a c string. I have been actively trying to remove String from my source. Also I am using std::vector because I found in some applications that it is much easier to utilize a dynamic array. IN terms of performance, I am only using the code if necessary

LEDStrip StripArray[11];
std::vector<RoomObject> RoomArray;

bool firstRun = true;

File testFile;

String Temp = "Room 1 Strip 1 LED 1-143 Group 1 ; Room 2 Strip 1,2 LED 144,1 Group 2 ; Room 3 Strip 2 LED 2-144 Group 3";
//String Temp = "Room:1;Strip:1;LED:1-143 Room:2;Strip:1,2;LED:144,1 Room:3;Strip:2;LED:2-144";

// Global variables for the Ethernet portion
byte mac[] = {0x00, 0xBA, 0xDA, 0xDF, 0xAC, 0x02};
unsigned int localPort = 8888;  
IPAddress ip(192, 168, 1, 178);
EthernetUDP udp;


void ParseSDCardFile(String fileString);

void setup() {
  String fileString = "";
  Serial.begin(9600);
  Serial.println("-------- New Program Running --------");

  Ethernet.init(Ethernet_CS_PIN);
  Ethernet.begin(mac, ip);

  if(Ethernet.hardwareStatus() == EthernetNoHardware)
    Serial.println("Ethernet Hardware not connected");
  else
    Serial.println("Ethernet connected");

  if(Ethernet.linkStatus() == LinkOFF)
    Serial.println("No cable connected");
  else
    Serial.println("Link status up and communicating");

  // Open file of SD Card file logic here and read into a string

  if(!SD.begin(CS_PIN))
  {
    Serial.println("SD port failed to init");
  }
  else 
    Serial.println("initilization complete");

  testFile = SD.open("config.ini");

  if(testFile)
  {
    while(testFile.available())
    {
      char readValue = testFile.read();
      fileString.concat(readValue);// Future update. Could rewrite this section where it reads one line at a time and process the infomation, then reads a second and repeats instead of reading the entire thing first
    }

    testFile.close();
  }
  else
  {
    fileString = Temp;
    Serial.println("Error reading file");
  }
    
  
  

  ParseSDCardFile(fileString);
  //ParseSDCardFileOld(fileString);

  Serial.println("Parsed SD CARD file"); // freeze up occurs here
}


void ParseSDCardFile(String fileString)
{
  Serial.println("Parsing file");
  char *outerPtr = nullptr;
  char *inner1ptr = nullptr;
  char *inner2ptr = nullptr;

  char *RoomToken = strtok_r(fileString.c_str(), " ", &outerPtr);
  uint16_t RoomCount = 1;
  bool ParsingComplete = false;
  RoomObject *NewRoom = new RoomObject;

  while(RoomToken != NULL)
  {
    if(strcmp(RoomToken, "Room"))
    {
      RoomToken = strtok_r(NULL, " ", &outerPtr);

      long tempValue(std::strtol(RoomToken, nullptr, 10));
      uint8_t finalValue(0);
      finalValue = static_cast<uint8_t>(tempValue); 

      NewRoom->SetRoomID(finalValue);
      RoomCount++;
    }
    else if(strcmp(RoomToken, "Strip"))
    {
      RoomToken = strtok_r(NULL, " ", &outerPtr);

      std::vector<uint8_t> LEDStripNumber;

      if(strchr(RoomToken, ','))
      {
        // There are 2 strips here
        char *secondLevelToken = strtok_r(RoomToken, ",", &inner1ptr);
        while(secondLevelToken != NULL)
        {
          long tempValue(std::strtol(secondLevelToken, nullptr, 10));
          uint8_t finalValue(0);
          finalValue = static_cast<uint8_t>(tempValue); 
          LEDStripNumber.push_back(finalValue);
          secondLevelToken = strtok_r(NULL, ",", &inner1ptr);
        }
      }
      else
      {
        long tempValue(std::strtol(RoomToken, nullptr, 10));
        uint8_t finalValue(0);
        finalValue = static_cast<uint8_t>(tempValue); 
        LEDStripNumber.push_back(finalValue);
      }

      inner1ptr = nullptr;
      NewRoom->setLEDStripNumberReference(LEDStripNumber);  
    }
    else if(strcmp(RoomToken, "LED"))
    {
      RoomToken = strtok_r(NULL, " ", &outerPtr);

      std::vector<uint8_t> LEDnumberCount;

      if(strchr(RoomToken, ','))
      {
        char *secondLevelToken = strtok_r(RoomToken, ",", &inner1ptr);
        while(secondLevelToken != NULL)
        {
          long tempValue(std::strtol(secondLevelToken, nullptr, 10));
          uint8_t finalValue(0);
          finalValue = static_cast<uint8_t>(tempValue); 
          LEDnumberCount.push_back(finalValue);

          secondLevelToken = strtok_r(NULL, ",", &inner1ptr);
        }
      }
      else if(strchr(RoomToken, '-'))
      {
        uint8_t lowerValue = 0;
        uint8_t higherValue = 0;
        char *secondLevelToken = strtok_r(RoomToken, "-", &inner1ptr);

        while(secondLevelToken != NULL)
        {
          long tempValue(std::strtol(secondLevelToken, nullptr, 10));
          uint8_t finalValue(0);
          finalValue = static_cast<uint8_t>(tempValue); 
          
          if(lowerValue == 0)
            lowerValue = finalValue;
          else if(higherValue == 0)
            higherValue = finalValue;

          secondLevelToken = strtok_r(NULL, ",", &inner1ptr);
        }

        for(int i = lowerValue; i < higherValue + 1; i++) 
        {
          LEDnumberCount.push_back(i);
        }   
      }
      NewRoom->setLEDNumberArray(LEDnumberCount); 
      inner1ptr = nullptr;
    }
    else if(strcmp(RoomToken, "Group"))
    {
      RoomToken = strtok_r(NULL, " ", &outerPtr);

      long tempValue(std::strtol(RoomToken, nullptr, 10));
      uint8_t finalValue(0);
      finalValue = static_cast<uint8_t>(tempValue); 

      NewRoom->setGroupID(finalValue);
    }
    else if(strcmp(RoomToken, ";"))
    {
      RoomArray.push_back(*NewRoom);
      NewRoom = new RoomObject;
      inner1ptr = nullptr;
      inner2ptr = nullptr;
    }
    
    RoomToken = strtok_r(NULL, " ", &outerPtr);
  }
}

what Arduino and IO devices are you using?
post Serial monitor output indicating the problem
where in the code of post #1 does it lock up?

Hello horace. I am using the Arduino Mega Pro (it is a smaller one. Knock off from the official one that you can get on Amazon). Here is the serial output that I am getting:

-------- New Program Running --------
Ethernet connected
Link status up and communicating
SD port failed to init
Error reading file
Parsing file
Par-------- New Program Running --------

Now, sometimes, it will lock up and other times, it will restart.

As for the I/O pins, I am not using very many of them. I have the Mega pro connected to and Arduino shield via a PCB. So the SPI line is connected, plus 11 general purpose I/O pins (for controlling LED lights), and the I/O pins going to the Arduino Ethernet shield.

I am very doubtful about using objects and in particular std::vector<> on a small microcontroller such as the mega
it only has SRAM 8K and constructing/destructing objects can soon fragment the memory and cause crashes of the program
consider using a more powerful micros such as the Arduino Due or an ESP32?

Yes, I agree. However, for this version, I am currently locked into using the Mega because the boards have been made that utilizes the footprint. For the next version, the Arduino will be upgraded to a more powerful one that has more RAM.

As for the vector, I know that it is not really meant for microcontrollers but I needed to have a dynamic array. I was thinking about implementing one myself but using the vector is the easier route. The thing is, I am only using 20% of SRAM at compile time. Right now, I only have the 3 rooms. I do agree once the rooms get larger we can run into issues related to memory fragment.

Bu for the issue at hand, is there any way I can do some sort of de-fragmentation?

can you not set the array to the maximum possible size?
or use a different data structure such as a circular buffer?

At this time, I am unable to set the max size because the device can be used in different applications where I am not sure how many led channels are going to be used for the different applications. (the vector that is dynamic stores the number of LED channels that will be used. Some applications can use 15 others 100). For other parts, I can explore more to see if I can atleast reserve an amount for the vector.

As for the circular buffer, can I dynamically add things to it?

rather than using std::vector you could allocate the arrays using malloc() and then deallocate using free()
you can have the same problems of memory fragmentation as with vector but it can make you think more about when you allocate and deallocate which vector tends to hide from you
your main problem is you are probably using an unsuitable microcontroller for the task you have

circular buffers are useful when processing data streams, e.g.

  1. sensor data is being sampled regularly in an interrupt routine and added to the buffer
  2. the main loop is extracting data and processing it

depending on other tasks the main processing loop is doing athe amount of data in the buffer can vary - one has to check for buffer overflow etc

Thank you Horace,

After reviewing the code, I decided to re-write the logic and I moved away from using std::vector. Everything is now a static array. For the array that holds the rooms or channels, I am going to hard code this to be the max size that it can be.

Unfortunately, after this, the issue still persisted. After some more time debugging, I think that I narrowed down the where the issue is happening.

In my setup function, I have some lines of code that will turn on the first 3 rooms with colors. Everything is fine until it sets the color and turns on the LEDs. With that code in there, I am getting a crash. When the code is removed, no crash.

The weird part is, it crashes on a println statement which is 2 code blocks before setting the color.

If you have new code, you need to share it.

Okay, so you turn on LEDs and the code crashes. How many LEDs? What's the power source, do you have enough current reserve to power the LEDS, or are you using your Arduino's supply to power the LEDs?

Hello all. I am currently powering the LEDs through the 5V from the MCU. The 5V is from the USB power. In my testing, I disconnected the power from the LED strips and I was still getting the issue. I am currently testing the code with the static arrays that I have built in and will report how the tests went.

So technically, the LEDs never turned on since the power was disconnected and yet the controller was freezing

Before you start turning them on, be advised, don't do this. Power them separately, but connect the LED power gnd and the Arduino gnd.
Also, when NOT turned on, each LED draws 1 mA from the 5V source, so if you have more than a few, you're starting to load your Arduino too much. The Arduino power circuit is designed to power itself and a few tens of mA of external circuits, at most.

Ironically, when powered from USB, the USB source will power more peripherals than the Arduino will, so users get into trouble when moving to external supplies after their project works well powered from the USB.

I have not studied your code in full but i did notice a lot of while statements. Avoid these if possible because the are blocking functions. They block the running of the code as long as they are true. You are better of using an if statement which allows your loop to run efficiently

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.