Christmas Countdown Clock

by Henkeify in Circuits > Raspberry Pi

4398 Views, 53 Favorites, 0 Comments

Christmas Countdown Clock

IMG_6873.JPG
IMG_6837.JPG
IMG_6927.JPG

Recent studies have shown that we are happier when we have something to look forward to, sometimes even happier than the thing we are anticipating will actually make us!

I really like christmas so I made this countdown clock which I will keep in my book shelf so I can always know how long it is until Christmas day.

I used a raspberry pi, a small LCD screen, Tinkercad for case design and a 3D printer.

Supplies

IMG_6100.jpg
snagit4.png
IMG_6108.jpg
  • Raspberry pi (I used a 3B+ but any pi which you can connect a small screen to will work)
  • Raspberry pi peripherals
  • Mouse
  • Keyboard
  • Screen with HDMI cable
  • Micro SD memory card
  • Power supply
  • Small screen, I used this non touch LCD screen which connects over GPIO but I really recommend that you get one that connects via HDMI, that is much easier. A 5-inch 480x800 screen will fit the case I designed.
  • 3D printed parts
  • 4 small wood screws (I used countersunk 3mm outer diameter and 11mm total length)
  • Screwdriver

Design Case

snagit5.png
snagit3.png
snagit14.png
snagit7.png
snagit9.png

I designed the case using Tinkercad, it consists of a box which will hold the pi, a middle plate which the screen will rest on and a top part which will hold the screen in place. They each have 4 aligning holes which the wooden screws will be placed in to secure the case.

The bottom piece contains holes which a raspberry pi power cable can be inserted into, the holes also help heat escape.

This is the link to the tinkercad project so that you can edit the design to fit your particular setup or just go ahead and download the parts as STL files and print.

Speaking of...

Print Parts

snagit1.png
snagit2.png
IMG_6079.jpg
IMG_6080.jpg

I sliced the parts using Prusaslicer, I used 10% infill and a 0.4 nozzle. These parts are designes so that you don't need any support materials, as long as your printer can handle a little bit of overhang angle.

I used Addnorths E-PLA on my old Prusa mk2.5 and the pieces came out really good.

I only had white filament at home but this clock would really benefit from some festive colours!

Set Up Raspberry Pi

2023-01-11-181114_800x480_scrot.png
2023-01-11-181838_800x480_scrot.png
2023-01-12-190536_800x480_scrot.png
2023-01-12-190453_800x480_scrot.png

Burn the raspbian image to your SD card and start the pi as you would any pi setup. If this is the first time you set up a pi, follow this tutorial to get started.

Connect the pi to any big old screen for now, no small screen yet.

Once you are up and running we will need to perform these tasks before we get to the actual code:

  • Edit the boot config file to enable the LCD screen (Only if you use a screen which connects over GPIO, if you use an HDMI one you can skip this)
  • Disable screen saver (We want the pi to show the screen all the way until Christmas)
  • Hide the task bar in the top of the screen


Enable external screen (again, this step is only if you use a GPIO interface for your screen)

Open a new terminal window and enter the following command

sudo nano /boot/config.txt

Scroll all the way to the bottom and paste the following lines.

dtoverlay=dpi24
enable_dpi_lcd=1
display_default_lcd=1
dpi_group=2
dpi_mode=87
dpi_output_format=0x6f005
hdmi_timings=800 0 40 48 88 480 0 13 3 32 0 0 0 60 0 32000000 6
framebuffer_width=800
framebuffer_height=480

If your screen has a different resolution than 480x800 the you will need to adjust for that.

The config file should now look like picture nr 2 (at least the bottom parts).

Press Ctrl + X to exit the file and when prompted if you want to save, press Y and the Enter.


Disable screen blanking

Go the Start menu --> Preferences --> Raspberry pi configuration and then go to the Display tab.

For some reason I couldn't take screen shots while navigating the menu, sorry about that, but you want to end up at picture nr 3 and then go ahead and disable screen blanking, that will make sure that your screen doesn't go black after the pi has been idle for a while.


Hiding the top task bar

Hover the mouse over the task bar at the top of the screen and right click, then chose Panel settings and click the tab Advanced and then check the box Minimize panel when not in use. Set the size of the panel to as many pixels as you like, I chose 1. To be able to reach the top panel after this, hover the mouse where the panel used to be and it will reappear.

Make Code

2023-01-12-205114_800x480_scrot.png

I used Guizero for the gui, it is a simple library which sits on top of the more popular Tkinter but is made more user friendly for beginners. I learned a bit about this using this book which is published by Raspberry pi Press, which is part of the official Raspberry Pi.

You will need to install guizero but is really simple, in a new terminal window enter

pip3 install guizero

and you are good to go.


I will try to explain some pieces of the code below but if you want, you can just grab it and run.

Open a new window in your favourite python editor, I use Thonny.

Paste this code and save it as whatever you like, mine is called Christmastimer.py

from guizero import App, Text
import time
import datetime

def update():

    now = datetime.datetime.now()

    christmas = datetime.datetime(2023,12,25,00,00)

    diff = christmas-now
    diff = str(diff)
    
    blank = []
    colon = []

    for i in range(len(diff)):
        if diff[i] == " ":
            blank.append(i)

    for j in range(len(diff)):
        if diff[j] == ":":
            colon.append(j)
    

    days = diff[0:blank[0]]
    hours = diff[(blank[1] + 1):colon[0]]
    minutes = diff[(colon[0] + 1):colon[1]]
    seconds = diff[(colon[1] + 1):(colon[1] + 3)]

    if hours[0] == "0":
        k = hours[1]
        hours = k

    if minutes[0] == "0":
        l = minutes[1]
        minutes = l

    if seconds[0] == "0":
        m = seconds[1]
        seconds = m
    
    text_days.value = days + " days"

    if hours == "1":
        text_hours.value = hours + " hour"
    else:
        text_hours.value = hours + " hours"
    
    if minutes == "1":
        text_minutes.value = minutes + " minute"
    else:
        text_minutes.value = minutes + " minutes"

    if seconds == "1":
      text_seconds.value = seconds + " second"  
    else:
        text_seconds.value = seconds + " seconds"
        
    text_seconds.after(500,update)
    
app = App(title="Christmas Timer",width=810,height=500)
app.bg = (20, 107, 58)

text_0 = Text(app, text="")
text_1 = Text(app, text = "It is currently", size = 70,color="red")
text_days = Text(app, text="", size = 40,color="red")
text_hours = Text(app, text="", size = 40,color="red")
text_minutes = Text(app, text="", size = 40,color="red")
text_seconds = Text(app, text="", size = 40,color="red")
text_2 = Text(app,text = "until Christmas!", size = 70,color="red")

text_seconds.after(500,update)

app.display()


Explaining the code

The main part of the program is actually the small bit at the bottom.

app = App(title="Christmas Timer",width=810,height=500)
app.bg = (20, 107, 58)

text_0 = Text(app, text="")
text_1 = Text(app, text = "It is currently", size = 70,color="red")
text_days = Text(app, text="", size = 40,color="red")
text_hours = Text(app, text="", size = 40,color="red")
text_minutes = Text(app, text="", size = 40,color="red")
text_seconds = Text(app, text="", size = 40,color="red")
text_2 = Text(app,text = "until Christmas!", size = 70,color="red")

text_seconds.after(500,update)

app.display()

The first lines just defines a guizero app (width and height should match your small screen resolution so you might want to change this depending on your hardware) and sets background color to a Christmasy green.

The next lines defines text objects, with text associated to them, color and size. Note that some of the have text="", this is because we will update them using our function later.

text_seconds.after(500,update)

This line tells the program to run the function update after 500 milliseconds.

Speaking of the function update, in broad strokes it checks what date and time it is now and compares that to Christmas day 2023 (this is where you replace the date for christmas day if you want to look forward to any other date)

now = datetime.datetime.now()

christmas = datetime.datetime(2023,12,25,00,00)

diff = christmas-now
diff = str(diff)


The rest of the function just parses the string containing the difference between now and Christmas day and distributes that information to the days, hours, minutes and seconds strings.

    blank = []
    colon = []

    for i in range(len(diff)):
        if diff[i] == " ":
            blank.append(i)

    for j in range(len(diff)):
        if diff[j] == ":":
            colon.append(j)
    

    days = diff[0:blank[0]]
    hours = diff[(blank[1] + 1):colon[0]]
    minutes = diff[(colon[0] + 1):colon[1]]
    seconds = diff[(colon[1] + 1):(colon[1] + 3)]


We want to format the values a bit nicely so depending on wether i.e. hours contains a starting 0, we may want to change the string a bit (so the final text goes from "09 hours" to just "9 hours")

    if hours[0] == "0":
        k = hours[1]
        hours = k

    if minutes[0] == "0":
        l = minutes[1]
        minutes = l

    if seconds[0] == "0":
        m = seconds[1]
        seconds = m


The last part of the function adds the trailing text after the value and checks if the number of i.e. hours is singular and changes the text accordingly ("1 hour" instead of "1 hours"), then the function updates the text objects from the main code (you know, the ones with the text="") and finally, the code calls itself,

    text_seconds.after(500,update)

so it keeps updating, otherwise the program would just run once and never change the values.


I hope that my explanation made some sense, please do not hesitate to ask if you have questions about it or any comments at all.

Assemble

IMG_6097.jpg
IMG_6096.jpg
IMG_6098.jpg
IMG_6101.jpg
IMG_6087.jpg
IMG_6103.jpg
IMG_6110.jpg

Now it is time to shut down the pi and connect it to your small screen, depending on how your screen works you might need to run it through the middle plate before you attach the ribbon cable to the pi:s GPIOS. Flick the switch which starts the back light of the screen and the connect your mouse (keyboard shouldn't be needed at this point) and your power supply, remember to run it through the hole in the bottom of the box!

Before you power the pi, make sure your cable will reach the place you want to put it in when it is done, it is a bit cumbersome to power it down, open the box and restart it if you want to move location of your countdown timer.

If you have done your setup correct you will be met with the usual raspbian background but much smaller, congratulations!

Now you just have to open the code in your editor again and click run. Hopefully it should fit the screen perfectly but you might need to tweak the size of the window and text a bit before it looks perfect.

When you are happy with the program and it looks like picture nr 3, disconnect the mouse (and keyboard) and the place the pi in the box and gently push the ribbon cable inside the box and put the middle piece on it, make sure you are not damaging the pi or the cable.

Place the screen on the middle piece and then put the cover on top.

When you are happy with the alignment, use your small screws (they should be a bit bigger in outer diameter than the hole and not too long) to secure everyting in place with a screwdriver.

Enjoy Anticipating Christmas

IMG_6871.JPG
IMG_6916.JPG

Place the countdown clock somewhere you will see it and enjoy the wait.