Programming a button to go back from a while menu thing

I need to figure out how to leave the function and get back to the main menu.

Hello, i am doing an project for my Uni and can't get past this problem. I have 4 buttons, Button up (bu) , down (bd) , select (bs) and back (bb), i have a function called " void masurareRezistenta() ", from which i measure the resistance and update constantly, if the button thing work i will make it update after 2-3 second maybe and just to keep the value until I pull out the resistor. the problem here is i can't get out of the function and be on the main menu, tried different things with other constant that change when i press the back button and should get me out of the while but nothing, tried ChatGPT and it's making something weird that i leave the measuring menu but first press it gets a freeze and at the second press of the back button i really leave the menu.

Down here is the code, if i figure this thing out all that's left it's easy, i plan to make resistance to be measure after 2-3 seconds so i can have enough time for a good value and to be exact like on a multimeter.

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_CS    10  // Chip select (CS)
#define TFT_RST   8   // Reset pin
#define TFT_DC    9   // Data/Command pin

int bb = 5;   // Buton Back (BB)
int bu = 4;  // Buton Up (BU)
int bd = 3;  // Buton Down (BD)
int bs = 2;  // Buton Select (BS)

int stare1 = -1; 
int stare2 = -1;
int stare3 = -1;
int stare4 = 0;
bool bs_apasat = false;

 // Ohm metru //
const int sensorPin = A0;  // Analog input pin that senses Vout
int sensorValue = 0;       // sensorPin default value
float Vin = 5;             // Input voltage
float Vout = 0;            // Vout default value
float Rref = 999;          // Reference resistor's value in ohms
float R = 0;               // Tested resistor's default value
  //Ohm metru //

int meniu = 1;  // Meniul curent, începe de la 1

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

void setup() {
  Serial.begin(9600);  // Initialize Serial Monitor
  pinMode(bu, INPUT_PULLUP);  // Setare buton Up ca INPUT_PULLUP
  pinMode(bd, INPUT_PULLUP);  // Setare buton Down ca INPUT_PULLUP
  pinMode(bs, INPUT_PULLUP);  // Setare buton Select ca INPUT_PULLUP
  pinMode(bb, INPUT_PULLUP);

  tft.init(240, 320);  // Inițializare ecran 240x320 pixeli
  tft.setRotation(1);  // Rotire ecran
  tft.fillScreen(ST77XX_BLACK);  // Fundal negru
  tft.setTextColor(ST77XX_WHITE);  // Text alb
  tft.setTextSize(2);  // Dimensiune text
  afisaremeniu();  // Afișează meniul inițial
}

void afisaremeniu() {
   //tft.fillScreen(ST77XX_BLACK);  // Șterge ecranul
  switch (meniu) {
    case 1:
      tft.fillRect(10,30,10,180, ST77XX_BLACK );
      tft.setCursor(10, 30);
      tft.print(">");
      tft.setCursor(30, 30);
      tft.print("Rezistenta");  // Selectat Meniu 1
      tft.setCursor(30, 80);
      tft.print("Capacitate");
      tft.setCursor(30, 130);
      tft.print("Inductanta");
      tft.setCursor(30, 180);
      tft.print("Info");
    break;
    case 2:
      tft.fillRect(10,30,10,180, ST77XX_BLACK );
      tft.setCursor(10, 80);
      tft.print(">");
      tft.setCursor(30, 30);
      tft.print("Rezistenta");
      tft.setCursor(30, 80);
      tft.print("Capacitate");  // Selectat Meniu 2
      tft.setCursor(30, 130);
      tft.print("Inductanta");
      tft.setCursor(30, 180);
      tft.print("Info");
    break;
    case 3:
      tft.fillRect(10,30,10,180, ST77XX_BLACK );
      tft.setCursor(10, 130);
      tft.print(">");
      tft.setCursor(30, 30);
      tft.print("Rezistenta");
      tft.setCursor(30, 80);
      tft.print("Capacitate");
      tft.setCursor(30, 130);
      tft.print("Inductanta");  // Selectat Meniu 3
      tft.setCursor(30, 180);
      tft.print("Info");
    break;
    case 4:
      tft.fillRect(10,30,10,180, ST77XX_BLACK );
      tft.setCursor(10, 180);
      tft.print(">");
      tft.setCursor(30, 30);
      tft.print("Rezistenta");
      tft.setCursor(30, 80);
      tft.print("Capacitate");
      tft.setCursor(30, 130);
      tft.print("Inductanta");  // Selectat Meniu 3
      tft.setCursor(30, 180);
      tft.print("Info");
    break;
  }
}

void loop() {

  int stare1 = digitalRead(bu);
  int stare2 = digitalRead(bd);
  int stare3 = digitalRead(bs);
  int stare4 = digitalRead(bb);

  // Navigare în meniu folosind butonul Up (BU)
  if (stare1 == 1 && bs_apasat == false) {  // Buton Up
    meniu--;  // Mergem la meniul anterior
   if (meniu < 1) { meniu = 4; }  // Revin la ultimul meniu dacă scade sub 1
    afisaremeniu();  // Actualizează meniul pe ecran
    delay(200);  // Debounce
    stare1 = 0;
  }
    // Navigare în meniu folosind butonul Down (BD)
  if (stare2 == 1 && bs_apasat == false) {  // Buton Down
    meniu++;  // Trecem la următorul meniu
    if (meniu > 4) { meniu = 1; }  // Revin la primul meniu dacă depășește 3
    afisaremeniu();  // Actualizează meniul pe ecran
    delay(200);  // Debounce
    stare2 = 0;
  }
  // Execută acțiunea selectată cu butonul Select (BS)
  if (stare3 == 1 && bs_apasat == false) {  // Buton Select ( se duce in meniu )
    actiune();  // Execută acțiunea pentru meniul curent
    delay(200);  // Debounce
    stare3 = 0;
    bs_apasat = true;
  }
  if (stare4 == 1 && bs_apasat == true ){
    tft.fillScreen(ST77XX_BLACK);
    afisaremeniu();
    delay(200);
    stare4 = 0;
    bs_apasat = false;
  }
  delay(100);
}
void actiune() {
  switch (meniu) {
    case 1:
     masurareRezistenta();
    break;

    case 2:
       tft.fillScreen(ST77XX_BLACK);
       tft.setCursor(10, 30);
       tft.print("Testare Meniu 2!"); 
    break;
    case 3:
       tft.fillScreen(ST77XX_BLACK);
       tft.setCursor(10, 30);
       tft.print("Testare Meniu 3!");
    break;
    case 4:
      tft.fillScreen(ST77XX_BLACK);
      tft.setCursor(10, 30);
      tft.print("Testare Meniu 4!");
    break;
}
}
void masurareRezistenta() {
   tft.fillScreen(ST77XX_BLACK);
    tft.setCursor(10, 10);
    tft.print("Masurare rezistenta:");
      int masurare = 1;
     while (masurare == 1 ) {
            // Citește valoarea senzorului
            sensorValue = analogRead(sensorPin);  // Citește Vout pe pinul analogic A0
            Vout = (Vin * sensorValue) / 1023.0;  // Conversie la volți
            R = Rref * (1 / ((Vin / Vout) - 1));
            tft.fillRect(10, 50, 220, 30, ST77XX_BLACK);  // Curăță zona de afișare
            tft.setCursor(10, 50);
            
                if (R > 500000) {  // Rezistență infinită sau foarte mare
                    tft.print("R: Inf");
                } else if (R > 999) {  // Conversie la kOhm
                    tft.print("R: ");
                    tft.print(R / 1000.0, 2);  // 2 zecimale pentru precizie
                    tft.print(" kOhm");
                } else {  // Rezistență în Ohmi
                    tft.print("R: ");
                    tft.print(R, 2);  // 2 zecimale pentru precizie
                    tft.print(" Ohm");
                }
           delay(1000);
        
     }
}
    
    





Search the forum for something called 'several things at the same time' or sometimes called a state machine.

To ensure that the masurareResistenta function can be exited when the "Back" button (bb) is pressed, you need to change the logic of the while loop inside this function. The problem in your code is that the masurare variable does not change depending on the buttons being pressed, and the loop runs endlessly.

Here's how to fix it:

  1. Add a check for the state of the Back button inside the while loop.
  2. Instead of the masurare variable, use a boolean variable, such as bool running, which will control the execution of the loop.

Here's the updated code for the masurareResistenta function:

void masurareResistenta() {
tft.fillScreen(ST77XX_BLACK);
tft.setCursor(10, 10);
tft.print("Masurare rezistenta:");

bool running = true; // Boolean variable to control the loop

while (running) {
// Check for the "Back" button
int stare4 = digitalRead(bb);
if (stare4 == 0) { // The "Back" button is pressed
running = false; // Exit the loop
break;
}

// Read the sensor value
sensorValue = analogRead(sensorPin); // Read Vout on analog pin A0
Vout = (Vin * sensorValue) / 1023.0; // Convert to volts
if (Vout > 0) {
R = Rref * (1 / ((Vin / Vout) - 1));
} else {
R = 0; // If Vout is 0, the resistor is not connected
}

// Update the value on the screen
tft.fillRect(10, 50, 220, 30, ST77XX_BLACK); // Clear the display area
tft.setCursor(10, 50);

if (R > 500000) { // Very high or infinite resistance
tft.print("R: Inf");
} else if (R > 999) { // Conversion to kOhm
tft.print("R: ");
tft.print(R / 1000.0, 2); // 2 decimal places
tft.print(" kOhm");
} else { // Resistance in Ohm
tft.print("R: ");
tft.print(" Ohm");
}

delay(2000); // Delay between measurements
}

// Return to main menu
tft.fillScreen(ST77XX_BLACK);
afisaremeniu();
}

Explanation of changes:

  1. Added a logical variable running: It determines whether to continue the while loop.
  2. Checking the state of the "Back" button: Uses the function digitalRead(bb) to end the loop when the button is pressed.
  3. Delay between measurements: Uses delay(2000) to update the values ​​every 2 seconds.

Other improvements:

  • Handling the "Back" button in the main loop: If the user chooses not to exit the measurement function, the "Back" button will work correctly.
  • Clearing the value output area: Removes residual characters when updating data.

this is basicaly the solution chatgpt gave me.... now i can acces masurareRezistenta stay on for 200 ms and the it shows up the main menu where i have to press the back button so i can go to the real main menu where i can navigate with the arrow

what several things ? the solution sound logical but the code is not, if i use and "if" the value it works but i don't have enough time to see the real value or the stabile value of the resitance, if i us an "while" i can't get out or i get another main menu and have to press the back button again, and still is not clear how keep the good value there

chatGPT copies its own mistakes? Also known as "propagation of errors."

Here is my code from the SmarWatch project, there is a menu and an exit from it is implemented. I hope this helps somehow!!

#include <LowPower.h>
#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

RTC_DS3231 rtc;
DateTime dt;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Define button pins
const int buttonUpPin = A0; // Button to navigate up
const int buttonDownPin = A2; // Button to navigate down
const int buttonMenuPin = A1; // Button to open the menu
bool buttonPressed = false;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 10;
int buttonUpState;
int lastButtonUpState = HIGH;
int buttonDownState;
int lastButtonDownState = HIGH;
int buttonMenuState;
int lastButtonMenuState = HIGH;
bool menuDisplayed = false; // State variable for menu display

// Variables to track menu navigation
int currentMenuItem = 0;
const int totalMenuItems = 5; // Updated to include "Turn Off Watch"
const char *menuItems[] = {
  "Always-on display",
  "Eco Mode",
  "Method get temp",
  "Turn Off Watch(!)",
  "Back"
};

// Timer for brightness reduction
unsigned long previousMillis = 0;
unsigned long interval = 30000; // 30 sec, modified in Eco Mode

// Timer for display off
unsigned long displayOffMillis = 0;
unsigned long displayOffInterval = 240000; // 4 min, modified in Eco Mode

// Variable to track temperature adjustment state
bool temperatureAdjustmentState = false; // false means subtract 3°C, true means add 2°C

// Variable to track always-on display state
bool alwaysOnDisplayState = false; // false means always-on display is off, true means always-on display is on

// Variable to track Eco Mode state
bool ecoModeState = false; // false means Eco Mode is off, true means Eco Mode is on

void setup() {
  pinMode(buttonUpPin, INPUT_PULLUP); // Set the button pin to input with pull-up
  pinMode(buttonDownPin, INPUT_PULLUP); // Set the button pin to input with pull-up
  pinMode(buttonMenuPin, INPUT_PULLUP); // Set the button pin to input with pull-up

  Serial.begin(9600);

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.display();
  delay(2000);

  display.clearDisplay();
  display.display();
}

String DayOfTheWeek(uint8_t Day) {
  String DayText;
  if (Day == 0)  DayText = "Sunday";
  if (Day == 1)  DayText = "Monday";
  if (Day == 2)  DayText = "Tuesday";
  if (Day == 3)  DayText = "Wednesday";
  if (Day == 4)  DayText = "Thursday";
  if (Day == 5)  DayText = "Friday";
  if (Day == 6)  DayText = "Saturday";
  return DayText;
}

String DayMonthYear(uint8_t Day, uint8_t Month, uint16_t Year) {
  String DayMonthYearText;
  if (Month < 10) DayMonthYearText += "0";
  DayMonthYearText += String(Month) + "/";

  if (Day < 10) DayMonthYearText += "0";
  DayMonthYearText += String(Day) + "/";

  DayMonthYearText += String(Year);

  return DayMonthYearText;
}

String AddLeadingZero(uint8_t x) {
  String AddLeadingZeroText;
  if (x < 10) AddLeadingZeroText = "0";
  AddLeadingZeroText += String(x);
  return AddLeadingZeroText;
}

String CurrentTime(uint8_t H, uint8_t I, uint8_t S = 0) {
  String CurrentTimeText = AddLeadingZero(H) + ":" + AddLeadingZero(I);
  if (S != 0) {
    CurrentTimeText += ":" + AddLeadingZero(S);
  }
  return CurrentTimeText;
}

void displayMenu() {
  display.clearDisplay();

  for (int i = 0; i < totalMenuItems; ++i) {
    int yPos = i * 8; // Calculate Y position based on item index

    // Draw bullet point if current item is selected
    if (i == currentMenuItem) {
      display.fillRect(2, yPos + 2, 4, 4, SSD1306_WHITE); // Draw white bullet at (2, yPos + 4)
    }

    // Display menu item text
    display.setCursor(10, yPos);
    display.setTextSize(1);
    display.setTextColor(i == currentMenuItem ? SSD1306_WHITE : SSD1306_WHITE);
    display.println(menuItems[i]); // Replace with your menu item text

    // Display dot next to "Always-on display" if always-on display state is true
    if (i == 0 && alwaysOnDisplayState) {
      display.fillRect(120, yPos + 2, 4, 4, SSD1306_WHITE); // Adjust coordinates for dot placement
    }

    // Display dot next to "Eco Mode" if eco mode state is true
    if (i == 1 && ecoModeState) {
      display.fillRect(120, yPos + 2, 4, 4, SSD1306_WHITE); // Adjust coordinates for dot placement
    }
    // Display dot next to "Switch hand temp" if temperature adjustment state is true (+0°C)
    if (i == 2 && temperatureAdjustmentState) {
      display.fillRect(120, yPos + 2, 4, 4, SSD1306_WHITE); // Adjust coordinates for dot placement
    }

  }

  display.display();
}

void loop() {
  dt = rtc.now();

  // Handle button press with debounce
  int readingUp = digitalRead(buttonUpPin);
  int readingDown = digitalRead(buttonDownPin);
  int readingMenu = digitalRead(buttonMenuPin);

  if (readingUp != lastButtonUpState) {
    lastDebounceTime = millis();
  }
  if (readingDown != lastButtonDownState) {
    lastDebounceTime = millis();
  }
  if (readingMenu != lastButtonMenuState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readingUp != buttonUpState) {
      buttonUpState = readingUp;
      if (buttonUpState == LOW) {
        buttonPressed = true;
        if (menuDisplayed) {
          currentMenuItem = (currentMenuItem - 1 + totalMenuItems) % totalMenuItems; // Navigate up with wrap-around
        }
      }
    }
    if (readingDown != buttonDownState) {
      buttonDownState = readingDown;
      if (buttonDownState == LOW) {
        buttonPressed = true;
        if (menuDisplayed) {
          currentMenuItem = (currentMenuItem + 1) % totalMenuItems; // Navigate down with wrap-around
        }
      }
    }
    if (readingMenu != buttonMenuState) {
      buttonMenuState = readingMenu;
      if (buttonMenuState == LOW) {
        buttonPressed = true;
        if (!menuDisplayed) {
          menuDisplayed = true; // Open the menu
          currentMenuItem = 0; // Reset to the first menu item
        } else {
          // Handle menu selection
          switch (currentMenuItem) {
            case 0:
              // Handle "Always-on display" action
              alwaysOnDisplayState = !alwaysOnDisplayState;
              delay(5);
              ecoModeState = false;
              delay(5);
              menuDisplayed = false; // Close the menu
              break;
            case 1:
              // Handle "Eco Mode" action
              ecoModeState = !ecoModeState; // Toggle Eco Mode state
              delay(5);
              alwaysOnDisplayState = false;
              if (ecoModeState) {
                interval = 15000; // Set brightness reduction interval to 15 sec
                displayOffInterval = 60000; // Set display off interval to 1 min
              } else {
                interval = 30000; // Set brightness reduction interval to 30 sec
                displayOffInterval = 240000; // Set display off interval to 4 min
              }
              delay(5);
              menuDisplayed = false; // Close the menu
              break;
            case 2:
              // Handle "Switch hand temp" action
              temperatureAdjustmentState = !temperatureAdjustmentState; // Toggle temperature adjustment state
              delay(5);
              menuDisplayed = false; // Close the menu
              break;
            case 3:
              // Handle "Turn Off Watch" action
              display.ssd1306_command(SSD1306_DISPLAYOFF); // Turn off the display
              previousMillis = millis(); // Reset brightness reduction timer
              displayOffMillis = millis(); // Reset display off timer
              sleepNow();
              menuDisplayed = false; // Close the menu
              break;
            case 4:
              menuDisplayed = false; // Close the menu
              break;
          }
        }
      }
    }
  }

  lastButtonUpState = readingUp;
  lastButtonDownState = readingDown;
  lastButtonMenuState = readingMenu;

  if (buttonPressed) {
    display.ssd1306_command(SSD1306_DISPLAYON); // Turn on the display
    display.ssd1306_command(SSD1306_SETCONTRAST);
    display.ssd1306_command(0xFF); // Set brightness to 100%
    previousMillis = millis(); // Reset the brightness reduction timer
    displayOffMillis = millis(); // Reset the display off timer
    buttonPressed = false;
  }

  // Handle brightness reduction
  if (!alwaysOnDisplayState && (millis() - previousMillis >= interval)) {
    display.ssd1306_command(SSD1306_SETCONTRAST);
    display.ssd1306_command(0x01); // Set brightness to 1%
    previousMillis = millis(); // Reset the timer to prevent repeated brightness reduction
  }

  // Handle display off
  if (!alwaysOnDisplayState && (millis() - displayOffMillis >= displayOffInterval)) {
    display.ssd1306_command(SSD1306_DISPLAYOFF); // Turn off the display
    menuDisplayed = false; // Close the menu if it was open
  }

  if (menuDisplayed) {
    displayMenu();
  } else {
    display.clearDisplay();

    if (alwaysOnDisplayState) {
      // Display always-on display screen
      display.setCursor(0, 0);
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.println(DayMonthYear(dt.day(), dt.month(), dt.year())); // Display today's date in the top left corner

      display.setCursor(3, 25);
      display.setTextSize(3);
      display.setTextColor(SSD1306_WHITE);
      display.println(CurrentTime(dt.hour(), dt.minute()));

      display.ssd1306_command(SSD1306_SETCONTRAST);
      display.ssd1306_command(0x01); // Set brightness to minimum
    } else if (ecoModeState) {
      // Display Eco Mode screen
      //      display.setCursor((SCREEN_WIDTH - 6 * 6) / 3, (SCREEN_HEIGHT - 8) / 2); // Centered horizontally and vertically
      //      display.setTextSize(3);
      //      display.setTextColor(SSD1306_WHITE);
      //      display.println(CurrentTime(dt.hour(), dt.minute()));


      // display.fillRect(0, 0, 128, 16, SSD1306_WHITE);
      display.fillRect(0, 17, 128, 16, SSD1306_BLACK);
      //      display.fillRect(0, 31, 128, 33, SSD1306_WHITE);

      display.setCursor(1, 1);
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.println(DayOfTheWeek(dt.dayOfTheWeek()));

      display.setCursor(1, 18);
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.println(DayMonthYear(dt.day(), dt.month(), dt.year()));

      display.setCursor(3, 35);
      display.setTextSize(3);
      display.setTextColor(SSD1306_WHITE);
      display.println(CurrentTime(dt.hour(), dt.minute()));

      float temp = rtc.getTemperature();
      if (temperatureAdjustmentState) {
        temp += 0.0; // Add 0°C
      } else {
        temp -= 4.1; // Subtract 4.1°C
      }
      display.setCursor(85, 18);
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.print(temp, 1);
      display.setCursor(117, 16);
      display.print("C");

      display.setCursor(100, 35);
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.println(AddLeadingZero(dt.second()));




      display.ssd1306_command(SSD1306_SETCONTRAST);
      display.ssd1306_command(0x01); // Set brightness to minimum
    } else {
      // Display normal clock screen
      display.fillRect(0, 0, 128, 16, SSD1306_WHITE);
      display.fillRect(0, 17, 128, 16, SSD1306_BLACK);
      display.fillRect(0, 31, 128, 33, SSD1306_WHITE);

      display.setCursor(1, 1);
      display.setTextSize(2);
      display.setTextColor(SSD1306_BLACK);
      display.println(DayOfTheWeek(dt.dayOfTheWeek()));

      display.setCursor(1, 18);
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.println(DayMonthYear(dt.day(), dt.month(), dt.year()));

      display.setCursor(3, 35);
      display.setTextSize(3);
      display.setTextColor(SSD1306_BLACK);
      display.println(CurrentTime(dt.hour(), dt.minute()));

      display.setCursor(100, 35);
      display.setTextSize(2);
      display.setTextColor(SSD1306_BLACK);
      display.println(AddLeadingZero(dt.second()));

      float temp = rtc.getTemperature();
      if (temperatureAdjustmentState) {
        temp += 0.0; // Add 0°C
      } else {
        temp -= 4.1; // Subtract 4.1°C
      }
      display.setCursor(85, 18);
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.print(temp, 1);
      display.setCursor(117, 16);
      display.print("C");
    }

    display.display();
  }
  delay(100);
}

// Placeholder function for putting Arduino to sleep
void sleepNow() {
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}

The several things are reading the resistance and displaying the main menu, and reading buttons.
Change the while in the resistor read to something like the following.

unsigned long rMsrElap = 250;    // 250ms to read the R
unsigned long rTimeStart;
rTimeStart = millis();
while (millis() < (rTimeStart + rMsrElap))
etc

The first time i did it alone with some simple “if”, then i changed to “while” and after i got to him with the problem, still don’t understand what need to be done. Even if i have another variable to do the while or an “do {} while” i can’t get out of the menu, and have to press twice the back button. I know that maybe a solution is to put everything in the void loop :frowning: , but i want everything in order and to show that I understand what is happening, i’ll have some presentation about this project and 90% i know what i did, but i am stuck here

Just really search for it and you will see

This depends on the overall logic and can be done. It is just you that the solution did not come quickly to your mind. You have to read and learn about it.

absolutely 100 Million percent sure you can get out of a while-loop by polling your back-button

inside the while-loop

not clear what you want to say with that

This might be a problem of variable-scope or you can add another boolean variable
guess where ?

inside your while-loop

to go back up to your main-menu by only pressing the backbutton once

That is what a state-machine basically does
let do void loop() the "looping"

Here is a graphical explanation of the basic concept how non-blocking coding works

Sure the code runs down "in order" and you can make your code easy to understand by dividing your code into functions where each function does one thing

If you rewrite your code to use non-blocking timing and a state-machine
I am pretty sure you will earn a lot of reputation because then you are on the professional level

Sure this will take some time to learn. Once you have understood the basic principle you never want to go back

here is one tutorial that demonstrates how state-machines work

Not in my code, but there is a solution that i add an if( bb == High) or his digitalReal value, i can enter the main menu function and after i have to press again the button so i can be on the main main menu, i think this works something like a break for the resistor calculus and it stop calculating.

I just need to go back to the main menu :))), other solution i think would be to measure the resistante after some time using ifs and the button works with the if command, but how do i make it to measure repeatedly and not going back and forth ?

can't trap the resistance function with an infinite loop. need to invoke it independently (in a timer)

look this over

# include <Adafruit_GFX.h>
# include <Adafruit_ST7789.h>
# include <SPI.h>

#define TFT_CS    10  // Chip select (CS)
#define TFT_RST   8   // Reset pin
#define TFT_DC    9   // Data/Command pin

//                       sel back up down
const byte PinBut [] = {  2,   5,  4,  3 };

const int  Nbut      = sizeof(PinBut);
      byte butState [Nbut];

enum { B_sel, B_back , B_up, B_down};

// Ohm metru //
const int sensorPin = A0;  // Analog input pin that senses Vout
int sensorValue = 0;       // sensorPin default value
float Vin = 5;             // Input voltage
float Vout = 0;            // Vout default value
float Rref = 999;          // Reference resistor's value in ohms
float R = 0;               // Tested resistor's default value
//Ohm metru //

const int Nmenu = 4;
int       meniu = 1;  // Meniul curent, începe de la 1

Adafruit_ST7789 tft = Adafruit_ST7789 (TFT_CS, TFT_DC, TFT_RST);

// -----------------------------------------------------------------------------
const int NoBut = -1;
int
chkBut ()
{
    for (int n = 0; n < Nbut; n++)  {
        byte but = digitalRead (PinBut [n]);
        if (butState [n] != but)  {
            butState [n]  = but;
            delay (20);             // debounce

            if (LOW == but)
                return n;
        }
    }

    return NoBut;
}

// -----------------------------------------------------------------------------
const unsigned long MsecPeriod = 1000;
      unsigned long msec0;
bool tmr;

int  mode;

// -------------------------------------
void loop ()
{
    // background processing
    unsigned long msec = millis ();
    if (tmr && msec - msec0 >= MsecPeriod)  {
        msec0 = msec;

        switch (mode) {
        case 1:
            masurareRezistenta ();
            break;

        default:
            Serial.println ("  invalid mode");
            tmr = false;
            break;
        }
    }

    // monitor buttons
    switch (chkBut ())  {
    case B_back:
        Serial.println ("B_back");
        tmr = false;
        afisaremeniu ();    // Actualizeaz─â meniul pe ecran
        break;

    case B_down:
        Serial.println ("B_down");
        if (1 > --meniu)
            meniu = Nmenu;
        afisaremeniu ();    // Actualizeaz─â meniul pe ecran
        break;

    case B_sel:
        Serial.println ("B_sel");
        actiune ();         // Execută acțiunea pentru meniul curent
        afisaremeniu ();    // Actualizeaz─â meniul pe ecran
        break;

    case B_up:
        Serial.println ("B_up");
        if (Nmenu < ++meniu)
            meniu = 1;
        afisaremeniu ();  // Actualizeaz─â meniul pe ecran
        break;
    }
}

// -----------------------------------------------------------------------------
void afisaremeniu ()
{
    Serial.println (__func__);

    //tft.fillScreen (ST77XX_BLACK);  // ╚ÿterge ecranul
    switch (meniu) {
    case 1:
        tft.fillRect (10,30,10,180, ST77XX_BLACK );
        tft.setCursor (10, 30);
        tft.print ("> Rezistenta");  // Selectat Meniu 1
        tft.setCursor (10, 80);
        tft.print ("  Capacitate");
        tft.setCursor (10, 130);
        tft.print ("  Inductanta");
        tft.setCursor (10, 180);
        tft.print ("  Info");
        break;
    case 2:
        tft.fillRect (10,30,10,180, ST77XX_BLACK );
        tft.setCursor (10, 30);
        tft.print ("  Rezistenta");
        tft.setCursor (10, 80);
        tft.print ("> Capacitate");  // Selectat Meniu 2
        tft.setCursor (10, 130);
        tft.print ("  Inductanta");
        tft.setCursor (10, 180);
        tft.print ("  Info");
        break;
    case 3:
        tft.fillRect (10,30,10,180, ST77XX_BLACK );
        tft.setCursor (10, 30);
        tft.print ("  Rezistenta");
        tft.setCursor (10, 80);
        tft.print ("  Capacitate");
        tft.setCursor (10, 130);
        tft.print ("> Inductanta");  // Selectat Meniu 3
        tft.setCursor (10, 180);
        tft.print ("  Info");
        break;
    case 4:
        tft.fillRect (10,30,10,180, ST77XX_BLACK );
        tft.setCursor (10, 30);
        tft.print ("  Rezistenta");
        tft.setCursor (10, 80);
        tft.print ("  Capacitate");
        tft.setCursor (10, 130);
        tft.print ("  Inductanta");  // Selectat Meniu 3
        tft.setCursor (10, 180);
        tft.print ("> Info");
        break;
    }
}

// -----------------------------------------------------------------------------
void actiune ()
{
    Serial.println (__func__);

    switch (meniu) {
    case 1:
        tmr = true;
        mode = 1;
        break;

    case 2:
        tft.fillScreen (ST77XX_BLACK);
        tft.setCursor (10, 30);
        tft.print ("Testare Meniu 2!");
        break;
    case 3:
        tft.fillScreen (ST77XX_BLACK);
        tft.setCursor (10, 30);
        tft.print ("Testare Meniu 3!");
        break;
    case 4:
        tft.fillScreen (ST77XX_BLACK);
        tft.setCursor (10, 30);
        tft.print ("Testare Meniu 4!");
        break;
    }
}

// -----------------------------------------------------------------------------
void masurareRezistenta ()
{
    Serial.println (__func__);

    tft.fillScreen (ST77XX_BLACK);
    tft.setCursor (10, 10);
    tft.print ("Masurare rezistenta:");

    // Citește valoarea senzorului
    sensorValue = analogRead (sensorPin);  // Citește Vout pe pinul analogic A0
    Vout = (Vin * sensorValue) / 1023.0;  // Conversie la volți
    R = Rref * (1 / ((Vin / Vout) - 1));
    tft.fillRect (10, 50, 220, 30, ST77XX_BLACK);  // Curăță zona de afișare
    tft.setCursor (10, 50);

    if (R > 500000) {  // Rezistență infinită sau foarte mare
        tft.print ("R: Inf");
    }
    else if (R > 999) {  // Conversie la kOhm
        tft.print ("R: ");
        tft.print (R / 1000.0, 2);  // 2 zecimale pentru precizie
        tft.print (" kOhm");
    }
    else {  // Rezistență în Ohmi
        tft.print ("R: ");
        tft.print (R, 2);  // 2 zecimale pentru precizie
        tft.print (" Ohm");
    }
}

// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);  // Initialize Serial Monitor

    for (int n = 0; n < Nbut; n++)  {
        pinMode (PinBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (PinBut [n]);
    }

    tft.init (240, 320);  // Inițializare ecran 240x320 pixeli
    tft.setRotation (1);  // Rotire ecran
    tft.fillScreen (ST77XX_BLACK);  // Fundal negru
    tft.setTextColor (ST77XX_WHITE);  // Text alb
    tft.setTextSize (2);  // Dimensiune text

    afisaremeniu ();  // Afișează meniul inițial
}


Here you "just need to .... "

2nd time
Here you "just need to.... "

3rd-time
Here you "just need to.... "
4th, 5th, 6th and so on and on and on

and by repeating this pattern you end up with not only
some additional if-conditions

but with more and more complex if-conditions or nested if-conditions
because you have to add more and more flag-variables because the different parts of your code start to interfere with each other.

The switch-case-break-approach reduces the number of nescessary if-conditions to the minimum because in every situation only that parts of your code get executed that are nescessary all other get not executed which means the can not interfere.

But I guess you will have to make the experience on your own to be trapped into too many if-conditions before you see
switch-case-break is the better choice

Did you start another username and topic?

It is the EXACT code as post #1.

Starting from your code, here is what I came up with :

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

#define TFT_CS   10   // Chip select (CS)
#define TFT_RST   8   // Reset pin
#define TFT_DC    9   // Data/Command pin

#define  PRESSED  LOW // Using Pull-up, the button press connects to the GND
#define RELEASED HIGH

int   backButtonPin = 5;    // Buton Back (BB)
int     upButtonPin = 4;    // Buton Up (BU)
int   downButtonPin = 3;    // Buton Down (BD)
int selectButtonPin = 2;    // Buton Select (BS)
enum button_t : uint8_t {NONE, UP, DOWN, SELECT, BACK} button;

uint16_t menuLineNumber[] = {0, 30, 80, 130, 180};

// Ohm metru //
const int sensorPin = A0;  // Analog input pin that senses Vout
int sensorValue = 0;       // sensorPin default value
float Vin = 5.0;             // Input voltage
float Vout = 0.0;            // Vout default value
float Rref = 999.0;          // Reference resistor's value in ohms
float R = 0.0;               // Tested resistor's default value
//Ohm metru //

void (*measurePtr)(void) = NULL;

int menuLine = 1;  // Meniul curent, începe de la 1

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

void afisaremeniu() {
  tft.fillScreen(ILI9341_BLACK);
  tft.setCursor(30, 30);
  tft.print("Rezistenta");
  tft.setCursor(30, 80);
  tft.print("Capacitate");
  tft.setCursor(30, 130);
  tft.print("Inductanta");
  tft.setCursor(30, 180);
  tft.print("Info");
}

void afisareLine() {
  static uint16_t oldMenuLine = 0;
  
  tft.setTextColor(ILI9341_BLACK); 
  tft.setCursor(10, menuLineNumber[oldMenuLine]);
  tft.print('>');
  tft.setTextColor(ILI9341_WHITE); 
  oldMenuLine = menuLine;
  tft.setCursor(10, menuLineNumber[menuLine]);
  tft.print('>');
}

void setup() {
  Serial.begin(115200);  // Initialize Serial Monitor
  pinMode(    upButtonPin, INPUT_PULLUP);  // Setare buton Up ca INPUT_PULLUP
  pinMode(  downButtonPin, INPUT_PULLUP);  // Setare buton Down ca INPUT_PULLUP
  pinMode(selectButtonPin, INPUT_PULLUP);  // Setare buton Select ca INPUT_PULLUP
  pinMode(  backButtonPin, INPUT_PULLUP);

  tft.begin();  // Initializare ecran 240x320 pixeli
  tft.setRotation(1);  // Rotire ecran
  // tft.fillScreen(ILI9341_BLACK);  // Fundal negru
  tft.setTextColor(ILI9341_WHITE);  // Text alb
  tft.setTextSize(2);  // Dimensiune text
  afisaremeniu();  // Afi?eaza meniul ini?ial
  afisareLine();
}

void loop() {
  static button_t oldButton = NONE;

  if     (digitalRead(    upButtonPin) == PRESSED) { button = UP;}
  else if(digitalRead(  downButtonPin) == PRESSED) { button = DOWN;}
  else if(digitalRead(selectButtonPin) == PRESSED) { button = SELECT;}
  else if(digitalRead(  backButtonPin) == PRESSED) { button = BACK;}
  else { button = NONE;}

  if (oldButton != button) {
    oldButton = button;
    switch (button) {
      case UP:  // Navigare în meniu folosind butonul Up (BU)
        if (menuLine == 1) {
          menuLine = 4;  // Revin la ultimul meniu daca scade sub 1
        }
        else {
          menuLine--;  // Mergem la meniul anterior
        }
        afisareLine();  // Actualizeaza meniul pe ecran
        break;
        
      case DOWN:  // Navigare în meniu folosind butonul Down (BD)
        if (menuLine == 4) {
          menuLine = 1;   // Revin la primul meniu daca depa?e?te 3
        }
        else {
          menuLine++;     // Trecem la urmatorul meniu
        }
        afisareLine();    // Actualizeaza meniul pe ecran
        break;
        
      case SELECT:  // Executa ac?iunea selectata cu butonul Select (BS)
        actiune();  // Executa ac?iunea pentru meniul curent
        // bs_apasat = true;
        break;
        
      case BACK:  // Back
        measurePtr = NULL;
        afisaremeniu();
        afisareLine();  // Actualizeaza meniul pe ecran
        break;
        
    }
  }
  if (measurePtr) (*measurePtr)();
  delay(100);
}

void actiune() {
  switch (menuLine) {
    case 1:
      tft.fillScreen(ILI9341_BLACK);
      tft.setCursor(10, 10);
      tft.print("Masurare rezistenta:");
      measurePtr = masurareRezistenta;
      break;

    case 2:
      tft.fillScreen(ILI9341_BLACK);
      tft.setCursor(10, 30);
      tft.print("Testate Meniu 2!");
      break;
    case 3:
      tft.fillScreen(ILI9341_BLACK);
      tft.setCursor(10, 30);
      tft.print("Testate Meniu 3!");
      break;
    case 4:
      tft.fillScreen(ILI9341_BLACK);
      tft.setCursor(10, 30);
      tft.print("Testate Meniu 4!");
      break;
  }
}
void masurareRezistenta() {
  Serial.print('.');
  // Cite?te valoarea senzorului
  sensorValue = analogRead(sensorPin);  // Cite?te Vout pe pinul analogic A0
  Vout = (Vin * sensorValue) / 1023.0;  // Conversie la vol?i
  R = Rref * (1 / ((Vin / Vout) - 1));
  tft.fillRect(10, 50, 220, 30, ILI9341_BLACK);  // Cura?a zona de afi?are
  tft.setCursor(10, 50);

  if (R > 500000.0) {  // Rezisten?a infinita sau foarte mare
    tft.print("R: Inf");
  }
  else if (R > 999.0) {  // Conversie la kOhm
    tft.print("R: ");
    tft.print(R / 1000.0, 2);  // 2 zecimale pentru precizie
    // tft.print(" kΩ");
    tft.print(" kOhm");
  }
  else {  // Rezisten?a în Ohmi
    tft.print("R: ");
    tft.print(R, 2);  // 2 zecimale pentru precizie
    // tft.print(" Ω");
    tft.print(" Ohm");
  }
}

As I used the Wokwi simulator, I swapped the ST7789 for an ILI9341 but the difference is minimal.

Wokwi Diagram.json

{
"version": 1,
"author": "Anonymous maker",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-nano", "id": "nano", "top": 0, "left": 0, "rotate": 90, "attrs": {} },
{
"type": "board-ili9341-cap-touch",
"id": "lcd1",
"top": -116.48,
"left": 177.54,
"rotate": 90,
"attrs": {}
},
{
"type": "wokwi-pushbutton-6mm",
"id": "btn1",
"top": 74.6,
"left": 412.8,
"attrs": { "color": "green", "label": "Up" }
},
{
"type": "wokwi-pushbutton-6mm",
"id": "btn2",
"top": 122.6,
"left": 412.8,
"attrs": { "color": "green", "label": "Down" }
},
{
"type": "wokwi-pushbutton-6mm",
"id": "btn3",
"top": 122.6,
"left": 364.8,
"attrs": { "color": "green", "label": "Select" }
},
{
"type": "wokwi-pushbutton-6mm",
"id": "btn4",
"top": 122.6,
"left": 307.2,
"attrs": { "color": "green", "label": "Back" }
},
{
"type": "wokwi-slide-potentiometer",
"id": "pot1",
"top": -14,
"left": -92,
"rotate": 270,
"attrs": { "travelLength": "30", "value": "512" }
},
{
"type": "wokwi-text",
"id": "pot1",
"top": 120,
"left": -10,
"attrs": { "text": "Device\nunder Test" }
}
],
"connections": [
[ "nano:13", "lcd1:SCK", "green", [ "h0" ] ],
[ "nano:12", "lcd1:MISO", "green", [ "h0" ] ],
[ "nano:11", "lcd1:MOSI", "green", [ "h0" ] ],
[ "nano:10", "lcd1:CS", "green", [ "h0" ] ],
[ "nano:9", "lcd1:D/C", "green", [ "h0" ] ],
[ "nano:8", "lcd1:RST", "green", [ "h0" ] ],
[ "nano:A5", "lcd1:SCL", "green", [ "h0" ] ],
[ "nano:A4", "lcd1:SDA", "green", [ "h0" ] ],
[ "nano:5", "btn4:1.l", "green", [ "v79.8", "h193.5" ] ],
[ "nano:4", "btn1:1.l", "green", [ "v70.2", "h299.1" ] ],
[ "nano:3", "btn2:1.l", "green", [ "v60.6", "h299.1" ] ],
[ "nano:2", "btn3:1.l", "green", [ "v51", "h251.1" ] ],
[ "nano:GND.3", "btn4:2.r", "black", [ "v60.6", "h240.7" ] ],
[ "nano:GND.3", "btn3:2.r", "black", [ "v60.6", "h298.3" ] ],
[ "nano:GND.3", "btn2:2.r", "black", [ "v60.6", "h346.3" ] ],
[ "nano:GND.3", "btn1:2.r", "black", [ "v60.6", "h346.3" ] ],
[ "pot1:SIG", "nano:A0", "green", [ "h0" ] ]
],
"dependencies": {}
}