Maker.io main logo

How to Build a Connected Kitchen Timer using the Arduino IoT Cloud

2022-04-19 | By Maker.io Staff

License: See Original Project

Kitchen timers are an absolute necessity for everyone serious about their cooking and baking. ‎Besides other things, these handy little helpers remind you to take that cake out of the oven ‎before it burns. However, as simple conventional kitchen timers are, they also lack some ‎features that can come in handy, especially when you do other household tasks while waiting for ‎the oven. ‎

For one, conventional timers don’t let you check the remaining time from a distance, and you ‎also can’t extend the timer without having to access it physically. Therefore, this article discusses ‎a simple beginner-friendly connected kitchen timer that lets you access most of its features from ‎an online dashboard as well as the physical device itself.‎

BOM

Part/Qty.

The Schematic Diagram‎

The schematic diagram of this project is relatively simple, as the HT16K33 display module ‎communicates with the Arduino via I2C. Therefore, you only need to connect the Arduino to the ‎module using four wires: two for data and two for supplying the module with power. Additionally, ‎the circuit contains four tactile switches that let users set the time, start the timer, and pause it if ‎necessary. Lastly, the timer also includes a small piezo beeper that lets users know when the ‎countdown reaches zero.

 

This image shows the schematic diagram of this project.

Other than the active components, the schematic diagram also contains the four 2.2K pull-down ‎resistors for the four tactile pushbuttons. You can conveniently assemble the project on any ‎medium-size breadboard:‎

All components neatly fit on a medium-size breadboard

All components neatly fit on a regular medium-size breadboard.‎

Configuring the Arduino IoT Cloud‎

This project contains a few features that users can access from an interactive, web-based ‎interface using any modern web browser. I chose to connect the Arduino Nano 33 IoT to the ‎Arduino IoT cloud, as that solution offers fantastic reliability and incredible customizability. The ‎cloud service also provides all the features this project requires. However, this article won’t go ‎into the details of setting up new devices and the basics of configuring the Arduino IoT cloud. ‎Instead, it assumes that you already know the basics and the terms used in the cloud application. ‎You can refer to another article to learn more about setting up devices and creating projects on ‎the Arduino IoT cloud website!‎

Head over to the Arduino IoT cloud website and create a new thing to start the project. Then, link ‎a previously connected device to the newly created thing and enter your network credentials. ‎Next, create these four variables:‎

iot

Create four variables, enter your network credentials, and select a valid device in the new ‎thing’s dashboard in the Arduino IoT cloud.‎

The two boolean variables will allow users to start, stop, and pause the timer from the web ‎interface, and the two integers let users see the current remaining time and set a new time if ‎necessary. Set the permissions of all variables to “Read & Write.”‎

Navigate to the Arduino IoT cloud dashboards page and set up a new dashboard for the thing ‎you just created. Place two pushbuttons, one slider, and a value widget on the dashboard. Link ‎the two buttons to the boolean variables you created earlier. These buttons will allow users to ‎start, stop, and pause the timer without having to access the physical device. Then, link the slider ‎to the setTimerValue variable. Lastly, make the value widget display the secondsRemaining ‎variable. You can arrange and scale the widgets as you like:‎

dashboard

Your dashboard should look similar to this. However, feel free to arrange and scale the widgets ‎according to your needs.‎

The Firmware Code‎

Navigate to the source code view once you set up the thing and the dashboard within the ‎Arduino IoT cloud application. There you can see that the Arduino IoT cloud has already ‎generated some source code for synchronizing the shared variables with the cloud. In addition, ‎the Arduino sketch contains a few auto-generated functions that the MCU calls whenever the ‎user updates one of the variables (including the button states) in the online interface. Therefore, ‎you can use the onPauseTimerChange() and onStartTimerChange() methods to detect which of ‎the buttons a user interacted with on the web interface:‎

screenshot

This screenshot shows the two functions responsible for transmitting button presses from the ‎web interface to the Arduino board. The screenshot only shows sample code not present in the ‎finished firmware source code.‎

The onSetTimerValueChange function is the only other callback the program utilizes. The ‎firmware uses this function to update the 14-segment display when the user changes the timer ‎value in the online dashboard.‎

Besides the synchronization callback functions, the firmware code contains a few more helper ‎methods:‎

Copy Code
void doBeep(void)
{
unsigned long currentMillis = millis();

if(currentMillis - lastMillisBeepUpdate > BEEP_DELAY)
{
if(!buzzerOn)
{
tone(SPEAKER_PIN, 1000);
buzzerOn = true;
}
else
{
tone(SPEAKER_PIN, 0);
buzzerOn = false;
}

lastMillisBeepUpdate = currentMillis;
}
}

void doTimerUpdate(void)
{
unsigned long currentMillis = millis();

if(currentMillis - lastMillisTimerUpdate > 1000)
{
if(!timerPaused)
{
secondsRemaining -= 1;
lastMillisTimerUpdate = currentMillis;
writeToDisplay(secondsRemaining);
}
else
{
if(displayOn)
{
disp.clear();
disp.writeDisplay();
displayOn = false;
}
else
{
writeToDisplay(secondsRemaining);
displayOn = true;
}

lastMillisTimerUpdate = currentMillis;
}

if(secondsRemaining <= 0)
mode = 2;
}
}

void doPhysicalButtonUpdate(void)
{
unsigned long currentMillis = millis();

if(currentMillis - lastMillis > DEBOUNCE_DELAY && !lastUpdateButtonDown)
{
if(mode == 0 && plusButtonDown)
{
setTimerValue = (setTimerValue + TIMER_INCREASE_VALUE > TIMER_MAX_VALUE) ? TIMER_MAX_VALUE : setTimerValue + TIMER_INCREASE_VALUE;
writeToDisplay(setTimerValue);
}
else if(mode == 0 && minusButtonDown)
{
setTimerValue = (setTimerValue - TIMER_INCREASE_VALUE < 0) ? 0 : setTimerValue - TIMER_INCREASE_VALUE;
writeToDisplay(setTimerValue);
}
else if(startButtonDown)
{
if(mode == 0)
{
activateTimer(setTimerValue);
}
else if(mode == 1)
{
deactivateTimer();
}
else if(mode == 2)
{
stopBuzzer();
}
}
else if(mode == 1 && pauseButtonDown && timerActive)
{
timerPaused = !timerPaused;
}

lastUpdateButtonDown = startButtonDown || pauseButtonDown || plusButtonDown || minusButtonDown;
lastMillis = currentMillis;
}
}

void writeToDisplay(int num)
{
int a = num / 1000;
int b = (num - a * 1000) / 100;
int c = (num - a * 1000 - b * 100) / 10;
int d = (num - a * 1000 - b * 100 - c * 10);

disp.writeDigitAscii(0, (char)(48 + a));
disp.writeDigitAscii(1, (char)(48 + b));
disp.writeDigitAscii(2, (char)(48 + c));
disp.writeDigitAscii(3, (char)(48 + d));
disp.writeDisplay();
}

void stopBuzzer(void)
{
writeToDisplay(setTimerValue);
tone(SPEAKER_PIN, 0);
mode = 0;
}

The doPhysicalButtonUpdate function checks if the user pressed any of the four physical ‎buttons on the timer device. It only reacts to button inputs if enough time has elapsed since the ‎function last detected and processed an input. The mode variable defines how the program ‎should handle user inputs. If the device is in mode zero, it reacts to the user pressing the plus and ‎minus buttons to increase or decrease the currently set time. If the user presses the start button, ‎the software starts the timer (if the mode variable is zero), stops the timer (if the mode variable is ‎one), or stops the beeping (if the device is in mode two).‎

The writeDisplay function is a straightforward helper method that splits a number into individual ‎digits before sending each of them to the 14-segment display. Note that the display accepts ‎ASCII characters. Therefore, the code offsets the value sent to the display by 48, as the number ‎‎48 represents the character for the number zero. You can read this article to learn more about ‎the HT16K33 display driver.‎

Next, the doTimerUpdate function counts down the remaining time every second as long as the ‎user doesn’t pause the countdown. Once the countdown reaches zero, the device switches to ‎mode two and starts beeping to alert the user. If the user pauses the countdown, the firmware ‎starts flashing the display to indicate that the countdown got paused.‎

Lastly, the doBeep helper function turns the piezo speaker on and off periodically once the timer ‎reaches zero. It does that by calling the standard tone function that outputs a static waveform to ‎the pin attached to the piezo speaker. Finally, the stopBuzzer helper method resets the 14-‎segment display, turns off the speaker, and switches the firmware back to mode zero. The ‎update method uses this mode variable to determine how it should react to user inputs and how ‎to update certain variables:‎

Copy Code
void loop()
{
ArduinoCloud.update();

startButtonDown = digitalRead(START_BTN);
pauseButtonDown = digitalRead(PAUSE_BTN);
plusButtonDown = digitalRead(PLUS_BTN);
minusButtonDown = digitalRead(MINUS_BTN);

doPhysicalButtonUpdate();

if(mode == 1)
{
Serial.println("Update mode 1");
doTimerUpdate();
}
else if(mode == 2)
{
doBeep();
}

if(!startButtonDown && !pauseButtonDown && !plusButtonDown && !minusButtonDown)
lastUpdateButtonDown = false;
}

Due to the previously discussed helper functions, the loop method of the firmware program is ‎short and easy to understand. The program first updates the synchronized variables with the ‎Arduino IoT cloud. Then, it checks whether the user pressed any of the physical buttons before ‎calling the doPhysicalButtonUpdate helper function that processes the inputs. Then, the loop ‎function either updates the countdown or starts beeping, depending on the current program state. ‎Finally, the last line of the update function ensures that the device doesn’t detect the same button ‎press multiple times, for example, when a user pushes the button down for a prolonged period.‎

finish

This image shows the finished timer device in action.‎

Lastly, the setup function initializes the serial monitor, the Arduino IoT cloud variables, the GPIO ‎pins, and the 14-segment display:‎

Copy Code
void setup()
{
// Initialize serial and wait for port to open:
Serial.begin(9600);

// Defined in thingProperties.h
initProperties();

// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);

// Init GPIO
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(PAUSE_BTN, INPUT);
pinMode(MINUS_BTN, INPUT);
pinMode(PLUS_BTN, INPUT);
pinMode(START_BTN, INPUT);

// Init display
disp.begin(DISPLAY_ADDRESS);
disp.setBrightness(4);
disp.clear();
disp.writeDisplay();
}

Follow this link to download the complete firmware source code.‎

Conclusion‎

This article discussed a simple connected kitchen timer build perfect for beginners and hobbyists ‎starting with IoT projects. However, more experienced makers can add multiple other features ‎that enhance the finished project, for example, a custom 3D-printed enclosure that houses the ‎electronic components.‎

The hardware consists of an Arduino Nano 33 IoT development board, four tactile pushbuttons, a ‎small piezo speaker, a 14-segment display, and passive components such as resistors. I ‎assembled the parts using a standard solderless breadboard.‎

The software part of the project starts with setting up the necessary variables and dashboard ‎widgets in the Arduino IoT cloud. All the features presented in this article work with the free plan ‎of the Arduino IoT cloud, as the firmware only requires four synchronized variables. The ‎dashboard lets users view the remaining time and set new timers and stop an active countdown. ‎The Arduino IoT cloud automatically generates source code, and this project's firmware builds ‎upon that base. The code might look complicated at first, but that is mainly due to several ‎smaller helper methods that handle recurring tasks such as parsing user input, advancing the ‎timer, and printing characters to the 14-segment display. However, the standard setup and loop ‎methods are relatively short, as they only call the helper functions in the correct order.

制造商零件编号 ABX00032
ARDUINO NANO 33 IOT WITH HEADERS
Arduino
¥219.78
Details
制造商零件编号 3128
0.54" 4-DIGIT 14-SEGMENT BLUE
Adafruit Industries LLC
¥117.54
Details
制造商零件编号 MJTP1230
SWITCH TACTILE SPST-NO 0.05A 12V
APEM Inc.
¥1.79
Details
制造商零件编号 CF14JT2K20
RES 2.2K OHM 5% 1/4W AXIAL
Stackpole Electronics Inc
¥0.81
Details
制造商零件编号 PS1240P02BT
BUZZER PIEZO 3V 12.2MM TH
TDK Corporation
¥4.72
Details
制造商零件编号 MIKROE-1097
BREADBOARD TERMINAL STRIP
MikroElektronika
¥75.75
Details
制造商零件编号 BC-32626
JUMPER KIT VARIOUS 140PCS
Bud Industries
¥88.93
Details
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum