Using Digital Pins to Read 2 Push Buttons

First off, I’m not sure if this is the correct place for this, but it seems correct to me.

Now, my project is that I want to measure the time for an event to happen. I am using an Arduino UNO, with two push buttons (for now until I can connect them to micro switches on the device we need to measure the time of) and an LCD I2C to display the results.

The idea is that there are two buttons – Start and Stop. When the Start button is pressed, it records the milliseconds on the LCD display. When the stop button is pressed, it records the milliseconds at that point.

I have the two buttons wired from digital pins 8 and 9 to ground (ie. digital 8, switch, ground, etc.)

The problem I’m having is that the stop button works, but the start button doesn’t do anything. Is there something weird going on with the LCD display? Should I be using different digital pins? I tried 7 and 8, but no change…

Any ideas or direction would be greatly appreciated!!

Thanks.

/*
 Fall Time Measurement

 E. Greg Noseworthy
 27-May-2019
*/

#include <LiquidCrystal.h>        // include the library code:

int StartPin=8;
int StopPin=9;
int StartTime=0;
int StopTime=0;

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  Serial.begin(9600);             // set up the baud rate
  
  lcd.begin(16, 2);               // set up the LCD's number of columns and rows:
  
  // Print a message to the LCD.
  //         0123456789ABCDEF
  lcd.setCursor(0,0);
  lcd.print("START");
  lcd.setCursor(0,1);
  lcd.print("STOP");

  pinMode(StartPin,INPUT_PULLUP); // set the digital IO pins to input
  pinMode(StopPin,INPUT_PULLUP);
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):

  if(digitalRead(StartPin)==LOW)
  {
    StartTime=millis();
  }
  if(digitalRead(StopPin)==LOW)
  {
    StopTime=millis();
  }
  
  // print the number of seconds since reset:
  lcd.setCursor(8, 0);
  lcd.print(StartTime);
  lcd.setCursor(8, 1);
  lcd.print(StopTime);
}
int StartTime=0;
int StopTime=0;

Always use unsigned long, not int, for variables associated with millis() or micros().

the start button doesn't do anything.

How do you know this?
What does the program output look like?

Every pass through the loop() function (tens to hundreds of thousands of times each second), some values will be written to the LCD, and it is never erased. So the screen appearance can become quite confusing.

Most people wait until the information has changed and is ready to be displayed before printing to a cleared LCD screen.

Interesting point about the updates. I will put the update inside the if statement and see what happens.

Other than that, the screen just says;
START 0
STOP 1745

The "STOP" value will update when I press the start button, but nothing ever changes. It remains 0 no matter what.

I have a feeling that the LCD screen is doing something that overrides the normal operation of the digital IO pins?

To that end, one solution that I have though of is to make a voltage divider that the two buttons switch in so there are 4 different voltages that can be read by one analog input.... but I'd like to know what is going on with the digital IP's.

Thanks.

Greg

Study the StateChangeDetection example about only responding to the buttons' initial push (rather than throughout the period they are depressed).

You perhaps have a wiring fault in the start button? Have you checked the button itself with a multimeter?

LCD screen is doing something that overrides the normal operation of the digital IO pins

Extremely unlikely. Check for wiring problems.

I did some poking and you are correct -- one of the hookup wires I was using was broken... I have never seen this happen before with these hookup wires, but... there you have it. I replaced that wire and BAM! Works great.

Now I'm going to dig into the 'change state' example to trigger only on the positive edge of the switch rather than the level...

Thanks for the help!!

Greg

Just to close this out… the code is working just like I had hoped it would, so I thought I would post the final result here in case somebody get’s here looking for a similar answer.

This is going to measure fall time. We have a switch that remains ‘on’ and the time starts when that’s ‘off’. This shows up as ‘armed’ and ‘triggered’ on the display. The time stops when the second switch is pushed ‘on’. As soon as that happens, it displays the time in milliseconds.

Resetting the device (by putting it back into it’s ready to fall state, turning on the first switch) sets it back to ‘armed’ and clears out the time.

/*
 Fall Time Measurement

 E. Greg Noseworthy
 27-May-2019
*/

#include <LiquidCrystal.h>        // include the library code:

int StartPin=8;
int StopPin=9;

// when a button is pressed it is 'low'
// the start is set to 'low' when armed
// stop is low when triggered
int ButtonStartState=LOW;
int LastStartState=LOW;
int ButtonStopState=HIGH;
int LastStopState=HIGH;

int StartT=0;
int StopT=0;

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  Serial.begin(9600);             // set up the baud rate
  
  lcd.begin(16, 2);               // set up the LCD's number of columns and rows:
  
  // Print a message to the LCD.
  //         0123456789ABCDEF
  lcd.setCursor(0,0);
  lcd.print("STATUS");
  lcd.setCursor(0,1);
  lcd.print("TIME [MS]");
  lcd.setCursor(10,0);
  lcd.print("Armed...");
  lcd.setCursor(10,1);
  lcd.print("        ");
  
  pinMode(StartPin,INPUT_PULLUP); // set the digital IO pins to input
  pinMode(StopPin,INPUT_PULLUP);
}

void loop() {
  // read the pushbutton input pin:
  ButtonStartState = digitalRead(StartPin);
  ButtonStopState = digitalRead(StopPin);

  // compare the buttonState to its previous state
  if (ButtonStartState != LastStartState)
  {
    // if the state has changed, then check that the change was from LOW to HIGH
    // ie. the trigger has been pulled and circuit is 'open'
    if (ButtonStartState == HIGH)
    {
      // this means it's triggered.  Set start time and display trig'd
      StartT=millis();
      lcd.setCursor(10,0);
      lcd.print("Trig'd  ");
    }else
    {
      // if it's HIGH then it has gone back to Armed.  Also clear STOP readings
      lcd.setCursor(10,0);
      lcd.print("Armed  ");
      lcd.setCursor(10,1);
      lcd.print("        ");
      StartT=0;
      StopT=0;
    }
  }
  // if the button is pressed, it's stop.
  if (ButtonStopState != LastStopState)
  {
    if (ButtonStopState == LOW)
    {
      // if there is a stop time, then ignore the this trigger.
      if(StopT==0){
        StopT=millis();
        lcd.setCursor(10,1);
        lcd.print(StopT-StartT);
      }
    }
  }
  LastStartState = ButtonStartState;
  LastStopState = ButtonStopState;
}

Thanks for all the help!

Greg

GregNoseworthy:
I did some poking and you are correct -- one of the hookup wires I was using was broken... I have never seen this happen before with these hookup wires

It may be your first time, it will not be your last time to find a wire broken. Especially with those flexible jumper wires and/or a solderless breadboard the first thing to check is wiring and connetions if something doesn't work as expected.

Good it was a simple fix :slight_smile: