Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Air quality monitor using the Open Book and Adafruit PMSA003I Air Quality Breakout
import displayio
from adafruit_display_text.label import Label
class LinePlot(displayio.Group):
def __init__(
self,
font,
*,
x=0,
y=0,
width=300,
height=200,
color=0xFFFFFF,
**kwargs
):
super().__init__(max_size=5, **kwargs)
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self._palette = displayio.Palette(2)
self._palette[0] = 0
self._palette.make_transparent(0)
self._palette[1] = color
char_width = font.get_glyph(ord("M")).width
char_height = font.get_glyph(ord("M")).height
self._label_ymax = Label(font, x=0, y=0, max_glyphs=5, color=color)
self._label_ymin = Label(font, x=0, y=height - char_height, max_glyphs=5, color=color)
self._plot_image = displayio.Bitmap(width - 5 * char_width, height, 2)
self._plot_origin_x = 5 * char_width
self.max_values = self._plot_image.width - 1
self.values = [0] * self.max_values
self._plot_added = False
self.draw_plot()
self.append(self._label_ymax)
self.append(self._label_ymin)
def push_value(self, value):
self.values.pop(0)
self.values.append(value)
self.draw_plot()
def draw_plot(self):
self._plot_image.fill(0)
for x in range(0, self._plot_image.width):
self._plot_image[x, self._plot_image.height - 1] = 1
for y in range(0, self._plot_image.height):
self._plot_image[0, y] = 1
ymin = min(self.values)
ymax = max(self.values)
self._label_ymax.text = f"{ymax:5}"
self._label_ymin.text = f"{ymin:5}"
if ymin != ymax:
for i in range(0, len(self.values)):
scaled_value = self._plot_image.height - 1 - round((float(self.values[i] - ymin) / float(ymax - ymin)) * float(self._plot_image.height - 1))
self._plot_image[i + 1, int(scaled_value)] = 1
if self._plot_added:
self.pop(0)
plot = displayio.TileGrid(self._plot_image, pixel_shader=self._palette, x=self._plot_origin_x, y=0)
self.insert(0, plot)
self._plot_added = True
import time
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogIn
import adafruit_pm25
import displayio
import terminalio
from adafruit_display_text.label import Label
from lineplot import LinePlot
display = board.DISPLAY
# air quality sensor
i2c = busio.I2C(board.SCL, board.SDA, frequency=100000)
pm25 = adafruit_pm25.PM25_I2C(i2c)
# power monitors
vbat = AnalogIn(board.BATTERY)
vbus = AnalogIn(board.USB)
ui = displayio.Group(max_size=16)
title_label = Label(terminalio.FONT, x=6, y=4, max_glyphs=48, color=0xFFFFFF)
ui.append(title_label)
white_bitmap = displayio.Bitmap(300, 376, 1)
white_palette = displayio.Palette(1)
white_palette[0] = 0xFFFFFF
background = displayio.TileGrid(white_bitmap, pixel_shader=white_palette, x=0, y=24)
ui.append(background)
plots = list()
particles = [0.3, 0.5, 1, 2.5, 5, 10]
for i in range(0, len(particles)):
label = Label(terminalio.FONT, x=0, y=56 + i * 63, text="> {}um\n /dL".format(particles[i]), color=0, line_spacing=0.75)
plot = LinePlot(terminalio.FONT, x=20, y=27 + i * 63, width=280, height=58, color=0)
plots.append(plot)
ui.append(label)
ui.append(plot)
display.show(ui)
while True:
title_label.text = f"Air Quality Monitor VBat: {2 * 3.3 * vbat.value / 65535:4.3}V VBus: {2 * 3.3 * vbus.value / 65535:4.3}V"
try:
aqdata = pm25.read()
print(aqdata)
except RuntimeError:
print("Unable to read from sensor, retrying...")
continue
plots[0].push_value(aqdata["particles 03um"])
plots[1].push_value(aqdata["particles 05um"])
plots[2].push_value(aqdata["particles 10um"])
plots[3].push_value(aqdata["particles 25um"])
plots[4].push_value(aqdata["particles 50um"])
plots[5].push_value(aqdata["particles 100um"])
display.refresh()
time.sleep(10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.