2D Array and total destruction

Hello Arduino Community,

Although this is my first post to the forum I'm not new to Arduino, I have been fiddling with them for years now. I usually don't have to many problems because I find the solution on this fabulous forum or the internet in general but this time I'm stumped...

All right so I don't use 2D arrays very often, and I'm working on a project the needs a rather massive 2D byte array. Yes and yes I calculated how much ram I was using and it came out to a modiste 1.4kb so I figured usage wasn't a problem.

Ok so setting up the array goes well even with all it's massiveness:

#define defaultScale 1 
#define defaultKey 2 

byte scaleValues [50] [10] = {
{0,2,4,5,7,9,11,12,14,16},
{0,2,3,5,7,9,11,12,14,15},
{0,2,3,5,7,8,11,12,14,15},
{0,2,5,7,9,12,14,17,19,21},
{0,3,5,7,10,12,15,17,19,22},
{0,3,5,6,7,10,12,15,17,18},
{0,2,5,7,10,12,14,17,19,22},
{0,3,5,6,8,10,11,13,15,17},
{0,2,3,5,7,9,10,12,14,15},
{0,2,4,5,7,9,10,12,14,16},
{0,1,3,5,7,8,10,12,13,15},
{0,2,4,6,7,9,11,12,14,16},
{0,1,3,5,6,8,10,12,13,15},
{0,1,3,4,6,7,9,10,13,15},
{0,2,3,5,6,8,9,11,14,15},
{0,2,4,6,8,10,14,16,18,20},
{0,3,4,7,8,11,15,16,19,20},
{0,3,5,6,7,10,12,15,17,18},
{0,2,4,7,9,12,14,16,19,21},
{0,1,4,5,7,8,11,12,13,16},
{0,1,4,6,8,10,11,12,13,16},
{0,2,4,6,8,9,10,14,16,18},
{0,1,3,5,7,9,11,12,13,15},
{0,1,3,5,7,8,10,12,13,15},
{0,2,4,6,9,10,12,14,16,18},
{0,1,4,5,8,9,12,13,16,17},
{0,2,4,6,7,8,10,12,14,16},
{0,2,3,6,7,8,10,12,14,15},
{0,2,3,4,6,7,8,9,11,12},
{0,2,3,5,6,8,9,11,12,14},
{0,2,4,6,8,10,12,14,16,18},
{0,1,3,4,6,7,9,10,12,13},
{0,2,4,5,6,8,10,12,14,16},
{0,2,4,6,7,9,10,12,14,16},
{0,1,3,4,6,8,10,12,13,15},
{0,2,3,5,7,8,10,12,14,15},
{0,2,5,7,9,10,12,14,17,19},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};

byte noteValues [12] = {60,61,62,63,64,65,66,67,68,69,70,71};

byte notes[10];

Ok so far all is well the program compiles and runs just fine with the above lines in the program. The real fun start when I added in these lines of code:

 for(int i = 0; i < 10;i++){
      notes[i] = noteValues[defaultKey] + scaleValues[defaultScale] [i]; 
    }

As soon as I uploaded this and it ran it instantly pooped out and froze. Oh but it gets better! Then it refused to be reprogrammed, you heard me right it wouldn't except a new sketch. I also tried it with another atmega328 first starting with just the initialization lines (works fine) then with that for loop (chaos). I'm betting that I'm going to have to re-burn the bootloader to get the chip functional again.

Any thoughts on why my for loop is creating such a commotion? It could just be that I'm fundamentally approaching this the wrong way. But I think I got the Arduino bootloader stuck in some kinda infinite loop preventing it from being programmed over serial...

Thanks in advance!

Usually to get sketch downloading to work again, you can:
Press & hold down the reset button.
Start the IDE download.
When the IDE shows "compiled xxx of 32xxx bytes" or something similar, release Reset button.
Might take a couple of tries to release it at the right point.

Any thoughts on why my for loop is creating such a commotion?

No and we won't have untill you post all your code an we can see what it is doing. Just posting those fragments tell us next to nothing.

If you have a sketch that breaks the boot loader it will be a first.

I did try reseting the board manually during uploading a couple of times to try and get it to reprog but no luck, the only way I was able to get it working again was to re-burn the boot loader manually.

The only reason I didn't post this code before is because it's mucho big, 600 lines big... :wink:
[EDIT]

well it seems I can't post all my code because I exceeded the max allowed length of 9500 chars.....

Anyway the majority of this code was all working before I added that for loop in there. After the loop is added it gets pissed off. Also as an experiment I isolated the code I though was problematic in an isolated sketch to see if this would brick it, and it didn't! It only bricks the atmega328 when it's in the original code.

Isolated code test:

#define defaultScale 1 //default scale to start at if none is coosen minor
#define defaultKey 2 //default key to start in if none is choosen D

//this 2D array contains all the scale data
byte scaleValues [50] [10] = {
{0,2,4,5,7,9,11,12,14,16},
{0,2,3,5,7,9,11,12,14,15},
{0,2,3,5,7,8,11,12,14,15},
{0,2,5,7,9,12,14,17,19,21},
{0,3,5,7,10,12,15,17,19,22},
{0,3,5,6,7,10,12,15,17,18},
{0,2,5,7,10,12,14,17,19,22},
{0,3,5,6,8,10,11,13,15,17},
{0,2,3,5,7,9,10,12,14,15},
{0,2,4,5,7,9,10,12,14,16},
{0,1,3,5,7,8,10,12,13,15},
{0,2,4,6,7,9,11,12,14,16},
{0,1,3,5,6,8,10,12,13,15},
{0,1,3,4,6,7,9,10,13,15},
{0,2,3,5,6,8,9,11,14,15},
{0,2,4,6,8,10,14,16,18,20},
{0,3,4,7,8,11,15,16,19,20},
{0,3,5,6,7,10,12,15,17,18},
{0,2,4,7,9,12,14,16,19,21},
{0,1,4,5,7,8,11,12,13,16},
{0,1,4,6,8,10,11,12,13,16},
{0,2,4,6,8,9,10,14,16,18},
{0,1,3,5,7,9,11,12,13,15},
{0,1,3,5,7,8,10,12,13,15},
{0,2,4,6,9,10,12,14,16,18},
{0,1,4,5,8,9,12,13,16,17},
{0,2,4,6,7,8,10,12,14,16},
{0,2,3,6,7,8,10,12,14,15},
{0,2,3,4,6,7,8,9,11,12},
{0,2,3,5,6,8,9,11,12,14},
{0,2,4,6,8,10,12,14,16,18},
{0,1,3,4,6,7,9,10,12,13},
{0,2,4,5,6,8,10,12,14,16},
{0,2,4,6,7,9,10,12,14,16},
{0,1,3,4,6,8,10,12,13,15},
{0,2,3,5,7,8,10,12,14,15},
{0,2,5,7,9,10,12,14,17,19},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};

byte noteValues [12] = {60,61,62,63,64,65,66,67,68,69,70,71};

byte notes[10];





void setup(){
  Serial.begin(9600);
  Serial.println("BEGIN!");
 
  //load default notes into system
    for(int i = 0; i < 10;i++){
      notes[i] = noteValues[defaultKey] + scaleValues[defaultScale] [i];
      Serial.println(notes[i]); 
    } 
  
  Serial.println("Shortly after the fail");
}


void loop(){
  Serial.println("looping...");
  
  delay(500);
  }

Here is the original code: warning this code is messy and long :roll_eyes:

because I can't add all my code, here is the top portion of it that contains the offending code:

/*  Laser Harp Controller 
 *  Eric Goodchild
 *  4/15/12
 *  Revision History: V1.6.2
 *    
 *  Added support for other scales
 */

#include <avr/interrupt.h> 
#include <stdlib.h>
#include <avr/io.h>
#include <MIDI.h>
#include <SoftwareSerial.h>


#define laserTrig 2 //Laser sensor trigger from TAOS sensor
#define galvoDrive 9 //Galvo amp output +-5VDC
#define laserBlanking 8 //laser blanking control 
#define beamHold 500 //beam hold time in uS 
#define beamBlank 600 //veam balnk time in uS
#define Period 1 //PWM period in microseconds
#define DATAOUT     11  // SDI pin 7 on AD5206
#define SPICLOCK    13 // CLK pin 8 on AD5206
#define SLAVESELECT 10 // CS pin 5 on AD5206
#define harpCenter 128 // ceneter posision of beams
#define trigEnable 4
#define statLED 19 // statis LED
#define OCSW 3 //Open close stoggle switch closed = HIGH open = LOW
#define upOct 5 //pedle pressed = HIGH
#define downOct 6 //pedle pressed = HIGH
#define pedal 7
#define defaultDetune -12
#define softTx 9
#define softRx 14
#define defaultScale 1 //default scale to start at if none is coosen minor
#define defaultKey 2 //default key to start in if none is choosen D

SoftwareSerial LCD(softRx, softTx); // RX, TX

//this 2D array contains all the scale data
byte scaleValues [50] [10] = {
{0,2,4,5,7,9,11,12,14,16},
{0,2,3,5,7,9,11,12,14,15},
{0,2,3,5,7,8,11,12,14,15},
{0,2,5,7,9,12,14,17,19,21},
{0,3,5,7,10,12,15,17,19,22},
{0,3,5,6,7,10,12,15,17,18},
{0,2,5,7,10,12,14,17,19,22},
{0,3,5,6,8,10,11,13,15,17},
{0,2,3,5,7,9,10,12,14,15},
{0,2,4,5,7,9,10,12,14,16},
{0,1,3,5,7,8,10,12,13,15},
{0,2,4,6,7,9,11,12,14,16},
{0,1,3,5,6,8,10,12,13,15},
{0,1,3,4,6,7,9,10,13,15},
{0,2,3,5,6,8,9,11,14,15},
{0,2,4,6,8,10,14,16,18,20},
{0,3,4,7,8,11,15,16,19,20},
{0,3,5,6,7,10,12,15,17,18},
{0,2,4,7,9,12,14,16,19,21},
{0,1,4,5,7,8,11,12,13,16},
{0,1,4,6,8,10,11,12,13,16},
{0,2,4,6,8,9,10,14,16,18},
{0,1,3,5,7,9,11,12,13,15},
{0,1,3,5,7,8,10,12,13,15},
{0,2,4,6,9,10,12,14,16,18},
{0,1,4,5,8,9,12,13,16,17},
{0,2,4,6,7,8,10,12,14,16},
{0,2,3,6,7,8,10,12,14,15},
{0,2,3,4,6,7,8,9,11,12},
{0,2,3,5,6,8,9,11,12,14},
{0,2,4,6,8,10,12,14,16,18},
{0,1,3,4,6,7,9,10,12,13},
{0,2,4,5,6,8,10,12,14,16},
{0,2,4,6,7,9,10,12,14,16},
{0,1,3,4,6,8,10,12,13,15},
{0,2,3,5,7,8,10,12,14,15},
{0,2,5,7,9,10,12,14,17,19},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};

//this array conatains the 16 byte scale names
char* scaleNames [50] = {
"Major",
"Minor",
"Harmonic Minor",
"Pentatonic Major",
"Pentatonic Minor",
"Pentatonic Blues",
"Pentatonic Neutr",
"Aeolian",
"Dorian",
"Mixolydian",
"Phrygian",
"Lydian",
"Locrain",
"Dim Half",
"Dim Whole",
"Whole",
"Augmented",
"Blues",
"Diatonic",
"Double Harmonic",
"Enigmatic",
"Lead Whole Tone",
"Neoploitan Major",
"Neoploitan Minor",
"Prometheus",
"6 Tone Sym",
"Lydian Minor",
"Lydian Dim",
"9 Tone Scale",
"Aux Dim",
"Aux Aug",
"Aux Dim Blues",
"Major Locrian",
"Overtone",
"Dim Whole Tone",
"Pure Minor",
"Dominant 7th",
"User Def 1",
"User Def 2",
"User Def 3",
"User Def 4",
"User Def 5",
"User Def 6",
"User Def 7",
"User Def 8",
"User Def 9",
"User Def 10",
"User Def 11",
"User Def 12",
"User Def 13"
};

//this array conatains the base note names 
char* noteNames [12] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};

//this array contains the base note values
byte noteValues [12] = {60,61,62,63,64,65,66,67,68,69,70,71};


int detune = -12;
unsigned int pwmPeriod;
unsigned int beamPosition = 128; //the location of the beam 0 - 100 range. start in center 
unsigned long dutyCycle = 50;
unsigned long currentMillis = 0;
unsigned long timeStamp = 0;
boolean beamAdvance = false;
boolean strings[12];
boolean playing[12];
byte notes[10];
byte Dminor[10] = {
  60,62,63,65,66,68,70,72,74,75};
int beamPos[10] ={
  -102,-77,-51,-26,0,25,51,75,102,127};
volatile boolean trigged = false;



void setup(){
  byte clr;
  pinMode(statLED, OUTPUT);
  pinMode(OCSW, INPUT);
  pinMode(upOct, INPUT);
  pinMode(downOct, INPUT);
  pinMode(pedal, INPUT);
  pinMode(trigEnable, OUTPUT);
  pinMode(laserTrig,INPUT);
  pinMode(galvoDrive, OUTPUT);
  pinMode(laserBlanking, OUTPUT);
  pinMode(DATAOUT, OUTPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);

  digitalWrite(SLAVESELECT,HIGH); // desabilita dispositivo
  digitalWrite(laserBlanking, LOW); //start with blanking enabled
  digitalWrite(trigEnable,HIGH);
  digitalWrite(statLED,HIGH); //turn off statis LED

  attachInterrupt(0, beamTrig, LOW); //attach the beam trigger interrupt

  MIDI.begin(1);
  LCD.begin(9600);

  //setup SPI 
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);

  //move beam to ceneter start
  spi_transfer(5);
  spi_transfer(harpCenter);

  //Clear the LCD
  LCD.write(254);
  LCD.write(1); 
  LCD.print("Laser Harp V1.6e");
  LCD.print("Booting");

  //display booting screen
  for(int i =0;i<=3;i++){
    LCD.print(".");
    delay(1000);

  }
  //clear LCD
  LCD.write(254);
  LCD.write(1);

   
    
    LCD.print("  Harp Closed   ");
    while(digitalRead(pedal));
    LCD.write(254);
    LCD.write(1);
    LCD.print("  Opening Harp  ");
    harpOpen(0.01, false);
    LCD.write(254);
    LCD.write(1);
    
    LCD.print("Key:");
    LCD.print(noteNames[defaultKey]); 
    
    LCD.write(254);
    LCD.write(134);

    LCD.print("Detune:");
    LCD.print(detune);
    
    LCD.write(254);
    LCD.write(192);
    LCD.print(scaleNames[defaultScale]); //print out default scale
    
    //load default notes into system
    for(int i = 0; i < 10;i++){
      notes[i] = noteValues[defaultKey] + scaleValues[defaultScale] [i]; 
    }

   
  


}

If you zip up your code you can attach it to the post using the Additional Options drop down at the bottom of the reply box.

LCD.print("  Opening Harp  ");

When you were totting-up your arrays sizes, did you include strings?

I'm skeptical about your memory use calculations. Some time ago one of the old hands here posted a code fragment that can be used to measure actual memory use. I suggest you add that and see how much memory you actually have spare:

// this function will return the number of bytes currently free in RAM      
extern int  __bss_end; 
extern int  *__brkval; 
int freemem()
{ 
 int free_memory; 
 if((int)__brkval == 0) 
   free_memory = ((int)&free_memory) - ((int)&__bss_end); 
 else 
   free_memory = ((int)&free_memory) - ((int)__brkval); 
 return free_memory; 
}

I suppose this a bit of a noob comment.. as I am not as experienced as ya'll.. :blush:

but the first thought I had brought me back to some readings that a bootloader can be loaded.. (but maybe the fuses not set correctly?).. and it will accept a sketch the first time.. hence over writing the bootloader. (and needing the bootloader written again tot take a new sketch again)

Could this be the issue? :slight_smile:

I wish It was that easy. The fuses are set correctly. Also I have run many many other sketches on this board and chip, it's just when I add in that for loops that it goes nutz.