Arduino Keypad Countdown Timer with Rainbow Alarm & Tilt Shutoff
Flip the clock.
Devices & Components
1
Arduino Uno Rev3
1
85dBA Piezo Transducer (Speaker)
1
NeoPixel Ring - 24 x 5050 RGB LED with Integrated Drivers
1
3x4 Matrix Keypad
1
Tilt Sensor
1
Adafruit 7-Segment LED Matrix Backpack
Software & Tools
Arduino IDE
Project description
Code
Tilt Clock Code
cpp
1#include <Adafruit_NeoPixel.h> 2#include <Keypad.h> 3#include <Adafruit_LEDBackpack.h> 4 5const byte ROWS = 4; 6const byte COLS = 3; 7const int LED = 4; 8const int NUM_PIXELS = 24; 9const char KEYMAP[ROWS][COLS] = 10{ 11 {'1', '2', '3'}, 12 {'4', '5', '6'}, 13 {'7', '8', '9'}, 14 {'*', '0', '#'}, 15}; 16 17String input = ""; 18const int TILT = A0; 19int isTilt = 0; 20 21byte ROW_PINS[ROWS] = {13, 12, 11, 10}; 22byte COL_PINS[COLS] = {9, 8, 7}; 23 24Keypad keypad = Keypad(makeKeymap(KEYMAP), ROW_PINS, COL_PINS, ROWS, COLS); 25Adafruit_7segment display = Adafruit_7segment(); 26Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED, NEO_GRB + NEO_KHZ800); 27 28// Timer Variables 29long totalSeconds = 0; 30bool timerRunning = false; 31unsigned long lastTick = 0; 32 33// Alarm State Variables 34bool alarmActive = false; // Tracks if the alarm is currently going off 35const int SPEAKER = 6; 36 37void setup() 38{ 39 pinMode(TILT, INPUT); 40 pinMode(SPEAKER, OUTPUT); 41 Serial.begin(9600); 42 display.begin(); 43 updateDisplay(0); 44 pixels.begin(); 45 pixels.setBrightness(150); 46 pixels.show(); 47} 48 49void loop() 50{ 51 char key = keypad.getKey(); 52 53 // Read the tilt sensor state continuously 54 if (analogRead(TILT) == 1013) { 55 isTilt = 0; 56 } else { 57 isTilt = 1; 58 } 59 60 // --- TILT SENSOR ALARM TURN OFF --- 61 // If the alarm is currently blasting and the tilt sensor is triggered (isTilt == 1), shut everything down and reset. 62 if (alarmActive && isTilt == 1) { 63 resetTimer(); 64 alarmActive = false; 65 noTone(SPEAKER); // Stop the sound 66 clearPixels(); 67 Serial.println("Alarm turned off via Tilt Sensor!"); 68 } 69 70 if (key != NO_KEY) { 71 tone(SPEAKER, 350, 40); 72 // CASE 1: Numeric input (Only if timer/alarm isn't active) 73 if (key >= '0' && key <= '9' && !timerRunning && !alarmActive && input.length() < 4) { 74 input += key; 75 updateDisplay(input.toInt()); 76 } 77 78 // CASE 2: '#' Starts the countdown 79 else if (key == '#' && !timerRunning && !alarmActive && input.length() > 0) { 80 int targetTime = input.toInt(); 81 int minutes = targetTime / 100; 82 int seconds = targetTime % 100; 83 84 totalSeconds = (minutes * 60) + seconds; 85 86 if (totalSeconds > 0) { 87 timerRunning = true; 88 lastTick = millis(); 89 Serial.println("Timer Started!"); 90 } 91 } 92 93 // CASE 3: '*' Resets everything 94 else if (key == '*') { 95 resetTimer(); 96 alarmActive = false; 97 noTone(SPEAKER); 98 clearPixels(); 99 Serial.println("Timer Reset."); 100 } 101 } 102 103 // TIMER TICK LOGIC 104 if (timerRunning) { 105 if (millis() - lastTick >= 1000) { 106 lastTick += 1000; 107 totalSeconds--; 108 109 int displayMinutes = totalSeconds / 60; 110 int displaySeconds = totalSeconds % 60; 111 int displayTime = (displayMinutes * 100) + displaySeconds; 112 113 updateDisplay(displayTime); 114 115 // Check if time is up 116 if (totalSeconds <= 0) { 117 timerRunning = false; 118 alarmActive = true; // Trigger the alarm state! 119 Serial.println("TIME IS UP! Alarm Active. Tilt device to stop."); 120 } 121 } 122 } 123 124 // ALARM BEHAVIOR LOGIC 125 // If the alarm is active, run alert loop 126 if (alarmActive) { 127 // Flash the display "0000" on and off every 250ms using millis 128 if ((millis() / 250) % 2 == 0) { 129 display.clear(); 130 display.writeDisplay(); 131 noTone(SPEAKER); 132 } else { 133 updateDisplay(0); 134 tone(SPEAKER, 1000); 135 } 136 long firstPixelHue = (millis() * 250); // Multiply to adjust the spinning speed (higher = faster) 137 138 for (int i = 0; i < NUM_PIXELS; i++) { 139 // Calculate a unique hue value for each pixel around the 24-LED ring 140 int pixelHue = firstPixelHue + (i * 65536L / NUM_PIXELS); 141 pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(pixelHue))); 142 } 143 pixels.show(); 144 } 145} 146 147void updateDisplay(int value) { 148 display.print(value, DEC); 149 if (timerRunning) { 150 display.drawColon(true); 151 } else { 152 display.drawColon(false); 153 } 154 display.writeDisplay(); 155} 156 157void resetTimer() { 158 timerRunning = false; 159 input = ""; 160 totalSeconds = 0; 161 updateDisplay(0); 162} 163 164void clearPixels() { 165 for (int i = 0; i < NUM_PIXELS; i++) { 166 pixels.setPixelColor(i, pixels.Color(0, 0, 0)); 167 } 168 pixels.show(); 169}
Comments
Only logged in users can leave comments