Kitchen timer
Create a timer that can be used to time boiling pasta, board-game turns, or cookies in the oven. Create and explore a playful interface with flashy lights and a buzzer alarm!
Components and supplies
1
Modulino® Distance
1
Modulino Kitchen timer bundle UNO R4 WiFi
1
Modulino® Buzzer
1
Modulino Pixels
1
Modulino® Knob
1
Modulino Kitchen timer bundle Nano R4
Apps and platforms
1
Arduino IDE 2.0
Project description
Code
Main sketch
c
Main sketch to upload to your board
1#include <Modulino.h> 2 3#if defined(ARDUINO_UNOR4_WIFI) 4#include <Arduino_LED_Matrix.h> 5#include "animation.h" //Include animation.h header file 6 7ArduinoLEDMatrix matrix; 8#endif 9 10// Telling the program what Sensors we are going to use. 11ModulinoKnob knob; 12ModulinoPixels pixels; 13ModulinoBuzzer buzzer; 14 15// Used for Hands-free control 16ModulinoDistance distance; 17 18// Variables used for Flipping control 19/* 20ModulinoMovement movement; 21float x; 22bool flipDetected = false; 23unsigned long lastFlipTime = 0; 24const int FLIP_THRESHOLD = 1; 25int lastX = 0; 26*/ 27 28// This variable tracks the state our hourglass is in. 29int state = 0; 30 31// This variable is used to store a reference point to the time when we start the hourglass enters its "timing" state 32unsigned long timerStarted; 33 34// These variables are used to determine which direction you turn the knob. 35int lastKnobVal = 0; 36int currentKnobVal = 0; 37 38bool buttonPress; 39int minutes = 0; 40 41bool lastKnobPress = false; 42 43// Variables for distance sensor hand-wave detection 44int lastDistance = 0; 45bool handWaveDetected = false; 46unsigned long lastWaveTime = 0; 47const int WAVE_THRESHOLD = 30; // Distance threshold in mm 48const int WAVE_COOLDOWN = 1000; // Minimum time between wave detections (ms) 49 50// Variables for fade animation 51unsigned long fadeStartTime = 0; 52const int FADE_DURATION = 2000; // Total fade cycle duration in ms 53const int FADE_MIN_BRIGHTNESS = 10; // Brightness 0-100 54const int FADE_MAX_BRIGHTNESS = 100; // Brightness 0-100 55 56void setup() { 57 Serial.begin(9600); 58 delay(1500); 59 60 // Looks for the Modulinos on the Qwiic connector and connects to them. 61 Modulino.begin(); 62 63 knob.begin(); 64 pixels.begin(); 65 buzzer.begin(); 66 distance.begin(); 67 68 // Used for Flipping control 69 // movement.begin(); 70 71#if defined(ARDUINO_UNOR4_WIFI) 72 matrix.begin(); 73#endif 74} 75 76void loop() { 77 78 bool currentlyPressed = knob.isPressed(); 79 80 // To make sure the program only registers one press we only act when the state changes 81 if (lastKnobPress == false && currentlyPressed == true) { 82 buttonPress = true; 83 } 84 lastKnobPress = currentlyPressed; 85 86 // Check for hand wave gesture 87 checkHandWave(); 88 89 // Check for device flip 90 // checkFlip(); 91 92 minutes = minutes + readKnob(); 93 94 // Keep the minutes value within the range 95 if (minutes < 0) { 96 minutes = 0; 97 } 98 if (minutes > 24) { 99 minutes = 24; 100 } 101 102 // State machine 103 if (state == 0) { 104 // Idle state 105 if (buttonPress) { 106 state = 1; 107 timerStarted = millis(); 108#if defined(ARDUINO_UNOR4_WIFI) 109 startAnimation(); 110#endif 111 } 112 } else if (state == 1) { 113 // Timing state 114 if (millis() - timerStarted > 60000) { 115 // This code will run once every minute after the timer starts 116 timerStarted = millis(); 117 minutes = minutes - 1; 118 } 119 if (minutes <= 0) { 120#if defined(ARDUINO_UNOR4_WIFI) 121 stopAnimation(); 122#endif 123 fadeStartTime = millis(); // Start fade animation 124 state = 2; 125 } 126 if (buttonPress || handWaveDetected) { 127#if defined(ARDUINO_UNOR4_WIFI) 128 pauseAnimation(); 129#endif 130 fadeStartTime = millis(); // Start fade animation 131 state = 3; // Paused state 132 } 133 } else if (state == 2) { 134 // Alarm state 135 buzzer.tone(800 - 200 * sin(millis()), 100); 136 fadePixels(); // Update fade animation 137 if (buttonPress || handWaveDetected) { 138 state = 0; 139 } 140 } else if (state == 3) { 141 // Paused state 142 fadePixels(); // Update fade animation 143 if (buttonPress || handWaveDetected) { 144 state = 1; 145 timerStarted = millis(); 146#if defined(ARDUINO_UNOR4_WIFI) 147 startAnimation(); 148#endif 149 } 150 } 151 152 buttonPress = false; 153 handWaveDetected = false; // Reset hand wave flag 154 155 // Only update normal pixel display if not in paused or alarm state 156 if (state != 3 && state != 2) { 157 turnOnPixels(); 158 } 159} 160 161void checkHandWave() { 162 // Read current distance 163 int currentDistance; 164 if(distance.available()){ 165 currentDistance = distance.get(); 166 } 167 168 // Check if enough time has passed since last wave detection (debouncing) 169 if (millis() - lastWaveTime > WAVE_COOLDOWN) { 170 // Detect if hand moved close (within threshold) from farther away 171 if (currentDistance < WAVE_THRESHOLD && lastDistance >= WAVE_THRESHOLD) { 172 handWaveDetected = true; 173 buttonPress = true; 174 lastWaveTime = millis(); 175 Serial.println("Hand wave detected!"); 176 } 177 } 178 179 lastDistance = currentDistance; 180} 181 182 183// Function to check if the device is flipped 184/* 185void checkFlip() { 186 187 movement.update(); 188 x = movement.getX(); 189 190 // Check if enough time has passed since last flip (debouncing) 191 if (millis() - lastFlipTime > WAVE_COOLDOWN) { 192 // Detect if device is flipped (within threshold) 193 if (x < FLIP_THRESHOLD && lastX >= FLIP_THRESHOLD) { 194 flipDetected = true; 195 buttonPress = true; 196 lastFlipTime = millis(); 197 Serial.println("Flip detected!"); 198 } 199 } 200 201 lastX = x; 202} 203*/ 204 205void fadePixels() { 206 // Calculate elapsed time since fade started 207 unsigned long elapsedTime = millis() - fadeStartTime; 208 209 // Calculate position in the fade cycle (0 to 1) 210 float fadeProgress = (float)(elapsedTime % FADE_DURATION) / FADE_DURATION; 211 212 // Calculate brightness using sine wave for smooth fade (0 to 1) 213 float brightness = 0.5 + 0.5 * sin(fadeProgress * 2 * PI - PI / 2); 214 215 // Map brightness to LED brightness range (0-100) 216 int ledBrightness = FADE_MIN_BRIGHTNESS + (int)(brightness * (FADE_MAX_BRIGHTNESS - FADE_MIN_BRIGHTNESS)); 217 218 // Update all pixels with fade brightness 219 pixels.clear(); 220 221 for (int i = 0; i < minutes; i++) { 222 if (i >= 0 && i < 8) { 223 pixels.set(i, BLUE, ledBrightness); 224 } 225 } 226 227 int howManyGreen = 0; 228 if (minutes > 8) { 229 howManyGreen = minutes - 8; 230 } 231 for (int i = 0; i < howManyGreen; i++) { 232 if (i >= 0 && i - 1 < 8) { 233 pixels.set(i, GREEN, ledBrightness); 234 } 235 } 236 237 int howManyRed = 0; 238 if (minutes > 16) { 239 howManyRed = minutes - 16; 240 } 241 for (int i = 0; i < howManyRed; i++) { 242 if (i >= 0 && i - 1 < 8) { 243 pixels.set(i, RED, ledBrightness); 244 } 245 } 246 247 pixels.show(); 248} 249 250int readKnob() { 251 lastKnobVal = currentKnobVal; 252 currentKnobVal = knob.get(); 253 254 if (currentKnobVal > lastKnobVal) { 255 return 1; 256 } else if (currentKnobVal < lastKnobVal) { 257 return -1; 258 } else { 259 return 0; 260 } 261} 262 263void turnOnPixels() { 264 int howManyGreen = 0; 265 if (minutes > 8) { 266 howManyGreen = minutes - 8; 267 } 268 269 int howManyRed = 0; 270 if (minutes > 16) { 271 howManyRed = minutes - 16; 272 } 273 274 pixels.clear(); 275 276 for (int i = 0; i < minutes; i++) { 277 if (i >= 0 && i < 8) { 278 pixels.set(i, BLUE, 100); 279 } 280 } 281 for (int i = 0; i < howManyGreen; i++) { 282 if (i >= 0 && i - 1 < 8) { 283 pixels.set(i, GREEN, 100); 284 } 285 } 286 for (int i = 0; i < howManyRed; i++) { 287 if (i >= 0 && i - 1 < 8) { 288 pixels.set(i, RED, 100); 289 } 290 } 291 292 pixels.show(); 293} 294 295#if defined(ARDUINO_UNOR4_WIFI) 296void startAnimation() { 297 matrix.loadSequence(hourglass); 298 matrix.play(true); 299} 300void pauseAnimation() { 301 matrix.loadSequence(pause); 302 matrix.play(true); 303} 304void stopAnimation() { 305 const uint32_t clear2[] = { 306 0x00000000, 307 0x00000000, 308 0x00000000 309 }; 310 matrix.loadFrame(clear2); 311} 312#endif
animation.h
c
File for LED matrix animations
1uint32_t hourglass[][4] = { 2 { 3 0xe07f99fe, 4 0x1fc1fc1f, 5 0xe1f99e07, 6 66 7 }, 8 { 9 0xe07f99fe, 10 0x1ff1fc1f, 11 0xe1f99e07, 12 66 13 }, 14 { 15 0xe07f99fe, 16 0x1ffdfc1f, 17 0xe1f99e07, 18 66 19 }, 20 { 21 0xe07f99fe, 22 0x1ffffc1f, 23 0xe1f99e07, 24 66 25 }, 26 { 27 0xe07f99fe, 28 0x1ffffc3f, 29 0xe1f99e07, 30 66 31 }, 32 { 33 0xe07f99fe, 34 0x1bfffc3f, 35 0xe1f99e07, 36 66 37 }, 38 { 39 0xe07f99fe, 40 0x3bffbc3f, 41 0xe1f99e07, 42 66 43 }, 44 { 45 0xe07f9bfe, 46 0x3bffbc3b, 47 0xe1f99e07, 48 66 49 }, 50 { 51 0xe07f9bfe, 52 0x3bffbc3b, 53 0xe3f99e07, 54 66 55 }, 56 { 57 0xe07f9bbe, 58 0x3bffbc3b, 59 0xe3f9be07, 60 66 61 }, 62 { 63 0xe07b9bbe, 64 0x3bffbc7b, 65 0xe3f9be07, 66 66 67 }, 68 { 69 0xe07b9bbe, 70 0x3bffbc7b, 71 0xe7b9be07, 72 66 73 }, 74 { 75 0xe07b9bbe, 76 0x39ffbc7b, 77 0xe7b9be07, 78 66 79 }, 80 { 81 0xe07b9bbe, 82 0x79ff9c7b, 83 0xe7b9be07, 84 66 85 }, 86 { 87 0xe07b9bbe, 88 0x79ff9c79, 89 0xe7b9fe07, 90 66 91 }, 92 { 93 0xe07b9f9e, 94 0x79ff9c79, 95 0xe7b9fe07, 96 66 97 }, 98 { 99 0xe07b9f9e, 100 0x78ff9cf9, 101 0xe7b9fe07, 102 66 103 }, 104 { 105 0xe0799f9e, 106 0xf8ff8cf9, 107 0xe799fe07, 108 66 109 }, 110 { 111 0xe0799f8e, 112 0xf8ff8cf8, 113 0xef99fe07, 114 66 115 }, 116 { 117 0xe0799f87, 118 0xf87f87f8, 119 0x7f99fe07, 120 66 121 }, 122 { 123 0xe0799f87, 124 0xf83f83f8, 125 0x7f99fe07, 126 66 127 } 128}; 129const uint32_t pause[][4] = { 130 { 131 0x6001, 132 0x2082081, 133 0x100e0000, 134 66 135 }, 136 { 137 0x8011, 138 0x2082081, 139 0x100e0000, 140 66 141 }, 142 { 143 0xe010, 144 0x2002081, 145 0x100e0000, 146 66 147 }, 148 { 149 0xe011, 150 0x2082001, 151 0xe0000, 152 66 153 }, 154 { 155 0xe011, 156 0x2082081, 157 0x10080000, 158 66 159 }, 160 { 161 0xe011, 162 0x2082080, 163 0x10060000, 164 66 165 }, 166 { 167 0xe011, 168 0x80081, 169 0x100e0000, 170 66 171 } 172};
Comments
Only logged in users can leave comments