The previous article “Implementation and Experience of Pointer Dial Function for ESP32C3 Smartwatch” shared the functionality of the pointer dial on the ESP32C3 smartwatch. In the video, the Redmi Band 2 was used for comparison, which shows the main screen after touch and goes to sleep after 5 seconds. We have created a default sleep and touch display effect based on the Redmi Band 2.
This similar functionality can also be ported to Lichuang Practical.
1. Introduction to the Smartwatch
This smartwatch is controlled by the ESP32C3 and is equipped with a1.69-inch
touchscreen with a resolution of240x320
. The display driver used isST7789
, and the touch driver isCST816T
.
2. Touch Driver
There is no relevant Python driver forCST816T
found on Github, so I rewrote the C language driver into aMicropython
driver. The download link is: https://gitee.com/py2012/cst816t
3. Network Connection and Time Retrieval
The time displayed in the previous article is the system time. Once the USB connection is disconnected, the time resets to midnight. To get real-time, we need to connect to the internet. The relevant function code is as follows:
def do_connect(): wlan = network.WLAN(network.STA_IF) wlan.active(True) if not wlan.isconnected(): print('Connecting to WIFI...') tft.text(font, 'connecting to network...',0,0)# no Chinese character library wlan.connect('SSID', 'password')# Replace SSID and password with WIFI account password i = 1 while not wlan.isconnected(): # Wait for wireless connection print("Connecting...{}".format(i)) tft.text(font, "Connecting...{}".format(i),0,16) i += 1 utime.sleep(1) print('network config:', wlan.ifconfig()) tft.text(font, 'network config:{}'.format(wlan.ifconfig()),0,16)
def sync_ntp(): print("Starting to sync network time") tft.text(font, "loading",0,32) try: ntptime.NTP_DELTA = 3155644800 # Default ntptime.host = 'pool.ntp.org' # NTP server, default is "pool.ntp.org" ntptime.settime() # Modify device time except: sync_ntp()
4. Touch Display
TheCST816T
driver contains aFingerIndex
parameter, which confirms whether the screen is touched by judging theFingerIndex
parameter. The default state is sleep (screen displays black), and when the screen is touched, it shows the time dial, and goes to sleep again after 6 seconds. The reference code is as follows:
"""PY Learning Notes"""from machine import Pin, SPIimport utimeimport mathimport st7789import ntptimeimport networkimport vga1_bold_16x16 as fontfrom cst816t import CST816T
'''Relevant functions omitted, see above for details'''# Initialize display screentft = config()tft.init()tft.fill(st7789.BLACK)# Initialize touch screent = CST816T(sda_pin=11, scl_pin=7, rst_pin=10, int_pin=9)
def main(): # Connect to the internet and get time do_connect() sync_ntp() width = tft.width() height = tft.height() radius = min(width, height) ofs = (width - radius) // 2 center_x = radius // 2 + ofs - 1 center_y = radius // 2 - 1
# Draw dial background face = "face_320x240_3.jpg"# Change to black background tft.jpg(face, 0, 0, st7789.SLOW)
# Create polygons for hour, minute, and second hands # The polygon must be a closed convex polygon, otherwise there will be problems. second_len = int(radius * 0.65 / 2) second_poly = hand_polygon(second_len, 2) minute_len = int(radius * 0.6 / 2) minute_poly = hand_polygon(minute_len, 2) hour_len = int(radius * 0.5 / 2) hour_poly = hand_polygon(hour_len, 3)
# Calculate the constants for the angles of the hands. pi_div_6 = math.pi/6 pi_div_30 = math.pi/30 pi_div_360 = math.pi/360 pi_div_2160 = math.pi/2160
# Initialize boundary rectangle variables for drawing hour, minute, and second hands. # Calling bounding with True will reset the boundary, calling with False will disable the boundary tft.bounding(True) hour_bound = tft.bounding(True) minute_bound = tft.bounding(True) second_bound = tft.bounding(True)
last_touch_time = 0 # Record last touch time screen_timeout = 6 # Screen timeout (seconds) screen_on = False # Screen display status
# Initial state is black screen tft.fill(st7789.BLACK)
while True: current_time = utime.time() FingerIndex,x,y,_ = t.getTouch() # Detect touch events if FingerIndex != 0: # When there is touch if not screen_on: # If the screen is off # Redisplay dial background tft.jpg(face, 0, 0, st7789.SLOW) screen_on = True last_touch_time = current_time # Check if the screen needs to be turned off if screen_on and (current_time - last_touch_time > screen_timeout): tft.fill(st7789.BLACK) # Fill black to achieve sleep screen_on = False # Only update the clock when the screen is on if screen_on: # Save the current time (seconds) to determine when to update the display. last = current_time
# Get current hour, minute, and second _, _, _, hour, minute, second, _, _ = utime.localtime() # Convert to Beijing time hour = (hour + 8) % 24 # Convert 24-hour format to 12-hour format hour = hour % 12 if hour % 12 != 0 else 12
# Calculate the angle (radians) of the hour hand # Every hour turns 30 degrees(π/6), every minute turns 0.5 degrees(π/360), every second turns(1/120) degrees(π/21600) hour_ang = ( (hour * pi_div_6) + (minute * pi_div_360) + (second * math.pi/21600)) + math.pi # Add 180 degrees to compensate for screen rotation
# Calculate the angle (radians) of the minute hand # Every minute turns 6 degrees(π/30), every second turns 0.1 degrees(π/1800) minute_ang = ( (minute * pi_div_30) + (second * math.pi/1800)) + math.pi # Add 180 degrees to compensate for screen rotation
# Calculate the angle (radians) of the second hand second_ang = (second * pi_div_30) + math.pi # Add 180 degrees to compensate for screen rotation
# Erase the last drawn boundary area of the hour hand x1, y1, x2, y2 = hour_bound tft.fill_rect(x1, y1, x2, y2, st7789.BLACK)
# Erase the last drawn boundary area of the minute hand x1, y1, x2, y2 = minute_bound tft.fill_rect(x1, y1, x2, y2, st7789.BLACK)
# Erase the last drawn boundary area of the second hand x1, y1, x2, y2 = second_bound tft.fill_rect(x1, y1, x2, y2, st7789.BLACK)
# Draw the center point after erasing the boundary area to reduce flicker tft.fill_circle(center_x, center_y, 5, st7789.RED)
tft.bounding(True) # Clear boundary rectangle
# Draw and fill the hour hand polygon rotated to hour_ang tft.fill_polygon(hour_poly, center_x, center_y, st7789.WHITE, hour_ang)
# Get the boundary rectangle drawn by the hour polygon and reset the boundary box for the next polygon hour_bound = tft.bounding(True, True)
# Draw and fill the minute hand polygon rotated to minute_ang tft.fill_polygon(minute_poly, center_x, center_y, st7789.WHITE, minute_ang)
# Get the boundary rectangle drawn by the minute polygon and reset the boundary box for the next polygon minute_bound = tft.bounding(True, True)
# Draw and fill the second hand polygon rotated to second_ang tft.fill_polygon(second_poly, center_x, center_y, st7789.RED, second_ang)
# Get the boundary rectangle drawn by the second polygon and reset the boundary box for the next polygon second_bound = tft.bounding(True, True)
# Draw the center point again to cover the second hand tft.fill_circle(center_x, center_y, 5, st7789.RED)
# Wait until the current second changes while last == utime.time() and screen_on: FingerIndex,x,y,_ = t.getTouch() if FingerIndex != 0: last_touch_time = utime.time() if utime.time() - last_touch_time > screen_timeout: screen_on = False tft.fill(st7789.BLACK) break utime.sleep_ms(50) else: utime.sleep_ms(100) # Reduce polling frequency when the screen is off
main()
1. The ESP32C3 smartwatch is connected to 3.3V and is always on by default, which cannot be adjusted. Therefore, black filling is used instead of sleep (however, it does not save power).
2. The dial is not finely polished, and there may be some blurriness next to the scale, which is not noticeable in reality but is quite obvious in the video. Please ignore it.
Recommended Reading:
-
High-precision voltage measurement experimental device based on ADS1115 (4. Capacitor charging and discharging experiment)
-
Make a camera-controlled car for less than 100 yuan (Part 2)
-
Lichuang Practical ESP32S3 Practical: How to Display Camera Images in Real-time on the Screen
-
Sky Star STM32 Solder a Battery Holder: Create a Smart Clock
-
ESP32-C3 E-ink Screen Electronic Clock (Based on Micropython)
-
Micro Weather Station Based on RP2040 and MicroPython