Motivation
It is winter. The air is dry. Beyond slathering my face in Burt's Bees, we have mostly suffered in this dryness. I am anti-humidifier. They seem like diva equipment. And who wants to clean them weekly? Ugh. But no more! It is time. Also, my last Pi project broke important barriers in my brain - mostly emotional - and now it seems much easier to try new Pi things. Also also, I had another Pi lying around.
Hardware setup
For this project, I used:
Note: I was unable to use the Raspberry Pi 3b case that comes with this CanaKit kit - the Enviro pHat doesn't fit under the case's middle layer. Word to the wise!
Software setup
This was a bit of a journey.
First, I downloaded the latest version of the Raspberry Pi operating system - specifically, the Raspberry Pi OS with desktop. I flashed it onto the micro-SD card using balenaEtcher. After inserting that SD card into the Pi, as well as attaching all the peripherals (monitor, keyboard, mouse, power), I powered it on and then shaved the yak that is installing everything. At the end of this part of the journey, you have a perfectly serviceable little Linux desktop that I believe all children around 5 years old should have. Free Pis for all kids!
Second, well... I spent a lot of time being ridiculous and tinkering with the shell and dotfiles of the Pi. I just want a comfortable programming environment, dammit! This meant first copying over my .vimrc
... and then just going whole hog and copying over all my .dotfiles, installing zsh
(z-shell), installing ohmyzsh.sh, and generally futzing. The main learning here was that installing things on OSX means using brew
a lot (e.g. brew install whatever
), while the Raspberry Pi OS - given it's a type of Debian system, like Ubuntu (the most popular (?) Linux OS) - used a lot of sudo apt get install
. Other than that, this part was basically smooth sailing and not much to report.
Third was getting acquainted with the actual software for the Enviro. I relied heavily on this tutorial from the creators, Getting Started with Enviro+, not to be confused with this very similarly titled tutorial for their older model. HEHHHH. Yeah, I definitely got confused. And that's the main thing I learned in this Pi project - that these projects are small and often changing and so it takes a bit of detective work to figure out how all the pieces go together. Which was fun! Very gratifying!
Anyway, the pieces I ended up needing were the enviroplus-python
library (Pimoroni has, again, a very similar one, enviro-phat
, which I won't link because then you will get confused. I'm pretty sure enviroplus-python
is the one we should be using, at least at this point in time.)
More hardware
So this library was super interesting. It basically installed a bunch of other Pimoroni Python packages which related to the sensors on the pHat (pHAT? HAT? read more here...). These sensors are, specifically:
- A BME280 sensor which records temperature, humidity, and pressure. I believe the official docs are here.
- An LTR-559 light and (optical) proximity sensor. I believe the official docs for that are these.
There's also a tiny microphone and LED screen, though I haven't explored those almost at all yet. More to come on those!
And more software
The main questions I had, after running through the enviroplus-python
off-the-shelf examples, was what were the units on these sensors? The proximity sensoring, especially, was kinda baffling. The numbers get very "big" (in the thousands) if you put your hand over the sensor, and quite low (down to zero) if you don't. So, thousands of... what?
It turned out finding the answer to this question was not straightforward, and the official answer was basically an "uhhhh 🤷". This GitHub issue includes the Pimoroni thoughts on the matter and the official docs basically say it's "count". Though count of what?!
A brief digression on how the optical sensor works
I dove into this a little bit. The LTR-559 is an optical sensor. (There are other types of proximity sensors that use other parts of the electromagnetic spectrum to "see" if there's an object in front of them.) An optical sensor works by using light - it measures the reflected light, as far as I can tell. So the numbers the sensor is returning are a "count" (according to the official docs), which the Pimoroni authors think is either the number of LED pulses the sensor emitted that returned an object (e.g. "I shot out 500 pulses and 499 of them reflected light back, so your number is 499"?) or the actual "number of light units", typically measured as a
lux
(wiki - a measure of "luminous flux per unit area").Either way, big numbers from that sensor = lots of reflected light = something is close.
This YouTube video by Modern Robotics Inc gives a very nice and thorough (and digestible) explanation.
Final Software: the actual little script
To start with, I just wanted to start collecting the data for some of our rooms. For now, I'm just writing that data to a CSV file that the Pi is holding, and every so often I ssh
into the Pi and check on it. I've been noodling over the idea of (1) making the data more stream-y (Kafka?) and/or (2) making a web UI (like the Pi-hole!) using Flask and Bokeh (Bokeh so pretty...).
#!/usr/bin/env python3
import time
import csv
from datetime import datetime
from ltr559 import LTR559
from bme280 import BME280
ltr = LTR559()
bme = BME280()
header = ['datetime', 'light', 'proximity', 'temperature', 'humidity']
data_file = 'data/room.csv'
try:
# Write the header once
with open(data_file, 'w') as f:
writer = csv.writer(f)
writer.writerow(header)
while True:
f = open(data_file, 'a')
writer = csv.writer(f)
today = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ltr.update_sensor()
lux = ltr.get_lux()
prox = ltr.get_proximity()
temp = bme.get_temperature()
pres = bme.get_pressure()
hum = bme.get_humidity()
writer.writerow([today, f"{lux:.2f}", f"{prox:.2f}", f"{temp:.2f}", f"{hum:.2f}"])
time.sleep(60)
f.close()
except KeyboardInterrupt:
pass
The units for the other sensor readings (apart from proximity) are:
- LTR559 - Light: lux
- BME280 - Temperature: Celsius
- BME280 - Pressure: hectopascal (hPa)
- BME280 - Humidity: relative humidity
Interpreting the results
My brain is in Fahrenheit, but I have a general sense of Celsius (20 is comfortable! 0 is freezing! 40 is hotttt). I have no similar sense for luxes, hectopascals, and even relative humidity. The relative humidity in the rooms we measured has always been around ~17%. Which seems awfully low. But what does that mean? Apparently the Sahara Desert is typically around 25%. What the heck.
Oh yeah, and I need to compensate for the heat of the Raspberry Pi, as this Pimoroni example shows.
Conclusion
Well, this was a lot of fun, despite what my initial Pi pessimism ("is it all just off the shelf?!"). I do feel like my creativity has been unlocked and I'm learning lots of little things as well (hectopascals!); those were the two things I was after (learning, creativity). I'm very pumped to keep tinkering with this and to BUY MORE PIIIIIIS.