adding an extra TONE to the code

Hi guys,

in the sketch I use is some code to create a warning tone.

But I like to add an extra tone what takes a second longer and higher pitch

It is about this line: tone(3, NOTE_CS6, 3000)

So it does: output on pin3 , tone is NOTE_CS6, duration is 3000ms

But I want one extra higher tone, right after the NOTE_CS6

So what I hear now is tuut, tuut, tuut.

But I like to hear tuut, tuut, tuut, tuuuuuuut (with a higher pitch)

I hope you understand what i try to say.

Thanks for your time

#include <LiquidCrystal.h>
#include "ScrollableMenu.h"
#include "notes.h"

#define uint unsigned int

/********* Main Program Defines **********/
/*****************************************/
#define TIMER_MODE_COUNTDOWN 1
#define TIMER_MODE_DISABLED 0

#define REGIME_MENU     1
#define REGIME_WORKOUT  0

#define MENUS_COUNT 3
#define WARNING_SIGNAL_LIMIT_SECONDS 10

#define MUSIC_WARN   1
#define MUSIC_SWITCH 2
#define MUSIC_END    3
/*****************************************/

/********** LCD Keypad Defines ***********/
/*****************************************/
#define KEYPAD_NONE -1
#define KEYPAD_RIGHT 0
#define KEYPAD_UP 1
#define KEYPAD_DOWN 2
#define KEYPAD_LEFT 3
#define KEYPAD_SELECT 4
/*****************************************/

/************** Classes ******************/
/*****************************************/

class LCDKeypad: public LiquidCrystal {
  public:
    LCDKeypad();
    int button();
};

/*****************************************/

class WorkoutInterval {
  public:
    char *name;
    uint duration;
    
    WorkoutInterval(char *n, uint d);
};

/*****************************************/

class Workout {
  public:
    char *name;
    uint countOfIntrvals;
    uint currentInterval;
    WorkoutInterval *intervals;
    uint cycle;  //if == 0 - do not loop (end at intervals)
  
    Workout(char *n, uint cnt, uint c, WorkoutInterval *intvrls);
    void incCurrInterval();
    WorkoutInterval getCurrInterval();
};

/*****************************************/

WorkoutInterval restInterval = WorkoutInterval("Break",  60);
WorkoutInterval time3min       = WorkoutInterval("Train", 183);
WorkoutInterval time4min       = WorkoutInterval("Train", 243);
WorkoutInterval time5min       = WorkoutInterval("Train", 303);



WorkoutInterval boxingIntervals1[] =        {restInterval, time3min};
WorkoutInterval boxingIntervals2[] =        {restInterval, time4min};
WorkoutInterval boxingIntervals3[] =        {restInterval, time5min};


Workout workouts[MENUS_COUNT] = {
  Workout("3 minutes training      ", 2, 1, boxingIntervals1),
  Workout("4 minutes training      ", 6, 1, boxingIntervals2),
  Workout("5 minutes training      ", 8, 1, boxingIntervals3)
  
};
char currentWorkout = 0;

char timerMode = TIMER_MODE_DISABLED;
char regime = REGIME_MENU;
unsigned int seconds = 0;

LCDKeypad lcd;
ScrollableMenu scrollableMenu(2, MENUS_COUNT, drawMenu);

/************ Class' Methods *************/
/*****************************************/

LCDKeypad::LCDKeypad() : LiquidCrystal(8, 9, 4, 5, 6, 7){}

int LCDKeypad::button(){
  static int NUM_KEYS=5;
  static int adc_key_val[5] ={30, 150, 360, 535, 760};
  int k, input;
  input=analogRead(0);
  for (k = 0; k < NUM_KEYS; k++){
    if (input < adc_key_val[k]){
      return k;
    }
  }
  if (k >= NUM_KEYS){
    k = -1;     // No valid key pressed
  }
  return k;
}

/*****************************************/

Workout::Workout(char *n, uint cnt, uint c, WorkoutInterval *intvrls) {
  name = n;
  countOfIntrvals = cnt;
  intervals = intvrls;
  cycle = c;
  currentInterval = 0;
}

void Workout::incCurrInterval() {
  ++currentInterval;
  if(currentInterval >= countOfIntrvals){
    currentInterval = 0;
  }
}

WorkoutInterval Workout::getCurrInterval() {
  return intervals[currentInterval];
}

/*****************************************/

WorkoutInterval::WorkoutInterval(char *n, uint d) {
  name = n;
  duration = d;
}

/*****************************************/

/************ Main Routines **************/
/*****************************************/

void drawMenu(int menuItem, int row, char isActive){
  clearRow(row); 
  lcd.setCursor(0, row);
  if(isActive) {
    lcd.print(">");
  } else {
    lcd.print(" ");
  }
  lcd.print(workouts[menuItem].name);
}

void showTime(){
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("Golden Glory Gym");
  
  unsigned int localSec = seconds;
  lcd.setCursor(1, 1);
  lcd.print(workouts[currentWorkout].name);
    

 
  if(workouts[currentWorkout].getCurrInterval().name != 0){
    lcd.print(" (");
    lcd.print(workouts[currentWorkout].getCurrInterval().name);
    lcd.print(")");
  }
  lcd.setCursor(7, 2);
  lcd.print((int)(localSec / 60));
  lcd.print(":");
  if(localSec % 60 < 10) {
    lcd.print("0");
  }
  lcd.print(localSec % 60);
}

void clearRow(int row) {
  lcd.setCursor(0, row);
  lcd.print("                ");
}

void sound(int type){
  switch(type) {
    case MUSIC_WARN:
      tone(3, NOTE_B4, 1000);
      break;
    case MUSIC_SWITCH:
      tone(3, NOTE_CS6, 3000);
      break;
    case MUSIC_END:
      tone(3, NOTE_GS3, 5000);
      break;
    
  }
}

void initTimer1(int seconds){
    // initialize timer1 
    noInterrupts();           // disable all interrupts
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;

    // Set timerVal to the correct value for our interrupt interval
    //16MHz / prescaller / wanted_frequency
    int timerVal = (F_CPU / 1024) * seconds;
    if(timerVal > 65535) {  //if more than maximum, than set to maximum
        timerVal = 65535;
    }
    
    OCR1A = timerVal;                       //compare register
    TCCR1B |= (1 << WGM12);                 // CTC moge
    TCCR1B |= (1 << CS12) | (1 << CS10);    // 65535 prescaler 
    TIMSK1 |= (1 << OCIE1A);                // enable timer compare interrupt
    interrupts();                           // enable all interrupts
}

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;
          int soundToPlay = MUSIC_SWITCH;
          if(workouts[currentWorkout].cycle == 0 && workouts[currentWorkout].countOfIntrvals == currInterval + 1) {
            soundToPlay = MUSIC_END;
            timerMode = TIMER_MODE_DISABLED;
          } else {
            workouts[currentWorkout].incCurrInterval();
            seconds = workouts[currentWorkout].getCurrInterval().duration;
          }
          sound(soundToPlay);
          //enableTimer1Interrupts();
        }
        
        if(seconds == WARNING_SIGNAL_LIMIT_SECONDS){
          //sound warning
          //disableTimer1Interrupts();
          sound(MUSIC_WARN);
          //enableTimer1Interrupts();
        }
    }
    if(regime != REGIME_MENU) {
      showTime();
    }
}

/*void enableTimer1Interrupts() {
  noInterrupts();
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
}

void disableTimer1Interrupts() {
  noInterrupts();
  TIMSK1 = 0;
  interrupts();
}*/

void setup() {
    lcd.begin(20, 4);
    scrollableMenu.draw();
    initTimer1(1);
}

void loop() {
   int key = KEYPAD_NONE, prevKey = KEYPAD_NONE;
   while(1) {
     key = lcd.button();
     if(key != KEYPAD_NONE && key != prevKey){
       if(regime == REGIME_WORKOUT) {
         regime = REGIME_MENU;
         scrollableMenu.draw();
       } else {
         switch(key) {
           case KEYPAD_UP:
              scrollableMenu.keyUp();
              scrollableMenu.draw();
              break;
          case KEYPAD_DOWN:
              scrollableMenu.keyDown();
              scrollableMenu.draw();
              break;
          case KEYPAD_LEFT:  //quit menu
              regime = REGIME_WORKOUT;
              showTime();
              break;
          case KEYPAD_RIGHT:
          case KEYPAD_SELECT:
              timerMode = TIMER_MODE_DISABLED;
              currentWorkout = scrollableMenu.getCurrent();
              workouts[currentWorkout].currentInterval = 0;
              seconds = workouts[currentWorkout].intervals[0].duration;
              regime = REGIME_WORKOUT;
              timerMode = TIMER_MODE_COUNTDOWN;
              showTime();
              break;
         }
       }
     }
     prevKey = key;
     delay(50);
   }
}

Since you only posted part of your code, I'll only post part of the answer.

tone() is a non-blocking function. To make another tone you have to

PaulS:
Since you only posted part of your code, I'll only post part of the answer.

tone() is a non-blocking function. To make another tone you have to

hahahaha, I thought that would make it more easy.

I'm just a starter Pauls give me the time to learn please.

But I edited and put the whole code.

void sound(int type)

Are you sure that you can use an int to hold the values 1, 2, and 3? Are you sure you don't need a long or a long long?

You REALLY need to understand what you can, and can NOT do in an interrupt service routine. ANYTHING to do with an LCD is verboten in an ISR.

Your ISR determines what note to start playing, and calls the function to start playing that note . That function knows how long to play the note for.

Given your code, I don't understand what it actually does (because I don't know how the timer is set up). Nor do I understand how that differs from what you want.

Hi Pauls,

thanks for your wide explanation and your patience with me.

The code was not written by me, I'm really a starter and try to edit this code that it does what I need.

Thanks to this forum I have managed to make the changes and is it working 100%

But to make it perfect I want to have another warning tone as explained in my first message.

What the sketch does is the following:

You can choose 3 kinds of training.

3,4 or 5 minutes training.

When you choose for a 3 minutes training the display starts to countdown from 3 minutes and 3 seconds
Giving 3 times a tone from a second each, so when the last tone finished the counter is exact on 3 minutes.

When there are only 10 seconds left from the training round it gives a warning that the training round is almost finished and the break starts.

10 seconds later the full 3 minutes are past and it gives a final signal telling the break has begon.

The break starts counting down from 1 minute and after 50 seconds it gives a warning the training starts again in 10 seconds.

When the full minute of the break has finished the whole thing starts over again