LCD Menus and Sub-Menus

So, I just finished the code for my project that uses 3 different sensors, using 3 push buttons for menu navigation buttons and a 20x4 LCD output.

so the problem I'm facing is that when I enter a sub-menu, the sensor value does not update/refresh (somehow after I enter the menu or sub-menu the sensor value freezes) I have to go back to the initial display so that the sensor value changes and refreshes.

is this related to the problem in the void loop?

*sorry for my bad english, hope you guys understand it

here's my code

#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#include <LiquidCrystal_I2C.h>       // Memanggil library LCD
#define bUP 7
#define bOK 6
#define bDN 5

#define DITEKAN LOW
#define BOUNCE 50

LiquidCrystal_I2C lcd(0x27, 20, 4);  // Mengatur alamat LCD dan dimensi LCD, yaitu 20 kolom dan 4 baris

//Sensor Temperatur dan TDS
#define ONE_WIRE_BUS 2
#define TdsSensorPin A2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float tdsValue = 0;

//Sensor Turbiditas
#define TurbiditySensorPin A0
float turbidityVolt;
float turbidityNTU;

int currentMenu = 0;

void setup(void) 
{
  lcd.init();
  lcd.backlight();

  pinMode(bUP, INPUT_PULLUP);
  pinMode(bOK, INPUT_PULLUP);
  pinMode(bDN, INPUT_PULLUP);

  sensors.begin();
  sensors.setResolution(12);
}

void loop(void) {
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    Settingmenu();
    
  }

  lcd.setCursor (0,0);
  lcd.print("Project Alat Ukur");
  lcd.setCursor (0,1);
  lcd.print("Kualitas Fisik Air");
  lcd.setCursor (0,2);
  lcd.print("by Nadhif");
  lcd.setCursor (0,3);
  lcd.print("[DOWN]   [OK]   [UP]");

  // Read TDS and temperature 
  sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0);
  tempC = round(tempC * 100) / 100.0;
  
  //Read Turbidity
  turbidityVolt = 0;
  for (int i = 0; i < 800; i++) {
    turbidityVolt += (analogRead(TurbiditySensorPin) / 1023.0) * 5;
  }
  turbidityVolt /= 800;
  turbidityVolt = round_to_dp(turbidityVolt, 2);

  if (turbidityVolt < 2.5) {
    turbidityNTU = 3;
  } else {
    turbidityNTU = -1120.4 * sq(turbidityVolt) + 5742.3 * turbidityVolt - 4353.8;
    turbidityNTU = turbidityNTU / 1000; // dividing by 1000
  }

  // Update nilai sensor suhu pada sub-menu
  if (currentMenu == 1) {
    lcd.setCursor(0, 0);
    lcd.print("Temperature: ");
    lcd.print(tempC); // Display temperature with 2 decimal places
    lcd.print(" C");
  }
}

void Settingmenu() {
  // Definisi label sebelum pemanggilan goto
  setMENU1:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto setSUBMENU1;
    //........................SUBMENU......................
  } else if(digitalRead(bUP) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bUP) == DITEKAN) {}
    lcd.clear();
    goto setMENU4;
  } else if(digitalRead(bDN) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bDN) == DITEKAN) {}
    lcd.clear();
    goto setMENU2;
  }

  lcd.setCursor(0,0);
  lcd.print("->Temperature");
  lcd.setCursor(0,1);
  lcd.print("  TDS");
  lcd.setCursor(0,2);
  lcd.print("  Turbidity");
  lcd.setCursor(0,3);
  lcd.print("  [BACK]");
  goto setMENU1;

  // Menambahkan definisi label untuk submenu
  setSUBMENU1:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto setMENU1;
    //
  }
  lcd.setCursor(0,0);
  lcd.print("Temperature: ");
  lcd.print(sensors.getTempCByIndex(0)); // Display temperature with 2 decimal places
  lcd.print(" C");
  delay(1500);
  lcd.clear();
  goto setSUBMENU1;
  
  setMENU2:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto setSUBMENU2;
    //........................SUBMENU......................
  } else if(digitalRead(bUP) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bUP) == DITEKAN) {}
    lcd.clear();
    goto setMENU1;

  } else if(digitalRead(bDN) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bDN) == DITEKAN) {}
    lcd.clear();
    goto setMENU3;

  }
  
  lcd.setCursor(0,0);
  lcd.print("  Temperature");
  lcd.setCursor(0,1);
  lcd.print("->TDS");
  lcd.setCursor(0,2);
  lcd.print("  Turbidity");
  lcd.setCursor(0,3);
  lcd.print("  [BACK]");
  goto setMENU2;

  setMENU3:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto setSUBMENU3;
    //........................SUBMENU......................
  } else if(digitalRead(bUP) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bUP) == DITEKAN) {}
    lcd.clear();
    goto setMENU2;

  } else if(digitalRead(bDN) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bDN) == DITEKAN) {}
    lcd.clear();
    goto setMENU4;

  }

  lcd.setCursor(0,0);
  lcd.print("  Temperature");
  lcd.setCursor(0,1);
  lcd.print("  TDS");
  lcd.setCursor(0,2);
  lcd.print("->Turbidity");
  lcd.setCursor(0,3);
  lcd.print("  [BACK]");
  goto setMENU3;

  setMENU4:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto ENDSET;
    //........................SUBMENU......................
  } else if(digitalRead(bUP) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bUP) == DITEKAN) {}
    lcd.clear();
    goto setMENU3;

  } else if(digitalRead(bDN) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bDN) == DITEKAN) {}
    lcd.clear();
    goto setMENU1;

  }

  lcd.setCursor(0,0);
  lcd.print("  Temperature");
  lcd.setCursor(0,1);
  lcd.print("  TDS");
  lcd.setCursor(0,2);
  lcd.print("  Turbidity");
  lcd.setCursor(0,3);
  lcd.print("->[BACK]");

  goto setMENU4;
  
  // SUBMENU
  //.......................................................................
  setSUBMENU2:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto setMENU2;
    //
  }
  lcd.setCursor(0,0);
  lcd.print(" TDS: ");
  lcd.print(tdsValue, 0);
  lcd.print(" PPM");
  goto setSUBMENU2; 
  //......................................................................
  setSUBMENU3:
  if(digitalRead(bOK) == DITEKAN){
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    goto setMENU3;
    //
  }
  lcd.setCursor(0,0);
  lcd.print(" Turbiditas: ");
  lcd.print(turbidityNTU);
  lcd.print (" NTU");
  goto setSUBMENU3;
  //.......................................................................

  ENDSET:
  lcd.clear();
  delay(100);
}

float round_to_dp(float in_value, int decimal_place) {
  float multiplier = pow(10.0, decimal_place);
  in_value = round(in_value * multiplier) / multiplier;
  return in_value;
}

The "goto" commands are not letting your program read the sensors.

Try replacing "goto" with function calls. This will let your program read a button and return to the main program, then read a sensor and return to the main program, then repeat.

I have used your configuration in this example sketch to read all the buttons and read one sensor...

#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#include <LiquidCrystal_I2C.h>       // Memanggil library LCD
#define bUP 7
#define bOK 6
#define bDN 5

#define DITEKAN LOW
#define BOUNCE 50

LiquidCrystal_I2C lcd(0x27, 20, 4);  // Mengatur alamat LCD dan dimensi LCD, yaitu 20 kolom dan 4 baris

//Sensor Turbiditas
#define TurbiditySensorPin A0

void setup(void)
{
  lcd.init();
  lcd.backlight();

  pinMode(bUP, INPUT_PULLUP);
  pinMode(bOK, INPUT_PULLUP);
  pinMode(bDN, INPUT_PULLUP);
}

void loop(void) {
  if (digitalRead(bOK) == DITEKAN) {
    delay(BOUNCE);
    while (digitalRead(bOK) == DITEKAN) {}
    lcd.clear();
    setSUBMENU1(); // this is a function call
  }
  if (digitalRead(bUP) == DITEKAN) {
    delay(BOUNCE);
    while (digitalRead(bUP) == DITEKAN) {}
    setSUBMENU2(); // this is a function call
  }
  if (digitalRead(bDN) == DITEKAN) {
    delay(BOUNCE);
    while (digitalRead(bDN) == DITEKAN) {}
    setSUBMENU3(); // this is a function call
  }
  readSensor(); // read the sensor
}

void setSUBMENU1() {
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("SUBMENU1");
}

void setSUBMENU2() {
  lcd.clear();
  lcd.setCursor(0, 2);
  lcd.print("SUBMENU2");
}

void setSUBMENU3() {
  lcd.clear();
  lcd.setCursor (0, 3);
  lcd.print("SUBMENU3");
}

void readSensor() {
  lcd.setCursor (0, 0);
  lcd.print(analogRead(A0));
}
1 Like

do i need to change it for both menus and submenus or just submenus?

Your program should always read the buttons.

If the button choice was to read the sensor, your program should read the button and read the sensor.

Only display the menu and submenues when they have been selected.

Putting menus and submenus in their own functions makes it easy to call their function.

thank you for your advice, i just done it

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.