Skip to content

Commit d15e57a

Browse files
authored
Merge pull request #1191 from caternuson/clue_alti
Code for CLUE altimeter
2 parents f3b9548 + f1dae84 commit d15e57a

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

CLUE_Altimeter/clue_altimeter.py

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import time
2+
import struct
3+
import displayio
4+
import terminalio
5+
from microcontroller import nvm
6+
from adafruit_display_text import label
7+
from adafruit_bitmap_font import bitmap_font
8+
import adafruit_imageload
9+
from adafruit_clue import clue
10+
11+
# ==| USER CONFIG |=====================
12+
USE_METRIC = False
13+
DISPLAY_UPDATE = 1
14+
HOLD_TO_SET = 1
15+
FONT = terminalio.FONT
16+
BLUE = 0x53E4FF
17+
ORANGE = 0xFCDF03
18+
RED = 0xFA0000
19+
DEBOUNCE = 0.05
20+
SAMPLES = 10
21+
DELAY = 0.05
22+
STD_SLP = 1013.25
23+
# ==| USER CONFIG |=====================
24+
25+
# configure pressure sensor (see Table 15 in datasheet)
26+
clue._pressure.mode = 0x03 # normal
27+
clue._pressure.overscan_pressure = 0x05 # x16
28+
clue._pressure.overscan_temperature = 0x02 # x2
29+
clue._pressure.iir_filter = 0x02 # 4
30+
clue._pressure.standby_period = 0x01 # 62.5 ms
31+
32+
# restore saved sea level pressure from NVM
33+
clue.sea_level_pressure = struct.unpack("f", nvm[0:4])[0]
34+
35+
# --------------------------------------------------------------------
36+
# D I S P L A Y S E T U P
37+
# --------------------------------------------------------------------
38+
39+
# create main display group
40+
splash = displayio.Group(max_size=4)
41+
clue.display.show(splash)
42+
43+
# background
44+
bg_bmp, bg_pal = adafruit_imageload.load(
45+
"/network23.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette
46+
)
47+
for i, color in enumerate(bg_pal):
48+
if color == 0xFF0000:
49+
bg_pal.make_transparent(i)
50+
break
51+
background = displayio.TileGrid(bg_bmp, pixel_shader=bg_pal)
52+
53+
# a group for both altitude readouts
54+
alti_readouts = displayio.Group(max_size=2, scale=6)
55+
56+
# altitude (corrected)
57+
alti_disp = label.Label(FONT, text="12345", color=ORANGE)
58+
alti_disp.anchor_point = (0, 0)
59+
alti_disp.anchored_position = (7, 2)
60+
61+
# altitude (uncorrected)
62+
alt2_disp = label.Label(FONT, text="12345", color=ORANGE)
63+
alt2_disp.anchor_point = (0, 0)
64+
alt2_disp.anchored_position = (7, 15)
65+
66+
# add both alti's to group
67+
alti_readouts.append(alti_disp)
68+
alti_readouts.append(alt2_disp)
69+
70+
# barometric pressure and temperature
71+
aux_data = label.Label(FONT, text="P: 1234.56 T: 123.4", color=BLUE)
72+
aux_data.anchor_point = (0, 0)
73+
aux_data.anchored_position = (16, 212)
74+
75+
# calibration mode indicator
76+
cal_mode = label.Label(FONT, text=" ", color=RED, scale=4, x=150, y=200)
77+
78+
# add everything to splash
79+
splash.append(background)
80+
splash.append(alti_readouts)
81+
splash.append(aux_data)
82+
splash.append(cal_mode)
83+
84+
# --------------------------------------------------------------------
85+
# H E L P E R F U N C T I O N S
86+
# --------------------------------------------------------------------
87+
def compute_altitude(barometric_pressure, sea_level_pressure):
88+
"""Compute altitude (m) from barometric pressure (hPa) and sea level pressure (hPa)."""
89+
# https://www.weather.gov/media/epz/wxcalc/pressureAltitude.pdf
90+
return 44307.69396 * (1 - pow((barometric_pressure / sea_level_pressure), 0.190284))
91+
92+
93+
def compute_sea_level_pressure(barometric_pressure, altitude):
94+
"""Compute sea level pressure (hPa) from barometric pressure (hPa) and altitude (m)."""
95+
return barometric_pressure * pow((1 - (altitude / 44307.69396)), -5.2553)
96+
97+
98+
def average_readings(samples=10, delay=0.05):
99+
"""Return averaged readings for pressure and temperature."""
100+
pressure = 0
101+
temperature = 0
102+
for _ in range(samples):
103+
pressure += clue.pressure
104+
temperature += clue.temperature
105+
time.sleep(delay)
106+
return pressure / samples, temperature / samples
107+
108+
109+
def recalibrate(current_sea_level_pressure=None):
110+
"""Enter current altitude."""
111+
cal_mode.text = "CAL"
112+
alt2_disp.text = "-----"
113+
# wait for release if still being held
114+
while clue.button_a and clue.button_b:
115+
pass
116+
# get current value
117+
altitude = int(alti_disp.text)
118+
done = False
119+
while not done:
120+
now = time.monotonic()
121+
# increase
122+
if clue.button_a and not clue.button_b:
123+
altitude -= 1
124+
time.sleep(DEBOUNCE)
125+
# decrease
126+
elif clue.button_b and not clue.button_a:
127+
altitude += 1
128+
time.sleep(DEBOUNCE)
129+
# hold both to set
130+
elif clue.button_a and clue.button_b:
131+
while clue.button_a and clue.button_b:
132+
if time.monotonic() - now > HOLD_TO_SET:
133+
print("done")
134+
done = True
135+
break
136+
alti_disp.text = "{:5d}".format(altitude)
137+
cal_mode.text = " "
138+
# change clue settings
139+
if not USE_METRIC:
140+
altitude *= 0.3048
141+
# get current local pressure
142+
barometric_pressure, _ = average_readings(SAMPLES, DELAY)
143+
# compute sea level pressure and set
144+
clue.sea_level_pressure = compute_sea_level_pressure(barometric_pressure, altitude)
145+
# store in NVM for later use
146+
nvm[0:4] = struct.pack("f", clue.sea_level_pressure)
147+
148+
149+
def update_display():
150+
"""Update the display with latest info."""
151+
barometric_pressure, temperature = average_readings(SAMPLES, DELAY)
152+
altitude = compute_altitude(barometric_pressure, clue.sea_level_pressure)
153+
alt2tude = compute_altitude(barometric_pressure, STD_SLP)
154+
if not USE_METRIC:
155+
altitude *= 3.28084 # ft
156+
alt2tude *= 3.28084
157+
# barometric_pressure *= 0.0145038 # psi
158+
temperature = 32 + 1.8 * temperature # deg F
159+
alti_disp.text = "{:5d}".format(int(altitude))
160+
alt2_disp.text = "{:5d}".format(int(alt2tude))
161+
aux_data.text = "P: {:7.2f} T: {:5.1f}".format(barometric_pressure, temperature)
162+
163+
164+
# --------------------------------------------------------------------
165+
# M A I N L O O P
166+
# --------------------------------------------------------------------
167+
last_update = time.monotonic()
168+
169+
while True:
170+
171+
now = time.monotonic()
172+
173+
# update display with latest info
174+
if now - last_update > DISPLAY_UPDATE:
175+
update_display()
176+
last_update = now
177+
178+
# hold both to recalibrate
179+
if clue.button_a and clue.button_b:
180+
# accumulate hold time
181+
while clue.button_a and clue.button_b:
182+
if time.monotonic() - now > HOLD_TO_SET:
183+
print("set")
184+
recalibrate(clue.sea_level_pressure)
185+
break
186+
# wait for release if still being held
187+
while clue.button_a and clue.button_b:
188+
pass

CLUE_Altimeter/network23.bmp

28.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)