{"id":52356,"date":"2026-11-01T10:51:00","date_gmt":"2026-11-01T10:51:00","guid":{"rendered":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/"},"modified":"2026-11-01T10:51:00","modified_gmt":"2026-11-01T10:51:00","slug":"smart-alarm-clock","status":"publish","type":"siratek_tutorial","link":"https:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/","title":{"rendered":"Project, a Smart Alarm Clock"},"content":{"rendered":"<body><p><\/p>\n<h2>What you will build<\/h2>\n<p>A clock that shows the time on a 16\u00d72 display, lets you set an alarm with buttons, and wakes you with a tune. Press to snooze, hold to stop.<\/p>\n<p>It is the most interactive project in the library, and that is what it teaches. The others read sensors and report; this one has to <strong>listen to a person<\/strong>, which means a menu, buttons that behave differently on a press and a hold, and a display that shows the right thing at the right time.<\/p>\n<h2>Before you begin<\/h2>\n<h3>Parts<\/h3>\n<table>\n<thead>\n<tr>\n<th>Part<\/th>\n<th>Siratek product<\/th>\n<th>Its own tutorial<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Arduino Uno<\/td>\n<td>2219<\/td>\n<td><em>Getting Started with Arduino Uno<\/em><\/td>\n<\/tr>\n<tr>\n<td>16\u00d72 LCD with I2C backpack<\/td>\n<td>2484<\/td>\n<td><em>A 16\u00d72 LCD over I2C<\/em><\/td>\n<\/tr>\n<tr>\n<td>DS3231 real time clock<\/td>\n<td>2522<\/td>\n<td><em>Keeping Time with a DS3231<\/em><\/td>\n<\/tr>\n<tr>\n<td>Passive buzzer<\/td>\n<td>8051<\/td>\n<td><em>Play Tones with a Passive Buzzer<\/em><\/td>\n<\/tr>\n<tr>\n<td>Three tactile push buttons<\/td>\n<td>49488<\/td>\n<td><em>Read a Push Button<\/em><\/td>\n<\/tr>\n<tr>\n<td>Breadboard and jumper wires<\/td>\n<td><\/td>\n<td><em>Using a Breadboard<\/em><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Three buttons: <strong>Mode<\/strong>, <strong>Up<\/strong> and <strong>Down<\/strong>. All three wired to ground with <code>INPUT_PULLUP<\/code>, so no resistors are needed.<\/p>\n<h3>Two addresses on one bus<\/h3>\n<p>The display and the clock both sit on <code>A4<\/code> and <code>A5<\/code>. The display\u2019s backpack answers at <strong>0x27 or 0x3F<\/strong>, and the clock at <strong>0x68<\/strong>, so they do not clash.<\/p>\n<p>Run the bus scanner first and note which address your backpack uses. <em>A 16\u00d72 LCD over I2C<\/em> explains why it is a coin toss and why copying <code>0x27<\/code> from a tutorial is a poor idea.<\/p>\n<h3>Buttons are the hard part, not the clock<\/h3>\n<p>This is worth saying before you start, because it shapes the whole sketch.<\/p>\n<p>Reading a button is trivial. Making three buttons feel right is not, and a clock that is annoying to set is a clock nobody sets. Three behaviours are needed:<\/p>\n<ul>\n<li><strong>A press<\/strong>: a single, debounced action. Used for Mode, and for snooze.<\/li>\n<li><strong>A repeat<\/strong>: hold Up and the minutes should keep climbing, slowly at first then faster. Otherwise setting an alarm for 06:45 means forty-five separate presses.<\/li>\n<li><strong>A long hold<\/strong>: distinct from a press. Used to stop the alarm, so a sleepy hand cannot cancel it by accident.<\/li>\n<\/ul>\n<p>All three come from one small piece of code, below, and that piece is the most reusable thing in this project.<\/p>\n<h2>How it works<\/h2>\n<h3>Modes<\/h3>\n<p>The clock is always in exactly one mode, and Mode cycles between them:<\/p>\n<table>\n<thead>\n<tr>\n<th>Mode<\/th>\n<th>Shows<\/th>\n<th>Up and Down<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>SHOW_TIME<\/code><\/td>\n<td>Time, date, alarm<\/td>\n<td>Nothing<\/td>\n<\/tr>\n<tr>\n<td><code>SET_ALARM_HOUR<\/code><\/td>\n<td>Alarm, hour flashing<\/td>\n<td>Change the hour<\/td>\n<\/tr>\n<tr>\n<td><code>SET_ALARM_MINUTE<\/code><\/td>\n<td>Alarm, minute flashing<\/td>\n<td>Change the minute<\/td>\n<\/tr>\n<tr>\n<td><code>SET_ALARM_ONOFF<\/code><\/td>\n<td>Alarm on or off<\/td>\n<td>Toggle it<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Pressing Mode from the last one returns to <code>SHOW_TIME<\/code> and saves. The same state-machine idea as the pedestrian crossing, with a person driving the transitions instead of a timer.<\/p>\n<h3>Ringing<\/h3>\n<p>When the alarm time arrives and the alarm is on, the clock enters a ringing state:<\/p>\n<ul>\n<li><strong>Press any button<\/strong>: snooze for nine minutes.<\/li>\n<li><strong>Hold Mode for two seconds<\/strong>: stop until tomorrow.<\/li>\n<li><strong>After ten minutes<\/strong> with no response: give up, so a clock in an empty house does not sound all day.<\/li>\n<\/ul>\n<p>The alarm fires on a <strong>minute match<\/strong>, and the sketch records which minute it fired in so it does not fire again within the same minute.<\/p>\n<h3>Remembering the alarm<\/h3>\n<p>The alarm setting is kept in the Uno\u2019s <strong>EEPROM<\/strong>, so it survives power being removed. Without that, every power cut loses the setting, which for a clock is most of the point.<\/p>\n<p>EEPROM has a finite write endurance, around a hundred thousand writes per location, so the sketch writes <strong>only when the setting changes<\/strong>, not on every loop. Writing in <code>loop()<\/code> would use that up in a day.<\/p>\n<h2>Pin reference<\/h2>\n<table>\n<thead>\n<tr>\n<th>Device<\/th>\n<th>Pin<\/th>\n<th>Connect to<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>LCD backpack<\/td>\n<td><code>GND<\/code>, <code>VCC<\/code><\/td>\n<td>Uno <code>GND<\/code>, <code>5V<\/code><\/td>\n<\/tr>\n<tr>\n<td>LCD backpack<\/td>\n<td><code>SDA<\/code>, <code>SCL<\/code><\/td>\n<td>Uno <code>A4<\/code>, <code>A5<\/code><\/td>\n<\/tr>\n<tr>\n<td>DS3231<\/td>\n<td><code>GND<\/code>, <code>VCC<\/code><\/td>\n<td>Uno <code>GND<\/code>, <code>5V<\/code><\/td>\n<\/tr>\n<tr>\n<td>DS3231<\/td>\n<td><code>SDA<\/code>, <code>SCL<\/code><\/td>\n<td>Uno <code>A4<\/code>, <code>A5<\/code><\/td>\n<\/tr>\n<tr>\n<td>Buzzer<\/td>\n<td><code>+<\/code><\/td>\n<td>Uno <code>D9<\/code><\/td>\n<\/tr>\n<tr>\n<td>Buzzer<\/td>\n<td><code>-<\/code><\/td>\n<td>Uno <code>GND<\/code><\/td>\n<\/tr>\n<tr>\n<td>Mode button<\/td>\n<td><\/td>\n<td>Uno <code>D2<\/code> to <code>GND<\/code><\/td>\n<\/tr>\n<tr>\n<td>Up button<\/td>\n<td><\/td>\n<td>Uno <code>D3<\/code> to <code>GND<\/code><\/td>\n<\/tr>\n<tr>\n<td>Down button<\/td>\n<td><\/td>\n<td>Uno <code>D4<\/code> to <code>GND<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<figure class=\"siratek-tutorial-figure\"><img decoding=\"async\" src=\"http:\/\/siratek.net\/wp-content\/uploads\/2026\/11\/smart-alarm-clock-wiring.svg\" alt=\"A clock with an LCD and a DS3231 sharing the I2C bus, three buttons to ground, and a buzzer, with the four modes the Mode button cycles through\" loading=\"lazy\"><figcaption>Two I2C devices at different addresses, three buttons using the internal pull-ups, and one buzzer.<\/figcaption><\/figure>\n<h2>Build it in stages<\/h2>\n<h3>Stage 1: scan, then show the time<\/h3>\n<p>Run the bus scanner and note both addresses. Then put the time on the display, with no buttons and no alarm. That alone is a working clock and proves the two hardest parts.<\/p>\n<p>Leave it running while you build the rest.<\/p>\n<h3>Stage 2: one button, printing to serial<\/h3>\n<p>Get the button helper below working with the Mode button and <code>Serial.print()<\/code>. Check that a press reports once, a hold repeats, and a long hold reports separately.<\/p>\n<p><strong>Do this before touching the display.<\/strong> Button behaviour is fiddly, and debugging it through a 16-character screen is miserable.<\/p>\n<h3>Stage 3: the modes<\/h3>\n<p>Add Up and Down, and the four modes, still printing to serial. Then put the modes on the display.<\/p>\n<h3>Stage 4: the alarm<\/h3>\n<p>Add the buzzer, the ringing state and the EEPROM. The complete sketch below.<\/p>\n<h2>The complete sketch<\/h2>\n<pre><code>\/\/ Siratek: a smart alarm clock.\n\/\/ LCD and DS3231 share I2C; three buttons to ground; a passive buzzer.\n\n#include &lt;Wire.h&gt;\n#include &lt;LiquidCrystal_I2C.h&gt;\n#include &lt;RTClib.h&gt;\n#include &lt;EEPROM.h&gt;\n\n\/\/ Use the address your scanner printed.\nLiquidCrystal_I2C lcd(0x27, 16, 2);\nRTC_DS3231 rtc;\n\nconst int buzzerPin = 9;\nconst int MODE_BTN = 2, UP_BTN = 3, DOWN_BTN = 4;\n\nconst int EEPROM_HOUR = 0, EEPROM_MINUTE = 1, EEPROM_ON = 2, EEPROM_MAGIC = 3;\nconst byte MAGIC = 0x5A;          \/\/ says \"these bytes are ours\"\n\nenum Mode { SHOW_TIME, SET_ALARM_HOUR, SET_ALARM_MINUTE, SET_ALARM_ONOFF };\nMode mode = SHOW_TIME;\n\nbyte alarmHour = 7, alarmMinute = 0;\nbool alarmOn = false;\nbool settingChanged = false;\n\nbool ringing = false;\nunsigned long ringingSince = 0;\nint firedInMinute = -1;           \/\/ so it fires once per minute, not repeatedly\n\nunsigned long lastDraw = 0;\n\n\/\/ ---------------------------------------------------------------- buttons\n\nstruct Button {\n  byte pin;\n  bool stable;                    \/\/ debounced level, true when pressed\n  unsigned long changedAt;\n  unsigned long pressedAt;\n  unsigned long lastRepeat;\n  bool longFired;\n};\n\nButton buttons[3];\n\nvoid setupButton(Button&amp; b, byte pin) {\n  pinMode(pin, INPUT_PULLUP);\n  b.pin = pin;\n  b.stable = false;\n  b.changedAt = b.pressedAt = b.lastRepeat = 0;\n  b.longFired = false;\n}\n\n\/\/ Returns: 0 nothing, 1 a press, 2 a repeat, 3 a long hold.\nbyte pollButton(Button&amp; b) {\n  bool now = (digitalRead(b.pin) == LOW);\n\n  if (now != b.stable) {\n    if (millis() - b.changedAt &lt; 30) {\n      return 0;                   \/\/ still bouncing\n    }\n    b.changedAt = millis();\n    b.stable = now;\n\n    if (now) {\n      b.pressedAt = millis();\n      b.lastRepeat = millis();\n      b.longFired = false;\n      return 1;                   \/\/ the moment of the press\n    }\n    return 0;                     \/\/ release\n  }\n\n  if (!b.stable) {\n    return 0;\n  }\n\n  unsigned long held = millis() - b.pressedAt;\n\n  if (held &gt; 2000 &amp;&amp; !b.longFired) {\n    b.longFired = true;\n    return 3;\n  }\n\n  \/\/ Repeat while held: slow at first, then faster.\n  if (held &gt; 600) {\n    unsigned long gap = (held &gt; 3000) ? 80 : 250;\n    if (millis() - b.lastRepeat &gt;= gap) {\n      b.lastRepeat = millis();\n      return 2;\n    }\n  }\n\n  return 0;\n}\n\n\/\/ ---------------------------------------------------------------- storage\n\nvoid loadAlarm() {\n  if (EEPROM.read(EEPROM_MAGIC) != MAGIC) {\n    \/\/ First run on this board: EEPROM holds whatever it held.\n    saveAlarm();\n    return;\n  }\n  alarmHour = EEPROM.read(EEPROM_HOUR);\n  alarmMinute = EEPROM.read(EEPROM_MINUTE);\n  alarmOn = EEPROM.read(EEPROM_ON) != 0;\n\n  if (alarmHour &gt; 23) alarmHour = 7;\n  if (alarmMinute &gt; 59) alarmMinute = 0;\n}\n\nvoid saveAlarm() {\n  \/\/ EEPROM.update writes only if the value differs, which saves the endurance.\n  EEPROM.update(EEPROM_HOUR, alarmHour);\n  EEPROM.update(EEPROM_MINUTE, alarmMinute);\n  EEPROM.update(EEPROM_ON, alarmOn ? 1 : 0);\n  EEPROM.update(EEPROM_MAGIC, MAGIC);\n}\n\n\/\/ ---------------------------------------------------------------- display\n\nvoid two(byte v) {\n  if (v &lt; 10) lcd.print('0');\n  lcd.print(v);\n}\n\nvoid draw() {\n  DateTime now = rtc.now();\n\n  lcd.setCursor(0, 0);\n  if (ringing) {\n    lcd.print(F(\"** ALARM **     \"));\n  } else {\n    two(now.hour()); lcd.print(':');\n    two(now.minute()); lcd.print(':');\n    two(now.second());\n    lcd.print(F(\"   \"));\n    two(now.day()); lcd.print('\/');\n    two(now.month());\n  }\n\n  lcd.setCursor(0, 1);\n  switch (mode) {\n    case SHOW_TIME:\n      lcd.print(F(\"Alarm \"));\n      two(alarmHour); lcd.print(':'); two(alarmMinute);\n      lcd.print(alarmOn ? F(\" on \") : F(\" off\"));\n      lcd.print(F(\"   \"));\n      break;\n    case SET_ALARM_HOUR:\n      lcd.print(F(\"Set hour   \"));\n      two(alarmHour); lcd.print(':'); two(alarmMinute);\n      break;\n    case SET_ALARM_MINUTE:\n      lcd.print(F(\"Set minute \"));\n      two(alarmHour); lcd.print(':'); two(alarmMinute);\n      break;\n    case SET_ALARM_ONOFF:\n      lcd.print(alarmOn ? F(\"Alarm: on       \") : F(\"Alarm: off      \"));\n      break;\n  }\n}\n\n\/\/ ------------------------------------------------------------------ alarm\n\nconst int melody[] = {880, 988, 1047, 988};\nint melodyStep = 0;\nunsigned long lastNote = 0;\n\nvoid ringTune() {\n  if (millis() - lastNote &gt;= 350) {\n    lastNote = millis();\n    tone(buzzerPin, melody[melodyStep], 200);\n    melodyStep = (melodyStep + 1) % 4;\n  }\n}\n\nvoid startRinging() {\n  ringing = true;\n  ringingSince = millis();\n  melodyStep = 0;\n}\n\nvoid stopRinging() {\n  ringing = false;\n  noTone(buzzerPin);\n}\n\nvoid snooze() {\n  stopRinging();\n  \/\/ Nine minutes on, as alarm clocks have always done.\n  alarmMinute = (alarmMinute + 9) % 60;\n  if (alarmMinute &lt; 9) {\n    alarmHour = (alarmHour + 1) % 24;\n  }\n  firedInMinute = -1;\n  settingChanged = true;\n}\n\n\/\/ ------------------------------------------------------------------- main\n\nvoid setup() {\n  Serial.begin(9600);\n\n  lcd.init();\n  lcd.backlight();\n  lcd.setCursor(0, 0);\n  lcd.print(F(\"Siratek clock\"));\n\n  if (!rtc.begin()) {\n    lcd.setCursor(0, 1);\n    lcd.print(F(\"No clock found\"));\n    while (1) { delay(100); }\n  }\n  if (rtc.lostPower()) {\n    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n  }\n\n  setupButton(buttons[0], MODE_BTN);\n  setupButton(buttons[1], UP_BTN);\n  setupButton(buttons[2], DOWN_BTN);\n\n  pinMode(buzzerPin, OUTPUT);\n  loadAlarm();\n\n  delay(800);\n  lcd.clear();\n}\n\nvoid adjust(int delta) {\n  switch (mode) {\n    case SET_ALARM_HOUR:\n      alarmHour = (alarmHour + 24 + delta) % 24;\n      settingChanged = true;\n      break;\n    case SET_ALARM_MINUTE:\n      alarmMinute = (alarmMinute + 60 + delta) % 60;\n      settingChanged = true;\n      break;\n    case SET_ALARM_ONOFF:\n      alarmOn = !alarmOn;\n      settingChanged = true;\n      break;\n    default:\n      break;\n  }\n}\n\nvoid loop() {\n  byte modeEvent = pollButton(buttons[0]);\n  byte upEvent   = pollButton(buttons[1]);\n  byte downEvent = pollButton(buttons[2]);\n\n  if (ringing) {\n    ringTune();\n\n    if (modeEvent == 3) {                  \/\/ held: stop until tomorrow\n      stopRinging();\n    } else if (modeEvent == 1 || upEvent == 1 || downEvent == 1) {\n      snooze();\n    } else if (millis() - ringingSince &gt; 600000UL) {\n      stopRinging();                       \/\/ give up after ten minutes\n    }\n  } else {\n    if (modeEvent == 1) {\n      mode = (Mode) ((mode + 1) % 4);\n      if (mode == SHOW_TIME &amp;&amp; settingChanged) {\n        saveAlarm();\n        settingChanged = false;\n      }\n      lcd.clear();\n    }\n\n    if (upEvent == 1 || upEvent == 2)   adjust(+1);\n    if (downEvent == 1 || downEvent == 2) adjust(-1);\n\n    DateTime now = rtc.now();\n    if (alarmOn\n        &amp;&amp; now.hour() == alarmHour\n        &amp;&amp; now.minute() == alarmMinute\n        &amp;&amp; firedInMinute != now.minute()) {\n      firedInMinute = now.minute();\n      startRinging();\n      lcd.clear();\n    }\n  }\n\n  \/\/ Redraw four times a second, not every pass.\n  if (millis() - lastDraw &gt;= 250) {\n    lastDraw = millis();\n    draw();\n  }\n}<\/code><\/pre>\n<h3>The three decisions that matter most<\/h3>\n<p><strong><code>pollButton()<\/code> returns an event, not a state.<\/strong> One function, three behaviours, and the rest of the sketch reads as \u201cif the Mode button was pressed\u201d rather than fiddling with timestamps. It is the most reusable thing here; lift it into your next project.<\/p>\n<p><strong><code>EEPROM.update()<\/code>, not <code>EEPROM.write()<\/code>.<\/strong> <code>update()<\/code> reads first and writes only if the value differs. On a clock that saves whenever a setting changes, that is the difference between using a handful of the EEPROM\u2019s hundred thousand writes and using them all.<\/p>\n<p><strong>The display is redrawn four times a second<\/strong>, not every pass of <code>loop()<\/code>. The LCD is slow, and redrawing it constantly makes the buttons feel unresponsive because the loop spends its time talking to the screen.<\/p>\n<h2>Testing it<\/h2>\n<table>\n<thead>\n<tr>\n<th>Try this<\/th>\n<th>It should<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Watch the seconds<\/td>\n<td>Advance steadily, no stutter<\/td>\n<\/tr>\n<tr>\n<td>Press Mode four times<\/td>\n<td>Cycle the modes and return to the time<\/td>\n<\/tr>\n<tr>\n<td>Hold Up in minute mode<\/td>\n<td>Climb slowly, then speed up after a few seconds<\/td>\n<\/tr>\n<tr>\n<td>Set an alarm a minute ahead<\/td>\n<td>Ring at the right moment<\/td>\n<\/tr>\n<tr>\n<td>Press any button while ringing<\/td>\n<td>Snooze; it rings again nine minutes later<\/td>\n<\/tr>\n<tr>\n<td>Hold Mode while ringing<\/td>\n<td>Stop, and not ring again today<\/td>\n<\/tr>\n<tr>\n<td>Set an alarm, unplug, plug back in<\/td>\n<td>Keep the alarm setting and the time<\/td>\n<\/tr>\n<tr>\n<td>Leave it ringing<\/td>\n<td>Give up after ten minutes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The seventh is the one that proves the EEPROM and the clock battery are both doing their jobs, and it is the reason this is a clock rather than a demonstration.<\/p>\n<h2>Making it yours<\/h2>\n<ul>\n<li><strong>A light that comes on before the alarm.<\/strong> An LED or a relay, switched fifteen minutes early and brightened with PWM. Waking to light is pleasanter than waking to sound.<\/li>\n<li><strong>Temperature on the display.<\/strong> The DS3231 measures its own, free: <code>rtc.getTemperature()<\/code>. It reads a little high, which <em>Keeping Time with a DS3231<\/em> explains.<\/li>\n<li><strong>A proper tune.<\/strong> The melody here is four notes. <em>Play Tones with a Passive Buzzer<\/em> has the note tables.<\/li>\n<li><strong>Dim the backlight at night.<\/strong> The backpack\u2019s backlight jumper can be replaced with a transistor on a PWM pin.<\/li>\n<li><strong>Set the time from the buttons.<\/strong> The sketch sets the alarm but not the clock. Two more modes and the same <code>adjust()<\/code> pattern, and you no longer need to recompile to correct it.<\/li>\n<\/ul>\n<p>That last one is a genuinely good exercise, because it reuses everything already here.<\/p>\n<h2>Troubleshooting<\/h2>\n<table>\n<thead>\n<tr>\n<th>Symptom<\/th>\n<th>Likely cause<\/th>\n<th>Check or fix<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Display blank, backlight on<\/td>\n<td>Contrast<\/td>\n<td>Turn the blue trimmer through its range<\/td>\n<\/tr>\n<tr>\n<td>Nothing found on the bus<\/td>\n<td><code>SDA<\/code> and <code>SCL<\/code> swapped<\/td>\n<td><code>SDA<\/code> is <code>A4<\/code>, <code>SCL<\/code> is <code>A5<\/code><\/td>\n<\/tr>\n<tr>\n<td>Display works, clock not found<\/td>\n<td>Address, or the coin cell<\/td>\n<td>Scan; expect 0x68<\/td>\n<\/tr>\n<tr>\n<td>Time resets on every power-up<\/td>\n<td><code>adjust()<\/code> unconditional<\/td>\n<td>Guard it with <code>lostPower()<\/code><\/td>\n<\/tr>\n<tr>\n<td>Alarm lost on power-up<\/td>\n<td>Not saved to EEPROM<\/td>\n<td><code>saveAlarm()<\/code> when leaving the menus<\/td>\n<\/tr>\n<tr>\n<td>Buttons feel sluggish<\/td>\n<td>Display redrawn every pass<\/td>\n<td>Redraw four times a second<\/td>\n<\/tr>\n<tr>\n<td>One press changes the hour twice<\/td>\n<td>Not debounced<\/td>\n<td>Check the 30 ms guard<\/td>\n<\/tr>\n<tr>\n<td>Hold does not repeat<\/td>\n<td>Repeat branch not reached<\/td>\n<td>It starts after 600 ms<\/td>\n<\/tr>\n<tr>\n<td>Alarm rings repeatedly in one minute<\/td>\n<td><code>firedInMinute<\/code> not set<\/td>\n<td>It is set when ringing starts<\/td>\n<\/tr>\n<tr>\n<td>Buzzer silent<\/td>\n<td>Active buzzer, not passive<\/td>\n<td><code>tone()<\/code> needs a passive one<\/td>\n<\/tr>\n<tr>\n<td>Snooze sets a strange time<\/td>\n<td>Hour not carried<\/td>\n<td>The <code>% 60<\/code> wrap needs the hour bump<\/td>\n<\/tr>\n<tr>\n<td>Display garbled after hours<\/td>\n<td>Noise on a long I2C run<\/td>\n<td>Shorten the leads<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Sources and attribution<\/h2>\n<p>All text, wiring guidance and code in this project are original Siratek work.<\/p>\n<ul>\n<li>Component behaviour is as described in <em>A 16\u00d72 LCD over I2C<\/em>, <em>Keeping Time with a DS3231<\/em>, <em>Play Tones with a Passive Buzzer<\/em> and <em>Read a Push Button<\/em>, including the backpack\u2019s variable address, the <code>lostPower()<\/code> behaviour and the <code>tone()<\/code> timer conflict.<\/li>\n<li>EEPROM write endurance is from the ATmega328P datasheet.<\/li>\n<\/ul>\n<p>The nine-minute snooze is the long-standing convention rather than anything required. No third-party tutorial text, diagrams, photographs or code has been reproduced here.<\/p>\n<p><\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>A clock that shows the time on a 16&#215;2 display, lets you set an alarm with buttons, and wakes you with a tune. Press to snooze, hold to stop.<\/p>\n","protected":false},"featured_media":0,"template":"","siratek_tutorial_level":[],"class_list":["post-52356","siratek_tutorial","type-siratek_tutorial","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Project, a Smart Alarm Clock - siratek<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Project, a Smart Alarm Clock - siratek\" \/>\n<meta property=\"og:description\" content=\"A clock that shows the time on a 16x2 display, lets you set an alarm with buttons, and wakes you with a tune. Press to snooze, hold to stop.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/\" \/>\n<meta property=\"og:site_name\" content=\"siratek\" \/>\n<meta property=\"og:image\" content=\"http:\/\/siratek.net\/wp-content\/uploads\/2026\/11\/smart-alarm-clock-wiring.svg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/\",\"url\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/\",\"name\":\"Project, a Smart Alarm Clock - siratek\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/siratek.net\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/#primaryimage\"},\"image\":{\"@id\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/siratek.net\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/smart-alarm-clock-wiring.svg\",\"datePublished\":\"2026-11-01T10:51:00+00:00\",\"breadcrumb\":{\"@id\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/#primaryimage\",\"url\":\"https:\\\/\\\/siratek.net\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/smart-alarm-clock-wiring.svg\",\"contentUrl\":\"https:\\\/\\\/siratek.net\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/smart-alarm-clock-wiring.svg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/smart-alarm-clock\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/siratek.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorials\",\"item\":\"https:\\\/\\\/siratek.net\\\/index.php\\\/tutorials\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Project, a Smart Alarm Clock\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/siratek.net\\\/#website\",\"url\":\"https:\\\/\\\/siratek.net\\\/\",\"name\":\"siratek\",\"description\":\"Your Best Electronic Retail Shop\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/siratek.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Project, a Smart Alarm Clock - siratek","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/","og_locale":"en_US","og_type":"article","og_title":"Project, a Smart Alarm Clock - siratek","og_description":"A clock that shows the time on a 16x2 display, lets you set an alarm with buttons, and wakes you with a tune. Press to snooze, hold to stop.","og_url":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/","og_site_name":"siratek","og_image":[{"url":"http:\/\/siratek.net\/wp-content\/uploads\/2026\/11\/smart-alarm-clock-wiring.svg","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/","url":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/","name":"Project, a Smart Alarm Clock - siratek","isPartOf":{"@id":"https:\/\/siratek.net\/#website"},"primaryImageOfPage":{"@id":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/#primaryimage"},"image":{"@id":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/#primaryimage"},"thumbnailUrl":"http:\/\/siratek.net\/wp-content\/uploads\/2026\/11\/smart-alarm-clock-wiring.svg","datePublished":"2026-11-01T10:51:00+00:00","breadcrumb":{"@id":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/#primaryimage","url":"https:\/\/siratek.net\/wp-content\/uploads\/2026\/11\/smart-alarm-clock-wiring.svg","contentUrl":"https:\/\/siratek.net\/wp-content\/uploads\/2026\/11\/smart-alarm-clock-wiring.svg"},{"@type":"BreadcrumbList","@id":"http:\/\/siratek.net\/index.php\/tutorials\/smart-alarm-clock\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/siratek.net\/"},{"@type":"ListItem","position":2,"name":"Tutorials","item":"https:\/\/siratek.net\/index.php\/tutorials\/"},{"@type":"ListItem","position":3,"name":"Project, a Smart Alarm Clock"}]},{"@type":"WebSite","@id":"https:\/\/siratek.net\/#website","url":"https:\/\/siratek.net\/","name":"siratek","description":"Your Best Electronic Retail Shop","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/siratek.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/siratek.net\/index.php\/wp-json\/wp\/v2\/siratek_tutorial\/52356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/siratek.net\/index.php\/wp-json\/wp\/v2\/siratek_tutorial"}],"about":[{"href":"https:\/\/siratek.net\/index.php\/wp-json\/wp\/v2\/types\/siratek_tutorial"}],"version-history":[{"count":0,"href":"https:\/\/siratek.net\/index.php\/wp-json\/wp\/v2\/siratek_tutorial\/52356\/revisions"}],"wp:attachment":[{"href":"https:\/\/siratek.net\/index.php\/wp-json\/wp\/v2\/media?parent=52356"}],"wp:term":[{"taxonomy":"siratek_tutorial_level","embeddable":true,"href":"https:\/\/siratek.net\/index.php\/wp-json\/wp\/v2\/siratek_tutorial_level?post=52356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}