TTGO T8 ESP32-S2 ST7789 Display NTP Clock in CircuitPython

TTGO T8 ESP32-S2 ST7789 Display NTP Clock in CircuitPython. Following on from my last post on the TTGO T8 ESP32-S2 ST7789, I just could not leave that lovely screen sitting there doing nothing.

Seems other’s felt the same, more on that later. My OCD can make me, what some might call “obsessive”, so there was never really going to be any option other than sticking with it and get this working in CircuitPython.

Finding code by Netroy on

Of course there there were errors, I was using CircuitPython 7.0.0 for one thing, but that’s OK, so began the journey of debugging.

And, with due thanks to everyone, I give you…

What we have here is a TTGO T8 ESP32-S2 ST7789 checking it’s file, opening a WiFi connection, then the file connecting to and syncing with the time server getting the current time before displaying it on the ST7789 sleeping then doing it again.

Before we move on I must assume that you have followed this post.

and have your ESP32-S2 ST7789 setup and working at this level.

You will need to download the CircuitPython libraries and unzip the Library bundle to a directory of your choosing on your local drive.

Create on your CIRCUITPY drive a lib folder

Then copy complete adafruit_display_text folder from the adafruit-circuitpython-bundle zip folder you just unzipped, to the new lib folder on your CIRCUITPY drive.

When you’re done it all should look like this.

You will also need to create a file with the following content…

# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it

secrets = {
    'ssid' : 'home_wifi_network',
    'password' : 'wifi_password',
    'aio_username' : 'my_adafruit_io_username',
    'aio_key' : 'my_adafruit_io_key',
    'timezone' : "America/New_York", #

Note –

edit the ssid to be ssid of your router to the internet

edit password to be the password for the above

edit Location to be your location; mine is Australia/Brisbane

Now create or edit the file

# original code by Netroy on
# mods  for CircuitPython 7.0.0 TTGO T8 ESP32-S2 ST7789 2021
# By Al McDivitt iotXplain
import struct
import time
import board
import displayio
import rtc
import socketpool
import terminalio
import wifi
from adafruit_display_text import label

  from secrets import secrets
except ImportError:
  print("WiFi secrets are kept in, please add them there!")

TZ_OFFSET = +36000

NTP_PORT = 123

def get_ntp_time(pool):
  packet = bytearray(48)
  packet[0] = 0b00100011

  for i in range(1, len(packet)):
    packet[i] = 0

  with pool.socket(pool.AF_INET, pool.SOCK_DGRAM) as sock:
    sock.sendto(packet, (NTP_SERVER, NTP_PORT))
    destination = time.monotonic_ns()

  seconds = struct.unpack_from("!I", packet, offset=len(packet) - 8)[0]
  monotonic_start = seconds - 2_208_988_800 - (destination // 1_000_000_000)
  return time.localtime(time.monotonic_ns() // 1_000_000_000 + monotonic_start + TZ_OFFSET)

TEXT_COLOR = 0xd257ff

def init_ui(display):
  splash = displayio.Group()

  color_bitmap = displayio.Bitmap(display.width, display.height, 1)
  color_palette = displayio.Palette(1)
  color_palette[0] = BACKGROUND_COLOR

  bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)

  # Draw a smaller inner rectangle
  inner_bitmap = displayio.Bitmap(display.width - BORDER * 2, display.height - BORDER * 2, 1)
  inner_palette = displayio.Palette(1)
  inner_palette[0] = FOREGROUND_COLOR
  inner_sprite = displayio.TileGrid(inner_bitmap, pixel_shader=inner_palette, x=BORDER, y=BORDER)

  text_label = label.Label(terminalio.FONT, color=TEXT_COLOR, text="Starting", anchor_point=(0.5, 0.5))
  text_width = text_label.bounding_box[2] * FONTSCALE
  text_group = displayio.Group(
      x=display.width // 2 - text_width // 2,
      y=display.height // 2,

  return text_label

def update_time(text_label):
  now = time.localtime()
  text_label.text = "%02.d:%02.d:%02.d" % (now.tm_hour, now.tm_min, now.tm_sec)
  #note by al
display = board.DISPLAY
text_label = init_ui(display)

print("Connecting to ", secrets["ssid"])["ssid"], password=secrets["password"])
print("Connected with IP ",
text_label.text = "Connected"

pool = socketpool.SocketPool(
now = get_ntp_time(pool)
rtc.RTC().datetime = now
print("Synced with NTP")
text_label.text = "Synced"

while True:


TZ_OFFSET = +36000 # this is my offset +10:00 hours… you will need too adjust this to suit your offset.

If you are using the MU editor when you save the changes to the file the ESP32s2 device should restart and check it’s file, open a wifi connection, then the will connect with the time server showing messages about these steps before displaying the time on the ST7789 , before sleeping, then doing it again.

ESP32-S2 ST7789 Display NTP Clock in CircuitPython

Now while I was obsessed with getting the ESP32 S2 with ST7789 working with CircuitPython, someone else was going about it another way…

I was contacted by Bernard from who had a go working with the ESP32 S2 with ST7789 using MicroPython, he found there was little information about the screen. So, returned to his preference for working in the Arduino environment, with considerable success I might add.

Anyway, have a look at the work Bernard has been doing.

Thanks for the contact Bernard, I will be checking out more of your code soon.

So everyone, I think that’s a wrap, getting to this point has been interesting. I admit some of the debugging on the code was down to just edit the code and pray. Maybe I’m crazy, but in some ways I did enjoy the journey and I do like what the combination of the TTGO T8 ESP32-S2 ST7789 and CircuitPython can do, in the end.. Damn OCD.