Arduino Crashing and Printing out Garbage

Hey everyone,

I'm working on a project for school, and I have to be able to read 160 individual instructions and send pins high or low depending on the logic. When it is all said and done, there will be 350+ instructions that will have to be kept.

To do this, I am using a char* array to store each individual instruction. The way that each instruction set is saved is that there are 20 instruction subsets, with each instruction subset being an integer that in broken into 8-bits inside of mySetup.

After several attempts of frustration, my program crashes in Loop() and restarts in Setup(). I am using a Arduino Boarduino (uses ATmega328) to run the program.

I am thinking that the program with the code has something to do with the pointer, but I don't know how to fix it.

Here is my code:

const char *a[16];
const char *b[16];
const char *c[16];

void loada() {
  a[0] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1";            // ***** Oil Lights *****
  a[1] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3";
  a[2] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7";
  a[3] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15";
  a[4] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63";
  a[6] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127";
  a[7] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255";
  a[8] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,255";
  a[9] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,255";
  a[10] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,255";          // ***** End Oil Lights *****  
  a[11] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0";           // ***** Ship Entrance *****
  a[12] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,16,0";
  a[13] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,48,0";
  a[14] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,112,0";
  a[15] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,240,0";        //5
}

void loadb() {
  b[0] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,240,0";
  b[1] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,251,240,0";
  b[2] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,251,240,0";
  b[3] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,255,240,0";
  b[4] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,1,255,240,0";       //10
  b[5] = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,3,255,240,0";
  b[6] = "0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,112,3,255,240,0";
  b[7] = "0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,112,3,255,240,0";
  b[8] = "0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,240,7,255,240,0";
  b[9] = "0,0,0,0,0,0,0,0,0,0,0,0,0,24,128,240,15,255,240,0";    //15
  b[10] = "0,0,0,0,0,0,0,0,0,0,0,0,0,25,128,240,31,255,240,0";
  b[11] = "0,0,0,0,0,0,0,0,0,0,0,0,0,25,128,240,63,255,240,0";
  b[12] = "0,0,0,0,0,0,0,0,0,0,0,0,0,27,128,240,127,255,240,0";
  b[13] = "0,0,0,0,0,0,0,0,0,0,0,0,0,27,128,240,127,255,240,0";
  b[14] = "0,0,0,0,0,0,0,0,0,0,0,0,0,27,128,241,255,255,240,0";    //20
  b[15] = "0,0,0,0,0,0,0,0,0,0,0,0,0,27,128,243,255,255,240,0";
}

void loadc() {
  c[0] = "0,0,0,0,0,0,0,0,0,0,0,0,0,27,128,247,255,255,240,0";
  c[1] = "0,0,0,0,0,0,0,0,0,0,0,0,0,27,128,255,255,255,240,0";    // ***** End of Ship Entrace *****
  c[2] = "0,0,0,0,0,0,0,0,0,0,0,0,18,91,128,255,255,255,240,0";    // ***** Straight Flashing *****
  c[3] = "0,0,0,0,0,0,0,0,0,0,0,0,13,155,128,255,255,255,240,0";
  c[4] = "0,0,0,0,0,0,0,0,0,0,0,0,18,91,128,255,255,255,240,0";
  c[5] = "0,0,0,0,0,0,0,0,0,0,0,0,13,155,128,255,255,255,240,0";
  c[6] = "0,0,0,0,0,0,0,0,0,0,0,0,18,91,128,255,255,255,240,0";
  c[7] = "0,0,0,0,0,0,0,0,0,0,0,0,13,155,128,255,255,255,240,0"; 
  c[8] = "0,0,0,0,0,0,0,0,0,0,0,0,18,91,128,255,255,255,240,0";
  c[9] = "0,0,0,0,0,0,0,0,0,0,0,0,13,155,128,255,255,255,240,0";
  c[10] = "0,0,0,0,0,0,0,0,0,0,0,0,18,91,128,255,255,255,240,0";
  c[11] = "0,0,0,0,0,0,0,0,0,0,0,0,13,155,128,255,255,255,240,0";    
  c[12] = "0,0,0,0,0,0,0,0,0,0,0,0,63,219,128,255,255,255,240,0";       // ***** End Straight Flashing *****  
  c[13] = "0,0,0,0,0,0,0,0,0,0,2,1,63,219,128,255,255,255,240,0";    // ***** Dace/Darter Sea Intro *****
  c[14] = "0,0,0,0,0,0,0,0,0,0,0,0,63,219,128,255,255,255,240,0";
  c[15] = "0,0,0,0,0,0,0,0,0,0,2,1,63,219,128,255,255,255,240,0";  
}

void setup() {
  Serial.begin(115200);
  pinMode(5,OUTPUT);                     /* Setting up my communications pins to outputs */
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(A1,OUTPUT);
  Serial.print(F("Inside Setup\n"));
}

void loop() {
  digitalWrite(5,HIGH);
  digitalWrite(A1,LOW);
  
  Serial.print(F("Before Timesets Setup\n"));
  loada();                               /* Grabbing the first 16 instructions */
  for(int i = 0; i < 16; i++) {
    Serial.print(a[i]);                  /* Print out the instruction from the group of 16 */
    Serial.print(F("\n"));  
    mySetup(a[i]);                       /* Sends instruction set to mySetup to extract each instruction subset */
  }
  loadb();
  for(int i = 0; i < 16; i++) {
      Serial.print(b[i]);
      Serial.print(F("\n"));
      mySetup(b[i]);
    }
  loadc();
  for(int i = 0; i < 16; i++) {
      Serial.print(c[i]);
      Serial.print(F("\n"));
      mySetup(c[i]); 
    }  
}

Here is my serial output:

Inside Setup
Bef0,0,0,Inside Setup
Be5,0,0,0,0,0,0,0)Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
BeInside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
BeInside Setup
Bef0Inside Setup
Bef0Inside Setup
Be5,Inside Setup
Bef0Inside Setup
BeInside Setup
Bef0Inside Setup
Bef0Inside Setup
Be0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup
BeInside Setup
Bef0Inside Setup
Bef0Inside Setup
Be5,0,0,0,0,0,Inside Setup
Bef0Inside Setup
Bef0Inside Setup
Bef0Inside Setup

Thanks in advance!

You are running out of RAM. You only have 2K on the atmega328p, and your constants such as "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1" are using up just about all of it. You need to do one of the following:

  1. Move those constants to PROGMEM.

  2. Instead of storing them as character data, store them as bytes. This means that each entry takes 1 byte (instead of 1 to 3 characters), and you don't need to store the commas or null terminators, saving half the RAM. You can convert each byte to int for Serial.print and print the commas in the loop.

Okay, I think that solved my problem! XD

I decided to go with PROGMEM with using chars. But as you said, I'm still gonna have to find a way to slim down the code because it's ~55 bytes per instruction, which is much too high for my application.

Do you really need all of those zeros in the arrays ? They would seem to be superfluous as you are wasting nearly half of the arrays storing nothing.

Why are they strings, with all the commas that convey nothing, and waste space?

Do you really need all of those zeros in the arrays ?

Yeah, they still serve as place holders. My application requires that a complete instruction set is sent out each time.

Why are they strings, with all the commas that convey nothing, and waste space?

Because that seemed like the best way to hold everything. And the commas are separators between instruction subsets. Without some sort of separator, I don't know how to make the program distinguish between the different subsets.

I figured out what I'm gonna do. If I say "z19,1", I could have a function that looks for 'z', and uses the next character(s) to fill in the zeros!

And the commas are separators between instruction subsets. Without some sort of separator, I don't know how to make the program distinguish between the different subsets.

Storing the 0s and other values as ints (or bytes) seems to make more sense.

There is no non-numeric data in your strings, so why is storing the data as a string that needs to be parsed and turned back into numeric data a good idea?

I agree, storing them as three 16 x 20 byte arrays (preferably in progmem) would make more sense.

Example:

b[10] = "0,0,0,0,0,0,0,0,0,0,0,0,0,25,128,240,31,255,240,0"

Represents 50 (49 + 1) bytes of memory consumed, but only 20 bytes of information at most.
Even if you have to store an extra byte to represent the data length, that's still a saving of over 50%.

Hey guys, I just wanted to give this some closure. I went with using PROGMEM with strings and using z[number of zeros],...,0 and it worked out quite well! I was able to cut out about 7,000 bytes from my code, and was able to make everything fit and work as it should!

Thanks for all your help! I appreciate it! :smiley: