Using tone after switch case

I have been googling for hours but i'm not able to find a solution for my problem.

If I make a simple sketch like this:

void setup() {
  tone(15, 1000);
  delay(1000);
  noTone(15);
  tone(15, 1500);
  delay(1000);
  noTone(15);
   tone(15, 1000);
  delay(1000);
  noTone(15);
  tone(15, 1500);
  delay(1000);
  noTone(15);
  
}
 
void loop() {
  

  
}

Then I hear two tones like a police car.

but when I put this code in my other sketch under "case"I only get one tone.
What I'm i doing wrong an how to solve it?

void sound(int type){
  switch(type) {
    case MUSIC_WARN:
  tone(15, 1000);
  delay(1000);
  noTone(15);
  tone(15, 1500);
  delay(1000);
  noTone(15);
  tone(15, 1000);
  delay(1000);
  noTone(15);
  tone(15, 1500);
  delay(1000);
  noTone(15);
  break;

That snippet of code looks fine. The problem must be elsewhere in your sketch. Show us the entire code.

It is a complicated sketch but it is only the sound part I have problems with.
I need two tones after each other, jusy after "case" but seems like an inpossible task for me.

notes.h (1.85 KB)

pitches.h (1.95 KB)

ScrollableMenu.cpp (1.62 KB)

ScrollableMenu.h (675 Bytes)

test.ino (10.3 KB)

The only place I can see tone() functions, and the switch case that's giving you problems is the sound() function defined near the end of your sketch.

But the only place I can see the sound() function being called is inside the ISR() function - I'm assuming some clever stuff is going on with interrupts that I don't understand, because I can't see how or when ISR() gets called.

I do know you have to keep interrupt service routines super-short though. Set some flags, update some variables, and return, that kind of thing.

Your ISR calls a bunch of other functions, some of which try to go on for several seconds. I think that's the problem.

Thank you very much for your replies and the energy you have put into this.
Very appreciated.

Yes it is complicated and I did not write it as i'm a newbie with Arduino.

What it does is timing several workout programs.

On the display you choose which workout and then it counts down giving a signal when it is time for a break and time to start training again. And 10 seconds before the time is finished it gives a warning meaning 10 seconds left.
Only I find the tones very poor that is why I want to change the audio signals in 2 tone signals.

But it is difficult to do that and i don;t understand why.

sound() is called from ISR and delay() is called inside sound() which leads to your problem. There is really no reason for you to be using interrupts to keep track of elapsed seconds. Your code seems very over-complicated.

Your code seems very over-complicated.

Yes i have heart that before but the problem is I'm not advanced enough to write my own code so I have to use this code and sees how it works for me and I must say I came very far.

I have my lights red en green for train and break working well and some other things working perfect.
as a matter of fact it is already doing all i need but just 1 tone sounds so boring.

Is there away around it to get the "dual tone"?

The problems i know but now the solution :slight_smile:

Move the code that generates the sounds out of the ISR. Instead, of making the sounds itself, the ISR should set some flag variables.

Then put code the main loop() to check the flag variables and calls sound() whenever it's appropriate.

Do you mind showing me a little bit in the code which part.
i'm a new guy in Arduino stuff and it is little bit complicated for me.
But still learning

Move the code that generates the sounds out of the ISR

I guess you mean this part of code, can you make a suggestion?

ISR(TIMER1_COMPA_vect) {        // interrupt service routine 
    if(timerMode != TIMER_MODE_DISABLED){
        //countdown seconds
        if(seconds > 0){
          seconds--;
        } else {
          //disableTimer1Interrupts();
          int currInterval = workouts[currentWorkout].currentInterval;
          
           digitalWrite(31, !digitalRead(31));  
           digitalWrite(33, !digitalRead(33)); 
           int soundToPlay = MUSIC_BREAK;
              
           if(digitalRead(led) != HIGH)
  
       soundToPlay = MUSIC_TRAIN;
           
          if(workouts[currentWorkout].cycle == 0 && workouts[currentWorkout].countOfIntrvals == currInterval + 1) {
            soundToPlay = MUSIC_TRAIN;
            timerMode = TIMER_MODE_DISABLED;
          } else {
            workouts[currentWorkout].incCurrInterval();
            seconds = workouts[currentWorkout].getCurrInterval().duration;
          }
          sound(soundToPlay);
          //enableTimer1Interrupts();
        }

OK, here's what you need to change.

I can't test this code where I am at the moment so I've probably missed something.

Up near the top of the sketch, probably after all the #define lines, add a line to declare a global variable called soundToPlay. It needs to be volatile because we're mucking about with interrupts. Like this:

volatile byte soundToPlay = 0;

Then in your ISR,
remove the declaration of soundToPlay.
remove the call to sound() and replace them with lines that modify the soundToPlay flag like this:

ISR(TIMER1_COMPA_vect)  // interrupt service routine
{

  if (timerMode != TIMER_MODE_DISABLED)
  {
    //countdown seconds
    if (seconds > 0)
    {
      seconds--;
    }
    else
    {
      //disableTimer1Interrupts();
      int currInterval = workouts[currentWorkout].currentInterval;

      digitalWrite(31, !digitalRead(31));
      digitalWrite(33, !digitalRead(33));
      //  int soundToPlay = MUSIC_BREAK; //this is global now. Don't re-declare it.
      soundToPlay = MUSIC_BREAK; //modify the flag

      if (digitalRead(led) != HIGH)
      {
        soundToPlay = MUSIC_TRAIN;
      }

      if (workouts[currentWorkout].cycle == 0 && workouts[currentWorkout].countOfIntrvals == currInterval + 1) {
        soundToPlay = MUSIC_TRAIN;
        timerMode = TIMER_MODE_DISABLED;
      }
      else
      {
        workouts[currentWorkout].incCurrInterval();
        seconds = workouts[currentWorkout].getCurrInterval().duration;
      }
      //  sound(soundToPlay); // Don't do this here
      //enableTimer1Interrupts();
    }

    if (seconds == WARNING_SIGNAL_LIMIT_SECONDS) {
      //sound warning
      //disableTimer1Interrupts();
      // sound(MUSIC_WARN); //don't do this
      soundToPlay = MUSIC_WARN;  //do this instead
      //enableTimer1Interrupts();
    }
  }
  if (regime != REGIME_MENU) {
    showTime();
  }
}

Then at the end of your main loop add a call to sound().
This looks at the soundToPlay variable and decides what sound to play (or stay silent).
Then reset the flag ready for next time.

The last few lines of the sketch need to look something like this

    prevKey = key;
    
    sound(soundToPlay);  //play appropriate sound
    soundToPlay = 0;  //reset flag ready for next time
   
    delay(50);

  }
}

GypsumFantastic you are in one word a GENIUS!!!

It works spot on, perfect.
you did not made one mistake I onlY had to copy and paste.

Thank you very much for your time and energy you put in my problem.

you are great