DIY-ing My Way to Better Ventilation

If you scroll back two posts, you’ll find one about COVID-19 risk mitigation strategies. One of the items in that post was DIY CO2 monitoring – based on research that showed that CO2 concentration in an indoor space correlates with infection risk. Since I wrote that post, I’ve actually built two DIY monitors, and they’re being used on a weekly basis to support decisions around when additional ventilation (opening windows, using fans to circulate fresh air) is needed. Note that this measure is in addition to having all participants wear masks 100% of the time and running an inexpensive, ad-hoc air filter in one of the two spaces used.

From Humble Beginnings…

I already had both a MagTag and a PyPortal, two small Internet-enabled devices you can program using a specialized version of Python. I started out making just one purchase: a Qwiic/STEMMA compatible CO2 Sensor breakout board plus a cable to connect it. When the sensor and cable arrived, I discovered that, while I could connect to the MagTag, I didn’t have the correct cable to connect the sensor to the PyPortal, which is really what I wanted – for the color screen. Back to the online cart I went for more spending!


While I waited for the correct cable to arrive, I gave the sensor a spin using my MagTag, which is presently employed as a small weather widget. Since it was already reporting useful information, why not add a little more, right?

The Adafruit SCD-30 sensor reports CO2 concentration, relative humidity, and ambient temperature. You can get better accuracy from it by regularly feeding it the current atmospheric pressure in millibars. If you have access to a cylinder of calibration gas, you can use that to calibrate it. Otherwise, it has a “self-calibration” feature where the sensor will adjust itself as long as a) you allow it to run continuously and b) you give it access to fresh air at least once every 24 hours. This works because the average concentration of CO2 in fresh outdoor air is approximately 400ppm. The sensor will keep track of the daily low concentration and make adjustments based on those readings after several days of continuous operation.

The first thing I did was add the reported CO2 concentration and ambient temperature to the weather widget display. It was a tight squeeze, but I was able to fit both in at the end of the location name. Ok! I got the hang of using the SCD-30 Python library to fetch information. That’s a great start.

And then, Delivery Day!

Once my correct cable arrived, I moved the sensor over to the PyPortal and began working through other tasks. I hadn’t yet learned how to use CircuitPython to position and display text, so I did that next. By the time I checked my script into a shiny new git repository, it would wait for the sensor to report that a reading was ready, then pull the CO2, humidity, and temperature readings into variables. It would convert the temperature to display in degrees Fahrenheit, and display all three metrics on the screen, in green if below 1000ppm CO2, in yellow if between 1000 and 1500, and in red if above 1500ppm. I added in changing the color of the PyPortal’s neopixel LED a little later on.

Just having a CO2 reading wasn’t enough for me, though! I ordered a pressure sensor and a RTC board, both also Qwiic/STEMMA compatible, and some more cables. I wanted a system that was accurate, that could work without Internet access, and that could support writing sensor readings into a log file with a timestamp for analysis later.


As I was nearing completion of my PyPortal script, I discovered an issue: it would boot up just fine if I connected it to my computer (via USB; that’s how the executable scripts are accessed), but would boot up very slowly or not at all if I powered it by an electrical socket adapter (“wall wart”). I did a bunch of testing and consulted with the PyPortal experts on the forums, and finally, the source of the trouble was identified: the PyPortal, by default, supplies 5v to the JST I2C connector. If one is going to run the kind of sensors I was running, the power level needs to be shifted to 3v3 (by cutting a PCB trace and soldering two adjacent pads together). That isn’t something I wanted to do to my PyPortal, so I decided to pivot to another piece of hardware I already had.

Do you like Pi?

Until recently, there were six Raspberry Pi boards in my house, ranging from Model B Rev 2 boards (2012 says hi!) all the way to an 8GB Raspberry Pi 4. Each one is host to one or more locally-running self-hosted services, including RetroPie, Plex, PiHole, WordPress, Grocy, Django, Prometheus, and Grafana.

I ordered a SparkFun Qwiic HAT- an adapter that seats onto a Raspberry Pi’s GPIO pins and has four Qwiic connectors. I decided to use my Portable Pi, a Raspberry Pi 3 + 7-inch official touchscreen housed in a SmartiPi enclosure with separate power input for the screen. When I bought it, I also purchased a Pelican case with customizable foam so it could travel safely. It would be just the thing to bring along with me to the local weekly SCA fighter practice and art night.

a 7-inch screen displays the output of a python script that reads data from CO2 and pressure sensors, and then displays that information on the screen.
CO2 Monitor Script running on a portable Raspberry Pi computer

I dropped a copy of my PyPortal script, installed the Blinka Python library, and got to work modifying the script to work with the 7-inch touchscreen using the Pygame library, which also features touchscreen support. I came up with a script that displays the CO2, temperature, humidity, and pressure, with red/yellow/green color changes at breakpoints defined in the script, and logs everything to a csv file.

Don’t Speak Too Loudly, or Everyone Will be Wanting One

Yep. I talked to people about it. I talked to local SCA people about it. I talked about it way back when I was still working out the script with the PyPortal. “How much would it cost to build one?” they asked. (The answer is, somewhere between $130 and $160, for a build with a color screen, depending on what sizes and types of parts are chosen.)

The local chapter can vote to spend money on such things, and they did. So I ordered some parts. I went with the following configuration:

  • Raspberry Pi Zero W (with Header)
  • 2.8″ mini TFT touchscreen
  • SparkFun Qwiic HAT
  • GPIO splitter (seats on the Raspberry Pi’s GPIO and splits off two sets of connected GPIO pins – one for the touchscreen and one for the Qwiic HAT)
  • Adafruit SCD-30 CO2 sensor breakout with Qwiic/STEMMA ports
  • SparkFun Qwiic LED Stick

I supplied a micro-USB cable for power because I have loads of them around the house. After I complete the configuration, I’ll 3D print an enclosure to hold and protect it all.

Of course, a different screen means a different Python library for the display! So I needed to rework the script again. While I was doing that, I was also asked if it can do audible alarms (it totally can with minimal fuss if you have a Bluetooth speaker handy!) so I added that capability. I wanted to be able to easily import logged data into a MySQL database for data display in Grafana, so I set up a second log type. I added command line flags somewhere in there – you can turn debug on (or off, depending on what the default is), enable Grafana logs (off by default, you need to supply a location name for the log), pass in a local air pressure reading if you don’t have a pressure sensor attached, specify a log filename, and turn regular logging on/off (depending on the default).

Add a Little Spark

An animated GIF composed of a time-lapse photoset illustrating the behavior of the sparkline.

Most recently, I added a sparkline history – the last 18-25 CO2 readings are displayed across the screen between the “PPM” label and the temperature / rH / pressure label. This is not a true graph, as the column heights are freshly calculated every time a new reading is added and the oldest reading is discarded. A “zero” column height is assigned to the lowest number in the set and a “100” column height is assigned to the highest number in the set. The remaining numbers are assigned varying column heights based on their relative position between the high and low numbers, and columns are Unicode characters in the Block Elements group.

The sparkline will show you the trend over the last minute or so.

Eventually, I will build a custom enclosure for it to protect the delicate parts against damage.

Cool, How Can I Get One?

The short answer is: you build it yourself. If you choose the exact same configuration as one of the builds I’ve done so far, you’re in luck – I’ve posted the entire CO2 monitor git repository on my GitLab with an Open Source license. If you choose something different, you may be partly or completely on your own.

If you’re located in Harford or Eastern Baltimore Counties in Maryland, or York or Lancaster Counties in Pennsylvania, I’m available for hire to do custom builds at $75/hr plus the cost of parts and parts shipping. If you just want advice, you can get that for $35/hr.

The graphical output of this script can be piped out to an external display via HDMI. It can be modified to work with only a controller and an array of multi-color LEDs, a tiny OLED screen, or e-paper screens. Add a LiPo battery and a battery management board and you’ve got something very portable you can carry around with you for air quality sampling! Remember when choosing hardware that your chosen configuration is not guaranteed to work with my scripts out of the box until they’ve been tested, and even then, things can and do go wrong (usually it’s fixable and often not terribly expensive).

This is a great project for kids – younger ages will need assistance, but teens will likely be able to do this unassisted. I’m available for tutoring in the same locations as above, but a parent or guardian must be present at the location at all times.

One Last Thing

Remember that Raspberry Pi count I mentioned earlier? Today there are 8 of them in my house. The two new ones are Zero W models, one with headers, one without. One was purchased for this project, the other for an unrelated project).

10 Micro-electronics Projects that Aren’t Robotics

There’s more to educational/hobby micro-electronics than building robots.

If you or your kid can’t muster up excitement about robotics, go take a peek at these 10 projects. I’ve included a variety of different projects that do different things, run on different platforms, require different knowledge levels, and have different price points. Some of them also include the opportunity to learn about enclosure fabrication.

1. The Pimoroni Grow

This handy widget is a Raspberry Pi “HAT” (that stands for “Hardware-On-Top”). It connects to a Raspberry Pi’s GPIO pins, and is compatible with any Raspberry Pi model that has 40 GPIO pins (so, not the very earliest Pis). It is easy to connect to a Raspberry Pi – you just (carefully) plug it in so that all 40 pins are seated in the Grow’s GPIO socket. You can separate the two boards later if you need to.

The Grow uses connected capacitive touch sensors on custom-designed plant marker sticks to detect the moisture level in potted plant soil, and then gives a visual indication of moisture level for up to 3 sensors.

2. SparkFun OBD-II UART board

Learn how to read vehicle diagnostics over a serial connection. Those with more experience in micro-electronics should be able to, for example, create a portable version that runs on an Arduino or Raspberry Pi, features a screen and selection options, is rechargeable, and has a custom enclosure.

3. PiHut RasPi TV HAT

Feed digital OTA (broadcast) TV into this board while it’s plugged into a Raspberry Pi and you can stream broadcast TV to other devices on your network.

4. MagTag Pet Feeding Clock

Does your pet tell lies about not having been fed yet? This project is for you!

You can easily program this lightweight smart display to update the date and time your pet was last fed by pushing the left-most button. While it’s not included in the tutorial, a more advanced version of this would give you the ability to track most-recent mealtimes for up to 4 pets (or food plus 3 different medications).

5. Pwnagotchi WiFi Pentester

Test your home network’s wireless security.

Reminder: hack responsibly.

6. Digital-to-Analog Audio Conversion

Have you found a nice pair of old analog speakers at a yard sale? Give them new life with a Raspberry Pi HAT from HiFiBerry.

While you’re at it, you can use the same Raspberry Pi board to also host a local streaming music server using Jellyfin. Note that you will need to have music files stored locally.

7. Environment Sensor HAT

There’s no specific project tutorial for this one, but similar tutorials are available, and part of the lesson can be adapting to using different hardware. This HAT would be great for an offline local weather conditions display. It even has onboard motion sensing for those of you who live in places where earthquakes are frequent. For even more experienced programmers, how about including weather prediction by data analysis?

9. Binary Clock Soldering Kit

This Binary Clock project is a soldering kit that also presents an opportunity to custom fabricate a case. It comes with a printed circuit board, board components, and a pre-programmed IC, so no programming skills are needed for this one.

10. E-Paper Badge

Show your name (or whatever else you want) on a small e-paper display you can wear. You can add magnets to the back to attach it to your shirt or connect it to a badge lanyard (tip: make that easier by adding a bezel-type frame with lanyard loops).

Where to Next?

Once you learn the basic concepts of connecting peripherals and programming logic, you can take disparate components and make something completely new! There are quite a few hobby electronics suppliers out there these days, with lots of platform and form-factor options (we didn’t even get into soft circuits, which are electronics built into clothing using conductive thread and sew-on components!). Browse those tutorial sections, follow makers on Twitter, and maybe even write a tutorial of your own!

How to: Anki SRS + Learning Shorthand from a Manual = Magic

I’ve wanted to learn shorthand for a long time. In the mid-oughts, I bought a physical copy of The Gregg Shorthand Manual Simplified – Second Edition by John Robert Gregg, Louis A. Leslie, and Charles E. Zoubek. At the time, I tried following the book but it didn’t take. The book sat on my bookshelf for more than 15 years and moved across the country twice in that time.

Discovering Anki

I read Gabriel Wyner’s Fluent Forever last Autumn. This book provides specific instruction on how to leverage spaced repetition systems (flashcards with a system for how often you should see each card) for learning languages. I am in the midst of rebuilding my French language vocabulary using Anki, a computer-based spaced repetition system mentioned in Gabe’s book. While I was adding my first cards to Anki, it occurred to me that I might be able to use Anki to finally learn shorthand at the same time, so I loaded in the first lesson and gave it a shot. I now have a shorthand “vocabulary” of about 250 words and brief forms and have entered all of the individual words & brief forms in the Gregg book up to and including Lesson 11, with over 250 words & brief forms (566 cards) not yet seen.

The purpose of this post is to go into detail on how I set up my Gregg shorthand Anki deck. You could use any shorthand system you like, but you will need access to images of letter, word, and brief form outlines to compare against.

Setting Up Anki for Learning Shorthand

Let me begin with an important bit of Anki terminology: a note is an information pair – a question and an answer. From one note, you can have Anki generate one or more cards, which is what you’ll see when you review. If your question/answer pair is structured to allow reviewing in reverse (so you see the answer and have to recall the question), you can have Anki automatically create a second card from the same note that does this.

Repurpose as Needed

In card templating, I am cheating a bit and using the “Picture Card” templates that are available for free download from the Fluent Forever website’s “Gallery” page. These card templates are set up to produce two to three cards per vocabulary item “note” (letters, words, brief forms, practice sentences, etc). The note creation template has five fields: word, picture, information, pronunciation, and spelling-check. This template can create the following cards: a card that shows you the word and you must recall what is in the “picture” field and speak the word correctly; a card that shows you the picture and you must recall what is in the word field and speak the word correctly, and; a card that shows you the picture and plays a recording of the word being spoken (you provide the recordings here) and you must correctly spell the word. The “check spelling” field is a y/n question that defaults to no.

Let’s Get Down to Brass Tacks

So how did I leverage this card template for shorthand?

  • I extracted images of the example shorthand outlines in the book:
    • I used my phone to take photos of the shorthand outline examples in the book, starting with lesson 1
    • I copied the photos over to my computer and used the Windows Snipping Tool to collect grabs that only include the shorthand outlines – one for each long-hand vocab item.
    • For letters that are similar (s/f/v, r/l, k/g, etc), I took a grab of the entire example row, blotted out the alpha identifiers, and saved multiple copies, each with an arrow pointing at one of the shorthand outlines.
    • Save yourself some future headaches and name your snipped images after the words they represent, and put them into either a single folder or a set of folders organized by lesson.
  • I sat down with Anki and my book and added notes in the order that letters/words/brief forms appear in the book. You can drag/drop images from a folder into any Anki field if that makes it easier.
  • I put the long-hand letter, word, or brief form in the “word” field. Letters and brief forms are labeled as such in this field to differentiate cards (because most letters are also used as brief forms). I add the same label to the picture field as well because I also need to know this information when shown the reverse card.
  • I dropped the matching image into the “picture” field
  • In the “extra info” field, which only appears on card backs, I included a glyph of the letters/sounds used and any section notes for that outline type. I formatted the glyphs like this:


[th-e-r-o] the e represents the obscure o/u sound

  • Each individual letter/sound in the glyph is separated from the others either by a dash (most of the time) or a space (for disjointed strokes).
  • And finally, I add some tags at the bottom.
    • Each note in this deck is tagged “gregg”
    • Each word is tagged “words”
    • Each letter/sound is tagged “letters-sounds”
    • Each brief form is tagged “brief-forms”
    • Each item from a particular lesson is tagged with that lesson number.
    • Each comprehension sentence is tagged “reading-comprehension”
    • Each non-alpha symbol (numerals & punctuation) is tagged “symbols”

Time to Learn!

Once you’ve loaded a bunch of notes, it’s time to study! I have this deck set to introduce 10 new cards each day I study. Because it’s spaced repetition, I also review the cards that are due at the same time. On average, I see 5 reviews each day (but remember I’m studying other decks, too).

If you add notes in book order, you’ll also see them, new, in the same order. If you mess up and add them out of order, you can reorder them in the browse view. This is where having lesson number tags is valuable.

For each due item, I am either presented with longhand or shorthand. If I see shorthand, I must correctly identify the letter/word/phrase (and remember, if it’s a letter or brief form I’m supposed to be identifying, there’s a label with the shorthand image indicating that). Conversely, if I see longhand, I must take a pen and paper and accurately write out the shorthand. As I progress, I increase the threshold at which I find my shorthand outlines acceptable – because this involves learning new penmanship, not unlike learning calligraphy.

Be the Judge of Your Own Work

After I give or write my response, I click the answer button and am shown the reverse, which includes my letter/sound glyphs and notes about how certain sounds are written. I rate the card’s difficulty: if I got it wrong, it gets reviewed again the same day; if I had to think about it or my penmanship wasn’t great, it gets rated “hard”, if I got it close enough, it gets rated “good” and if I got it quickly and very right, it gets rated “Easy”. Those ratings determine when I will next see that card (Anki shows how much wait time each button adds) and you should do it in whatever way works for you because you are the only person who matters in this situation.

At first, I was also including the reading practice sentences, but that became tedious both in adding new cards and writing out the sentences, so I suspended the writing cards, left the reading comprehension cards, and haven’t added any more – especially as the comprehension examples grow in size from sentences to entire passages.

What I Might Do Later

For reading comprehension exercises, I may just create single cards that reference exercise numbers and keep the book nearby. I might record or download clips of vocab words being spoken and enable “spelling test” card creation to help train myself to write what I hear. Or, I might go find some podcasts with spoken English recorded at a slower pace intended for English-language learners and use them to practice writing what I hear – and then set a delay timer on those transcriptions for me to use for reading comprehension later on (because it’s important that you can read what you’ve written, amirite?). Lesson 11 isn’t even 1/4 of the way through the Gregg book, so I may hold off on transcribing live native speakers speaking at normal speeds, and before I start practicing on those, I might go and transcribe uncaptioned videos played at half-speed – and after I transcribe my transcription into longhand, I might just post the transcription as a comment on the video, because why not also do some volunteer work that helps people?