Raspberry Pi Pico - Alarm Clock

by Guitarman9119 in Circuits > Microcontrollers

12898 Views, 24 Favorites, 0 Comments

Raspberry Pi Pico - Alarm Clock

Raspberry Pi Pico - Alarm Clock Project
ezgif.com-gif-maker (1).gif

Hello everyone, do you have a Raspberry Pi Pico and want to build an alarm clock and need some guidance on getting started? If so, this instructable is for you.

This project is a straightforward alarm clock based on the Raspberry Pi Pico. The clock displays the time and date on the popular 16x2 character LCD and has an easy interface to set the alarm.

The clock has a very simple interface through 4 push buttons. This is an excellent project for anyone getting started with the Raspberry Pi Pico, as you will learn the basics of MicroPython and use standard popular modules.

Clock Operation - Interface

The clock has a button to set an alarm which it will ask to set the hour between 0 to 23. After confirming the hour, we can then select the minutes. The alarm sound comes from this passive buzzer that is inside the enclosure. Once the time is equal to the set time, the buzzer will start beeping - "Wake up," or you can change this to anything else, and the confirm button needs to be pressed to stop the buzzer.

Supplies

Sequence 01.00_01_14_22.Still001.png

To make this instructable as detailed as possible, I will include links from AliExpress; these are not affiliated links but will guide you on where to start. You might already have some of the components.

Feel free to change parts as needed depending on what you have available.

For the wood, it might be that you do not have access to a laser cutter, but there are online services that provide laser cutting, or the enclosure can be 3D printed or made out of cardboard. The enclosure is limited to your creativity.


- Raspberry Pi Pico + Header Pins + Cable - AliExpress

- 16 x 2 Character LCD display - AliExpress

- 4 Momentary Push Button Switch 16mm - AliExpress

- WS2812b 1m 60IP30 - AliExpress

- RTC DS1302 Real Time Clock Module - AliExpress

- Male-Female , Male-Male jumpers - AliExpress

- High Quality Passive Buzzer Module - AliExpress

- DC Connectors 5.5x2.1mm - AliExpress

1 * 2m - 20 AWG single core wire - AliExpress


Material:

3mm Plywood + Black Matt spray-paint

Equipment:

Ortur 2 Laser Master

Tools:

Soldering Iron, Wire stripper/cutter, Screwdriver, Glue

Optional:

3D printer, tools for cutting cardboard or wood if laser cutter is not used.

Note:

The above should be used to guide what will be needed to complete this project or make something similar. If your budget does not allow you to create this, you can replace the arcade and enclosure and use tactile switches on a breadboard.

Enclosure Design

Screenshot 2022-05-25 112437.png
Screenshot 2022-05-25 112330.png
Screenshot 2022-05-25 164209.png
alarm.00_04_28_12.Still001.png

The enclosure was designed first designed in MakerCase a cool online tool that let's you design cases depending on your specifications. The case plans can be downloaded to an DXF File and imported in your favorite CAD software. I went for Fusion360. The reason for choosing this software is that it is free to use with a hobbyist license. I have included all the files that you will need to cut. If not possible to cut the enclosure out of wood, alternatively 3D print or create your own enclosure from different materials.

The enclosure is very simple design which has T-slot joints.

After importing the DXF file in Fusion360 I made all the necessary slots and holes for the buttons, screens and dc plug and LED's connections. The DXF file is included below.

Now all that is left to do is either extrude and 3D print the enclosure or save the file to .dxf and use a laser cutter. The alternative will be to print this and stick on wood and cut out using power tools.

To give the enclosure a great looking finish I used some black spray-paint and give it 1-2 coats.

**Please note that the version of the case shown in instructables are different dimensions, which was difficult to fit all the components slight adjustments was made to the new DXF file included here.

Raspberry Pi Pico + Wiring

Pico Pinout.png
schematic3.png
Screenshot 2022-05-28 202644.png

Let's first look at the Raspberry Pi Pico. The Pico has 26 are multipurpose GPIOs (general-purpose input/output) which for our application is perfect since we we will be connecting a few buttons and modules. The pinout of the Pico is given above.

For the 16x2 character LCD we will be using the I2C 0 protocol of the Pico.

The rest of the push, buttons along with the modules can be connected to any GPIO pins. I have included two schematic diagram to show all the necessary connections, the fritzing diagram and Easy EDA diagram. I decided to use the breadboard to make to process easier, and will on a later stage design a PCB with all the components on a single board.

One side of the buttons will be connected to the 3.3V power by the Pico's 3V3 output on pin 36. Using the 20 AWG wire it was stripped clean of insulation and then connected to one pin of the buttons where after the connections was made proper by soldering the wire to the pin to make good connection. The buzzer and Realtime clock module will also receive power from the 3.3V.

The LCD and WS2182b LEDs will receive power from Vsys pin 39 which will also be the input power from the 5V DC power supply.

After making all the necessary connections you will first need to program the Pico before closing the case.


Installing MicroPython

ezgif.com-gif-maker (2).gif

Start with your Pico unplugged from USB. Hold down the BOOTSEL button, and while continuing to hold it (don't let go!), plug the Pico into USB. A short GIF above illustrates this step. Continue to hold the BOOTSEL button until the RPI-RP2 drive appears.

Drag the rp2-pico-20220117-v1.18.uf2  file to RPI-RP2.

Alternative method will be using Thonny to install MicroPython. If you are completely new to the Raspberry Pi Pico do not fear there are many videos and tutorials on getting started and I have included a tutorial here which you can find on my YouTube channel (Link).

Code Explanation

Now that you have your circuit on the breadboard. We can program the alarm clock function on the Pico. All the code for this project is available on GitHub.

We start by uploading all the needed libraries. Thanks to the following people that made the libraries link to their GitHub is given below.

LCD Display: https://github.com/T-622/RPI-PICO-I2C-LCD 

DS1302 Real-time clock: https://github.com/omarbenhamid/micropython-ds1302-rtc

Neopixel : https://github.com/blaz-r/pi_pico_neopixel

####################Import all the libraries#######################
from machine import I2C, Pin
from ds1302 import DS1302
from pico_i2c_lcd import I2cLcd
from neopixel import Neopixel
import utime
###################################################################

We will first set up our LCD. You will first need to get the address of your I2C device, which you can get by running the following script.

import machine
sda = machine.Pin(0)
scl = machine.Pin(1)
i2c = machine.I2C(0,sda=sda,scl=scl, freq=400000)
print(i2c.scan())

After getting the address, we can set up and initialize our LCD

################Setup LCD I2C and initialize#######################
I2C_ADDR     = 63
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16

i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
lcd.backlight_on()
###################################################################

We can now set up the DS1302 real-time clock.

################Setup DS1302 and initialize###########################
ds = DS1302(Pin(18),Pin(17),Pin(16))
ds.date_time() # returns the current datetime.
ds.date_time([2022, 5, 24, 0, 18, 24, 00]) # set datetime. comment out
print(ds.date_time())
######################################################################

This line of the code is critical

ds.date_time([2022, 5, 24, 0, 18, 24, 00]) # set datetime. comment out

Here you will set up the date and time by giving the following values: [year,month,day,weekday,hour,minute,second]; after you run the code, it is important to comment out the line and rerun the code. This will ensure the date and time are set and every time you power the Pico on and off, the clock will show the correct date and time

#ds.date_time([2022, 5, 24, 0, 18, 24, 00]) # set datetime. comment out

We then set up our buzzer, which we will use for the alarm.

#################initialize the Buzzer################################
buzzer = Pin(14, Pin.OUT)
buzzer.high()
######################################################################

We are using an example from the Neopixel library to display a line gradient of colors. Set the number of LEDs according to how many you have used for the project.

#################neopixel#############################################
numpix = 10
strip = Neopixel(numpix, 0, 2, "GRB")

red = (255, 0, 0)
orange = (255, 50, 0)
yellow = (255, 100, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
indigo = (100, 0, 90)
violet = (200, 0, 100)
colors_rgb = [red, orange, yellow, green, blue, indigo, violet]

# same colors as normaln rgb, just 0 added at the end
colors_rgbw = [color+tuple([0]) for color in colors_rgb]
colors_rgbw.append((0, 0, 0, 255))

# uncomment colors_rgbw if you have RGBW strip
colors = colors_rgb
# colors = colors_rgbw

step = round(numpix / len(colors))
current_pixel = 0
strip.brightness(80)

for color1, color2 in zip(colors, colors[1:]):
    strip.set_pixel_line_gradient(current_pixel, current_pixel + step, color1, color2)
    current_pixel += step

strip.set_pixel_line_gradient(current_pixel, numpix - 1, violet, red)
######################################################################

We then set up our interface with the alarm clock setting four pushbuttons as input

#################Buttons#############################################
Button_pins = [6,7,8,9]


Button = []
# Loop to assign GPIO pins and setup input and outputs
for x in range(0,4):


    Button.append(Pin(Button_pins[x], Pin.IN, Pin.PULL_DOWN))
    Button[x].value(0)
######################################################################

We set the initial values of the alarm

#################Set initial values of alarm############################################# 
set_hour = 25
set_minute = 3
set_second = 00
hour = 0
minute = 0
#########################################################################################  

The main function is the set_alarm(). This will be an overview of how it works. When the set alarm button is pushed, it will display the hour to be set and the minutes. The code is a bit long due to formatting the output on display. We return the set_hour and set_minute, which we will use in the check_alarm function.

def set_alarm():
    
    global set_hour
    global set_minute
    global set_second
    global hour
    global minute
   
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Set hour:")
    
    while Button[3].value() != 1:    
        if Button[1].value() == 1:
            set_hour += 1
            utime.sleep(0.1)
            set_hour = set_hour%24
            
        elif Button[2].value() == 1:
            set_hour -= 1
            utime.sleep(0.1)
            set_hour = set_hour%24
            
        hour = str(set_hour)
        
        while len(hour) < 2:
            hour = '0' + hour
        
        lcd.move_to(10,0)
        lcd.putstr(str(hour))
        
    lcd.clear()
    utime.sleep(0.3)
    lcd.move_to(0,0)
    lcd.putstr("Set minute:")
    
    while Button[3].value() != 1:
        if Button[1].value() == 1:
            set_minute += 1
            utime.sleep(0.1)
            set_minute = set_minute%60
        
        elif Button[2].value() == 1:
            set_minute -= 1
            utime.sleep(0.1)
            set_minute = set_minute%60
        
        minute = str(set_minute)
        while len(minute) < 2:
            minute = '0' + minute
            
        lcd.move_to(12,0)
        lcd.putstr(str(minute))
    
    lcd.clear()
    
    return(set_hour,set_minute)

The check_alarm function will check when the set_hour and set_minute are equal to the current time. The alarm will display "Wake Up!" and the buzzer will sound every 0.2 seconds.

def check_alarm(set_hour,set_minute,set_second):
     
    if set_hour == int(hr) and set_minute == int(m) and set_second == int(s) :
        while Button[3].value() != 1:
            lcd.clear()
            lcd.move_to(4,0)
            lcd.putstr("Wake Up!")
            utime.sleep(0.2)
            buzzer.low()
            utime.sleep(0.2)
            buzzer.high()
            lcd.clear()
    buzzer.high()

When the clock starts, it will display a message which you can choose to remove or change.

#########################Welcome Message#########################################
utime.sleep(1)        
buzzer.high()
### Welcome Message ###           
lcd.move_to(0,0)
lcd.putstr("Pico Alarm Clock")
lcd.move_to(0,1)
lcd.putstr("  Version 1.0   ")
utime.sleep(4)
lcd.clear()
#########################W########################################################

Now we can create an endless loop that will display the current date and time, check if the Set Alarm button is pushed, and check_alarm() to see if the alarm set time is equal to the current time.

while True:
    
    strip.rotate_right(1)
    strip.show()
    
    (Y,M,D,day,hr,m,s)=ds.date_time()
    if s < 10:
        s = "0" + str(s)
    if m < 10:
        m = "0" + str(m)
    if hr < 10:
        hr = "0" + str(hr)
    if D < 10:
        D = "0" + str(D)
    if M < 10:
        M = "0" + str(M)
        
    lcd.move_to(0,0)
    lcd.putstr("Time:")
    lcd.move_to(6,0)
    lcd.putstr(str(hr) + ":" + str(m) + ":" + str(s))
    lcd.move_to(0,1)
    lcd.putstr("Date:")
    lcd.move_to(6,1)
    lcd.putstr(str(D) + "/" + str(M) + "/" + str(Y))
    
    if Button[0].value() == 1:
        utime.sleep(0.1)
        print("Set Alarm")
        set_alarm()
    
    check_alarm(set_hour,set_minute,set_second)

This was a lot of explanation, but hopefully, the code makes sense. If you have any questions, please ask in the comments down below.

Assemble Alarm Clock

ezgif.com-gif-maker (3).gif

You now have a working alarm clock with all the code running. The final step is to assemble the clock and fit everything in the enclosure. Now, this might take some time, and you need to make sure that the cables are the correct length and are making a proper connection on the breadboard. In the future, creating a PCB version will eliminate any of the problems.

The case is easy to assemble using the bolts and nuts in the T-slot joints.

Future Improvement

As the saying goes, no project is ever really completed and can continually expand to make it better.

To continue with this project, I would look at replacing the buzzer with an mp3 module to play different songs.

Other possible ideas may be to convert this into an mp3 player with a Bluetooth module so this can become a proper modern mp3 alarm clock with speakers.

If you would like to collaborate, please reach out. I hope you found this instructable useful.