In the beginning God created the heaven and the earth. And human beings. And human beings created digital kitchen timers, like this one.
And human beings said, Cool but a little dismal. Let's make a better one!
And God said, I heard your call, let there be Arduinos: and there was Arduinos all over the earth, and that was good.
And human beings took an Arduino and created a better kitchen timer, like this one.
And God saw the new kitchen timer and said: I saw your new kitchen timer and it looks awful, but it seems too much fun! And that is good. :-)
Now that you know where all this came from, let's go deep into it.
You'll need a power source too: while playing around, the PC' USB port and cable will be enough.
First: please gather all needed components from the Starter Kit or your preferred component bin; if you don't have one, don't panic. There's plenty of on the Internet. You can find the component list below.
And, well, you'll need the code too. It's in its box, below again.
Basically, like any other similar device you can buy for a buck at any store near you. But this is yours. And this will show you how those little gadgets actually work.
The keyword here is: current mode. The timer itself can run in only one out of four modes at a time:
- IDLE - the timer is awaiting for your input, showing the currently set time amount; this is also the initial mode after power up or reset.
- SETUP - you can enter this mode by long-pressing S4 (in the code this is called also "reset button"); here, by using S3 ("start stop button"), you can choose which value to change in order to set the elapsed time to be counted down later; finally, using S2 ("down button") and S1 ("up button") respectively, you can decrease or increase the choosen value (hours, minutes or seconds).
- RUNNING - You can enter this mode by pressing S3, while leaving it will require both S3 or S4 (which will lead you to IDLE mode).
- RINGING - When the desider amount of time is elapsed, this mode is automatically activated; you can leave it (i.e., make the little boy stop ringing) by pressing any switch.
First, we need to include the proper libraries:
If you don't have them already, you'll need to download and install them:
- Paul Stoffregen's Time Library (please download the ZIP from the green "Clone or download" button)
- Arduino LiquidCrystal Library
Next, let's initialize that nice LCD module:
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Please feel free to scramble the pins at your will in order to obtain a nice wiring layout: don't follow me in this, as I did a terrible wiring plan! :D For instance, you can reverse the latter four pins in the above statement in order to avoid the yellow wires crossing you can see in the schematic below (obviously, you'll have to adjust the button pin constants accordingly, see below). Play, have fun! The life with Arduinos starts right after that copy/paste!
The next 51 code lines contain the static variables declaration and initialization. Please feel free to browse them, their crystal-clear names and some scattered comments will guide you understanding the whole thing.
The setup() function carries out the usual preliminary steps you've seen gazillions of times in any Arduino sketch out there and so far. The only notable statement is the first, which will set the initial LCD display cursor's position. Because, yes: this module requires you to setup a position along its rows and cols and then to "print" something, which will appear starting from that position.
Now let's move to the loop() function.
First of all, let's discover the switch statuses. In order to achieve this, the following code block is used for nearly each of them:
* Start/Stop button management
startStopButtonPressed = false;
startStopButtonState = digitalRead(startStopButtonPin);
if(startStopButtonState != startStopButtonPrevState)
startStopButtonPressed = startStopButtonState == HIGH;
startStopButtonPrevState = startStopButtonState;
A digitalRead is issued against the related pin and the result is compared to a previously readed value: if something has changed, the new value is stored for future reference and the bool "xxxButtonPressed" static variable is set to true if the button is pressed.
Looking at the circuit diagram below, you'll notice that each input pin is forced to LOW by a 10k resistor unless the corresponding switch is pressed and the pin itself is directly connected to +5V. A fairly classic scenario, uh?
Previously, I said "nearly each of them" because there's one button that acts in a different way than the others: S4. Its code block is capable of detecting the aforementioned long press in order to enter SETUP mode.
Next comes the mode management block switch: each case looks at the button state triggers ("xxxButtonPressed") and redirects the flow toward the proper new state, or performs the proper action.
currentMode = MODE_SETUP;
currentMode = currentMode == MODE_IDLE ? MODE_RUNNING : MODE_IDLE;
if(currentMode == MODE_RUNNING)
// STARTING TIMER!
startTime = now();
The previous code snippet shows how the IDLE mode is managed, and it's pretty self-explanatory. Another example shows how any button press while ringing will stop it:
if(resetButtonPressed || startStopButtonPressed || downButtonPressed || upButtonPressed)
currentMode = MODE_IDLE;
Looks easy, isn't it? :-) It is.
The next block - "Time management" - performs the actual time difference calculation, triggers the RINGING mode and actually rings the buzz when it's time to do so.
The last block - "LCD management" - manages the LCD display for each mode by printing the proper strings at their proper locations.
Now that this little puppy has no more secrets to you, let's see it in action. Thanks for watching, and have fun!