Help with Code - blocking menu

Greetings all,

Ive been trolling here for a month or so reading and learning lots.

Ive started a little project… The idea is a menu system to control things via 16x2 lcd and 6 keys.
(Please excuse the code…Its a personal test bed.)

Currently I have a menu setup (one item) that when selected is supposed to call a function that plays a melody…This works fine.

My problem is that I need the melody to play in the background and allow the menu system to resume so that other functions could be selected while the melody plays… Ie, stop the melody or select another to play… whatever!
I’m stuck, ive tried several solutions and all leave me with the menu “paused” on the last option while the melody is playing and only returning once the melody is finished.

Could some “boffin” show me how to achieve what I’m wanting to do before I pull all my hair out - PLEASE!

Note: I understand that delay is a blocking function, I think that my biggest problem is getting this sequence of notes to play without using a delay…

Many thanks.

Here is the code I’m working with currently:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <toneAC.h>

int melody[] = { 2, 4, 6, 8, 10, 0, 24, 29, 10 };
int noteDurations[] = { 4, 8, 8, 1, 4, 4, 4, 4, 1 };

int timer = 0;
long previousMillis = 0;
long interval = 20; 
unsigned long timestamp = 0;

// DEFINE ARDUINO PINS FOR THE NAVIGATION BUTTONS
#define UP_BOTTON_PIN       A0
#define DOWN_BOTTON_PIN     A1
#define LEFT_BOTTON_PIN     A2 
#define RIGHT_BOTTON_PIN    A3
#define CONFIRM_BOTTON_PIN  A4
#define ESCAPE_BOTTON_PIN   A5

menwiz tree;
// create lcd obj using LiquidCrystal lib
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int  list,sp=110;


void setup(){

  _menu *r,*s1,*s2,*s3,*s4,*s5;

  Serial.begin(19200);    
  tree.begin(&lcd,16,2); //declare lcd object and screen size to menwiz lib

  //create the menu tree
   r=tree.addMenu(MW_ROOT,NULL,F("Root"));
        
    s1=tree.addMenu(MW_VAR,r, F("Level 1"));
      s1->addVar(MW_ACTION,beep1);
      
       tree.navButtons(UP_BOTTON_PIN,DOWN_BOTTON_PIN,LEFT_BOTTON_PIN,RIGHT_BOTTON_PIN,ESCAPE_BOTTON_PIN,CONFIRM_BOTTON_PIN);
  }

void loop(){
  
  if(timer == 1)
  {
      int buttonState = 0;
      buttonState = digitalRead(A5);
      
    if (buttonState == LOW)
    {
      //lcd.clear();
      //lcd.setCursor(0,0);
      //lcd.print("ZZZZZZZZZZZZZZ");
      //timer = 0;
    }
   // set the cursor to column 0, line 1
   // (note: line 1 is the second row, since counting begins with 0):
   //lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("TIMER: ");
   lcd.setCursor(0, 1);
   // print the number of seconds since reset:
   lcd.print(millis()/1000);
  }
  else
  {
  tree.draw(); 
  }
  }

 
  void beep1(){  
    for (int thisNote = 0; thisNote < 12; thisNote++) {
    int noteDuration = 4000/noteDurations[thisNote];
    toneAC(melody[thisNote], 10, noteDuration, true); // Play thisNote at full volume for noteDuration in the background.
    delay(noteDuration);
    }  
  }

Note: I understand that delay is a blocking function, I think that my biggest problem is getting this sequence of notes to play without using a delay....

I don't know how big a problem that will be for you, but that IS what you need to do. The blink without delay example may provide inspiration.

By the way, the Arduino does NOT have a "background", so nothing happens "in the background". What can happen is that the Arduino is fast, and runs around looking for stuff to do. If there is nothing to do with the menu, it can go see if it is time to play another note.

That can make it appear that the sound is being played "in the background", but it really isn't.

Thank you for responding.

Ive tried many solutions over the last 2 days and none allow me to play a melody without a delay in it :frowning:

If you have some code examples for me I would appreciate it greatly.

Look at sheet music. There are notes shown, somewhat equally spaced across the page. They tell the musician to play a note for a period of time. That period of time is relatively short.

Now suppose that the interval as a long time. Say the music showed playing a middle C for 10 minutes, followed by a C# for 5 minutes, then a D for 3 minutes, and, finally a G for 12 minutes.

How would YOU cause this to happen? I'll spot you a pad of paper, a pencil, and a watch. Oh, and a device capable of playing each of the required notes. It's a dumb device though.

I'll give you a start. Write down the current time, and start middle C playing. Periodically, see if it is time to stop playing middle C. If it is, ???

OK. Now your turn. Complete the instructions.

In addition, check out the switch statement.

DRS, have you tried this instead of your beep1()?
http://arduino.cc/en/Reference/Tone