Skip to content

Instantly share code, notes, and snippets.

@joeycastillo
Created August 7, 2020 18:29
Show Gist options
  • Save joeycastillo/e70529e759756d3994640dee444d62d6 to your computer and use it in GitHub Desktop.
Save joeycastillo/e70529e759756d3994640dee444d62d6 to your computer and use it in GitHub Desktop.
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