How to make a Raspberry Pi alarm clock

Snipe
Snipe
Aug 18, 2018 · 13 min read

In this tutorial I will make an alarm clock with at its core the Raspberry Pi board. If you already have a Raspberry Pi in your possession; great!
Any Raspberry Pi should work for this project.

Goal of the project: the Raspberry Pi alarm clock

Component list

Since we don’t need a high-end model to make our alarm clock, we can get away with the cheaper alternative, the Raspberry Pi Zero.

Optional, any fasteners or screws will work

  • 4 #4–40 machine screws 3/4 inches long

This project uses the wiringPi libraries (by Gordon Henderson), for programming the GPIO in C in a style similar to the Arduino IDE.
WiringPi must be installed for this project.

WiringPi uses it’s own pin identification scheme. All pin numbers mentioned in the program or in the text are WiringPi references unless otherwise specified.

After installing WiringPi you can obtain a list showing the pin numbering for your specific model of Raspberry Pi by opening a command terminal and typing:

gpio readall

Getting started

I will use a case I already had in my possession, feel free to use any case you like or design one yourself. Alternatively, use the aluminium case listed in the component list above.

Step 1: Enclosure mounting holes

In order for the Raspberry Pi and the other components to fit nicely in the case, you will need to drill some holes. This process will depend on your specific case.

Metal casing with mounting holes drilled for the LCD, buttons and Raspberry Pi

Bottom:

The four holes that are already in the chassis are for the rubber feet, avoid those.
Position the Raspberry and the permaproto board for the amplifier as shown in the first picture. Mark, then continue to drill 1/8 inch mounting holes.
Install the four rubber feet.

Front:

Position the LCD screen centered on the front panel of the chassis, mark and drill the four 0,125 inch mounting holes.

Drill three 5 by 16 holes holes for the wires to run through and insert the grommets.

It can be very hard to drill large holes in thin sheet metal. For the larger holes I drilled them to quarter inch and used a conical reamer to further enlarge them. The conical reamer I used was purchased at the local hardware store. You can find a similar one here.

Back:

Drill an 0,125 inch hole about 7/8 inch in from both sides and 0,75 inch up from the bottom.

Drill an 0,125 inch hole 15mm to the left of this hole.
Open the center holes up to 0,5 inch diameter. The left side is the USB power connector.

Drill the three remaining 0,5 inch holes approximately where indicated in the picture, the location is not critical.

Top:

Drill a hole in the top centered side to side about 2 inches from the back and enlarge the hole to half an inch.

Step 2: Alarm amplifier

LM386 circuit and breadboard diagram

The amplifier for the alarm is based on the LM386 audio amplifier IC.
Build the circuit according to the specifications in the picture above.

The blue and green wires on the right of the drawing are dupont wires and are about seven inches long with female ends to connect to the end speaker.

The black and red wires on the left side of the diagram are about 2,5 inches long, they are dupont wires with female ends to connect to 5V and ground on the Raspberry Pi.

The yellow wire on the bottom left of the diagram is about 2,5 inches long.
It is a dupont wire with a female end that connects to WiringPi pin reference number 1, the PWM output from the Raspberry Pi. This is the input to the sound amplifier.

The white wire on the bottom right is the contrast for the LCD screen, it is a 22 gauge hookup wire.

The black wire on the bottom right is the ground for the switches, it is also 22 gauge hookup wire.

The pot on the left is the audio volume controller and the one on the right is the contrast controller for the LCD screen. Both pots are 10 kilo-Ohm.

Step 3: Raspberry Pi software configuration

This tutorial assumes that you have Raspbian already installed.

Let’s start off with configuring your device

sudo raspi-config

Enable SSH, and confirm if necessary.
Additionally, configure your wifi settings and make sure it automatically connects to your network upon rebooting.

With the next command we will gather the MAC address from your Raspberry Pi, we will need this later on to assign a static IP address to the device.

ifconfig

Each router has different procedures for binding a fixed local IP address to a MAC address, so for sake of simplicity we will not address this further in this tutorial.

Now that you have configured a static IP address you can remotely SSH into your Raspberry Pi. A great way to do so is by using Putty.

Default credentials:
Username: raspberry
Password: pi
*** YOU CAN UPDATE YOUR CREDENTIALS WITH THE sudo raspi-config COMMAND ***

After connecting we will install geany.

sudo apt-get install geany

Step 4: Fine-tuning the amplifier, frequency and volume

To test the amplifier, connect the red wire to physical pin 2 on the Raspberry Pi, this is a 5V pin.

Connect the black wire to physical pin 6 on the Raspberry Pi, this is the ground pin.

Connect the yellow wire to physical pin 12 on the Raspberry Pi, this is WiringPi pin reference 1, the PWM pin.

Copy this program to the Raspberry Pi, It is a very simple bash program to test the amplifier and make adjustments to the sound. It should turn on the buzzer for a couple of seconds.

sudo nano sound.c

And copy-paste this into the file:

/******************************************************************
* Filename: sound.c
*
* All pin numbers are wiringPi numbers unless otherwise specified.
******************************************************************/

#include <wiringPi.h>

int PWMpin = 1; // Alarm sound pin

/**************************************************************
* main() function
**************************************************************/
int main()
{
wiringPiSetup(); // Setup required by wiringPi

pinMode (PWMpin, PWM_OUTPUT); // Alarm sound pin
pwmSetMode(PWM_MODE_MS); // Mark/Space mode
pwmSetClock(100); // Default 100 (int)
pwmSetRange(1024); // Default 1024 (unsigned int)
int duty = 200; // Duty cycle

pwmWrite(PWMpin, duty); // sound alarm
delay(5000); // for five seconds.
pwmWrite(PWMpin, 0); // turn off alarm
return 0;
}

Proceed to save this script and compile it with

gcc -o sound -Wall -I/usr/local/include -L/usr/local/lib sound.c -lwiringPi

Finally, run it with

sudo ./sound

You need to use the sudo command because the Raspberry Pi requires you to be root for low tier access to the hardware, such as the GPIO pins.

Make sure you have the volume turned down when you initially start the script, it can get VERY loud.

Further adjust the frequency by changing the 100 in the line that says

pwmSetClock(100);

You can furthermore adjust the volume by changing the 200 in line

int duty = 200;

Remember these changes you made to include them in the final clock program.

In the clock script program these lines are located right above the while(1) in the main() function.

Step 5: The final clock program

Copy the final clock script to your Raspberry Pi.

/******************************************************************
* Filename: clock.c
*
* RaspberryPi alarm clock With special reminder feature.
*
* Compile: gcc -o clock -Wall -I/usr/local/include -L/usr/local/lib
* clock.c -lwiringPi -lwiringPiDev
*
* Execute: sudo ./clock
*
* All pin numbers are wiringPi numbers unless otherwise specified.
******************************************************************/
#include <time.h>
#include <stdio.h>
#include <wiringPi.h>
#include <lcd.h>

static int lcdhandle; // LCD screen

char hours[24][3] = {"12","01","02","03","04","05","06","07",
"08","09","10","11","12","01","02","03",
"04","05","06","07","08","09","10","11"};

char dow[7][4] = {"Sun","Mon","Tue","Wed",
"Thu","Fri","Sat"};

char months[12][4] = {"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"};

struct tm tm2; // Structures for getting time.
int timeh, timem, times; // Current time elements.
int date, month, year, wday;

int apin = 5; // Alarm button
int hpin = 6; // Set hours button
int mpin = 12; // Set minutes button
int spin = 13; // Special button

int PWMpin = 1; // Alarm sound pin

int aflag = 0; // Alarm flag
int sflag = 0; // special flag

int alh = 0; // Alarm hours
int alm = 0; // Alarm minutes

/*********************************************************
* gettime() function - Get system time and load it into
* global variables.
*********************************************************/
void gettime()
{
time_t now;
char *str;

now = time(NULL); // Get the time.
str = ctime(&now); // Convert it to a string.
strptime(str,"%a %b %d %H:%M:%S %Y",&tm2); // Convert from string.

timeh = tm2.tm_hour; // Copy times
timem = tm2.tm_min; // into global variables.
times = tm2.tm_sec;
date = tm2.tm_mday;
month = tm2.tm_mon;
year = tm2.tm_year;
wday = tm2.tm_wday;
}

/*********************************************************
* dsptime() function - Displays the time.
*********************************************************/
void dsptime()
{
lcdPosition (lcdhandle, 6, 0);
lcdPrintf(lcdhandle,"%s:", *hours+(timeh*3)); // Display hours
lcdPrintf(lcdhandle,"%02d", timem); // Display minutes
if(timeh<12) lcdPrintf(lcdhandle," AM"); // Display AM/PM
else lcdPrintf(lcdhandle," PM");

lcdPosition (lcdhandle, 0, 1);
lcdPrintf(lcdhandle," %s %s %d %d ",
*dow+(wday*4), *months+(month*4), date ,(1900+year));

if(sflag>0)
{
lcdPosition(lcdhandle,0, 3);
lcdPrintf(lcdhandle,"* ");
}
else
{
lcdPosition(lcdhandle,0, 3);
lcdPrintf(lcdhandle," ");
}

if(aflag==0) lcdPrintf(lcdhandle,"Alarm: OFF ");
else
{
lcdPrintf(lcdhandle,"Alarm: %s:%02d ", *hours+(alh*3), alm);
if(alh<12) lcdPrintf(lcdhandle,"AM");// Display AM/PM
else lcdPrintf(lcdhandle,"PM");
}

}

/*********************************************************
* dspalarm() function - Display the alarm time.
*********************************************************/
void dspalarm()
{
lcdPosition (lcdhandle, 0, 1);
lcdPrintf(lcdhandle,"Set Alarm: %s:%02d ", *hours+(alh*3), alm);
if(alh<12) lcdPrintf(lcdhandle,"AM");// Display AM/PM
else lcdPrintf(lcdhandle,"PM");
}

/*********************************************************
* setalarm() function - Set the time for the alarm
* and turn it on.
*********************************************************/
void setalarm()
{
lcdClear(lcdhandle);
dspalarm();
while(aflag==2)
{
while(digitalRead(hpin)==0) // Is minute button pressed?
{
alh++; // Increment alarm hour
if(alh>23) alh=0; // Hour can't be > 23
dspalarm(); // Redo the display
delay(500); // Time to read it
}
delay(25); // Debounce

while(digitalRead(mpin)==0) // Is minute button pressed?
{
alm+=5; // Add 5 to alarm minutes.
if(alm>59) alm=0; // Minute can't be > 59
dspalarm(); // Redo the display
delay(500); // Time to read it
}
delay(25); // Debounce

if(digitalRead(apin)==0)
{
while(digitalRead(apin)==0);
delay(25);
aflag = 3;
}
}
}

/**************************************************************
* main() function
**************************************************************/
int main()
{
int ptime = 70; // previous time after gettime()
int pday = 32; // Prevoius day

wiringPiSetup(); // Setup required by wiringPi

lcdhandle = lcdInit (4, 20, 4, 11,10, 0,2,3,4,0,0,0,0) ;

pinMode(apin, INPUT); // Set alarm pin to input pullup
pullUpDnControl(apin, PUD_UP);
pinMode(hpin, INPUT); // Set hours pin to input pullup
pullUpDnControl(hpin, PUD_UP);
pinMode(mpin, INPUT); // Set minutes pin to input pullup
pullUpDnControl(mpin, PUD_UP);
pinMode(spin, INPUT); // Set special pin to input pullup
pullUpDnControl(spin, PUD_UP);

pinMode (PWMpin, PWM_OUTPUT); // Alarm sound pin
pwmSetMode(PWM_MODE_MS); // Mark/Space mode
pwmSetClock(100); // Default 100 (int)
pwmSetRange(1024); // Default 1024 (unsigned int)
int duty = 200; // Duty cycle (0 - range)

while(1)
{
// Get and display system time
gettime();
if(ptime != times)
{
ptime = times; // Save time as previous time
dsptime(); // Display the time
}
// Toggle special flag if black button pressed or new day.
if(digitalRead(spin)==0) // If button pressed toggle
{ // special flag
while(digitalRead(spin)==0) // debounce
{
delay(25);
}
sflag = !sflag; // toggle
}
if(date != pday) // Is it a new day?
{
lcdClear(lcdhandle);
sflag = !sflag; // If so toggle special flag,
pday = date; // and save date as previous.
}

// Sound alarm.
if(timeh==alh) // If alarm hour
{
if(timem==alm) // and alarm minute
{
if(aflag==1) // and alarm flag == 1
{
pwmWrite(PWMpin, duty); // sound alarm
}
}
}

if(aflag==0) pwmWrite(PWMpin, 0); // Alarm off if button pressed
if(timem!=alm) pwmWrite(PWMpin, 0); // or 1 minute has passsed

// Turn alarm off, set alarm.
if(digitalRead(apin)==0) // Is alarm button pressed?
{
while(digitalRead(apin)==0) delay(25); // debounce

if(aflag==1) aflag=0; // If alarm flag set clear it.
else aflag = 2; // If alarm flag clear
}

if(aflag==2) setalarm(); // run alarm set function
if(timem != alm) if(aflag == 3) aflag = 1;
}
return 0;
}

If you have the volume or frequency in a previous step, change it again in this script.

Compile the program again with

gcc -o clock -Wall -I/usr/local/include -L/usr/local/lib clock.c -lwiringPi -lwiringPiDev

Finally, go ahead and run the clock script with

sudo ./clock

Step 6: Soldering the screen

The 20x4 LCD screen with the wires soldered in place

Drill out the 4 mounting holes on the LCD screen with a 7 by 64 drill so the #4 machine screws will fit in place.
Cut the ends off the dupont wires and strip the wires.

Use the same color wires as in the picture and diagram, In step 8 I will refer to these colors when connecting the wires with the rest of the board.

The red wire connected to pin 3 is a piece of 22 gauge hookup wire 6 inches long. All the other ones are female dupont wires.
Solder the white and black wires and the wires connecting more than one pin lastly.

Step 7: Mounting it all together

Internal assembly and mounting
External top button and assembly
Front view of the entire assembly

Depending on your case and positioning, these results can be different.

Step 8: Wiring

Internal wiring and breadboard close-up

Connect the Amplifier board to the Raspberry Pi like we did in the testing phase.

The red wire goes to physical pin 2 on the Raspberry Pi.
The black wire goes to physical pin 6 on the Raspberry Pi.
The yellow wire to physical pin 12 on the Raspberry Pi, this is WiringPi pin reference 1.

Connect the white and black wires from the amplifier to the breadboard, they must be in two entirely different columns.

The red wire from the LCD screen goes to the exact same column as the white wire coming from the amplifier.

The black wires from the three back panel switches respectively go in the same column as the black wire from the amplifier. In the picture of the breadboard you can clearly see there is one open position in this column. The black wire from the alarm switch will go right there.

Next, connect the wires from the screen to the Raspberry Pi.

The white wire goes to physical pin 5V.
The black wire goes to physical pin 9 — common Ground.
The orange wire connects to physical pin 26 — wiringPi pin reference 11.
The yellow wire connects to physical pin 24 — wiringPi pin reference 10.
The blue wire connects to physical pin 11 — wiringPi pin reference 0.
The green wire connects to physical pin 13 — wiringPi pin reference 2.
The purple wire connects to physical pin 15 — wiringPi pin reference 3.
The grey wire connects to physical pin 16 — wiringPi pin reference 4.

Connect the wires from the three back panel switches back to the Raspberry Pi.

The wire from the red switch goes to physical pin 22 — wiringPi reference 6.
The wire from the green switch goes to physical pin 19 — wiringPi reference 12.
The wire from the black switch goes to physical pin 21 — wiringPi reference 13.

Set the top very close to the chassis on the left side.

Connect the green and blue wires from the amplifier to the speaker.
Connect the dupont wire from the top switch to physical pin 18 — wiringPi pin reference 5.
Connect the black 22 gauge wire from the top switch to the breadboard, in the exact same column as all the other switches.

Finally, place the cover on top of the chassis and use the remaining four screws that came with the enclosure to secure the cover.+

Using the clock

There are two different methods for starting the clock.
Since you no longer have a monitor attached you have to start it blind or use ssh to get to your device.
Alternatively, add the bash script to startup with crontab.

Make sure your router has the static IP reserved for the clock.
Plug in the clock and wait a few minutes.
Connect with Putty to your clock.
Start the clock with the command:

sudo ./clock

Press CTRL-C to stop the program.
Start the clock again with the command:

sudo ./clock

You can use tmux to avoid the alarm script from ending as well. I recommend just adding the script to startup and rebooting the device entirely.

When you initially start the clock the alarm will be off.
Press the alarm button (the big one you placed on top) and it will bring up the screen to set the alarm.

The red button on the back advances the alarm +1H and the green button advances it +5M
Press the alarm button again and the alarm will be set to sound at the time you specified.

When the alarm sounds it will stay on for an entire minute and finally turn off by itself and remain set to sound at the same time the next day. You can change this interval in the clock script provided.

When the alarm sounds press the button once to turn it off completely, or three times to reset it for the same time.

Depending on your technical skills you might end up with something better than this. Here’s how it could look like in the end.

Check out my profile for more content :)
Snipe

Snipe

Written by

Snipe

I tinker with electronics and crypto assets.