Project tutorial
30-Minute Timer Alarm Clock

30-Minute Timer Alarm Clock © MIT

Simple Arduino-based 30-minute alarm clock with gentle "gong" sound.

  • 127 views
  • 0 comments
  • 1 respect

Components and supplies

Necessary tools and machines

3drag
3D Printer (generic)

About this project

A friend is starting a small business that rents a resource for 30 minute time slots.She looked for a timer that could alarm every 30 minutes (on the hour and half hour) with a pleasant gong sound, but couldn't find anything.

I offered to create a simple Arduino-based alarm clock.This design uses a Pro Micro microcontroller, DFPlayer Mini MP3 player, and a DS3231 real-time clock (RTC.)I used Fusion 360 to design the case, based on the Fusion 360 Tutorial – Easy Snap Fit Cases!

Supplies:

  • Arduino Pro Micro, 5 volt, 16 MHz
  • DFPlayer Mini MP3 player
  • MicroSD card
  • DS3231RTC
  • 1602 16x2 LCD with I2C Interface
  • small speaker
  • 2 small SPST pushbuttons
  • 5 volt DC power supply
  • Barrel jack for power input
  • various screws/standoff/nuts, etc.
  • perf board
  • female and male 2.54mm headers
  • 3D-printed case

Step 1: Prototype and Arduino Code Development

I prototyped the design with a SparkFun Inventor's Kit which includes an Arduino Uno board, breadboard, jumper wires, etc. This is good platform for prototyping Arduino projects, along with many other similar platforms.

I first used the "Tiny RTC" DS1307 real-time clock. It includes a CR2032 backup battery to keep time when the the overall project isn't powered.However, I learned that the DS3231 RTC is a better choice because it includes a temperature-compensated oscillator for more accurate time-keeping.Note that the DS3231M is not temperature compensated, so check carefully before purchasing.

The DFPlayer Mini MP3 Player documentation includes a connection diagram and sample code. This worked fine for me.For an alarm sound, I liked this "Singing bowl struck with a felt-tipped mallet" recording on Freesound.With Audacity, I converted the recording to mono, trimmed it to a shorter length, added a fadeout, and saved it to a .mp3 file. Then, I copied the .mp3 file to the SD card and inserted it in the DFPlayer Mini.(Of course, this design allows you to use any sound for the alarm.)

Two push buttons increase/decrease the time by one minute. I connected these to 2 pins that are enabled for interrupts and used attachInterrupt()

Code is in the "shoni_clock.ino" attachment.Resources for the Arduino code and connections:

DFPlayer Mini MP3 Player

  • #include "DFRobotDFPlayerMini.h"

Step 2: Circuit Diagram

I used Fritzing to design the circuit.

  • schematic Fritzing source: shoni_clock.fzz
  • schematic .pdf: shoni_clock_schem.pdf

Step 3: Case Design

This project was a fine opportunity to improve my 3D CAD design skills.I use Fusion 360.The Fusion 360 Tutorial – Easy Snap Fit Cases! demonstrates a useful technique for designing parameter-driven (length, width, height, shell thickness) cases with snap together features for a no-screws/glue enclosure.

I added holes and cutouts for the power jack, LCD display, time setting push buttons, and speaker.I designed a simple ring to mount the speaker to the inside top of the case.I used the Fusion 360 pattern tool to create the rectangular array of holes for the speaker.It would have been nicer to create a circular speaker grill pattern, but I couldn't find a simple way to do this.Someone had created a script for an older version of Fusion, but it doesn't install on the latest version.Have an idea on how to make a circular speaker pattern? Let us know with a comment.

I printed this in PLA on a Ender 3 printer.

3D printing design files:

Speaker mount:

  • Fusion 360 source: speaker_mount v1.f3d
  • STL: speaker_mount.stl

Case:

  • Fusion 360 source: ShoniClockCase v20.f3d
  • Enclosure STL: shoni_clock_case.stl
  • Bottom cover STL: shoni_clock_case_bottom_cover.stl

Code

shoni_clock.inoArduino
// Shoni's clock - alarms every 30 minutes

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include "RTClib.h"

// I2C LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// DFPlayer sound card
// https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299#Connection_Diagram
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
SoftwareSerial mySoftwareSerial(8, 9); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

#define ALARM_SECONDS 10        // seconds
#define ALARM_REPEAT_DELAY 2000 // milliseconds
#define ALARM_VOLUME 15         // 0 to 30
#define SESSION_TIME 30         // minutes; but this implementation only works for 30 minute sessions

// time adjust plus/minus buttons. LOW when pressed Connected to interrupt inputs, software debounced.
#define TPLUS_PIN 0
#define TMINUS_PIN 1
volatile int TPLUS_button = false;
volatile int TMINUS_button = false;

RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void playalarm() {
  myDFPlayer.volume(ALARM_VOLUME);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);  //Play the first mp3
}

void setup () {
  Serial.begin(57600);
  //while (!Serial); // for Leonardo/Micro/Zero
  Serial.println("Shoni's Clock");

  pinMode(TPLUS_PIN, INPUT_PULLUP);
  pinMode(TMINUS_PIN, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Shoni's Clock");
  delay(1000);

  mySoftwareSerial.begin(9600);

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RTC error!");
    delay(3000);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Clock time error!");
    delay(3000);
  }

  // following line sets the RTC to the date & time this sketch was compiled
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // This line sets the RTC with an explicit date & time, for example to set
  //rtc.adjust(DateTime(2019, 10, 12, 11, 59, 50));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  myDFPlayer.volume(ALARM_VOLUME);  //Set volume value. From 0 to 30
  playalarm();

  attachInterrupt(digitalPinToInterrupt(TPLUS_PIN), TPLUS_button_interrupt, LOW);
  attachInterrupt(digitalPinToInterrupt(TMINUS_PIN), TMINUS_button_interrupt, LOW);
}


void TPLUS_button_interrupt() {
  TPLUS_button = true;
}

void TMINUS_button_interrupt() {
  TMINUS_button = true;
}

void check_buttons() {
  int dir;
  if (TPLUS_button | TMINUS_button) {
    if (TPLUS_button) {
      dir = 1;
      //Serial.println("Adjust time -1 minute");
      delay(50);
      TPLUS_button = false;
    }
    if (TMINUS_button) {
      dir = -1;
      //Serial.println("Adjust time -1 minute");
      delay(50);
      TMINUS_button = false;
    }
    DateTime newtime = rtc.now() + (60 * dir);
    rtc.adjust(newtime);
  }
}

char d[16];
int prevmin = 99;
int alarmplaying;

void loop () {
  int minleft;
  int updateDisplay = true;
  check_buttons();

  DateTime now = rtc.now();
  // update display only if the minute has changed
  if (prevmin == now.minute()) {
    updateDisplay = false;
  }
  else {
    updateDisplay = true;
    prevmin = now.minute();
  }

  if (now.minute() == 0) {
    minleft = 0;
  }
  else if (now.minute() > 30) {
    minleft = 60 - now.minute();
  }
  else {
    minleft = 30 - now.minute();
  }

  // Display current time
  if (updateDisplay) {
    sprintf(d, "%2d:%02d", TwentyFourToTwelve(now.hour()), now.minute());
    Serial.println(d);
    lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print(d);
  }

  // Display time left in session
  if (minleft == 0) {
    if ((now.second() < ALARM_SECONDS)) {
      if (!alarmplaying) {
        playalarm();
        alarmplaying = true;
      }
      lcd.setCursor(0, 1);
      lcd.print("--Session over--");
      Serial.println("--Session over--");
      delay(ALARM_REPEAT_DELAY);
    }
    else {
      minleft = SESSION_TIME;
      alarmplaying = false;
    }
  }
  lcd.setCursor(0, 1);
  sprintf(d, "minutes left: %2d", minleft);
  lcd.print(d);
  //Serial.println(d);
  delay(500);
}

int TwentyFourToTwelve(int hour) {
  int h = hour % 12;
  if (h == 0) {
    h = 12;
  }
  return h;
}
Github
https://github.com/johnrickman/LiquidCrystal_I2C

Custom parts and enclosures

shoni_clock_case.stl
shoni_clock_case.stl
shoni_clock_case_bottom_cover.stl
shoni_clock_case_bottom_cover.stl
speaker_mount.stl
speaker_mount.stl
speaker_mount.stl
speaker_mount.stl

Schematics

shoni_clock
shoni_clock_Do0gmaqzri.fzz

Comments

Similar projects you might like

Alarm Clock and Timer Working Standalone

Project showcase by ozyRonald

  • 25,997 views
  • 12 comments
  • 25 respects

Washing Machine Timer

Project tutorial by Shahariar

  • 9,373 views
  • 7 comments
  • 14 respects

Arduino Wake Up Light Alarm Clock

Project tutorial by wolfidan

  • 6,044 views
  • 0 comments
  • 9 respects

TM1637 Digital Clock with time setup and alarm functionality

Project tutorial by mdraber

  • 7,931 views
  • 3 comments
  • 10 respects

LCD Alarm Clock with many faces

Project tutorial by John Bradnam

  • 7,506 views
  • 17 comments
  • 21 respects
Add projectSign up / Login