Introduction
This tutorial explains how a feature-packed alarm clock, complete with an LCD screen, buzzer, and a button to put it to sleep can be built with an Arduino Uno, a clock module, an active buzzer, and a handful of other sensors and components.
Hardware Required
You may purchase the individual components here:
- Arduino Uno R3
- LCD 16x02
- Solderless Breadboard 400 Tie Point
- Jumper Wire Male-Male 40x
- RP-S40-ST Thin Film Pressure Sensor
- Rainbow LED 1x5 Module WS2812
- Clock Module RTC DS3231
- Active Buzzer Module
- 10k Variable Resistor
- 10k Resistor
Connecting the Hardware
Connect the 10k variable resistor to the LCD display as follows.
- VSS (LCD) to GND (10k resistor)
- VDD (LCD) to 5V (10k resistor)
- V0 (LCD) to Output (10k resistor)
This connection allows the 10k variable resistor to control the contrast of the LCD screen. Adjust the variable resistor until you clearly see the words on the LCD.
Connect the LCD display to the Arduino Uno as follows.
- RS (LCD) to Pin 2 (Arduino Uno)
- RW (LCD) to Pin 3 (Arduino Uno)
- E (LCD) to GND (Arduino Uno)
- D4 (LCD) to Pin 4 (Arduino Uno)
- D5 (LCD) to Pin 5 (Arduino Uno)
- D6 (LCD) to Pin 6 (Arduino Uno)
- D7 (LCD) to Pin 7 (Arduino Uno)
- A (LCD) to 5V (Arduino Uno)
- K (LCD) to GND (Arduino Uno)
The RS pin on the LCD allows selection between its command register and data register. This lets us send commands to the LCD (such as a command to clear the LCD screen or to send data to be displayed on the LCD). The RW pins on the LCD toggle between 0 (for reading from the LCD) and 1 (for writing to the LCD). We will be setting these configurations through the Arduino Uno's pin 2 and 3 in our program later.
D4 to D7 are connected to the respective Pins 4 to 7 on the Arduino to display alphabets or numbers to the respective internal registers on the LCD. Pins E and K are connected to the Grounding Pins (GND) on the Arduino.
Pin A powers on the LCD backlight and is connected to the 5V pin on the Arduino.
Connect the RP-S40-ST Thin Film Pressure Sensor to the Arduino as follows:
This allows the Arduino to detect the change in voltage from the pressure sensor.
Connect the Rainbow LED module to the Arduino as follows:
- DIN (Rainbow LED) to Pin 8 (Arduino Uno)
- +5V (Rainbow LED) to 5V (Arduino Uno)
- GND (Rainbow LED) to GND (Arduino Uno)
The DIN pin on the Rainbow LED receives instruction through pin 8 from the Arduino Uno to light up. The 5V pin on the Rainbow LED receives powers from the Arduino. We will be writing instructions for the Arduino Uno to instruct the Rainbow LED to light up.
Connect the Active Buzzer module to the Arduino as follows:
- GND (Active Buzzer Module) to GND (Arduino Uno)
- I/O (Active Buzzer Module) to 9 (Arduino Uno)
- VCC (Active Buzzer Module) to 5V (Arduino Uno)
The I/O pin on the Active Buzzer Module receives instruction through pin 9 from the Arduino Uno to instruct it to buzz or to stop buzzing The VCC pin on the Active Buzzer Module receives powers from the Arduino. We will be writing instructions for the Arduino Uno to instruct the Active Buzzer Module to buzz or to stop buzzing.
Connect the Clock Module (RTC DS3231) to the Arduino as follows:
- SCL (Clock Module) to A5 (Arduino Uno)
- SDA (Clock Module) to A4 (Arduino Uno)
- VCC (Clock Module) to 5V (Arduino Uno)
- GND (Clock Module) to GND (Arduino Uno)
The SCL pin is used to synchronize data transfer between the Arduino Uno and the Clock Module. The SDA pin carries data between the Clock Module and the Arduino Uno.
Install the NeoPixel, Clock and Buzzer Modules' Libraries for Arduino
The NeoPixel library from AdaFruit will allow us to write codes on the Arduino Uno to communicate with the Rainbow LED. To install the NeoPixel library, start up the Arduino IDE. Go to Tools > Manage Libraries and search for NeoPixel. Scroll down to look for "AdaFruit NeoPixel" and install the latest version of this library.
The DS3231 library will allow us to write codes on the Arduino Uno to communicate with the Clock Module. To install the DS3231 library, start up the Arduino IDE. Go to Tools > Manage Libraries and search for DS3231. Scroll down to look for "RTC" and install the latest version of this library.
Click on File > Examples > RTC > DS3231 > DS3231_Auto example on the Arduino IDE. Uncomment line 12 “RTC.stopClock()” to set up a new clock time
#include <Wire.h>
#include <RTC.h>
static DS3231 RTC;
void setup()
{
Serial.begin(9600);
RTC.begin();
//RTC.stopClock();
Serial.print("Is Clock Running: ");
if (RTC.isRunning())
{
Upload the code and open the serial monitor and set the baud rate to 9600. Time will automatically be set based on your computer's time.
Programming the Arduino
The codes for this project is an adaption from our previous Floorboard Smart Light System project. The source code can be found in Kuriosity's Github Repository here. Here are some important code snippets and what they do.
The codes below include the required library.
// include libraries
#include <LiquidCrystal.h>
#include <Adafruit_NeoPixel.h>#include <Wire.h>
#include <RTC.h>
The threshold
definition determines how hard to press the sensor before triggering the Rainbow LED lights. LED_COUNT
is the total number of LEDs on the Rainbow LED strip. In our case, our LED strip has 5 LED lights. We will set the brightness of the LED lights to 150 so that the device does not draw too much power while still maintaining high brightness.
// declare user variables
#define THRESHOLD 500
#define LED_COUNT 5
#define BRIGHTNESS 150 // NeoPixel brightness
Declare the timing where the buzzer will sound.
#define ALARM_HOUR 11
#define ALARM_MINUTE 34
Declare the pins for the pressure sensor, the Rainbow LED, and the buzzer pin to receive instructions from the Arduino Uno.
// declare pins
const int forceSensorPin = A0;
const int ledPin = 8;
const int buzzerPin = 9;
Create the LCD, NeoPixel, and DS3231 objects with the respective pins and setup variables.
// create objects
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
Adafruit_NeoPixel strip(LED_COUNT, ledPin, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
DS3231 RTC;
Declare the variables to be used within our program.
// declare variables
bool alarm, alarmState;
int lastSecond;
long lastAlarmTime;
char timeFormat[9], dateFormat[11];
In the setup()
routine, we initialize the LCD and NeoPixel so that it is ready for use. Initialize the buzzer pin as an OUTPUT and default state HIGH so we can update it later to activate the buzzer.
void setup() {
// initialize LCD
lcd.begin(16, 2);
// initialize NeoPixel
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(BRIGHTNESS);
// initialize clock and set to 12H mode
RTC.begin();
RTC.setHourMode(CLOCK_H12);
// initialize pin
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, HIGH); // low trigger
}
Code an updateLCD()
function. We will call this function later to refresh the LCD. The sprintf function will format the time and date that it receives from the clock module in the format xx:xx:xx and xx/xx/xxxx. The LCD will display the correct timing in "AM" or "PM" and add a day of week (Sun to Sat) based on the value returned by calling RTC.getMeridiem()
and RTC.getWeek()
from the Clock Module.
void updateLCD() {
sprintf(timeFormat, "%02d:%02d:%02d", RTC.getHours(), RTC.getMinutes(), RTC.getSeconds());
sprintf(dateFormat, "%02d/%02d/%04d", RTC.getDay(), RTC.getMonth(), RTC.getYear());
lcd.clear();
lcd.setCursor(2, 0);
lcd.print(timeFormat);
if (RTC.getHourMode() == CLOCK_H12)
{
switch (RTC.getMeridiem())
{
case HOUR_AM :
lcd.print(" AM");
break;
case HOUR_PM :
lcd.print(" PM");
break;
}
}
lcd.setCursor(1, 1);
switch (RTC.getWeek())
{
case 1:
lcd.print("SUN");
break;
case 2:
lcd.print("MON");
break;
case 3:
lcd.print("TUE");
break;
case 4:
lcd.print("WED");
break;
case 5:
lcd.print("THU");
break;
case 6:
lcd.print("FRI");
break;
case 7:
lcd.print("SAT");
break;
}
lcd.setCursor(5, 1);
lcd.print(dateFormat);
}
Code a checkSensor()
function that returns a Boolean true or false based on whether the reading exceeds the threshold. Our code takes an average of 25 readings to smoothen the noise and get a more accurate reading.
// get an average reading from sensor for stability
bool checkSensor() {
float average = 0;
for (int i = 0; i < 25; i++) {
average += analogRead(forceSensorPin);
}
average = average / 25.0;
if (average > THRESHOLD) return true;
return false;
}
In the main loop, we update the LCD continuously every second to display the current date and time. The code also checks if the current date and time match the timings stated in our definition ALARM_HOUR
and ALARM_MINUTE
. If it does, we set the variable alarm
to true
to trigger the alarm to sound.
void loop() {
// update LCD every 1s
if (RTC.getSeconds() != lastSecond) {
updateLCD();
if (RTC.getHours() == ALARM_HOUR && RTC.getMinutes() == ALARM_MINUTE && RTC.getSeconds() == 0) {
alarm = true;
}
lastSecond = RTC.getSeconds();
}
When the alarm is triggered, the LED is set to blink. The code also toggles the buzzer to turn on and off every 100ms.
if (alarm) {
// toggle the alarm state every 100ms
if (millis() - lastAlarmTime > 100) {
alarmState = !alarmState;
lastAlarmTime = millis();
}
// flash the LED on & off
if (alarmState) {
// show red colour
strip.fill(strip.Color(255, 0, 0, strip.gamma8(255)));
}
else {// show blank
strip.fill(strip.Color(0, 0, 0, strip.gamma8(255)));
}
strip.show()
Our codes also check if the user has pressed the pressure sensor pad to snooze the alarm. If he does, the checkSensor()
function is set to true
and the code turns off the LED and buzzer.
if (checkSensor()) {
alarm = false;
}
}
else {
// turn off LED
strip.fill(strip.Color(0, 0, 0, strip.gamma8(255)));
strip.show();
// turn off buzzer
digitalWrite(buzzerPin, HIGH);
}
Using the Alarm Clock
Let's try to use the alarm clock. Download the program to the Arduino Uno, then power it up.
At the Arduino Uno, set the ALARM_HOUR and ALARM_MINUTE definitions to the timing that you will like the alarm to sound.
Run the program. Now, wait for the alarm to sound!
Snooze the alarm by pressing on the Thin Film Pressure Sensor.
Well done! You just built your very own alarm clock! The clock module will remember the time even when Arduino is powered down because it has a battery to keep the internal clock running.
Resources
- Download the full source code: Click Here