Tone() not working in switch case

Hi,
I've been working on a project using the Arduino mega, and I've run into a bit of a problem. I am trying to make my active buzzer play a series of notes when I press a button on my IR remote. Everything works fine until after the "song" is played once. The IR receiver still gets an input, (shown by the IR receiver light, lighting up) but I don't receive any more inputs from the remote. Before the buzzer goes I see the data from a button press in the serial monitor, but after the buzzer is played, it stays at 0.

#define NOTE_C5  523
#define NOTE_D5  587
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_G5  784
#define NOTE_A5  880
#define NOTE_AS5 932
const byte buzzerPin = 2                                                                                                                                 ;

//notes in the melody
int melody[] = {NOTE_D5, NOTE_AS5, NOTE_G5, NOTE_G5, NOTE_D5,
                NOTE_D5, NOTE_A5, NOTE_F5, NOTE_F5, NOTE_D5, NOTE_D5, NOTE_A5,
                NOTE_F5, NOTE_F5, NOTE_C5, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_F5
               };
//note durations. 4=quarter note / 8=eighth note
int noteDurations[] = {4, 4, 4, 8, 4,
                       8, 4, 4, 8, 4, 8, 4,
                       4, 8, 4, 4, 4, 8, 4
                      };

#include <IRremote.h>
#define IR_RECEIVE_PIN 3
#define IR_BUTTON_PLAY 22
#define IR_BUTTON_ONOFF 13

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(IR_RECEIVE_PIN);
}

void loop(){
  Serial.println(IrReceiver.decodedIRData.command);
if (IrReceiver.decode()) {
    IrReceiver.resume();
    int command = IrReceiver.decodedIRData.command;
    switch (command) {
      case IR_BUTTON_PLAY: {
          //iterate over the notes of the melody
          for (int thisNote = 0; thisNote < 19; thisNote++) {

            //to calculate the note duration, take one second. Divided by the note type
            int noteDuration = 1000 / noteDurations [thisNote];
            tone(2, melody [thisNote], noteDuration);

            //to distinguish the notes, set a minimum time between them
            //the note's duration +30% seems to work well
            int pauseBetweenNotes = noteDuration * 1.30;
            delay(pauseBetweenNotes);

            //stop the tone playing
            noTone(buzzerPin);
          }
          break;
        }
      case IR_BUTTON_ONOFF: {
          break;
        }
      default: {
          // do nothing
        }
    }
  }
}

Sounds like a timer conflict. Does the IR library that you're using promise to work with Tone()? It may try to use the same timer hardware. It would be mentioned in the IR documentation.

1 Like

Yep! that was the problem and adding

#define IR_USE_AVR_TIMER3

fixed the issue entirely!
Note: It had to be put in before

#include <IRremote.h>
1 Like

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