Skip to content

Commit 9d8e77c

Browse files
authored
Merge branch 'master' into sdcard-new-example
2 parents d595fdb + 9a87c0e commit 9d8e77c

File tree

5 files changed

+446
-1
lines changed

5 files changed

+446
-1
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.

CLUE_Sensor_Plotter/plotter.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,10 @@ def info(self, value):
782782
self._displayio_info = Label(self._font, text=value,
783783
line_spacing=line_spacing,
784784
scale=font_scale,
785-
background_color=self.INFO_FG_COLOR,
785+
background_color=None,
786786
color=self.INFO_BG_COLOR)
787+
self._displayio_info.palette[0] = self.INFO_FG_COLOR
788+
self._displayio_info.palette.make_opaque(0)
787789
# centre the (left justified) text
788790
self._displayio_info.x = (self._screen_width
789791
- font_scale * font_w * max_word_chars) // 2

Pixel_Chase_Game/code.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import time
2+
import random
3+
import board
4+
import neopixel
5+
import digitalio
6+
import adafruit_led_animation.color as color
7+
8+
# button pin setup
9+
button = digitalio.DigitalInOut(board.D5)
10+
button.direction = digitalio.Direction.INPUT
11+
button.pull = digitalio.Pull.UP
12+
13+
# neopixel setup
14+
pixel_pin = board.D6
15+
num_pixels = 61
16+
17+
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.2, auto_write=False)
18+
19+
# wheel and rainbow_cycle setup
20+
def wheel(pos):
21+
if pos < 0 or pos > 255:
22+
return (0, 0, 0)
23+
if pos < 85:
24+
return (255 - pos * 3, pos * 3, 0)
25+
if pos < 170:
26+
pos -= 85
27+
return (0, 255 - pos * 3, pos * 3)
28+
pos -= 170
29+
return (pos * 3, 0, 255 - pos * 3)
30+
31+
def rainbow_cycle(wait):
32+
for j in range(255):
33+
for i in range(num_pixels):
34+
rc_index = (i * 256 // 10) + j
35+
pixels[i] = wheel(rc_index & 255)
36+
pixels.show()
37+
time.sleep(wait)
38+
39+
# color_chase setup
40+
def color_chase(c, wait):
41+
for i in range(num_pixels):
42+
pixels[i] = c
43+
time.sleep(wait)
44+
pixels.show()
45+
time.sleep(0.5)
46+
47+
# function to blink the neopixels when you lose
48+
def game_over():
49+
color_chase(color.BLACK, 0.05)
50+
pixels.fill(color.RED)
51+
pixels.show()
52+
time.sleep(0.5)
53+
pixels.fill(color.BLACK)
54+
pixels.show()
55+
time.sleep(0.5)
56+
pixels.fill(color.RED)
57+
pixels.show()
58+
time.sleep(0.5)
59+
pixels.fill(color.BLACK)
60+
pixels.show()
61+
time.sleep(0.5)
62+
pixels.fill(color.RED)
63+
pixels.show()
64+
time.sleep(1)
65+
66+
# variables and states
67+
pixel = 0
68+
num = 0
69+
last_num = 0
70+
now_color = 0
71+
next_color = 1
72+
speed = 0.1
73+
level = 0.005
74+
final_level = 0.001
75+
new_target = True
76+
button_state = False
77+
78+
# neopixel colors
79+
colors = [color.RED, color.ORANGE, color.YELLOW, color.GREEN, color.TEAL, color.CYAN,
80+
color.BLUE, color.PURPLE, color.MAGENTA, color.GOLD, color.AQUA, color.PINK]
81+
82+
while True:
83+
84+
# button debouncing
85+
if not button.value and not button_state:
86+
button_state = True
87+
88+
# if new level starting..
89+
if new_target:
90+
# randomize target location
91+
y = int(random.randint(5, 55))
92+
x = int(y - 1)
93+
z = int(y + 1)
94+
new_target = False
95+
print(x, y, z)
96+
pixels[x] = color.WHITE
97+
pixels[y] = colors[next_color]
98+
pixels[z] = color.WHITE
99+
# delay without time.sleep()
100+
if (pixel + speed) < time.monotonic():
101+
# turn off pixel behind chaser
102+
if num > 0:
103+
last_num = num - 1
104+
pixels[last_num] = color.BLACK
105+
pixels.show()
106+
# keep target pixels their colors when the chaser passes
107+
if last_num in (x, y, z):
108+
pixels[x] = color.WHITE
109+
pixels[y] = colors[next_color]
110+
pixels[z] = color.WHITE
111+
# move chaser pixel by one
112+
if num < num_pixels:
113+
pixels[num] = colors[now_color]
114+
pixels.show()
115+
#print(num)
116+
#print("target is", y)
117+
num += 1
118+
# send chaser back to the beginning of the circle
119+
if num == num_pixels:
120+
last_num = num - 1
121+
pixels[last_num] = color.BLACK
122+
pixels.show()
123+
num = 0
124+
# if the chaser hits the target...
125+
if last_num in [x, y, z] and not button.value:
126+
button_state = False
127+
# fills with the next color
128+
pixels.fill(colors[next_color])
129+
pixels.show()
130+
print(num)
131+
print(x, y, z)
132+
# chaser resets
133+
num = 0
134+
time.sleep(0.5)
135+
pixels.fill(color.BLACK)
136+
pixels.show()
137+
# speed increases for next level
138+
speed = speed - level
139+
# color updates
140+
next_color = next_color + 1
141+
if next_color > 11:
142+
next_color = 0
143+
now_color = now_color + 1
144+
if now_color > 11:
145+
now_color = 0
146+
# setup for new target
147+
new_target = True
148+
print("speed is", speed)
149+
print("button is", button.value)
150+
# if the chaser misses the target...
151+
if last_num not in [x, y, z] and not button.value:
152+
button_state = False
153+
print(num)
154+
print(x, y, z)
155+
# fills with current chaser color
156+
pixels.fill(colors[now_color])
157+
pixels.show()
158+
# function to flash all pixels red
159+
game_over()
160+
# chaser is reset
161+
num = 0
162+
pixels.fill(color.BLACK)
163+
pixels.show()
164+
# speed is reset to default
165+
speed = 0.1
166+
# colors are reset
167+
next_color = 1
168+
now_color = 0
169+
# setup for new target
170+
new_target = True
171+
print("speed is", speed)
172+
print("button is", button.value)
173+
# when you have beaten all the levels...
174+
if speed < final_level:
175+
# rainbows!
176+
rainbow_cycle(0.01)
177+
time.sleep(1)
178+
# chaser is reset
179+
num = 0
180+
pixels.fill(color.BLACK)
181+
pixels.show()
182+
# speed is reset to default
183+
speed = 0.1
184+
# colors are reset
185+
next_color = 1
186+
now_color = 0
187+
# setup for new target
188+
new_target = True
189+
# time.monotonic() is reset for the delay
190+
pixel = time.monotonic()

0 commit comments

Comments
 (0)