Timer Function 5 secs

Hi all,

I basically want to have 4 different scroll options on my LCD display (0,1,2,3) when the user presses the "mode" button.

I want to have a timer run out after 5 seconds of the user not pressing the mode button (and then go to a verification screen, at which the user will press a "confirm" button).

Can someone post some code on how I can use a timer function? (If timer runs out, then go here; If mode button is pressed before timer runs out then scroll to next option.

Thank you,
Andrew

adventurer456:
Can someone post some code on how I can use a timer function?

buried in this is what you want, I believe...

Pete's video does a good job of walking through the way it works...

Link to the code...

Thank you, I am very new to arduio though. Would you mind posting the specific code that will work for me?

Andrew

This can be a framework.

I am very new to arduio though

I did not comment it (except for the variables) so you have to study it till you understand it

void loop() {
  // the currently active mode
  static byte activeMode = 0;
  // the selected mode before confimation
  static byte mode = 0;
  // timeout start time
  static unsigned long timeoutStartTime = 0;

  if(digitalRead(modeButton == LOW))
  {
    delay(1000);
    mode++;
    if(mode == 4)
    {
      mode = 0;
    }
    timeoutStartTime = millis();
  }

  if(digitalRead(confirmButton) == LOW)
  {
    timeoutStartTime = 0;
    activeMode = mode;
  }

  if(millis() - timeoutStartTime >= 5000)
  {
    timeoutStartTime = 0;
    mode = activeMode;
  }

  switch(activeMode)
  {
    case 0:
     ...
     ...
     break;
    case 1:
     ...
     ...
     break;
    case 2:
     ...
     ...
     break;
    case 3:
     ...
     ...
     break;
  }
}

Instead of directly reading the button, you actually need to use code based on the statechange example or the debounce example that come with the IDE; incorporate them. That will allow you to only change the mode variable on a transition from HIGH to LOW or LOW to HIGH and get rid of the long delay.

The code assumes button wired between pin and ground and use of pinMode(yourButton, INPUT_PULLUP) or the use of an external pull-up resistor.

Thank you. I am having trouble understanding the code you posted above. Can someone possibly help me edit the code I am posting here?

I want to have different options on the LCD scroll through based on a push of the push button. If nothing is pressed after 5 seconds, I want to have the LCD go to a “Confirm?” screen.

I have digitalPin 6 hooked up to a push button. I am attaching my circuit setup.

void setup() {

  lcd.begin(16,2);
  pinMode(BWButton, INPUT);
  lcd.setCursor(0,1);


}

void loop() {

int extraBackwall = 0;
char next = a;
lcd.print (extraBackwall);

if (char next = "a") && (BWButton = HIGH))
{char next = b;
extraBackwall = 1;
lcd.print(extraBackwall);}
if (char next = "b") && (BWButton = LOW)
{char next = bb;}

if ((char next = bb) && (BWButton = HIGH))
extraBackwall = 2;
lcd.print(extraBackwall);}
if ((char next = c) && (BWButton = LOW))
{extraBackwall = cc;}

if ((char next = cc) && (BWButton = HIGH))
{char next = d;
extrabackwall = 3;
lcd.print (extraBackwall);}
if ((char next = d) && (BWBtton = LOW))
{char next = dd;}

if ((char next = dd) && (BWButton = HIGH))
{char next = a;}
  
  
  
  
}

As I posted it, I will (try to) explain it :slight_smile:

  // the currently active mode
  static byte activeMode = 0;
  // the selected mode before confimation
  static byte mode = 0;
  // timeout start time
  static unsigned long timeoutStartTime = 0;

Three variables; due to the use of the keyword 'static', they will be remembered when loop is finished. activeMode is the mode that is currently active.
mode is a temporary variable that is incremented when the user pushes the mode button.
timeoutStartTime is the start time of the timeout; it will be set to the current time (millis()) each time that the mode button is pressed.

  if (digitalRead(modeButton == LOW))
  {
    delay(1000);
    mode++;
    if (mode == 4)
    {
      mode = 0;
    }
    timeoutStartTime = millis();
  }

If the mode button is pressed, the temporary mode variable is incremented; when mode reaches 4 (the number of menu entries), it goes back to 0 (the first menu number).

The delay of 1000 ms is a lazy way to debounce and give you time to release; as said, apply the principles as shown in the statechange example that comes with the IDE.

  if (digitalRead(confirmButton) == LOW)
  {
    timeoutStartTime = 0;
    activeMode = mode;
  }

If the confirm button is pressed, reset the start time of the timeout to 0 and make the active mode the temporary mode.

  if (millis() - timeoutStartTime >= 5000)
  {
    timeoutStartTime = 0;
    mode = activeMode;
  }

If more than 5 seconds have passed, reset the start time of the timeout to 0 and reset the temporary mode to the currently active mode. The currently active mode will not change.

  switch (activeMode)
  {
    case 0:
      ...
      ...
      break;
    case 1:
      ...
      ...
      break;
    case 2:
      ...
      ...
      break;
    case 3:
      ...
      ...
      break;
  }

The switch is used to execute the selected menu function based on currently selected active mode; it's basically a big if / else if /else if / ... . You just must fill in the dots.

As said, it's a framework that you can build on. The main aim was to show how you can use millis() to achieve the timeout.

Can someone possibly help me edit the code I am posting here?

I can comment on it; these are the first two.

Please post complete code including the stuff that is before setup().

  char next = a;

What is a? We have no idea. See comment (1). The same applies to b, bb etc

  if (char next = "a") && (BWButton = HIGH))

You're missing an opening '('.
char next = "a" assigns the string "a" to a character variable called next; it's not a compare statement. You also can't assign a string to a single character variable. Lastly, because you placed char in front of next, next is a new variable and not the variable next that you declared in the beginning of loop().

This if statement should probably look like

  if (next == a && BWButton == HIGH)

Now the question is what BWButton is? Is it the pin, is it the status of the pin? You never use a digitalRead to read the status of the button. Maybe this is what you want for that

  if (char next == a && digitalRead(BWButton) == HIGH)

Hi Sterretje, I have decided to use your first line of code. However, I am having trouble just setting the mode and active mode with my buttons. Using the code below, the mode and active mode just repeat 0,1,2,3 over and over again and aren't determined by the buttons.

The buttons are hooked up to digital pins 6 and 7.

Do you know what is wrong?

Andrew

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


void loop() {
  
pinMode(6, INPUT);
pinMode(7, INPUT);

int modeButton = 0;
int confirmButton = 0; 

modeButton = digitalRead(6);
confirmButton = digitalRead(7);

  
  
  // the currently active mode
  static byte activeMode = 0;
  // the selected mode before confimation
  static byte mode = 0;
  // timeout start time
  static unsigned long timeoutStartTime = 0;

  if(digitalRead(modeButton) == HIGH)
  {
    delay(1000);
    mode++;
    if(mode == 4)
    {
      mode = 0;
    }
    timeoutStartTime = millis();
  }

  if(digitalRead(confirmButton) == HIGH)
  {
    timeoutStartTime = 0;
    activeMode = mode;
  }

  if(millis() - timeoutStartTime >= 5000)
  {
    timeoutStartTime = 0;
    mode = activeMode;
    Serial.print("mode = "); Serial.print (mode); Serial.print("  activeMode = "); Serial.println(activeMode);
  }

  
  

  switch(activeMode)
  {
    case 0:
     
     
     break;
    case 1:
     
     
     break;
    case 2:
     
     
     break;
    case 3:
     
     
     break;
  }
}

This is one part that is wrong (in loop).

  int modeButton = 0;
  int confirmButton = 0;

  modeButton = digitalRead(6);
  confirmButton = digitalRead(7);

modeButton and confrmBuutton get values from the digitalReads; that means they will be either 0 or 1 (LOW or HIGH).

Next you use e.g

  if (digitalRead(modeButton) == HIGH)
  {

which translates to

  if (digitalRead(1) == HIGH)
  {

if the first digitalRead returned HIGH; so you're reading pin 1 in that case.

You first need to define/declare the two buttons.

const byte modeButton = 6;
const byte confirmButton = 7;

void setup()
{
  ...
  ...
}
void loop()
{
  ...
  ...
}

Next you need to setup the pin modes; not necessary if it's simply INPUT as that is the default but a good habit anyway as it's possible that the bootloader does not leave them in the expected state.

There is a led in your image; what is it supposed to do? For the below, please don't connect it till you have explained and we can incorporate if needed.

I can not judge from your image how the button is / buttons are exactly wired. For the below, wire the buttons between the Arduino pin and GND. The code makes use of the internal pull-up resistors to prevent floating inputs and that can cause false readings when the buttons are not pressed.

const byte modeButton = 6;
const byte confirmButton = 7;

void setup()
{
  // setup the buttons; buttons wired between pin and GND
  pinMode(modeButton, INPUT_PULLUP);
  pinMode(confirmButton, INPUT_PULLUP);

  Serial.begin(9600);
}
void loop()
{
  ...
  ...
}

Because the code activates the internal pull-up resistors, a digitalRead of a button that is not pressed will return HIGH and a digitalRead of a button that is pressed will return LOW.

And next you can fill in loop().

void loop()
{
  // the currently active mode
  static byte activeMode = 0;
  // the selected mode before confirmation
  static byte mode = 0;
  // timeout start time
  static unsigned long timeoutStartTime = 0;

  // if mode button pressed
  if (digitalRead(modeButton) == LOW)
  {
    // delay a little for debouncing and to give user a chance to release the button
    delay(1000);
    // increment the selected mode
    mode++;
    // debug
    Serial.print("mode = "); Serial.print (mode);
    // when selected mode exceeds the maximum, go back to the first menu
    if (mode == 4)
    {
      mode = 0;
    }
    // set the start time of the time out to the current time
    timeoutStartTime = millis();
  }

  // if thhe confirm button is pressed
  if (digitalRead(confirmButton) == LOW)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // make the selected mode the active mode
    activeMode = mode;
    // debug
    Serial.print("active mode change to "); Serial.println(activeMode);
  }

  // check if no button was pressed for 5 seconds
  if (millis() - timeoutStartTime >= 5000)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // restore the selected mode for the next time that the user presses the mode button
    mode = activeMode;
  }

  // do whatever
  switch (activeMode)
  {
    case 0:
      lcd.clear();
      lcd.print("Hello");
      break;
    case 1:
      lcd.clear();
      lcd.print("How");
      break;
    case 2:
      lcd.clear();
      lcd.print("is");
      break;
    case 3:
      lcd.clear();
      lcd.print("it");
      break;
  }
}

There is place for improvement; the delay(1000) should not be there but the code should basically be based on the state change detection example so you can react on the change of a button from High to LOW or vice versa. Also the code will constantly update the LCD (it might even flicker).

The latter is easy to prevent by adding a variable.

void loop()
{
  // the currently active mode
  static byte activeMode = 0;
  // the selected mode before confirmation
  static byte mode = 0;
  // timeout start time
  static unsigned long timeoutStartTime = 0;

  // make a copy of active mode to temporary mode variable so we can compare if it has changed
  byte tmpMode = activeMode;

  // if mode button pressed
  if (digitalRead(modeButton) == LOW)
  {
    // delay a little for debouncing and to give user a chance to release the button
    delay(1000);
    // increment the selected mode
    mode++;
    // debug
    Serial.print("mode = "); Serial.print (mode);
    // when selected mode exceeds the maximum, go back to the first menu
    if (mode == 4)
    {
      mode = 0;
    }
    // set the start time of the time out to the current time
    timeoutStartTime = millis();
  }

  // if the confirm button is pressed
  if (digitalRead(confirmButton) == LOW)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // make the selected mode the active mode
    activeMode = mode;
    // debug
    Serial.print("active mode change to "); Serial.println(activeMode);
  }

  // check if no button was pressed for 5 seconds
  if (millis() - timeoutStartTime >= 5000)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // restore the selected mode for the next time that the user presses the mode button
    mode = activeMode;
  }

  // only if the active mode has changed, update the display
  if (tmpMode != activeMode)
  {
    // update the display
    switch (activeMode)
    {
      case 0:
        lcd.clear();
        lcd.print("Hello");
        break;
      case 1:
        lcd.clear();
        lcd.print("How");
        break;
      case 2:
        lcd.clear();
        lcd.print("is");
        break;
      case 3:
        lcd.clear();
        lcd.print("it");
        break;
    }
  }
}

Thanks a ton. I've got it working now!!!
The LED in the pic was just to show that current was flowing through the circuit when I pressed the button. See the picture attached.

However, I am planning on having this execute, and then another void loop execute. When I try putting your code in void setup, it says "invalid reference to void loop".

Do you know how I can get this into void setup? Or can I have this void loop execute, and then when the confirm button is pressed, have a totally different void loop execute? Code for that?

Thanks,
Andrew

Please post the code that your tried and gave the error. It will also make it clearer what you try to achieve.

What you call void loop is called a function. The void in front of the loop() or setup() functions simply indicates that these functions don't return a value.

Thank you. It is coming along. So I am basically have a bunch of functions I want to execute that all need to be looping. See that your code will go under "void modes".

In the code below, I get that mode is undefined. I thought that just writing "modes ();" before "void modes ()" was defining it.

How do I define modes?

void setup() {
  }

void loop() {
 
  modes();
  
  void modes (){
    
   //sterretje,  your code here
   
  calibrate();
  }
  void calibrate (){
  measurements ();
  }
  void measurements (){}
  
  }

Thanks,
Andrew

OK, you can not define a function inside another function

So your code should look like

void setup()
{
  ...
  ...
}

void loop()
{
  ...
  ...

  modes();
}

void modes()
{
  ...
  ...
  calibrate();
}

void calibrate()
{
  measurements();
}

void measurements()
{
}

Thank you. So I need everything uder void meadsurements to be looping when it gets to void measreuments, but I can't seem to get the right notation.

I'm using

loop (){....}

and

loop (...)

and they both don't seem to work

How can I get everything under void measurements to be looping?

Andrew

Can you please refer to measurents() as function and not as void :wink:

Your description is not quite clear. Please try again. And post your code attempt, it might make it a little clearer as well. At this moment I don't see the relation between the active mode and the other parts of the code.

I will see if I can get back to you in 12 hours time.

Actually I got it using a while function. However, now I want to continue to what we worked on only after either the mode or confirm button is pressed.

Any ideas on how to fix this?

static byte modeButton=0;
static byte confirmButton=0;

while (modebutton < 1 )
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("      SMART");
lcd.setCursor(0,1);
lcd.print ("  FEMORAL GUIDE");
delay (4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Press any button");
lcd.setCursor(0,1);
lcd.print ("to continue.....");
delay (2000);

}

while (modeButton >0 )
{........ // the rest

There is something that you don’t understand from my original code. modeButton is a pin that is defined in the beginning of the code; it’s value should never change so a test like while (modebutton < 1 ) is quite useless.

The variable that you should test is the activeMode because that contains the mode that is selected once the confirmButton is pressed and that reflects what the user wants to do.

Now your code might work different, but I can’t say as you did not post your complete code.

Also, you never read the modeButton inside the while, so it will never change and you will be stuck in the while loop forever.

‘for’ loops and ‘while’ loops are hardly necessary in coding in the Arduino IDE and definitely not for the purpose that you intend. loop() is called numerous times per second (if you don’t use delay()) so it is the looping that you’re after.

To explain: there is a main() function that you usually will not see that basically does the following (do not implement the below)

void main()
{
  // call setup()
  setup();

  // forever
  while(1)
  {
    // call loop()
    loop();

    ...
    ...
  }
}

main is the start point of your application. It first calls your setup function and next calls (in an endless loop) loop().

So your code in loop should basically be simple
1)
read buttons and determine active mode
2)
using the switch statement, do whatever needs to be done based on the active mode.

void loop()
{
  // the currently active mode
  static byte activeMode = 0;
  // the selected mode before confirmation
  static byte mode = 0;
  // timeout start time
  static unsigned long timeoutStartTime = 0;

  // make a copy of active mode to temporary mode variable so we can compare if it has changed
  byte tmpMode = activeMode;

  // if mode button pressed
  if (digitalRead(modeButton) == LOW)
  {
    // delay a little for debouncing and to give user a chance to release the button
    delay(1000);
    // increment the selected mode
    mode++;
    // debug
    Serial.print("mode = "); Serial.print (mode);
    // when selected mode exceeds the maximum, go back to the first menu
    if (mode == 4)
    {
      mode = 0;
    }
    // set the start time of the time out to the current time
    timeoutStartTime = millis();
  }

  // if the confirm button is pressed
  if (digitalRead(confirmButton) == LOW)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // make the selected mode the active mode
    activeMode = mode;
    // debug
    Serial.print("active mode change to "); Serial.println(activeMode);
  }

  // check if no button was pressed for 5 seconds
  if (millis() - timeoutStartTime >= 5000)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // restore the selected mode for the next time that the user presses the mode button
    mode = activeMode;
  }

  // only if the active mode has changed, update the display
  if (tmpMode != activeMode)
  {
    // update the display
    switch (activeMode)
    {
      case 0:
        lcd.clear();
        lcd.print("Hello");
        break;
      case 1:
        lcd.print(measurement1());
        lcd.print(" units");
        break;
      case 2:
        lcd.print(measurement2());
        lcd.print(" units");
        break;
      case 3:
        lcd.print(measurement3());
        lcd.print(" units");
        break;
    }
  }
}


int measurement1()
{
  return analogRead(A0);
}
int measurement2()
{
  return analogRead(A1);
}
int measurement3()
{
  return analogRead(A2);
}

Now there is only one problem with this code and that it blocks when the button is pressed, something that one usually does not want.

If you provide some information about what the different modes are supposed to do, I can possibly work out some more detailed example code that will not use delays.

I came up with a simple example program.

A meter that can measure voltage, current and power. It has two buttons to select and set the mode.
It has a 16x2 LCD display that displays (in the first line) the mode while selecting or the mode that is set and displays the measured value for the selected mode on the second line.

First we will write a function that debounces the mode button. Before doing so, we define a debounce delay time (near the beginning of the code).

#include <LiquidCrystal.h>
#define DEBOUNCE_DELAY 150

/***************************************
  Button pins
  NOTE: both buttons between pin and GND
***************************************/
const byte modeButton = 6;
const byte confirmButton = 7;

// define number of rows and columns of the lcd
#define LCD_NUMCOLS 16
#define LCD_NUMROWS 2
// more lcd stuff here
...
...

void setup()
{
  // setup serial port for debugging
  Serial.begin(115200);

  // set the button mode to INPUT_PULLUP
  pinMode(modeButton, INPUT_PULLUP);
  pinMode(confirmButton, INPUT_PULLUP);

  // init the lcd
  lcd.begin(LCD_NUMCOLS, LCD_NUMROWS);
}

void loop()
{
  ...
  ...
}

Next we write the function to read the mode button

/*
  read the mode button
  returns:
    button state after state change
  note:
    current code assumes a button wired from pin to ground
    if the button is wired between Vcc and pin, change the initial values of previousState
*/
byte readModeButton()
{
  // remember the last state of the button; initialized to the non-pressed state of the button
  static byte lastButtonState = HIGH;
  // start time of debounce delay
  static unsigned long debounceStarttime = 0;

  // read the pushbutton input pin
  byte buttonState = digitalRead(modeButton);

  // if debounce not in progress (debounceStartTime equals 0) and button state has changed
  if (debounceStarttime == 0 && lastButtonState != buttonState)
  {
    // set debounce start time
    debounceStarttime = millis();
    // remember last state
    lastButtonState = buttonState;
  }

  // if debounce in progress
  if (debounceStarttime != 0)
  {
    // if debounce delay lapsed
    if (millis() - debounceStarttime >= DEBOUNCE_DELAY)
    {
      // allow 'recording' of new state
      debounceStarttime = 0;
    }
  }

  // return last remembered state of button
  return lastButtonState;
}

Try to understand this code. It reads the state of the button and if no delay is in progress compares it to the last known state. If that state changed, it will remember the last state.

While the delay is in progress, the code will not react on changes of the button; so either if you release the button or if it bounces, it will return the last known state after the change during the delay.

Next you need to write a similar function for the confirm button. Just make a copy, call it readConfirmButton and change the pin that is read by that function to confirmButton

Your full code should now look like

#include <LiquidCrystal.h>
#define DEBOUNCE_DELAY 150

...
...

void setup()
{
  ...
  ...
}

void loop()
{
  ...
  ...
}

/*
  read the mode button
  returns:
    button state after state change
  note:
    current code assumes a button wired from pin to ground
    if the button is wired between Vcc and pin, change the initial values of previousState
*/
byte readModeButton()
{
  ...
  ...
}

/*
  read the confirm button
  returns:
    button state after state change
  note:
    current code assumes a button wired from pin to ground
    if the button is wired between Vcc and pin, change the initial values of previousState
*/
byte readConfirmButton()
{
  ...
  ...
}

In the next step we will use those two functions to change the selected mode and confirm the mode

/*
  check the buttons
  returns:
    currently active mode
*/
byte checkButtons()
{
  // timeout start time
  static unsigned long timeoutStartTime = 0;

  // the mode that is currently active
  static byte activeMode = 0;
  // selected mode before confirm
  static byte mode = 0;

  // previous states of the buttons; initialized to the not-pressed state
  static byte lastModebuttonState = HIGH;
  static byte lastConfirmbuttonState = HIGH;

  // read the buttons
  byte modeButtonState = readModeButton();
  byte confirmButtonState = readConfirmButton();

  // if mode button pressed and previously not pressed
  if (modeButtonState == LOW && lastModebuttonState == HIGH)
  {
    // increment the selected mode
    mode++;
    // when selected mode exceeds the maximum, go back to the first menu
    if (mode == 4)
    {
      mode = 0;
    }

    lcdClearline(0);
    lcd.print(titles[mode]);
    lcd.print(" ?");

    // debug
    Serial.print("mode = "); Serial.println(mode);
    // set the start time of the time out to the current time
    timeoutStartTime = millis();
  }

  // if the confirm button is pressed and previously not pressed
  if (confirmButtonState == LOW && lastConfirmbuttonState == HIGH)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // make the selected mode the active mode
    activeMode = mode;
    // debug
    Serial.print("active mode change to "); Serial.println(activeMode);

    lcdClearline(0);
    lcd.print(titles[mode]);

  }

  // check if no button was pressed for 5 seconds
  if (timeoutStartTime != 0 && millis() - timeoutStartTime >= 5000)
  {
    // reset the start time of the time out
    timeoutStartTime = 0;
    // restore the selected mode for the next time that the user presses the mode button
    mode = activeMode;

    lcdClearline(0);
    lcd.print(titles[activeMode]);
  }

  // remember last button states
  lastModebuttonState = modeButtonState;
  lastConfirmbuttonState = confirmButtonState;

  // return the active mode
  return activeMode;
}

Again, try to understand this code. With some changes, it’s basically the same as I showed before. The changes are mostly that for each of the buttons the code checks if the state of the buttons changed. I’ve introduced a new function (lcdClearline()) and an array with menu titles; I will describe those in the next post.

The code in the previous uses an array with the mode titles. So when you cycle through the modes, you can see which mode is selected. For each mode there is a matching entry in the array. This will be displayed on the first line of the display (line 0 as computers usually count from 0).

The array goes near the top of the code

#include <LiquidCrystal.h>
#define DEBOUNCE_DELAY 150

/***************************************
  mode titles
***************************************/
const char *titles[] =
{
  "Welcome",
  "Voltage",
  "Current",
  "Power"
};

/***************************************
  Button pins
  NOTE: both buttons between pin and GND
***************************************/
const byte modeButton = 6;
const byte confirmButton = 7;

// define number of rows and columns of the lcd
#define LCD_NUMCOLS 16
#define LCD_NUMROWS 2
// more lcd stuff here
...
...


void setup()
{
  // setup serial port for debugging
  Serial.begin(115200);

  // set the button mode to INPUT_PULLUP
  pinMode(modeButton, INPUT_PULLUP);
  pinMode(confirmButton, INPUT_PULLUP);

  // init the lcd
  lcd.begin(LCD_NUMCOLS, LCD_NUMROWS);

  // print the first title
  lcd.print(titles[0]);
}

...
...

As mentioned, there is a new function which will clear the a specified line of the lcd; it does this by placing the cursor at the beginning of the line and writing a number of spaces and next placing the ursor again at the beginning of the line.

/*
  clear a line of the display
  in:
    lineNumber specifies the row to clear
*/
void lcdClearline(byte lineNumber)
{
  // check for invalid line numbets
  if (lineNumber >= LCD_NUMROWS)
  {
    return;
  }

  // create a buffer and fill with spaces
  char buffer[LCD_NUMCOLS + 1];
  memset(buffer, ' ', LCD_NUMCOLS);
  // add string terminator
  buffer[LCD_NUMCOLS] = '\0';

  // clear the line
  lcd.setCursor(0, lineNumber);
  lcd.print(buffer);
  lcd.setCursor(0, lineNumber);
}

This code basically fills a small text buffer with spaces and writes it to the lcd.

The below code in checkButtons() updates the first line if the selected mode (before confirmation) changes

    lcdClearline(0);
    lcd.print(titles[mode]);
    lcd.print(" ?");

It clears the first line of the display and prints the title. It also prints a ‘?’ to indicate that the mode is selected but not confirmed yet.

After a 5 second timeout or after confirmation, the same line will contain the active mode without the ‘?’.

I have an emergency; will continue later

So now we only have to do our loop(); it will determine the active mode using checkButtons and next take action using a switch/case.

void loop()
{
  // read the buttons and assign to activeMode.
  byte activeMode = checkButtons();

  lcdClearline(1);
  switch (activeMode)
  {
    case 0:
      break;
    case 1:
      lcd.print(measureVoltage());
      lcd.print(" Volt");
      break;
    case 2:
      lcd.print(measureCurrent());
      lcd.print(" Amp");
      break;
    case 3:
      lcd.print(measurePower());
      lcd.print(" Watt");
      break;
  }
}

The measureXXX functions are basically simple placeholders; you can replace them by what you need. Their implementations are below.

int measureVoltage()
{
  return analogRead(A0);
}

int measureCurrent()
{
  return analogRead(A1);
}

long measurePower()
{
  return (long)analogRead(A0) * (long)analogRead(A1);
}

The complete overview of the code (functions in proper C order)

// #include, #define, button and title declaration, lcd declaration
...
...


void readConfirmButton()
{
  ...
  ...
}

byte readModeButton()
{
  ...
  ...
}

byte checkButtons()
{
  ...
  ...
}

int measureVoltage()
{
  ...
  ...
}

int measureCurrent()
{
  ...
  ...
}

long measurePower()
{
  ...
  ...
}


void setup()
{
  ...
  ...
}

void loop()
{
  ...
  ...
}

Because there is no use of delays, the loop will execute very quickly; as a result the line that displays the measured values will be updated often (faster than the eye can follow). I leave it up to you to slow it down without making use of delay; checkButtons() and readXxButton() should give you enough information how to use millis() based timing to e.g. measure only every 500ms.