Change set values with lcd keypad shield.

Hi all!
I’m trying to write a code for an irrigation system, but I’m having trouble changing the set value for comparison to the humidity sensor value.
I have the lcd displaying the actual values from the humidity sensors. This value is compared with the set humidity, and if sensorvalue > sethumidity, a water pump is activated. I would like to be able to change the set humidity with the buttons from the lcd keypad shield. The code that I have so far is:

// LcdKeypad - Version: Latest 
#include <EEPROM.h>

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);







#define WATERPIN3 3
#define WATERPIN2 2
#define READSOILPIN A1
#define READSOILPIN2 A2

// higher number is more dry

#define WATERDELAY 5000
#define WATERPOSTDELAY 5000
int lcd_key     = 0;
int adc_key_in  = 0;
int MAXDRY1;
int MAXDRY2;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons(){               // read the buttons
    adc_key_in = analogRead(0);       // read the value from the sensor 

    // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
    // we add approx 50 to those values and check to see if we are close
    // We make this the 1st option for speed reasons since it will be the most likely result

    if (adc_key_in > 1000) return btnNONE; 

    // For V1.1 us this threshold
   /* if (adc_key_in < 50)   return btnRIGHT;  
    if (adc_key_in < 250)  return btnUP; 
    if (adc_key_in < 450)  return btnDOWN; 
    if (adc_key_in < 650)  return btnLEFT; 
    if (adc_key_in < 850)  return btnSELECT;  
*/
   // For V1.0 comment the other threshold and use the one below:
   
     if (adc_key_in < 50)   return btnRIGHT;  
     if (adc_key_in < 195)  return btnUP; 
     if (adc_key_in < 380)  return btnDOWN; 
     if (adc_key_in < 555)  return btnLEFT; 
     if (adc_key_in < 790)  return btnSELECT;   
   

    return btnNONE;                // when all others fail, return this.
}

void setup()
{
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  lcd.clear();

  Serial.begin(9600);
  pinMode(READSOILPIN, INPUT);
  pinMode(READSOILPIN2, INPUT);
  pinMode(WATERPIN3, OUTPUT);
  pinMode(WATERPIN2, OUTPUT);
  EEPROM.read (1); 
  EEPROM.read (2);
}

void loop()
{
  int SensorValue1 = analogRead(READSOILPIN); //take a sample
  
  int SensorValue2 = analogRead(READSOILPIN2); //take a sample
  lcd.clear();
  lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0
  lcd.print("Humedad:"); // Prints Sensor Val: to LCD
  lcd.print(analogRead(READSOILPIN)); // Prints value on Potpin1 to LCD
   lcd.print("/"); // Prints Sensor Val: to LCD
  lcd.print(analogRead(READSOILPIN2)); // Prints value on Potpin1 to LCD
  MAXDRY1 = EEPROM.read(1);
  MAXDRY2 = EEPROM.read(2);

 
  Serial.print(adc_key_in);
  
  switch (lcd_key) {
  lcd_key = read_LCD_buttons();
  
  case btnLEFT:{
         if (read_LCD_buttons == btnUP){
           (MAXDRY1++);
         }   
         else if (read_LCD_buttons == btnDOWN){
         (MAXDRY1--);
}
  case btnRIGHT: {
    if (read_LCD_buttons == btnUP){
           (MAXDRY2++);
         }   
         else if (read_LCD_buttons == btnDOWN){
         (MAXDRY2--);
}
  }
  }  
  }
   if(SensorValue1 >= MAXDRY1) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
  
   
   digitalWrite(WATERPIN3, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN3, LOW);
   delay(WATERPOSTDELAY);
  }
  
  if(SensorValue2 >= MAXDRY2) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
   
  
   digitalWrite(WATERPIN2, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN2, LOW);
   delay(WATERPOSTDELAY);
  }
  EEPROM.write (1,MAXDRY1);
  EEPROM.write (2,MAXDRY2);
  lcd.setCursor(8,1);
  lcd.print(MAXDRY1);
  lcd.print(MAXDRY2);
  
  
}

Any help is greatly appreciated!
(Okay, I’ve added Code Tags for you - next time, use the </> button when you post. Moderator)
Thanks!

 switch (lcd_key) {
  lcd_key = read_LCD_buttons();

It makes more sense to read the lcd button before you switch based on the result.

 lcd_key = read_LCD_buttons(); 
switch (lcd_key) {

You are attempting to read one of two button to determine if the user wants to update the values of MAXDRY1 or MAXDRY2 respectively. In the next loop() iteration you attempt to determine whether the user wants to increment or decrement the chosen value by checking to see what buttons have been pressed. One problem is that you are immediately then losing the information that the user wants to update either MAXDRY1 or MAXDRY2.

With your button shield with all buttons being read by the same analog pin, and one button interferes with the results of another, your only hope is to set a status variable that user is in the process of updating MAXDRY1 or MAXDRY2. Then you can test for the up/down presses and increment/decrement the selected MAXDRYx variable. This status variable should be reset if there is no button activity for, say, 5 seconds.

There is another problem with your code.
You should not write to the EEPROM on every loop iteration. This has a limited maximum number of write operations before it fails.

How can I make so that when I press a button, it goes into a calibration mode (lcd.setcursor (0,0)) while still showing the values of the sensors (lcd.setcursor(0,1)).

Tavobachi:
How can I make so that when I press a button, it goes into a calibration mode (lcd.setcursor (0,0)) while still showing the values of the sensors (lcd.setcursor(0,1)).

As a first step, I'd create a function reading the keys, which acts similar to the Serial.read() function and either returns -1 (in case no button was pressed since last calling the function or in case of a state-change-detection occurs:

  • return 'S' for Select cbutton
  • return 'U' for Up button
  • return 'D' for Down button
    return 'L for Left button
    return''R' for Right button

The 1602 LCD has three cursor modes:

  • no visible cursor
  • blinking undersore cursor
    -block cursor

For editing with the LCD Keypad shield, I'd possibly prefer the block cursor as an indication of the cursor position which can be edited at the moment.

I think, somewhere I should have an unused LCD Keypad Shield.

If you like, I could look after it, stack it on an UNO and develop soemething for "state-change-detection" of analog buttons and editing a humidity setpoint.

What do you actually need:
editing of a number with two digits and no decimals?
Or rather three digits with one decimal?
setpoint range from 10% up to 90% or what range do you need for editing?

Hi! :slight_smile:
The option to set a value would be an integer, that would increase or decrease depending on which button is pressed. I think my main issue is that all the buttons use the same port (A0), I would have to make it so that when a btn is pressed it goes into a calibration mode, until another btn is pressed or a set time goes by. Then it goes back to showing the sensor values.

adc_key_in should be local to read_LCD_buttons(); no need to have it global
lcd_key should be local to loop()

The below can be a framework that you can build on; it uses btnLeft to enter calibration mode and btnRight to terminate calibration mode.

// LcdKeypad - Version: Latest
#include <EEPROM.h>

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#define MODE_RUN 0
#define MODE_CALIBRATE 1

#define WATERPIN3 3
#define WATERPIN2 2
#define READSOILPIN A1
#define READSOILPIN2 A2

// higher number is more dry

#define WATERDELAY 5000
#define WATERPOSTDELAY 5000
int MAXDRY1;
int MAXDRY2;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons()                // read the buttons
{
  int adc_key_in = analogRead(0);       // read the value from the sensor

  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  // We make this the 1st option for speed reasons since it will be the most likely result

  if (adc_key_in > 1000) return btnNONE;

  // For V1.0 comment the other threshold and use the one below:

  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 195)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 555)  return btnLEFT;
  if (adc_key_in < 790)  return btnSELECT;

  return btnNONE;                // when all others fail, return this.
}

void setup()
{
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  lcd.clear();

  Serial.begin(9600);
  pinMode(READSOILPIN, INPUT);
  pinMode(READSOILPIN2, INPUT);
  pinMode(WATERPIN3, OUTPUT);
  pinMode(WATERPIN2, OUTPUT);
  EEPROM.read (1);
  EEPROM.read (2);
}

void loop()
{
  static int mode = MODE_RUN;

  int lcd_key = read_LCD_buttons();

  if (mode == MODE_RUN)
  {
    if (lcd_key == btnLEFT)
    {
      mode = MODE_CALIBRATE;
    }
    else
    {
      run(lcd_key);
    }
  }
  else if (mode == MODE_CALIBRATE)
  {
    if (calibrate(lcd_key) == true)
    {
      mode = MODE_RUN;
    }
  }
}

/*
  perform calibration
  in:
    button
  returns:
    true when calibration finished, else false
*/
bool calibrate(int btn)
{
  if (btn == buttonRight)
  {
    // save value
    ...
    ...
    // indicate calibration finished
    return true;
  }

  // do increment/decrement
  ...
  ...

  // indicate calibration still in progress
  return false;
}

void run(int btn)
{
  ...
  ...
}

You can fill in the details :wink:

Thank you! :slight_smile:

What does the last part do? the <void run(int btn)>

@sterretje In your example where would the comparison with the sensor values go?

< if(SensorValue1 >= MAXDRY1) …/>

Basically your existing code for the control (that was in your loop()) will now be in run(). So your compare will now be in run().

The run() function takes the button as a parameter so if needed you can use it to affect the flow inside the run() function.

This is how I filled your template, but when I press the btnleft to go into calibration mode it only works sometimes the first time, and it doesn’t work again. I removed the EEPROM to see if it would help, but it doesn’t.
Please help :frowning: !.

// LcdKeypad - Version: Latest


#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#define MODE_RUN 0
#define MODE_CALIBRATE 1

#define WATERPIN3 3
#define WATERPIN2 2
#define READSOILPIN A1
#define READSOILPIN2 A2

// higher number is more dry

#define WATERDELAY 5000
#define WATERPOSTDELAY 5000

int MAXDRY1; 
int MAXDRY2;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons()                // read the buttons
{
  int adc_key_in = analogRead(0);       // read the value from the sensor

  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  // We make this the 1st option for speed reasons since it will be the most likely result

  if (adc_key_in > 1000) return btnNONE;

  // For V1.0 comment the other threshold and use the one below:

  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 195)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 555)  return btnLEFT;
  if (adc_key_in < 790)  return btnSELECT;

  return btnNONE;                // when all others fail, return this.
}

void setup()
{
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  lcd.clear();

  Serial.begin(9600);
  pinMode(READSOILPIN, INPUT);   //Sensors pin (A1, A2), 
  pinMode(READSOILPIN2, INPUT);
  pinMode(WATERPIN3, OUTPUT);  // Dw(3, 2) to activate water pump
  pinMode(WATERPIN2, OUTPUT);
  
}

void loop()
{  
  static int mode = MODE_RUN;

  int lcd_key = read_LCD_buttons();

  if (mode == MODE_RUN)
  {
    if (lcd_key == btnLEFT)
    {
      mode = MODE_CALIBRATE;
      lcd.clear();
      lcd.print("Calibrate 1");
    }
    else
    {
     run(lcd_key);
    }
  }
  else if (mode == MODE_CALIBRATE)
  {
    if (calibrate(lcd_key) == true)
    {
      mode = MODE_RUN;
    }
  }
}/*
  perform calibration
  in:
    button
  returns:
    true when calibration finished, else false
*/
bool calibrate(int btn)
{
  if (btn == btnRIGHT)
  {
     // save value
   
    lcd.clear();
    lcd.print("done");
    delay(500); // indicate calibration finished
    lcd.clear();
    return true;
  }

  if (btn == btnUP){
    
   //for (int MAXDRY1=0; MAXDRY1 <= 1023; MAXDRY1++){ (tried this, didn't work)
    
    lcd.clear();
    lcd.print("mas");
    lcd.print(MAXDRY1);    // It keeps printing "0"
    MAXDRY1 = MAXDRY1++;      
   }  // do increment/decrement
  //}
  if (btn == btnDOWN)
  {
    lcd.clear();
    lcd.print("menos");
    lcd.print(MAXDRY1);         // it only prints the value "0"
    MAXDRY1 = MAXDRY1--;
  }
  
  

  // indicate calibration still in progress
  return false;
}

void run(int btn)                 // This is the only part that works fine :s
{
  if (btn == btnNONE){
   float SensorValue1 = analogRead(READSOILPIN); //take a sample
  float SensorValue2 = analogRead(READSOILPIN2); //take a sample
  float hum1 = (1- (SensorValue1/1023))*100;
  float hum2 = (1- (SensorValue2/1023))*100;
  lcd.clear();
  lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0
  lcd.print("Humedad:"); // Prints Sensor Val: to LCD
  lcd.setCursor(0,1);
  lcd.print(hum1); // Prints value on Potpin1 to LCD
   lcd.print("%/"); // Prints Sensor Val: to LCD
  lcd.print(hum2);
  lcd.print("%");// Prints value on Potpin1 to LCD
 
  if(SensorValue1 >= MAXDRY1) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
  
   
   digitalWrite(WATERPIN3, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN3, LOW);
   delay(WATERPOSTDELAY);
  }
  
  if(SensorValue2 >= MAXDRY2) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
   
  
   digitalWrite(WATERPIN2, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN2, LOW);
   delay(WATERPOSTDELAY);
  }
}
}

You call calibrate() with the button (btnLEFT) that was pressed. But, calibrate() doesn’t do anything when the input argument is btnLEFT.

    MAXDRY1 = MAXDRY1++;

The behavior of that statement is undefined. Use MAXDRY1++ OR MAXDRY1 = MAXDRY1 +1;

All capital letter names are, by convention, reserved for constants. You should not be incrementing, or decrementing, a constant.

If I comment "//" run (lcd_key)

Then calibrate mode works, but it adds more than 1 at a time, say if the value is 20, it adds 35 or 39 or 28. With the changes to lower case and maxdry1++.

With run (lcd_key) enabled I can access the calibration mode sometimes. If I press the left button after a while it works. Don't know why it only works sometimes.

Don't know why it only works sometimes.

You changed your code; you didn't post the changed code. We can't guess what you changed.

Here is the new code.

// LcdKeypad - Version: Latest


#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#define MODE_RUN 0
#define MODE_CALIBRATE 1

#define WATERPIN3 3
#define WATERPIN2 2
#define READSOILPIN A1
#define READSOILPIN2 A2

// higher number is more dry

#define WATERDELAY 5000
#define WATERPOSTDELAY 5000

int maxdry1 = 700; 
int maxdry2;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons()                // read the buttons
{
  int adc_key_in = analogRead(0);       // read the value from the sensor

  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  // We make this the 1st option for speed reasons since it will be the most likely result

  if (adc_key_in > 1000) return btnNONE;

  // For V1.0 comment the other threshold and use the one below:

  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 195)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 555)  return btnLEFT;
  if (adc_key_in < 790)  return btnSELECT;

  return btnNONE;                // when all others fail, return this.
}

void setup()
{
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  lcd.clear();

  Serial.begin(9600);
  pinMode(READSOILPIN, INPUT);
  pinMode(READSOILPIN2, INPUT);
  pinMode(WATERPIN3, OUTPUT);
  pinMode(WATERPIN2, OUTPUT);
  
}

void loop()
{  
  static int mode = MODE_RUN;

  int lcd_key = read_LCD_buttons();

  if (mode == MODE_RUN)
  {
    if (lcd_key == btnLEFT)
    {
      mode = MODE_CALIBRATE;
      lcd.clear();
      lcd.print("Calibrate 1");
      lcd.print(maxdry1);
    }
    else
    {
     run(lcd_key);
    }
  }
  else if (mode == MODE_CALIBRATE)
  {
    if (calibrate(lcd_key) == true)
    {
      mode = MODE_RUN;
    }
  }
}/*
  perform calibration
  in:
    button
  returns:
    true when calibration finished, else false
*/
bool calibrate(int btn)
{
  float SensorValue1 = analogRead(READSOILPIN); //take a sample
  float SensorValue2 = analogRead(READSOILPIN2);
  if (btn == btnRIGHT)
  {
     // save value
   
    lcd.clear();
    lcd.print("done");
    delay(500); // indicate calibration finished
    lcd.clear();
    return true;
  }

  if (btn == btnUP){
    
   //for (int maxdry1=0; maxdry1 <= 1023; maxdry1++){
    
    lcd.clear();
    lcd.print("mas ");
    lcd.print(maxdry1);
    maxdry1 = maxdry1 + 1;
    lcd.setCursor(0,1);
    lcd.print("(");lcd.print(SensorValue1);lcd.print(")");
   }  // do increment/decrement
  //}
  if (btn == btnDOWN)
  {
    lcd.clear();
    lcd.print("menos");
    lcd.print(maxdry1);
    maxdry1 = maxdry1 - 1;
    lcd.setCursor(0,1);
    lcd.print("(");lcd.print(SensorValue1);lcd.print(")");
  }
  
  

  // indicate calibration still in progress
  return false;
}

void run(int btn)
{
  if (btn == btnNONE){
   float SensorValue1 = analogRead(READSOILPIN); //take a sample
  float SensorValue2 = analogRead(READSOILPIN2); //take a sample
  float hum1 = (1- (SensorValue1/1023))*100;
  float hum2 = (1- (SensorValue2/1023))*100;
  lcd.clear();
  lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0
  lcd.print("Humedad:"); // Prints Sensor Val: to LCD
  lcd.setCursor(0,1);
  lcd.print(hum1); // Prints value on Potpin1 to LCD
   lcd.print("%/"); // Prints Sensor Val: to LCD
  lcd.print(hum2);
  lcd.print("%");// Prints value on Potpin1 to LCD
 
  if(SensorValue1 >= maxdry1) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
  
   
   digitalWrite(WATERPIN3, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN3, LOW);
   delay(WATERPOSTDELAY);
  }
  
  if(SensorValue2 >= maxdry2) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
   
  
   digitalWrite(WATERPIN2, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN2, LOW);
   delay(WATERPOSTDELAY);
  }
}
 /*if (btn == btnLEFT){
  int mode;
  mode == MODE_CALIBRATE;
 }*/
}

Then calibrate mode works, but it adds more than 1 at a time, say if the value is 20, it adds 35 or 39 or 28. With the changes to lower case and maxdry1++.

Sounds like a bouncing problem. Quick test is to add a delay(50) at the beginning of the calibration function.

If that fixes / improves the situation, you need to find a permanent solution; best is a millis() based solution (see the debounce example that comes with the IDE to get the idea) inthe function that reads the buttons.

I added the delay before the calibration process, but to get to the calibration mode from run mode, still takes a while to read the button. How can I make it change modes as soon as I press the button?.

// LcdKeypad - Version: Latest
#include <EEPROM.h>

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#define MODE_RUN 0
#define MODE_CALIBRATE 1

#define WATERPIN3 3
#define WATERPIN2 2
#define READSOILPIN A1
#define READSOILPIN2 A2

// higher number is more dry

#define WATERDELAY 5000
#define WATERPOSTDELAY 5000

int maxdry1; 
int maxdry2;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons()                // read the buttons
{
  int adc_key_in = analogRead(0);       // read the value from the sensor

  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  // We make this the 1st option for speed reasons since it will be the most likely result

  if (adc_key_in > 1000) return btnNONE;

  // For V1.0 comment the other threshold and use the one below:

  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 195)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 555)  return btnLEFT;
  if (adc_key_in < 790)  return btnSELECT;

  return btnNONE;                // when all others fail, return this.
}

void setup()
{
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  lcd.clear();

  Serial.begin(9600);
  pinMode(READSOILPIN, INPUT);
  pinMode(READSOILPIN2, INPUT);
  pinMode(WATERPIN3, OUTPUT);
  pinMode(WATERPIN2, OUTPUT);
  EEPROM.read (1); 
  EEPROM.read (2);
  
}

void loop()
{  
  static int mode = MODE_RUN;

  int lcd_key = read_LCD_buttons();

  if (mode == MODE_RUN)
  {
    if (lcd_key == btnLEFT)
    {
      mode = MODE_CALIBRATE;
      lcd.clear();
      lcd.print("Calibrate 1");
      lcd.print(maxdry1);
    }
    else
    {
     run(lcd_key);
    }
  }
  else if (mode == MODE_CALIBRATE)
  {
    if (calibrate(lcd_key) == true)
    {
      mode = MODE_RUN;
    }
  }
}/*
  perform calibration
  in:
    button
  returns:
    true when calibration finished, else false
*/
bool calibrate(int btn)
{
  float SensorValue1 = analogRead(READSOILPIN); //take a sample
  float SensorValue2 = analogRead(READSOILPIN2);
  if (btn == btnRIGHT)
  {
     // save value
   
    lcd.clear();
    lcd.print("done");
    delay(500); // indicate calibration finished
    lcd.clear();
    return true;
  }

  if (btn == btnUP){
    
   //for (int maxdry1=0; maxdry1 <= 1023; maxdry1++){
    
    lcd.clear();
    lcd.print("mas ");
    delay(50);
    lcd.print(maxdry1);
    maxdry1 = maxdry1 + 1;
    lcd.setCursor(0,1);
    lcd.print("(");lcd.print(SensorValue1);lcd.print(")");
   }  // do increment/decrement
  //}
  if (btn == btnDOWN)
  {
    lcd.clear();
    lcd.print("menos");
    delay(50);
    lcd.print(maxdry1);
    maxdry1 = maxdry1 - 1;
    lcd.setCursor(0,1);
    lcd.print("(");lcd.print(SensorValue1);lcd.print(")");
  }
  
    EEPROM.write (1,maxdry1);
    EEPROM.write (2,maxdry2);

  // indicate calibration still in progress
  return false;
}

void run(int btn)
{
  if (btn == btnSELECT){
   float SensorValue1 = analogRead(READSOILPIN); //take a sample
  float SensorValue2 = analogRead(READSOILPIN2); //take a sample
  float hum1 = (1- (SensorValue1/1023))*100;
  float hum2 = (1- (SensorValue2/1023))*100;
  lcd.clear();
  lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0
  lcd.print("Humedad:"); // Prints Sensor Val: to LCD
  lcd.setCursor(0,1);
  lcd.print(hum1); // Prints value on Potpin1 to LCD
   lcd.print("%/"); // Prints Sensor Val: to LCD
  lcd.print(hum2);
  lcd.print("%");// Prints value on Potpin1 to LCD
  maxdry1 = EEPROM.read(1);
  maxdry2 = EEPROM.read(2);
 
  if(SensorValue1 >= maxdry1) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
  
   
   digitalWrite(WATERPIN3, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN3, LOW);
   delay(WATERPOSTDELAY);
  }
  
  if(SensorValue2 >= maxdry2) 
  {
   // if the soil is too dry start watering for 3/4 a second then
   // wait for 5 seconds before monitoring again
   
  
   digitalWrite(WATERPIN2, HIGH);
   delay(WATERDELAY);
   digitalWrite(WATERPIN2, LOW);
   delay(WATERPOSTDELAY);
  }
}
 /*if (btn == btnLEFT){
  int mode;
  mode == MODE_CALIBRATE;
 }*/
}

How can I make it change modes as soon as I press the button?.

Find all the delay() calls. Remove them.

The intention was one delay in the beginning for testing. But ok, did it fix the problem?

And you can't get direct responses on a button that bounces. You will have to wait till the button is stable (either pressed or released). 50ms should be barely noticeable.

The only long delay that you have is after writing the eeprom (by the looks of it), not sure why you have that.

The delays fixed it.
And the EEprom write is there to save the set value of maxdry, in case the arduino loses power.
It still takes about 1 minute before I can access the calibration mode. Don't know what else to change/add.