Argon crashes when using tone();

Hey,
I’m making a little project that is able to play simple songs. I have an Argon with a little speaker connected to it, and send it a ‘play’ command via the cloud. After playing my little song, the led stays breathing the normal light blue for a few seconds, beeps twice again and crashes. The led flashes red: SOS 1 SOS 1.
If I remove the speaker, and leave the pin (D5) unconnected, it crashes in the same way.
If I comment out the ‘tone()’ line in the code, everything works perfectly (but no sound, obviously).

What am I overlooking?
Thanks!

int songPin = 5;
bool songReceived = false; //flag for loop
unsigned long toneStart = 0; //milliseconds, to time tones
int songIndex = 0; //which note of the song we are going to play

const int notes[]={262,294,329,349,392,440,494,523}; //in Hz. do re mi fa sol la si do
const int song[]={0,1,2,3};
const int noteLength = 500; //milliseconds

int receiveSong(String msg){
    songReceived = true;
    return 1;
}


boolean playSong() {
    
    //first note
    if(songIndex == 0){
        toneStart = millis()-(noteLength+1);
    }
    
    //playing note
    if(millis() - toneStart > noteLength){
        noTone(songPin);
        tone(songPin,notes[song[songIndex]]);  
        toneStart = toneStart + noteLength;
        songIndex ++;
    }
    
    //checking for end of song
    if(songIndex < sizeof(song)){
        return true;
    }else{
        songIndex = 0;
        noTone(songPin);
        return false;
    }

}



void setup() {
 Particle.function("song",receiveSong);
 pinMode(songPin, OUTPUT);
}

void loop() {   
    if(songReceived){
        songReceived = playSong();
    }
}

You are likely accidentally indexing outside the bounds of the notes or song arrays. You could print some debugging information to Serial to try to determine what is happening:

Serial.printlnf("songIndex: %d", songIndex);
Serial.printlnf("song[songIndex]: %d", song[songIndex]);
Serial.printlnf("notes[song[songIndex]]: %d", notes[song[songIndex]]);
tone(songPin, notes[song[songIndex]]);

EDIT:

Because song is an array of int, sizeof(song) will never return 4. As an int is 4 bytes (on Particle), sizeof(song) will return 16 (4 ints). Had you used byte, sizeof(song) would return 4.

If you wish to use int, an alternative would be:

if (songIndex < sizeof(song) / sizeof(int)) {
2 Likes

You were totally correct.

The real culprit was the ‘sizeof(song)’ bit. sizeof(array) returns the number of bytes the array contains, not the number of elements.

this works:

if(songIndex < (sizeof(song)/sizeof(song[0]))){
        //stuff
    }
2 Likes