Countdown Timer that speeds up with multiple inputs

I am a novice when it comes to Arduino and have done simple projects like transmitting I/O through xBee, turn simple I/O on and off, count, etc. I am looking at completing a kind of silly project that has a timer that has the ability to speed up when triggered by a simple input (possibly 8 inputs in no particular sequence). It is for one of my kids classes where they are asked a series of questions and for each wrong answer they are to push one button out of eight (no particular order). Once each button is pushed the clock begins to count down faster until time runs out.

Below is the code I have written. It does compile and download. It displays on a Adafruit LCD screen and does countdown. However, the time is off since I used a “delay.” I am super rusty at this and I believe to achieve an accurate time the internal clock needs to be used or possibly the millis() statement? Any thoughts on achieving a more accurate time and how to figure on increasing the speed when an input is pressed? Thanks in advance.

#include <avr/wdt.h>
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#define WHITE 0x7
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

unsigned long time;
long currentmillis = 0;
long hours = 0; //variables for hours
long mins = 0; //variables for mins
long secs = 0; //variables for secs

long timerH = 1; //time to be displayed on the LCD
long timerM = 1; //time to be displayed on the LCD
long timerS = 10; //time to be displayed on the LCD

const int LED = 13;

//////////////////////////////////////////////////////////////////////////////////////////////////
void softwareReset(uint8_t prescaller) //START WATCHDOG WITH THE PROVIDED PRESCALLER
{
wdt_enable(prescaller); //WAIT FOR THE PRESCALLER TIME TO EXPIRE
while(1){} //WITHOUT SENDING THE RESET SIGNAL BY USING THE WDT_RESET() METHOD
}

/////////////////////////////////////////////////////////////////////////////////////////////////

void setup()
{
Serial.begin(9600);
lcd.begin(16,2);
lcd.print(“Count Downtimer”);
delay(5000);
lcd.clear();
delay(150);
lcd.print("Hr ");
lcd.print("Min ");
lcd.print("Sec ");

pinMode(LED,OUTPUT);
}

void loop()
{
unsigned long currentmillis = millis();
secs = currentmillis/1000;
mins = secs/60;
hours = mins/60;

while (timerH >0 || timerM >0 || timerS >=0){

lcd.setCursor(0,1);
(timerH<10)?lcd.print(“0”):NULL;
lcd.print(timerH);
lcd.print(":");

lcd.setCursor(5,1);
(timerM<10)?lcd.print(“0”):NULL;
lcd.print(timerM);
lcd.print(":");

lcd.setCursor(11,1);
(timerS<10)?lcd.print(“0”):NULL;
lcd.print(timerS);

lcd.display();
stepDown();
delay(1000);
}
}
///////////////////////////////////////////////////////////////////////////

void stepDown()

{
if ((timerS - secs) > 0)
{
timerS -= 1;
}
else
{
if (timerM - mins > 0)
{
timerS = 59;
timerM -= 1;
}
else
{
if (timerH - hours > 0)
{
timerS = 59;
timerM = 59;
timerH -= 1;
}

else
{
trigger();
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////
void trigger() {
lcd.clear(); // clears the screen and buffer
lcd.setCursor(5, 1); // set timer position on lcd for end.
lcd.println("End Game! "); //PRINTS “END GAME” ON THE LCD
digitalWrite(LED,HIGH); //PIN 13 TURNS AN LED ON
delay(3000); //HOLD LED ON FOR 3 SEC
digitalWrite(LED,LOW); //PIN 13 TURNS LED OFF
lcd.clear(); //CLEAR THE LCD
delay(2000);

softwareReset(WDTO_1S); //RESTART IN 1 SECOND WITH TIME INSERTED IN THE BEGINNING
}
/////////////////////////////////////////////////////////////////////////////////////

delay(...) can be bad because not much else can happen during the delay time. millis() is better but could still be off a millisecond or two. This is probably close enough for working with humans as long as you allow for it. Use >= and not ==.

I don't know what type of Arduino you have, but most Arduinos (like the Uno) use a crystal controlled clock that is quite accurate. In any case, delay(...) and millis() operate from the same clock so they are equally accurate for most purposes.

Using millis(), you can record the time that something happens and check back later to see if enough time has passed to do something else. (For example, you can record the time that you put a pot of water on a burner to boil, and after four minutes have passed you can make your coffee.)

In the meantime, you can do other things.

delay(...) is convenient but little else happens while delay expires.

In your case, delay(1000) does not account for the execution of other code such as lcd.print(...) and lcd.setCursor(...). Use millis() and this problem can go away. I do not know how to make it go away for delay(1000) except by doing some sort of error-prone calibration.

"but most Arduinos (like the Uno) use a crystal controlled clock "

Most Arduinos, like the Uno, use a 3-terminal resonator for the system clock source.

Yes, you,are right. I didn’t want to get into the details of crystal vs. resonator. It is still highly accurate compared to what the OP is attempting.