else if statment not executed but condition is fulfilled

I am working on a hobby project - a stopwatch with lcd display. A switch (digitalRead(11)== HIGH) is used for starting the stopwatch and a push button (digitalRead(12)== HIGH) is used to stop the stopwatch if it is running. The problem is with the reset that is done with a start-reset switch (digitalRead(11)== LOW). The "else if" statement for reset is never executed although the conditions are fulfilled as the logic for this conditions are similar to one for STOP statement.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <StopWatch.h>

#define I2C_ADDR    0x27
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin, BACKLIGHT_PIN, POSITIVE);

StopWatch sw_millis;    // MILLIS (default)
StopWatch sw_micros(StopWatch::MICROS);
StopWatch sw_secs(StopWatch::SECONDS);

// start-reset pin 11
int start_reset_pin = 11;
// stop pin 12
int stop_pin = 12;
void setup()
{
  Serial.begin(9600);
  //start-reset pin signal
  pinMode(start_reset_pin, INPUT);      // sets the digital pin 11 as output
  pinMode(stop_pin, INPUT);      // sets the digital pin 12 as input
  lcd.begin(16, 2);              // initialize the lcd
  lcd.home ();                   // go home
}
void loop()
{
  if ((digitalRead(start_reset_pin) == LOW) && (digitalRead(stop_pin) == LOW))
  {
    // ready
    //lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TYPE");
    lcd.setCursor( 9, 0 );
    lcd.print("SSV");
    lcd.setCursor( 9, 0 );
    lcd.print ("READY");
    lcd.setCursor( 14, 0 );
    lcd.print ("   ");
    lcd.setCursor(0, 1);
    lcd.print("TIME:");
    lcd.setCursor(8, 1);
    lcd.print("0:00.00");
  }
  else if ((digitalRead(start_reset_pin) == HIGH) && (digitalRead(stop_pin) == LOW) && (sw_millis.state() == StopWatch::RESET))
  {
    // start
    lcd.setCursor( 9, 0 );
    lcd.print ("RUNNING");
    sw_millis.start();
  }
  else if ((sw_millis.state() == StopWatch::RUNNING) && (digitalRead(stop_pin) == HIGH))
  {
    // stop
    sw_millis.stop();
    lcd.setCursor( 9, 0 );
    lcd.print ("STOPPED");
    lcd.setCursor( 7, 1 );
    sw_millis.value();
  }
  else if ((sw_millis.state() == StopWatch::STOPPED) && (digitalRead(start_reset_pin) == LOW))
  {
    // reset - THIS IS NEVER EXECUTED???
    sw_millis.reset();
  }
  else if ((sw_millis.state() == StopWatch::RUNNING) && (digitalRead(start_reset_pin) == HIGH))
  {
    // runnging
    lcd.setCursor(7, 1);
    lcd.print(sw_millis.elapsed());
  }
  delay(10);
}
  pinMode(start_reset_pin, INPUT);      // sets the digital pin 11 as output

It most certainly does not!

The "else if" statement for reset is never executed

Which one of the 4 else if statements would that be?

Frankly, nested if statements are easier to see (and debug) the logic of than all the compound if statements you are using.

I'd be inclined to put some serial prints at the top of loop() and display the values of the things that take part in all those ifs to verify that they are what you think they are.

PaulS:

  pinMode(start_reset_pin, INPUT);      // sets the digital pin 11 as output

It most certainly does not!

The comment "//sets the digital pin 11 as output" is not correct. The pinMode() of pin 11 is correctly set to INPUT.

PaulS:
Which one of the 4 else if statements would that be?

I am having problems with the following else if statement (everything else is working ok):

 else if ((sw_millis.state() == StopWatch::STOPPED) && (digitalRead(start_reset_pin) == LOW))
 {
   // reset - THIS IS NEVER EXECUTED???
   sw_millis.reset();
 }

PaulS:
Frankly, nested if statements are easier to see (and debug) the logic of than all the compound if statements you are using.

I am more of a hobby programmer so I would ask you, if you can show me an example of nested if statements as I don't know what are you reffering to.

JimboZA:
I'd be inclined to put some serial prints at the top of loop() and display the values of the things that take part in all those ifs to verify that they are what you think they are.

JimboZA:
I'd be inclined to put some serial prints at the top of loop() and display the values of the things that take part in all those ifs to verify that they are what you think they are.

The use of serial prints was my first step. With a bit of mind work I found the improvized solution to call function reset() every time when the first statement is executed (ready). The doubt I have is because I use similar logic for stoping the stopwatch and it works OK, but I am having problems with stopwatch reset.

I think I found the solution to my problem. I had to add some additional conditions to my (else) if statements. Thanks for the kind help.

You have a number of conditions you want to check for. Is the stopwatch running? If it is, then stop makes sense. If it isn't, then the state of the stop switch doesn't matter. So, the outer if statement should be:

if(sw_millis.state() == StopWatch::STOPPED)
{
}
else
{
}

In the "it is running" block, you have to check for other events of interest (stop, reset). In the else block, you check for events of interest (start):

if(sw_millis.state() == StopWatch::STOPPED)
{
  if(digitalRead(start_reset_pin) == LOW)
  {
     // reset
  }
  if(digitalRead(step_pin) == LOW)
  {
    // stop
  }
}
else
{
  if(digitalRead(start_reset_pin) == LOW)
  {
    // start
  }
}

I think that you'll find that this structure is easier to understand than compound if statements.

It is indeed much easier to follow the logic with that structure PaulS, good point. Easy to read down the branches of the tree, so to speak.