Skip to content

Commit 09e159b

Browse files
authored
Merge pull request #2670 from adafruit/space_clock
Adding code and files for the space clock project
2 parents 0d13222 + 88ada9e commit 09e159b

4 files changed

Lines changed: 248 additions & 0 deletions

File tree

345 KB
Binary file not shown.

Qualia_S3_Space_Clock/code.py

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
# Written by Liz Clark (Adafruit Industries) with OpenAI ChatGPT v4 Aug 3rd, 2023 build
6+
# https://help.openai.com/en/articles/6825453-chatgpt-release-notes
7+
8+
# https://chat.openai.com/share/63cbe4c6-007f-4934-a458-a9c8a521620e
9+
# https://chat.openai.com/share/674c0f13-bc78-4d1e-be79-3bc777e29991
10+
11+
import time
12+
from math import pi, cos, sin
13+
import os
14+
import ssl
15+
import wifi
16+
import socketpool
17+
import adafruit_requests
18+
import board
19+
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
20+
import vectorio
21+
import displayio
22+
from adafruit_io.adafruit_io import IO_HTTP
23+
from jepler_udecimal import Decimal
24+
import keypad
25+
from adafruit_display_text import label
26+
from adafruit_bitmap_font import bitmap_font
27+
from adafruit_qualia.graphics import Graphics, Displays
28+
29+
key = keypad.Keys((board.A0,), value_when_pressed=False, pull=True)
30+
31+
timezone = -5
32+
33+
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
34+
print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}")
35+
36+
aio_username = os.getenv('ADAFRUIT_AIO_USERNAME')
37+
aio_key = os.getenv('ADAFRUIT_AIO_KEY')
38+
39+
context = ssl.create_default_context()
40+
print("socketpool")
41+
pool = socketpool.SocketPool(wifi.radio)
42+
print("requests")
43+
requests = adafruit_requests.Session(pool, context)
44+
print("io")
45+
io = IO_HTTP(aio_username, aio_key, requests)
46+
47+
earth_bitmap = displayio.OnDiskBitmap("/earth.bmp")
48+
mars_bitmap = displayio.OnDiskBitmap("/mars.bmp")
49+
50+
graphics = Graphics(Displays.ROUND40, default_bg=None, auto_refresh=True)
51+
52+
# Create a TileGrid to hold the bitmap
53+
earth_grid = displayio.TileGrid(earth_bitmap, pixel_shader=earth_bitmap.pixel_shader)
54+
55+
# Create a Group to hold the TileGrid
56+
earth_group = displayio.Group()
57+
58+
# Add the TileGrid to the Group
59+
earth_group.append(earth_grid)
60+
61+
# Create a TileGrid to hold the bitmap
62+
mars_grid = displayio.TileGrid(mars_bitmap, pixel_shader=mars_bitmap.pixel_shader)
63+
64+
def center(grid, bitmap):
65+
# Center the image
66+
grid.x -= (bitmap.width - graphics.display.width) // 2
67+
grid.y -= (bitmap.height - graphics.display.height) // 2
68+
69+
center(mars_grid, mars_bitmap)
70+
center(earth_grid, earth_bitmap)
71+
# Create a Group to hold the TileGrid
72+
mars_group = displayio.Group()
73+
74+
# Add the TileGrid to the Group
75+
mars_group.append(mars_grid)
76+
77+
graphics.display.root_group = mars_group
78+
79+
# Pointer using vectorio, first the hub
80+
pointer_pal = displayio.Palette(4)
81+
pointer_pal[0] = 0xff0000
82+
pointer_pal[1] = 0x000000
83+
pointer_pal[2] = 0x0000ff
84+
pointer_pal[3] = 0xffffff
85+
pointer_hub = vectorio.Circle(pixel_shader=pointer_pal, radius=16, x=0, y=0)
86+
pointer_hub.x = graphics.display.width // 2
87+
pointer_hub.y = graphics.display.height // 2
88+
89+
# Pointer itself
90+
pw = 15 # pointer width
91+
ph = 200 # pointer height
92+
pointer_points = [(pw,0), (pw,-ph), (-pw,-ph), (-pw,0)]
93+
pointer = vectorio.Polygon(pixel_shader=pointer_pal, points=pointer_points, x=0,y=0)
94+
pointer.x = graphics.display.width // 2
95+
pointer.y = graphics.display.height // 2
96+
mars_group.append(pointer)
97+
earth_group.append(pointer)
98+
hw = 13 # pointer width
99+
hh = 150 # pointer height
100+
hour_points = [(hw,0), (hw,-hh), (-hw,-hh), (-hw,0)]
101+
hour_hand = vectorio.Polygon(pixel_shader=pointer_pal, points=hour_points,
102+
x=0, y=0, color_index=1)
103+
hour_hand.x = graphics.display.width // 2
104+
hour_hand.y = graphics.display.height // 2
105+
mars_group.append(hour_hand)
106+
earth_group.append(hour_hand)
107+
108+
def calculate_number_position(number, center_x, center_y, radius):
109+
angle = (360 / 12) * (number - 3) # -3 adjusts the angle to start at 12 o'clock
110+
rad_angle = pi * angle / 180
111+
if number >=8:
112+
x = int(center_x + cos(rad_angle) * radius-40)
113+
x = int(center_x + cos(rad_angle) * radius)
114+
y = int(center_y + sin(rad_angle) * radius)
115+
return x, y
116+
117+
clock_face_numbers = {i: calculate_number_position(i, graphics.display.width // 2,
118+
graphics.display.height // 2, 300) for i in range(1, 13)}
119+
120+
font_file = "/Roboto-Regular-47.pcf"
121+
122+
for i in range(1, 13):
123+
mars_c = vectorio.Circle(pixel_shader=pointer_pal, radius=30, x=clock_face_numbers[i][0]+12,
124+
y=clock_face_numbers[i][1], color_index=1)
125+
earth_c = vectorio.Circle(pixel_shader=pointer_pal, radius=30, x=clock_face_numbers[i][0]+12,
126+
y=clock_face_numbers[i][1], color_index=3)
127+
if i >= 10:
128+
mars_c.x = mars_c.x + 14
129+
earth_c.x = earth_c.x + 14
130+
mars_group.append(mars_c)
131+
earth_group.append(earth_c)
132+
text = str(i)
133+
font = bitmap_font.load_font(font_file)
134+
135+
mars_text = label.Label(font, text=text, color=0xFFFFFF)
136+
earth_text = label.Label(font, text=text, color=0x000000)
137+
mars_text.x = clock_face_numbers[i][0]
138+
mars_text.y = clock_face_numbers[i][1]
139+
earth_text.x = clock_face_numbers[i][0]
140+
earth_text.y = clock_face_numbers[i][1]
141+
mars_group.append(mars_text)
142+
earth_group.append(earth_text)
143+
144+
mars_group.append(pointer_hub)
145+
earth_group.append(pointer_hub)
146+
147+
def update_time():
148+
print("time")
149+
now = io.receive_time()
150+
return now
151+
152+
def convert_time(the_time):
153+
h = the_time[3]
154+
if h >= 12:
155+
h -= 12
156+
a = "PM"
157+
else:
158+
a = "AM"
159+
if h == 0:
160+
h = 12
161+
return h, a
162+
163+
def mars_time():
164+
dt = io.receive_time()
165+
print(dt)
166+
utc_offset = 3600 * abs(timezone)
167+
tai_offset = 37
168+
millis = time.mktime(dt)
169+
unix_timestamp = millis + utc_offset
170+
171+
# Convert to MSD
172+
msd = (unix_timestamp + tai_offset) / Decimal("88775.244147") + Decimal("34127.2954262")
173+
print(msd)
174+
# Convert MSD to MTC
175+
mtc = (msd % 1) * 24
176+
mtc_hours = int(mtc)
177+
mtc_minutes = int((mtc * 60) % 60)
178+
mtc_seconds = int(((mtc * 3600)) % 60)
179+
180+
print(f"Mars Time: {mtc_hours:02d}:{mtc_minutes:02d}:{mtc_seconds:02d}")
181+
return mtc_minutes, mtc_hours
182+
183+
def time_angle(m, the_hour):
184+
if m == 15:
185+
m = 16
186+
elif m == 45:
187+
m = 46
188+
# Adjusted angle calculation for minute hand
189+
theta_minute = 360 - (m / 60) * 360
190+
theta_hour = ((the_hour / 12) + (m / (12 * 60))) * 360
191+
# Calculate coordinates for minute hand (mirrored)
192+
minute_x = -int(cos(pi * (theta_minute - 90) / 180) * ph)
193+
minute_y = int(sin(pi * (theta_minute + 90) / 180) * ph)
194+
hour_x = int(cos(pi * (theta_hour - 90) / 180) * hh)
195+
hour_y = int(sin(pi * (theta_hour + 90) / 180) * hh)
196+
pointer.points = [(pw, 0), (minute_x + 2, -minute_y), (minute_x - 2, -minute_y), (-pw, 0)]
197+
hour_hand.points = [(hw, 0), (hour_x + 2, -hour_y), (hour_x - 2, -hour_y), (-hw, 0)]
198+
199+
clock_timer = 1 * 1000
200+
clock_clock = ticks_ms()
201+
display_timer = 10 * 1000
202+
display_clock = ticks_ms()
203+
mars_second = 88775
204+
mars_clock = ticks_ms()
205+
clock = update_time()
206+
hour, am_pm = convert_time(clock)
207+
tick = clock[5]
208+
minute = clock[4]
209+
mars_min, mars_hour = mars_time()
210+
show_earth = True
211+
212+
time_angle(minute, hour)
213+
214+
while True:
215+
event = key.events.get()
216+
if event:
217+
if event.pressed:
218+
print("updating display")
219+
show_earth = not show_earth
220+
if show_earth:
221+
if pointer.color_index != 2:
222+
time_angle(minute, hour)
223+
graphics.display.root_group = earth_group
224+
pointer.color_index = 2
225+
pointer_hub.color_index = 2
226+
else:
227+
if pointer.color_index != 0:
228+
time_angle(mars_min, mars_hour)
229+
graphics.display.root_group = mars_group
230+
pointer.color_index = 0
231+
pointer_hub.color_index = 0
232+
if ticks_diff(ticks_ms(), clock_clock) >= clock_timer:
233+
tick += 1
234+
if tick > 59:
235+
tick = 0
236+
minute += 1
237+
if minute > 59:
238+
clock = update_time()
239+
hour, am_pm = convert_time(clock)
240+
tick = clock[5]
241+
minute = clock[4]
242+
print(f"{hour}:{minute:02} {am_pm}")
243+
mars_min, mars_hour = mars_time()
244+
if show_earth:
245+
time_angle(minute, hour)
246+
else:
247+
time_angle(mars_min, mars_hour)
248+
clock_clock = ticks_add(clock_clock, clock_timer)

Qualia_S3_Space_Clock/earth.bmp

506 KB
Binary file not shown.

Qualia_S3_Space_Clock/mars.bmp

506 KB
Binary file not shown.

0 commit comments

Comments
 (0)