From f76019f31cb8c4386bc0c3e96a38a5f7c73ecb53 Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Sat, 29 Oct 2022 13:02:42 +0100 Subject: [PATCH] Add time synchronization from NTP to GU clock example --- .../examples/galactic_unicorn/clock.py | 107 ++++++++++++++++-- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/micropython/examples/galactic_unicorn/clock.py b/micropython/examples/galactic_unicorn/clock.py index e56278d9..13fce333 100644 --- a/micropython/examples/galactic_unicorn/clock.py +++ b/micropython/examples/galactic_unicorn/clock.py @@ -1,9 +1,30 @@ +# Clock example with NTP synchronization +# +# Create a secrets.py with your Wifi details to be able to get the time +# when the Galactic Unicorn isn't connected to Thonny. +# +# secrets.py should contain: +# WIFI_SSID = "Your WiFi SSID" +# WIFI_PASSWORD = "Your WiFi password" +# +# Clock synchronizes time on start, and resynchronizes if you press the A button + import time import math import machine +import network +import ntptime from galactic import GalacticUnicorn from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY +try: + from secrets import WIFI_SSID, WIFI_PASSWORD + wifi_available = True +except ImportError: + print("Create secrets.py with your WiFi credentials to get time from NTP") + wifi_available = False + + # constants for controlling the background colour throughout the day MIDDAY_HUE = 1.1 MIDNIGHT_HUE = 0.8 @@ -90,21 +111,76 @@ def outline_text(text, x, y): graphics.text(text, x, y, -1, 1) +# Connect to wifi and synchronize the RTC time from NTP +def sync_time(): + if not wifi_available: + return + + # Start connection + wlan = network.WLAN(network.STA_IF) + wlan.active(True) + wlan.connect(WIFI_SSID, WIFI_PASSWORD) + + # Wait for connect success or failure + max_wait = 100 + while max_wait > 0: + if wlan.status() < 0 or wlan.status() >= 3: + break + max_wait -= 1 + print('waiting for connection...') + time.sleep(0.2) + + redraw_display_if_reqd() + gu.update(graphics) + + if max_wait > 0: + print("Connected") + + try: + ntptime.settime() + print("Time set") + except OSError: + pass + + wlan.disconnect() + wlan.active(False) + + +# NTP synchronizes the time to UTC, this allows you to adjust the displayed time +# by one hour increments from UTC by pressing the volume up/down buttons +# +# We use the IRQ method to detect the button presses to avoid incrementing/decrementing +# multiple times when the button is held. +utc_offset = 0 + +up_button = machine.Pin(GalacticUnicorn.SWITCH_VOLUME_UP, machine.Pin.IN, machine.Pin.PULL_UP) +down_button = machine.Pin(GalacticUnicorn.SWITCH_VOLUME_DOWN, machine.Pin.IN, machine.Pin.PULL_UP) + + +def adjust_utc_offset(pin): + global utc_offset + if pin == up_button: + utc_offset += 1 + if pin == down_button: + utc_offset -= 1 + + +up_button.irq(trigger=machine.Pin.IRQ_FALLING, handler=adjust_utc_offset) +down_button.irq(trigger=machine.Pin.IRQ_FALLING, handler=adjust_utc_offset) + + year, month, day, wd, hour, minute, second, _ = rtc.datetime() last_second = second -gu.set_brightness(0.5) -while True: - if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): - gu.adjust_brightness(+0.01) - - if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): - gu.adjust_brightness(-0.01) +# Check whether the RTC time has changed and if so redraw the display +def redraw_display_if_reqd(): + global year, month, day, wd, hour, minute, second, last_second year, month, day, wd, hour, minute, second, _ = rtc.datetime() if second != last_second: + hour += utc_offset time_through_day = (((hour * 60) + minute) * 60) + second percent_through_day = time_through_day / 86400 percent_to_midday = 1.0 - ((math.cos(percent_through_day * math.pi * 2) + 1) / 2) @@ -131,6 +207,23 @@ while True: last_second = second + +gu.set_brightness(0.5) + +sync_time() + +while True: + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + sync_time() + + redraw_display_if_reqd() + # update the display gu.update(graphics)