[HELP] online monitoring of a switch

Hello everybody!

I am new in Arduino and programing, I want to make a device for monitoring humidity of soil for automatic irrigating system,
I used following instructable for this goal. however, I made some changes to make it more applicable.

I made following changes:

1- watchdog timer to reset the system whenever it hangs
2- LCD backlight screen off timer for saving the LCD lifetime backlight LED
3- I used two digital output pins instead of VCC for Sensors, so I can turn them on only when I want to read them (to prevent corrosion of sensor electrodes)

because of these changes the loop is very long, on the other hand, I need a switch to turn the LCD backlight on whenever I want. with this issue, any switch written in the loop works after pushing switch button for about 2-3 sec which is Unpleasant!

anybody, could you help me to overcome this issue? how can I manage this very long loop? I guess the code for this project has turned to a real mess somehow.

I'll be really appreciated if anybody can help me, thanks.

Post you program here so that we can see what you are doing. Use code tags (</> top left icon in the forum editor)

The symptoms you describe sound like you are using delay() for timing and if so you will need to change to using millis() for timing.

See Using millis() for timing. A beginners guide and Several things at the same time if you are not familiar with how to use millis()

part 1

// libraries definition
#include <Wire.h>               // library for wire connection
#include <LiquidCrystal_I2C.h>  // library for I2C LCD
#include "RTClib.h"             // library for real time clock
#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control

// frequency musical notes
#define NOTE_C6  1047
#define NOTE_C3  131
#define NOTE_G3  196
#define NOTE_DS3  156

// pins definition
int levelSensorPin = 0;
int moistureSensorPin = 1;
int audioPin = 2;
int soggyLEDPin = 3;
int moistsoilLEDPin = 4;
int drysoilLEDPin = 5;
int pumpLEDPin = 6;
int pumpPin = 7;
int HSensorVCC = 9;
int LSensorVCC = 10;
int LCDBacklight = 8;

// variables
int levelSensorValue;       // stores the level sensor values
float moistureSensorValue;    // stores the moisture sensor values
int j = 0;
float MP;
int z;
int x;
int Val = 0;

// system messages
const char *string_table[] =
{
  //0
  "     Welcome! :D",
  //1
  "   LOW Water Level",
  //2
  "      Dry soil",
  //3
  "     Moist soil",
  //4
  "     Soggy soil",
  //5
  "The water pump is on",
  //6
  "       BALOOT",
  //7
  "  Watering System",
  //8
  "    Please wait!"
};

// objects definition
RTC_DS1307 RTC;
LiquidCrystal_I2C lcd(0x27, 20, 4);

//icon for water droplet
byte Droplet[8] =
{
  B00100,
  B00100,
  B01010,
  B01010,
  B10001,
  B10001,
  B10001,
  B01110,
};


void setup() {

  //wdt function start
  watchdogSetup();

  // serial initialization
  Serial.begin(9600);

  // LCD initialization
  lcd.init();
  lcd.backlight();     // Backlight On
  lcd.clear();         // clearscreen

  // Wire initialization
  Wire.begin();

  //creating LCD Char.
  lcd.createChar(1, Droplet);

  // RTC initialization
  RTC.begin();
  if (!RTC.isrunning()) {
    // date and time adjust as the PC computer date and time
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }

  // Arduino pins initalization
  pinMode(audioPin, OUTPUT);
  pinMode(soggyLEDPin, OUTPUT);
  pinMode(moistsoilLEDPin, OUTPUT);
  pinMode(drysoilLEDPin, OUTPUT);
  pinMode(pumpLEDPin, OUTPUT);
  pinMode(pumpPin, OUTPUT);
  pinMode(HSensorVCC, OUTPUT);
  pinMode(LSensorVCC, OUTPUT);
  pinMode(LCDBacklight, INPUT);

  //initial Pin Values for 9, 10, 7.
  digitalWrite(HSensorVCC, HIGH);
  digitalWrite(LSensorVCC, HIGH);
  digitalWrite(pumpPin, HIGH);

  // LCD initial messages
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(string_table[6]);
  lcd.setCursor(0, 1);
  lcd.print(string_table[7]);
  lcd.setCursor(0, 3);
  lcd.print(string_table[0]);
  wdt_reset();
  // reads the sensors
  levelSensorValue = analogRead(levelSensorPin);
  moistureSensorValue = analogRead(moistureSensorPin);
  // initialization delay
  delay(5000);
}


void loop() {

  //LCD Backlight button
  Val = digitalRead(LCDBacklight);
  while (Val == 1)
  {
    z = 0;
    Serial.println(z);
    Val = digitalRead(LCDBacklight);
  }

  //LCD turn of alarm
  if (z == 8) {
    for (int p = 0; p < 3; p++) {
      tone(audioPin, NOTE_C6, 250);
      delay(150);
    }
    noTone(audioPin);
  }

  lcd.clear();
  lcdbacklightsetting();
  wdt_reset();

  // RTC parameters definition
  DateTime myRTC = RTC.now();
  int H = myRTC.hour();
  int M = myRTC.minute();
  int S = myRTC.second();

  // call Clock Function
  RightHour();

  MP = (((1000 / moistureSensorValue) - 0.984251968) * 100) / 4.0157480315;

  //printing Sensor's values in serial monitoring and LCD
  Serial.println("Moisture is");  //in case of monitoring sensor values
  Serial.println(moistureSensorValue);
  Serial.println("Water Level is:");
  Serial.println(levelSensorValue);
  Serial.println("The Z is:");
  Serial.println(z);
  Serial.println("The X is:");
  Serial.println(x);
  //
  lcd.clear();
  lcd.setCursor(5, 0);
  lcd.write(1);
  lcd.setCursor(7, 0);
  lcd.print(MP);
  lcd.setCursor(12, 0);
  lcd.print("%");
  lcd.setCursor(1, 2);
  lcd.print("The Tank Level is:");
  if (levelSensorValue <= 600) {
    lcd.setCursor(0, 3);
    lcd.print("  The Tank is Full");
  }
  else {
    lcd.setCursor(0, 3);
    lcd.print(string_table[1]);
  }
  delay(2000);

  // if low water level: plays the low level alarm
  if (levelSensorValue > 600) {
    wdt_reset();
    // system messages
    lcd.clear();
    RightHour();
    lcd.setCursor(0, 3);
    lcd.print(string_table[1]);
    // plays the alarm sound
    for (int i = 0; i < 2; i++) {

      //audio alarm
      tone(audioPin, NOTE_G3, 200);
      delay(200);
      tone(audioPin, NOTE_C3, 200);
      delay(200);
      tone(audioPin, NOTE_DS3, 200);

      //LED Alarm
      digitalWrite(pumpLEDPin, HIGH);
      digitalWrite(drysoilLEDPin, HIGH);
      digitalWrite(soggyLEDPin, HIGH);
      digitalWrite(moistsoilLEDPin, HIGH);
      delay(50);
      digitalWrite(pumpLEDPin, LOW);
      digitalWrite(drysoilLEDPin, LOW);
      digitalWrite(soggyLEDPin, LOW);
      digitalWrite(moistsoilLEDPin, LOW);
      delay(50);
      digitalWrite(pumpLEDPin, HIGH);
      digitalWrite(drysoilLEDPin, HIGH);
      digitalWrite(soggyLEDPin, HIGH);
      digitalWrite(moistsoilLEDPin, HIGH);
      delay(50);
      digitalWrite(pumpLEDPin, LOW);
      digitalWrite(drysoilLEDPin, LOW);
      digitalWrite(soggyLEDPin, LOW);
      digitalWrite(moistsoilLEDPin, LOW);
      delay(850);
      noTone(audioPin);
    }
  }

  // check the moisture range
  if (moistureSensorValue >= 750) {
    // in case of dry soil:
    // system messages
    wdt_reset();
    lcd.clear();
    RightHour();
    lcd.setCursor(0, 3);
    lcd.print(string_table[2]);
    // lights up the correct LED
    digitalWrite(drysoilLEDPin, HIGH);
    digitalWrite(moistsoilLEDPin, LOW);
    digitalWrite(soggyLEDPin, LOW);
    // plays the alarm sound
    tone(audioPin, NOTE_C6, 100);
    delay(1000);
    noTone(audioPin);
  }
  if ((moistureSensorValue < 750) && (moistureSensorValue >= 238)) {
    // in case of moist soil:
    // system messages
    wdt_reset();
    lcd.clear();
    RightHour();
    lcd.setCursor(0, 3);
    lcd.print(string_table[3]);
    // lights up the correct LED
    digitalWrite(drysoilLEDPin, LOW);
    digitalWrite(moistsoilLEDPin, HIGH);
    digitalWrite(soggyLEDPin, LOW);
    delay(1000);
  }

exceed 9000 limit
go to part 2 for continue

part 2

if (moistureSensorValue < 238) {
    // in case of soggy soil:
    // system messages
    wdt_reset();
    lcd.clear();
    RightHour();
    lcd.setCursor(0, 3);
    lcd.print(string_table[4]);
    // lights up the correct LED
    digitalWrite(drysoilLEDPin, LOW);
    digitalWrite(moistsoilLEDPin, LOW);
    digitalWrite(soggyLEDPin, HIGH);
    delay(1000);
  }

  // between time 8:00:00 to 9:59:59 (morning check)
  if ((H >= 8) && (H <= 9) && (moistureSensorValue >= 750))
  {
    while (moistureSensorValue >= 750 && levelSensorValue <= 600) {
      // system messages
      wdt_reset();
      lcd.clear();
      RightHour();
      lcd.setCursor(0, 2);
      lcd.print(string_table[8]);
      lcd.setCursor(0, 3);
      lcd.print(string_table[5]);

      // turn the pump on
      digitalWrite(pumpPin, LOW);
      delay(150);
      //digitalWrite(pumpPinLow, HIGH);
      digitalWrite(pumpLEDPin, HIGH);
      delay(5000);
      // if the soil is not moist so far
      // check sensors again
      SensorRead();
      lcd.clear();
    }
    // turn the pump off
    digitalWrite(pumpPin, HIGH);
    // digitalWrite(pumpPinLow, HIGH);
    digitalWrite(pumpLEDPin, LOW);
    lcd.clear();
  }

  // between time 17:00:00 to 18:59:59 (afternoon check)
  else if ((H >= 17) && (H <= 18) && (moistureSensorValue >= 750))
  {

    while (moistureSensorValue >= 750 && levelSensorValue <= 600) {
      // system messages
      wdt_reset();
      lcd.clear();
      RightHour();
      lcd.setCursor(0, 2);
      lcd.print(string_table[8]);
      lcd.setCursor(0, 3);
      lcd.print(string_table[5]);

      // turn the pump on
      digitalWrite(pumpPin, LOW);
      delay(150);
      //digitalWrite(pumpPinLow, HIGH);
      digitalWrite(pumpLEDPin, HIGH);
      delay(5000);
      // if the soil is not moist so far
      // check sensors again
      SensorRead();
      lcd.clear();
    }
    // turn the pump off
    digitalWrite(pumpPin, HIGH);
    //digitalWrite(pumpPinLow, HIGH);
    digitalWrite(pumpLEDPin, LOW);
    lcd.clear();
  }
  else if (moistureSensorValue > 845)
  {

    while (moistureSensorValue >= 700 && levelSensorValue <= 600) {
      // system messages
      wdt_reset();
      lcd.clear();
      RightHour();
      lcd.setCursor(0, 2);
      lcd.print(string_table[8]);
      lcd.setCursor(0, 3);
      lcd.print(string_table[5]);

      // turn the pump on
      digitalWrite(pumpPin, LOW);
      delay(150);
      //digitalWrite(pumpPinLow, HIGH);
      digitalWrite(pumpLEDPin, HIGH);
      delay(5000);
      // if the soil is not moist so far
      // check sensors again
      SensorRead();
      lcd.clear();
    }
    // turn the pump off
    digitalWrite(pumpPin, HIGH);
    //digitalWrite(pumpPinLow, HIGH);
    digitalWrite(pumpLEDPin, LOW);
    lcd.clear();
  }
  
  //Sensor function
  SensorRead();

  //LCD Backlight button
  Val = digitalRead(LCDBacklight);
  while (Val == 1)
  {
    z = 0;
    Serial.println(z);
    Val = digitalRead(LCDBacklight);
  }
}

// Real Time Clock Function
void RightHour()
{
  DateTime Now = RTC.now();
  String clock_date = "  Date: ";
  String clock_hour = "   Time: ";

  int _day = Now.day();
  int _month = Now.month();
  int _year = Now.year();

  clock_date += fixZero(_day);
  clock_date += "/";
  clock_date += fixZero(_month);
  clock_date += "/";
  clock_date += _year;

  int _hour = Now.hour();
  int _minute = Now.minute();
  int _second = Now.second();

  clock_hour += fixZero(_hour);
  clock_hour += ":";
  clock_hour += fixZero(_minute);
  clock_hour += ":";
  clock_hour += fixZero(_second);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(clock_date);
  lcd.setCursor(0, 1);
  lcd.print(clock_hour);

    //LCD Backlight button
  Val = digitalRead(LCDBacklight);
  while (Val == 1)
  {
    z = 0;
    Serial.println(z);
    Val = digitalRead(LCDBacklight);
  }

  delay(500);
}


String fixZero(int i)
{
  String ret;
  if (i < 10) ret += "0";
  ret += i;
  return ret;
}

void watchdogSetup(void)
{
  cli();

  wdt_reset();

  WDTCSR |= (1 << WDCE) | (1 << WDE);

  WDTCSR = (1 << WDIE) | (1 << WDE) | (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (1 << WDP0);

  sei();

}

void lcdbacklightsetting() {

  //LCD Backlight button
  Val = digitalRead(LCDBacklight);
  while (Val == 1)
  {
    z = 0;
    Serial.println(z);
    Val = digitalRead(LCDBacklight);
  }

  Serial.println(".....................................Val is:");
  Serial.println(Val);
  Serial.println("...........................................");

  if ((moistureSensorValue < 750) && (moistureSensorValue >= 238) && (levelSensorValue <= 600) && (z >= 8)) {
    lcd.noBacklight();
    z = 9;
  }
  else if ((moistureSensorValue < 750) && (moistureSensorValue >= 238) && (levelSensorValue <= 600) && (z < 8)) {
    lcd.backlight();
    z = z + 1;
  }
  else {
    lcd.backlight();
    z = 0;
  }
}

ISR(WDT_vect)
{
  while (1);
}


void SensorRead () {
  if ((moistureSensorValue < 750) && (levelSensorValue <= 600) && (x >= 20) && (x < 101)) {
    digitalWrite(HSensorVCC, LOW);
    digitalWrite(LSensorVCC, LOW);
    x = x + 1;
  }
  else if ((x < 20) || (moistureSensorValue >= 750) || (levelSensorValue > 600)) {
    digitalWrite(HSensorVCC, HIGH);
    digitalWrite(LSensorVCC, HIGH);
    levelSensorValue = analogRead(levelSensorPin);
    moistureSensorValue = analogRead(moistureSensorPin);
    x = x + 1;
  }
  else {
    x = 0;
  }

    //LCD Backlight button
  Val = digitalRead(LCDBacklight);
  while (Val == 1)
  {
    z = 0;
    Serial.println(z);
    Val = digitalRead(LCDBacklight);
  }
}

UKHeliBob:
Post you program here so that we can see what you are doing. Use code tags (</> top left icon in the forum editor)

The symptoms you describe sound like you are using delay() for timing and if so you will need to change to using millis() for timing.

See Using millis() for timing. A beginners guide and Several things at the same time if you are not familiar with how to use millis()

dear, yes the original sketch has delay and I accept them when I modified it also
how does using milis can change it?

As expected the problem is caused by your use of the delay() function

A suggestion. Write down how many states the system can be in and give each a number starting at 0

For instance :

0 dry soil
1 wet soil
2 soggy soil
3 watering in progress
etc

Add the actions that take place in each state to the list

Perhaps
0 dry soil - add water for 10 seconds
1 wet soil - add water for 5 seconds
2 soggy soil - no action required
3 watering in progress for z seconds (millis() timing)

NOTE that I have invented the states and actions but you will know what is needed.

Add other states such as
4 display message x for s seconds

List any actions that must happen regardless of the current state such as
read soil humidity
read backlight button and change backlight state if it becomes pressed

Now you can structure your program using switch/case to execute only the code for the current state and still read inputs each time through loop()

You can do this with if/els but personally I find switch/case easy to read, particularly if you give each state a meaningful name.

UKHeliBob:
As expected the problem is caused by your use of the delay() function

A suggestion. Write down how many states the system can be in and give each a number starting at 0

For instance :

0 dry soil
1 wet soil
2 soggy soil
3 watering in progress
etc

Add the actions that take place in each state to the list

Perhaps
0 dry soil - add water for 10 seconds
1 wet soil - add water for 5 seconds
2 soggy soil - no action required
3 watering in progress for z seconds (millis() timing)

NOTE that I have invented the states and actions but you will know what is needed.

Add other states such as
4 display message x for s seconds

List any actions that must happen regardless of the current state such as
read soil humidity
read backlight button and change backlight state if it becomes pressed

Now you can structure your program using switch/case to execute only the code for the current state and still read inputs each time through loop()

You can do this with if/els but personally I find switch/case easy to read, particularly if you give each state a meaningful name.

thanks I will try it
for confirmation, you mean using switch/case can solve the case???

for confirmation, you mean using switch/case can solve the case???

You still have a lot of work to do but switch/case should make it easier for you in the long run. It is not a quick cure !