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
制造商零件编号 3128
0.54" 4-DIGIT 14-SEGMENT BLUE
Adafruit Industries LLC
制造商零件编号 MJTP1230
SWITCH TACTILE SPST-NO 0.05A 12V
APEM Inc.
制造商零件编号 CF14JT2K20
RES 2.2K OHM 5% 1/4W AXIAL
Stackpole Electronics Inc
制造商零件编号 PS1240P02BT
BUZZER PIEZO 3V 12.2MM TH
TDK Corporation
制造商零件编号 MIKROE-1097
BREADBOARD TERMINAL STRIP
MikroElektronika
制造商零件编号 BC-32626
JUMPER KIT VARIOUS 140PCS
Bud Industries
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