Optimizing code

On my 3310 LCD i'm hoping to have this menu layout:

I've done the temperature and water request code but no further yet

Is there a way to reuse the water request, set hour and set minute screens/code, setting different variables based on where the code is called from?

Have a look at functions and libraries :slight_smile:

Is there a way to reuse the water request, set hour and set minute screens/code,

Without actually seeing your code, who can say?

Alphabeta - thanks i will have a read up

here is the code in 2 parts:

#include <Time.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <nokia_3310_lcd.h>

// Temp/humidity display using nokia 3310 LCD display shield from nuelectronics.com

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

//keypad debounce parameter
#define DEBOUNCE_MAX 15
#define DEBOUNCE_ON  10
#define DEBOUNCE_OFF 3 

#define NUM_KEYS 5

#define NUM_MENUS      2
#define NUM_MENU_ITEM      6

// joystick number
#define UP_KEY 3
#define LEFT_KEY 0
#define CENTER_KEY 1
#define DOWN_KEY 2
#define RIGHT_KEY 4

// Pin used by Backlight, so we can turn it on and off. Pin setup in LCD init function
#define BL_PIN 7

// menu starting points
#define MENU_X      5            // 0-83
#define MENU_Y      0            // 0-5

// adc preset value, represent top value,incl. noise & margin,that the adc reads, when a key is pressed
// set noise & margin = 30 (0.15V@5V)
int  adc_key_val[5] ={
  30, 150, 360, 535, 760 };

// debounce counters
byte button_count[NUM_KEYS];
// button status - pressed/released
byte button_status[NUM_KEYS];
// button on flags for user program 
byte button_flag[NUM_KEYS];

// menu definition
char menu_items[NUM_MENUS][NUM_MENU_ITEM][14]={
{  "TEMPERATURE",
  "WATER REQUEST"},
{  "1",
  "1.5",
  "2",
  "2.5",
  "Bath",
  "None" }
};

void (*menu_funcs[NUM_MENUS][NUM_MENU_ITEM])(void) = {
{  temperature,
   waterreq },
{ shower1,
  shower15,
  shower2,
  shower25,
  bath,
  none }
};

char current_menu_num = 0;
char current_menu_item = 0;

int blflag = 1;  // Backlight initially ON
int temp1, temp2, temp3, temp4, temp5;
char temp[3];
char* shower;
char boileron;

Nokia_3310_lcd lcd=Nokia_3310_lcd();

void setup()
{

   pinMode(3, OUTPUT);
   sensors.begin();
   Serial.begin(9600);
   readsensors();
  // setup interrupt-driven keypad arrays  
  // reset button arrays
  for(byte i=0; i<NUM_KEYS; i++){
    button_count[i]=0;
    button_status[i]=0;
    button_flag[i]=0;
  }

  // Setup timer2 -- Prescaler/256
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  TCCR2B = (1<<CS22)|(1<<CS21);      

  ASSR |=(0<<AS2);

  // Use normal mode  
  TCCR2A =0;    
  //Timer2 Overflow Interrupt Enable  
  TIMSK2 |= (0<<OCIE2A);
  TCNT2=0x6;  // counting starts from 6;  
  TIMSK2 = (1<<TOIE2);    

  SREG|=1<<SREG_I;

  lcd.init();
  lcd.clear();

  //menu initialization
  current_menu_num = 0;      
  current_menu_item = 0;      
  init_MENU();
}

/* loop */
void loop() {
  
  long lastUpdate = 0;
  byte i;
  for(i=0; i<NUM_KEYS; i++) {
    if(button_flag[i] !=0) {

      button_flag[i]=0;  // reset button flag
//      i = lcd.get_key();
      switch(i){
      case UP_KEY:
        // current item to normal display
        lcd.writeString(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_num][current_menu_item], MENU_NORMAL );
        current_menu_item -=1;
        if(current_menu_item <0)  current_menu_item = NUM_MENU_ITEM -1;
        // next item to highlight display
        lcd.writeString(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_num][current_menu_item], MENU_HIGHLIGHT );
        break;
      case DOWN_KEY:
        // current item to normal display
        lcd.writeString(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_num][current_menu_item], MENU_NORMAL );
        current_menu_item +=1;
        if(current_menu_item >(NUM_MENU_ITEM-1))  current_menu_item = 0;
        // next item to highlight display
        lcd.writeString(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_num][current_menu_item], MENU_HIGHLIGHT );
        break;
      case LEFT_KEY:
        init_MENU();
        current_menu_item = 0;
        break;   
      case RIGHT_KEY:
        lcd.clear();
        (*menu_funcs[current_menu_num][current_menu_item])();
        lcd.clear();
        init_MENU();
        current_menu_item = 0;
        break;      
      }
    }
  }
}

/* menu functions */
void init_MENU(void) {

  byte i;
  lcd.clear();
  lcd.writeString(MENU_X, MENU_Y, menu_items[current_menu_num][0], MENU_HIGHLIGHT );

  for (i=1; i<NUM_MENU_ITEM; i++) {
    lcd.writeString(MENU_X, MENU_Y+i, menu_items[current_menu_num][i], MENU_NORMAL);
  }
}

// waiting for center key press
void waitfor_OKkey() {
  byte i;
  byte key = 0xFF;
  while (key!= CENTER_KEY){
//    key = lcd.get_key();

    for(i=0; i<NUM_KEYS; i++){
      if(button_flag[i] !=0){
        button_flag[i]=0;  // reset button flag
        if(i== CENTER_KEY) key=CENTER_KEY;
      }
    }
  }
}

// Check if joystick is moved or pressed
byte checkKeypressed() {
  byte key = 0xFF;

//  key = lcd.get_key();

  for(int i=0; i<NUM_KEYS; i++){
    if(button_flag[i] !=0){
      button_flag[i]=0;  // reset button flag
      if(i== CENTER_KEY) key=CENTER_KEY;
    }
  }
  return key;
}

void readsensors()
{
      sensors.requestTemperatures();
      temp1 = sensors.getTempCByIndex(0);
      temp2 = sensors.getTempCByIndex(1);
      temp3 = sensors.getTempCByIndex(2);
      temp4 = sensors.getTempCByIndex(3);
      temp5 = sensors.getTempCByIndex(4);
      
      if (temp1 < 18)// && temp4 >= 45)
      {
          shower = "0";
      }
      else if (temp1 == 18) // && temp2 >= 35 && temp3 <= 30)
      {
          shower = "1";
      }
      else if (temp1 == 20)
      {
          shower = "1.5";
      }
       else if (temp1 == 22)
      {
           shower = "2";
      }
      else if (temp1 == 24)
      {
           shower = "2.5 ";
      }
      else if (temp1 == 26)
      {
           shower = "BATH";
      }
}

Part 2:

void displaytemps()
{
  lcd.writeString(75, 0, "C", MENU_NORMAL);
  lcd.writeString(75, 1, "C", MENU_NORMAL);
  lcd.writeString(75, 2, "C", MENU_NORMAL);
  lcd.writeString(75, 3, "C", MENU_NORMAL);
  lcd.writeString(75, 4, "C", MENU_NORMAL);
  
      readsensors();
      
      itoa(temp1, temp, 10);
      lcd.writeString(60, 0, temp, MENU_NORMAL);
      itoa(temp2, temp, 10);     
      lcd.writeString(60, 1, temp, MENU_NORMAL);
      itoa(temp3, temp, 10);
      lcd.writeString(60, 2, temp, MENU_NORMAL);
      itoa(temp4, temp, 10);
      lcd.writeString(60, 3, temp, MENU_NORMAL);
      itoa(temp5, temp, 10);
      lcd.writeString(60, 4, temp, MENU_NORMAL);
}
// Display temperature in big digits, humidity in small digits underneath
void temperature() {

  long lastUpdate = 0;  // Force update
  byte i;
  byte key = 0xFF;

  // Display non changing text, there is a slight delay while first reading is taken

  lcd.writeString(0, 0, "Number", MENU_NORMAL);
  lcd.writeString(10, 1, "Of", MENU_NORMAL);
  lcd.writeString(0, 2, "Showers", MENU_NORMAL);
  lcd.writeString(0, 3, "avail:", MENU_NORMAL); 
  lcd.writeString(38, 5, "OK", MENU_HIGHLIGHT );

  // Loop to display temperaure/humidity with check for key press to exit
  while (key!= CENTER_KEY) {
    // Update temp
    if( millis() > lastUpdate + 1000) {
      // Read temperature and humidity
      displaytemps();
      lcd.writeString(5, 4, shower, MENU_NORMAL);
      lastUpdate = millis();
    }
    key = checkKeypressed();
  }
}

void waterreq() {

  current_menu_num = 1;
  current_menu_item = 0;
}

void mainmenu() {
  current_menu_num = 0;
  current_menu_item = 0;
}

void shower1()
{
  char* newtemp;
  char* oldtemp;
      readsensors();
      oldtemp = shower;
      while (oldtemp < "1")
      {
        //delay(1000);                        
        displaytemps();
        digitalWrite(3, HIGH);
        lcd.writeString(10, 2, "HEATING", MENU_NORMAL);
        newtemp = shower;
        oldtemp = newtemp;
      }
      current_menu_num = 0;
      current_menu_item = 0;    
    
  }

void shower15()
{
   char* newtemp;
   char* oldtemp;
   readsensors();
   oldtemp = shower;
   while (oldtemp < "1.5")
      {
        //delay(1000);                        
        displaytemps();
        lcd.writeString(10, 2, "HEATING", MENU_NORMAL);
        newtemp = shower;
        oldtemp = newtemp;
      }
      current_menu_num = 0;
      current_menu_item = 0;
};
void shower2()
{
 char* newtemp;
   char* oldtemp;
   readsensors();
   oldtemp = shower;
   while (oldtemp < "2")
      {
        //delay(1000);                        
        displaytemps();
        lcd.writeString(10, 2, "HEATING", MENU_NORMAL);
        newtemp = shower;
        oldtemp = newtemp;
      }
      current_menu_num = 0;
      current_menu_item = 0;
};

void shower25()
{
 char* newtemp;
   char* oldtemp;
   readsensors();
   oldtemp = shower;
   while (oldtemp < "2.5")
      {
        displaytemps();
        lcd.writeString(10, 2, "HEATING", MENU_NORMAL);
        newtemp = shower;
        oldtemp = newtemp;
      }
      current_menu_num = 0;
      current_menu_item = 0;
};
void bath()
{
   char* newtemp;
   char* oldtemp;
   readsensors();
   oldtemp = shower;
   while (oldtemp < "Bath")
      {
        //delay(1000);                        
        displaytemps();
        lcd.writeString(10, 2, "HEATING", MENU_NORMAL);
        newtemp = shower;
        oldtemp = newtemp;
      }
      current_menu_num = 0;
      current_menu_item = 0;
};
void none()
{
    current_menu_num = 0;
    current_menu_item = 0;
};

// The followinging are interrupt-driven keypad reading functions
//  which includes DEBOUNCE ON/OFF mechanism, and continuous pressing detection

// Convert ADC value to key number
char get_key(unsigned int input) {
  char k;
  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;
}
void update_adc_key() {
  int adc_key_in;
  char key_in;
  byte i;

  adc_key_in = analogRead(0);
  key_in = get_key(adc_key_in);
  for(i=0; i<NUM_KEYS; i++) {
    if(key_in==i) { //one key is pressed 
      if(button_count[i]<DEBOUNCE_MAX)       {
        button_count[i]++;
        if(button_count[i]>DEBOUNCE_ON)         {
          if(button_status[i] == 0)           {
            button_flag[i] = 1;
            button_status[i] = 1; //button debounced to 'pressed' status
          }
        }
      }
    } else  { // no button pressed
      if (button_count[i] >0) {  
        button_flag[i] = 0;      
        button_count[i]--;
        if(button_count[i]<DEBOUNCE_OFF) {
          button_status[i]=0;   //button debounced to 'released' status
        }
      }
    }
  }
}
// Timer2 interrupt routine -
// 1/(160000000/256/(256-6)) = 4ms interval

ISR(TIMER2_OVF_vect) {  
  TCNT2  = 6;
  update_adc_key();
}

Before tackling the extra menus and submenus i thought i would optimize the code i have.

As you can see there are 5 functions that essentially do the same thing but use a different value to do it. (shower1, shower15,..., BATH)
So i thought i'd create a function called boileron that i could pass this variable to so it could do the work regardless of which original function was called.

char* waterrequest

void bath()
{
  waterrequest = "BATH";
  boileron(waterrequest);
}

char* boileron(waterrequest)
{
   char* newtemp;
   char* oldtemp;
   readsensors();
   oldtemp = shower;
   while (oldtemp < waterrequest)
      {
        //delay(1000);                        
        displaytemps();
        lcd.writeString(10, 2, "HEATING", MENU_NORMAL);
        newtemp = shower;
        oldtemp = newtemp;
      }

      delay(2000);         
      current_menu_num = 0;
      current_menu_item = 0;
}

but it won't compile, the error is :
'waterrequest' was not declared in this scope

any ideas?

char* boileron(waterrequest)

You need to give it a type.

while (oldtemp < waterrequest)

That's going to cause you some grief.

Your non-void function doesn't return anything.

doh!
i just missed the data type before the variable.
compiles now