Maker.io main logo

World Clock

2,071

2025-07-11 | By Adafruit Industries

License: See Original Project LCD / TFT Solder / Desoldering

Courtesy of Adafruit

Guide by Ben Everard

Overview

clock_1

Create a world clock to show a satellite photo of the earth with the current midday at the center of the display. The map slowly scrolls across doing a complete loop every 24 hours.

This clock tracks solar time so the middle of the display is the point where the sun in highest in the sky. Solar time is usually quite close to the time our clocks show but doesn't take into account daylight savings or time zones that are ahead or behind solar time.

In the above photo, it's solar noon in England, so the time is 8am in New York and 5am in Los Angeles. Slightly confusingly, it's 1pm in London (because of daylight savings time).

Parts:

You might also need:

You'll need something like the following to power and program your clock.

If you have access to a 3D printer, you can print out your support for the clock. Alternatively, you can fabricate a support out of whatever you like. It would be fairly straightforward to make one out of wood or foam board. The mounting points on the LCD take M2 machine screws (or other screws that will fit through a 0.1 inch hole).

Connecting the Hardware

hardware_2

The Adafruit EYESPI BFF for QT Py comes with header pins that you can use to solder this board to the Adafruit QT Py S3, but you need to break them into two segments each 7 pins long.

Before powering up your soldering iron, do a dry fit to ensure you know what you're connecting to where. Make sure that you've connected the two boards the right way around (the flex cable port and the USB C port should be at the same end and each be on the outside of the sandwich. You can confirm that everything's as it should be because the 5V and A0 pins should be against their equivalent number on both boards. The plastic part of the pins should be between the two boards preventing any components from touching.

Keep everything together like this and solder each pin to make the connection permanent. It should look like the image below.

connection_3

Connect the Screen to the BFF

The EYESPI Cable connects the Adafruit 1.28" 240x240 Round TFT LCD Display to the Adafruit EYESPI BFF for QT Py. On both boards, there is a connector for flat cables. Gently lever up the darker plastic clip gently using your fingernail (or something similar) – it should rotate 90 degrees and expose some contact underneath. On either end of the cable there are exposed metal contacts. The metal contacts on one end of the cable should be placed on top of the metal contacts on the connector, then push the cable as far into the connector as it will go. Once in place, the dark plastic clip can be pressed back down to secure the cable. When it's connected properly, it should withstand a gentle tug – if it comes out, repeat the process being sure to push the cable as far into the connector as possible.

cable_4

cable_5

Repeat the process on the LCD side so that cable joins the Adafruit EYESPI BFF and the LCD.

lcd_6

That's the hardware connected, it's time to move onto the software.

CircuitPython

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

CircuitPython QuickStart

Follow this step-by-step to quickly get CircuitPython running on your board.

There are two versions of this board: one with 8MB Flash/No PSRAM and one with 4MB Flash/2MB PSRAM. Each version has their own UF2 build for CircuitPython. There isn't an easy way to identify which version of the board you have by looking at the board silk. If you aren't sure which version you have, try either build to see which one works.

There are two versions of this board: one with 8MB Flash/No PSRAM and one with 4MB Flash/2MB PSRAM.

Download the latest version of CircuitPython for the 8MB/No PSRAM version of this board via circuitpython.org

Download the latest version of CircuitPython for the 4MB/2MB PSRAM version of this board via circuitpython.org

Click the link above to download the latest CircuitPython UF2 file.

Save it wherever is convenient for you.

click_7

board_8

Plug your board into your computer, using a known-good data-sync cable, directly, or via an adapter if needed.

Click the reset button once (highlighted in red above), and then click it again when you see the RGB status LED(s) (highlighted in green above) turn purple (approximately half a second later). Sometimes it helps to think of it as a "slow double-click" of the reset button.

If you do not see the LED turning purple, you will need to reinstall the UF2 bootloader. See the Factory Reset page in this guide for details.

On some very old versions of the UF2 bootloader, the status LED turns red instead of purple.

For this board, tap reset and wait for the LED to turn purple, and as soon as it turns purple, tap reset again. The second tap needs to happen while the LED is still purple.

Once successful, you will see the RGB status LED(s) turn green (highlighted in green above). If you see red, try another port, or if you're using an adapter or hub, try without the hub, or different adapter or hub.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.

If after several tries, and verifying your USB cable is data-ready, you still cannot get to the bootloader, it is possible that the bootloader is missing or damaged. Check out the Factory Reset page for details on resolving this issue.

You will see a new disk drive appear called QTPYS3BOOT.

Drag the adafruit_circuitpython_etc.uf2 file to QTPYS3BOOT.

drive_9

The BOOT drive will disappear, and a new disk drive called CIRCUITPY will appear.

That's it!

boot_10

Code

Are you new to using CircuitPython? No worries, there is a full getting started guide here.

Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and installation in this tutorial.

Getting the image

The clock is going to display an image of the earth, so the first thing to do is get this image. NASA makes all their images free to use and has a full earth image made from multiple satellite photos stitched together. This has been converted into the right format and resized. The resulting image is available below. Save this image with the file name world.bmp to the root directory of your QT Py (depending on your browser, that probably means right click > Save Image As).

map_11

Set your environmental variables

The clock will get the current time from the internet, so it needs the details to log into your WiFi network. Open the settings.toml file on your QT Py (or create one if it doesn't already exist), and enter the following:

CIRCUITPY_WIFI_SSID = "YOUR-WIFI-SSID"

CIRCUITPY_WIFI_PASSWORD = "YOUR-WIFI-PASSWORD"

With the correct Wifi password and network name. Ensure the values on the right are in double quotes (")

Get the libraries and code

You'll need the following libraries.

  • adafruit_connection_manager.mpy

  • adafruit_gc9a01a.mpy

  • adafruit_ntp.mpy

The easiest way to get these is to click 'Download Project Bundle' below. This will give you a ZIP file containing the code and libraries you need for this project. Save this file somewhere on your computer and open it up. You should see folders for each of the current versions of CircuitPython. Take the code.py file and lib folder from the folder for your version of CircuitPython and copy them onto your QT Py.

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2025 Ben Everard for Adafruit Industries
#
# SPDX-License-Identifier: MIT
'''Display a world clock on a round LCD'''

import os
import time
import board
import displayio
import fourwire
from adafruit_gc9a01a import GC9A01A
import wifi
import adafruit_ntp
import adafruit_connection_manager

wifi.radio.connect(ssid=os.getenv('CIRCUITPY_WIFI_SSID'),
                   password=os.getenv('CIRCUITPY_WIFI_PASSWORD'))

pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600)

displayio.release_displays()
spi = board.SPI()
tft_cs = board.TX
tft_dc = board.RX

display_bus = fourwire.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=None
)

display = GC9A01A(display_bus, width=240, height=240, auto_refresh=False)

world = displayio.OnDiskBitmap("/world.bmp")

tile_grid_1 = displayio.TileGrid(world, pixel_shader=world.pixel_shader)
tile_grid_2 = displayio.TileGrid(world, pixel_shader=world.pixel_shader)

group = displayio.Group()

group.append(tile_grid_1)
group.append(tile_grid_2)
display.root_group = group

# Loop forever so you can enjoy your image
while True:
    tile_grid_1.x = (20*ntp.datetime.tm_hour)+120
    tile_grid_2.x = tile_grid_1.x-480
    display.refresh()
    time.sleep(60)

View on GitHub

As soon as this is all saved, the QT Py should reboot and after a few seconds, display an image of the world with the current mid-day point in the middle. If it doesn't then check that you have all the required files on the device, and that you are in an area with Wifi coverage.

saved_12

Map projection

There is a bit of a rendering error in this clock. The Earth is obviously a sphere, and the image we're using is a flat rectangle. There are various ways of squishing an image of a sphere onto a rectangle, but they all introduce errors.

Our clock doesn't account for the curvature of the earth. To us, this doesn't matter because it makes it easier to recognize the part of the Earth that's currently showing. If you'd prefer to render it in a different way, you can update the code however you'd like.

That's the electronics setup. Now to look at the physical setup.

Finishing Touches

Our clock holder needs to fulfill two basic tasks:

  1. Keep the clock face upright.

  2. Stop the pins on the QT Py touching the back of the LCD.

As long as you manage those things, you can set it up however you like. There is an STL file you can use if you want to but be as creative as you like with your housing.

You can download the clock holder STL file from https://www.printables.com/model/1281120-clock-holder or via the green button below. It should print on its side without supports. Two machine screws hold the LCD in place. There are no mounting holes on the QT Py, so you'll need to use a dollop of something sticky to hold it in place. I used White Tack, but hot glue would also work (but might be harder to remove). Whatever you use, just be careful to keep it away from the USB or STEMMA QT ports.

Clock Holder STL File

holder_13

Once everything's together, plug it into a power source and enjoy your world clock.

worldclock_14

Mfr Part # 5700
ADAFRUIT QT PY S3 WITH 2MB PSRAM
Adafruit Industries LLC
$102.90
View More Details
Mfr Part # 5772
EYESPI BREAKOUT BOARD QT PY/XIAO
Adafruit Industries LLC
Mfr Part # 5462
CABLE FFC/FPC 18POS 0.5MM 1.97"
Adafruit Industries LLC
Mfr Part # 6178
ADAFRUIT 1.28 240X240 ROUND TFT
Adafruit Industries LLC
$144.06
View More Details
Mfr Part # 4474
CABLE A PLUG TO C PLUG 3'
Adafruit Industries LLC
5V 2A SWITCHING POWER SUPPLY W/
Mfr Part # 1994
5V 2A SWITCHING POWER SUPPLY W/
Adafruit Industries LLC
Add all DigiKey Parts to Cart
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.