Skip to content

Commit 32498fe

Browse files
authored
Merge pull request #2452 from adafruit/desktop_air
Adding code for the desktop air quality monitor
2 parents 14d3756 + 476c738 commit 32498fe

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

Desktop_Air_Monitor/code.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
import os
5+
import ssl
6+
import time
7+
import microcontroller
8+
import board
9+
import wifi
10+
import socketpool
11+
import adafruit_requests
12+
import neopixel
13+
import displayio
14+
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
15+
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
16+
from adafruit_pm25.i2c import PM25_I2C
17+
import adafruit_scd4x
18+
from adafruit_display_text import bitmap_label
19+
from adafruit_bitmap_font import bitmap_font
20+
from adafruit_display_shapes.roundrect import RoundRect
21+
22+
# connect to SSID
23+
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))
24+
25+
pool = socketpool.SocketPool(wifi.radio)
26+
requests = adafruit_requests.Session(pool, ssl.create_default_context())
27+
28+
pool = socketpool.SocketPool(wifi.radio)
29+
30+
# adafruit IO info
31+
aio_username = os.getenv('aio_username')
32+
aio_key = os.getenv('aio_key')
33+
location = "America/New York"
34+
35+
# io HTTP for getting the time from the internet
36+
io = IO_HTTP(aio_username, aio_key, requests)
37+
38+
def reset_on_error(delay, error):
39+
print("Error:\n", str(error))
40+
print("Resetting microcontroller in %d seconds" % delay)
41+
time.sleep(delay)
42+
microcontroller.reset()
43+
44+
def c_to_f(temp_data):
45+
temperature_celsius = temp_data
46+
temperature_fahrenheit = temperature_celsius * 9 / 5 + 32
47+
return int(temperature_fahrenheit)
48+
49+
# setup NeoPixels
50+
pixel_pin = board.D13
51+
num_pixels = 8
52+
53+
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False)
54+
55+
red = (255, 0, 0)
56+
yellow = (255, 125, 0)
57+
green = (0, 255, 0)
58+
59+
i2c = board.STEMMA_I2C()
60+
61+
reset_pin = None
62+
63+
pm25 = PM25_I2C(i2c, reset_pin)
64+
aqdata = pm25.read()
65+
66+
scd4x = adafruit_scd4x.SCD4X(i2c)
67+
scd4x.start_periodic_measurement()
68+
69+
time.sleep(2)
70+
71+
co2 = int(scd4x.CO2)
72+
temp = c_to_f(scd4x.temperature)
73+
humidity = int(scd4x.relative_humidity)
74+
75+
pm2 = int(aqdata["pm25 standard"])
76+
pm2_x = [94, 94, 94, 94, 140, 185]
77+
pm2_colors = [green, green, green, green, yellow, red]
78+
79+
# display setup
80+
display = board.DISPLAY
81+
82+
bitmap = displayio.OnDiskBitmap("/airBG.bmp")
83+
84+
tile_grid = displayio.TileGrid(bitmap, pixel_shader=bitmap.pixel_shader)
85+
group = displayio.Group()
86+
group.append(tile_grid)
87+
88+
small_font_file = "/OCRA_small.pcf"
89+
small_font = bitmap_font.load_font(small_font_file)
90+
big_font_file = "/OCRA_big.pcf"
91+
big_font = bitmap_font.load_font(big_font_file)
92+
93+
pm2_text = bitmap_label.Label(big_font, text="%d" % pm2, x=42, y=40, color=0xFFFFFF)
94+
group.append(pm2_text)
95+
96+
co2_text = bitmap_label.Label(small_font, text="%d" % co2, x=50, y=107, color=0xFFFFFF)
97+
temp_text = bitmap_label.Label(small_font, text="%d" % temp, x=130, y=107, color=0xFFFFFF)
98+
humid_text = bitmap_label.Label(small_font, text="%d" % humidity, x=205, y=107, color=0xFFFFFF)
99+
group.append(co2_text)
100+
group.append(temp_text)
101+
group.append(humid_text)
102+
103+
pm2_outline = RoundRect(pm2_x[pm2], 19, 46, 46, 10, fill=None, outline=0xFFFFFF, stroke=3)
104+
group.append(pm2_outline)
105+
106+
pixels.fill(pm2_colors[pm2])
107+
pixels.show()
108+
109+
display.show(group)
110+
111+
sensor_texts = [pm2_text, co2_text, temp_text, humid_text]
112+
sensor_data = [pm2, co2, temp, humidity]
113+
114+
sensor_clock = ticks_ms()
115+
io_clock = ticks_ms()
116+
117+
sensor_check = 30000
118+
io_check = 300000
119+
first_run = True
120+
121+
try:
122+
# get feed
123+
pm25_feed = io.get_feed("pm25")
124+
except AdafruitIO_RequestError:
125+
# if no feed exists, create one
126+
pm25_feed = io.create_new_feed("pm25")
127+
try:
128+
# get feed
129+
temp_feed = io.get_feed("temp")
130+
except AdafruitIO_RequestError:
131+
# if no feed exists, create one
132+
temp_feed = io.create_new_feed("temp")
133+
try:
134+
# get feed
135+
co2_feed = io.get_feed("co2")
136+
except AdafruitIO_RequestError:
137+
# if no feed exists, create one
138+
co2_feed = io.create_new_feed("co2")
139+
try:
140+
# get feed
141+
humid_feed = io.get_feed("humid")
142+
except AdafruitIO_RequestError:
143+
# if no feed exists, create one
144+
humid_feed = io.create_new_feed("humid")
145+
146+
sensor_feeds = [pm25_feed, co2_feed, temp_feed, humid_feed]
147+
148+
while True:
149+
try:
150+
if first_run or ticks_diff(ticks_ms(), sensor_clock) > sensor_check:
151+
if scd4x.data_ready:
152+
co2 = int(scd4x.CO2)
153+
temp = c_to_f(scd4x.temperature)
154+
humidity = int(scd4x.relative_humidity)
155+
pm2 = int(aqdata["pm25 standard"])
156+
pm2_outline.x = pm2_x[pm2]
157+
pixels.fill(pm2_colors[pm2])
158+
pixels.show()
159+
for s in range(4):
160+
sensor_texts[s].text = "%d" % sensor_data[s]
161+
print("updated %d data" % sensor_data[s])
162+
time.sleep(0.2)
163+
sensor_clock = ticks_add(sensor_clock, sensor_check)
164+
165+
if first_run or ticks_diff(ticks_ms(), io_clock) > io_check:
166+
for z in range(4):
167+
io.send_data(sensor_feeds[z]["key"], sensor_data[z])
168+
print("sent %d to io" % sensor_data[z])
169+
time.sleep(1)
170+
io_clock = ticks_add(io_clock, io_check)
171+
if first_run:
172+
sensor_clock = ticks_ms()
173+
io_clock = ticks_ms()
174+
first_run = False
175+
# pylint: disable=broad-except
176+
except Exception as e:
177+
reset_on_error(10, e)

0 commit comments

Comments
 (0)