I'm trying to implement a stopwatch with an LCD display, and I'm supposed to be using the attachInterrupt command to catch the button press. The clock runs perfectly, but the button input isn't caught or acted upon at all.

In void setup(), I have set it up this way: attachInterrupt(digitalPinToInterrupt(buttonPin), buttonInterrupt, RISING);.

And the buttonInterrupt function only does start = !start, so in a sense just flipping the start variable.

This is the updated version of the code:

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int buttonPin = 7; 
volatile int buttonState; 
int lastButtonState;
long sec; 
long startTime;  

void setup() {
  lcd.begin(16, 2);
  pinMode(buttonPin, INPUT_PULLUP);
  lcd.print("Push the button!");

void loop() {
  buttonState = digitalRead(buttonPin); 
  if(buttonState == LOW){
    startTime = millis(); 
  while(buttonState == HIGH){
    long time = millis();
    long z = (time - startTime); 
    sec = (z/1000);
    long ms = z%1000; 
    if(buttonState == LOW){

void buttonInterrupt() {
  if(buttonState == LOW){
    buttonState = HIGH; 
    buttonState = LOW; 

The loop function works as far as time counting is concerned, but doesn't work to stop the time with the button. Any help is appreciated, I'm extremely new to Arduino (literally started yesterday). My circuit looks like this: https://i.imgur.com/yCR9fhP.png

If there is any other way to print the numbers other than printString, more than happy to hear them!


  • 1
    is variable start volatile?
    – Juraj
    Oct 18 '20 at 15:57
  • 1
    You better post the whole, compilable code, so things like the datatype of start are clear to people reading the question.
    – Sim Son
    Oct 18 '20 at 20:23
  • 1
    @Sim Son thanks for your answer! I have tried a different way of flipping the start variable, now that you mentioned boolean, it's clear to me my way didn't make any sense to flip 0 to 1. That being said, this solution did not fix the issue, and I'm not sure how to set msAtStart to millis() as this causes the stopwatch to tick to 0.1s and then tick back to 0.0. Thanks for your help! I have posted the whole, compilable code in my question body now.
    – Raighley
    Oct 19 '20 at 16:09
  • 1
    Does it start when you press the button, though?
    – ocrdu
    Oct 19 '20 at 19:17
  • 1
    Nothing at all from the button then. With the answer you got you from Edgar Bonet you should be able to get it to work. Get that button wired up properly first, and see what happens. Or I could post working code, but where's the fun in that?
    – ocrdu
    Oct 21 '20 at 17:02

There are several issues here. First and foremost, your button is wired incorrectly. If you connect one end of the button to +5V, then the other end should have a pushdown to GND, like here:

Wiring of a button

(Image from the Arduino Button example).

The second issue is the lack of debouncing. You should ignore the rising edges you sense for a few milliseconds after you record one.

The third issue is the timekeeping. As explained by Sim Son, your seconds will not be very accurate. It's better to just count the milliseconds elapsed since the button press, and then break the count into full seconds and remaining milliseconds.

  • Hi @edgar bonet - thanks so much for the answer! I have fixed a couple of things you talked about here. the stopwatch now starts upon the press of a button, but a second button press doesn't stop it. I assume that's because of the interrupt function, but I don't see where exactly the problem is. Any help is appreciated! Thanks. I have posted the updated code in the main body of the question. The debouncing I have not quite understood and haven't implemented yet.
    – Raighley
    Oct 21 '20 at 17:45
  • @Raighley: The code now is a mess, and I can't quite understand what it is trying to do. If you use INPUT_PULLUP, you don't need a pulldown, and the button is active when LOW. attachInterrupt() doesn't support a HIGH mode. There is no point in using both digitalRead() and attachInterrupt(). buttonState seems to serve two unrelated purposes. lastButtonState is never used... I suggest to restart from scratch: forget about interrupts, read about “button bounce”, and use a debouncing library. Oct 21 '20 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.