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.setCursor(0,0);
lcd.print("Push the button!");
attachInterrupt(digitalPinToInterrupt(buttonPin),buttonInterrupt,HIGH);
}
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;
lcd.setCursor(0,1);
lcd.print(sec);
lcd.print(".");
lcd.print(ms);
lcd.setCursor(8,1);
lcd.print("Secs");
if(buttonState == LOW){
break;
}
}
}
void buttonInterrupt() {
if(buttonState == LOW){
buttonState = HIGH;
}else{
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.sstatic.net/XHHy5.png
If there is any other way to print the numbers other than printString, more than happy to hear them!
Thanks!
1 Answer 1
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– Raighley2020年10月21日 17:45:45 +00:00Commented Oct 21, 2020 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 whenLOW
.attachInterrupt()
doesn't support aHIGH
mode. There is no point in using bothdigitalRead()
andattachInterrupt()
.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.Edgar Bonet– Edgar Bonet2020年10月21日 18:09:03 +00:00Commented Oct 21, 2020 at 18:09
volatile
?start
are clear to people reading the question.msAtStart
tomillis()
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.