/*
Start after red select-button is pressed, then display a counter that counts up until 20 and then finishes.
While running, it also checks the buttons pressed.
So it executes 3 tasks in parallel:
- blinking text
- counter counting & display it
- check buttons
https://home.et.utwente.nl/slootenvanf/2020/06/08/countdown-timers-tasks-in-parallel/
Author: F. van Slooten
*/
#include <U8g2lib.h>
#include <Bounce2.h>
byte button_pins[] = {4, 5, 6}; // button pins; 4/5 up/down, 6 = set/select
#define NUMBUTTONS sizeof(button_pins)
Bounce * buttons = new Bounce[NUMBUTTONS];
U8X8_SSD1306_128X64_NONAME_HW_I2C display(U8X8_PIN_NONE);
int count = 0; // start value of the counter (in seconds)
unsigned long previousMillis = 0, previousMillis2 = 0; // will store last time timer was updated
const unsigned long interval = 1000; // 1 second interval for countdown
char buf[10]; // text buffer; to be able to use draw2x2String to show the value
bool blink = true;
void setup() {
Serial.begin(9600);
// Make input & enable pull-up resistors on switch pins
for (int i = 0; i < NUMBUTTONS; i++) {
buttons[i].attach( button_pins[i] , INPUT_PULLUP ); //setup the bounce instance for the current button
buttons[i].interval(25); // interval in ms
}
// initialize display
display.begin();
display.setPowerSave(0);
display.setFont(u8x8_font_pxplusibmcgathin_f);
// wait until button pressed to proceed:
// (this while statement halts the program, until the button is pressed)
while(digitalRead(button_pins[NUMBUTTONS-1])==HIGH) ; // note the empty statement: ';' does nothing, thus waits for first button to be pressed (becomes LOW)
delay(1000); // wait 1 sec before starting
display.drawString(0, 7, "running");
Serial.println("Countdown running");
}
void loop() {
unsigned long currentMillis = millis();
// task 1: blink time on display every 300ms when setting it:
if (currentMillis - previousMillis2 > 300 && count<20) { // 300ms passed? and running counter?
previousMillis2 = currentMillis; // save the last time
blink = !blink;
if (blink) display.drawString(0, 7, "running");
else display.clearLine(7);
}
// task 2: update countdown timer every second
if (currentMillis - previousMillis > interval) { // interval passed?
previousMillis = currentMillis; // save the last time
if (count==20) {
display.drawString(0, 7, "counter finished");
}
else if (count<20) {
count++;
sprintf(buf, "%02d", count);
display.draw2x2String(2, 3, buf);
}
}
// task 3: check for pressed buttons
for (int i = 0; i < NUMBUTTONS; i++) {
// Update the Bounce instance :
buttons[i].update();
if ( buttons[i].fell() ) { // a button was pressed
sprintf(buf, "button %d press", i);
display.drawString(0,0,buf);
if ((i==2 && count==20)||(i==0 && count>20)) { // if button 2 was pressed and counter was finised, or device is off and first button pressed
count=0; // restart counter/turn on device
}
else if (i==0 && count<=20) { // if first button was pressed turn off
count=100; // set counter to high value (out of range)
display.clear();
}
} // end if (button pressed)
} // end for
}