Reflashing the Pocket CHIP in 2023

The C.H.I.P (and by extension, the Pocket C.H.I.P) was a short-lived single-board computer released in 2016. You can read more about it at the C.H.I.P Wikipedia Entry.

For simplicity, I will refer to this computer as the “CHIP” throughout the rest of this post.

The CHIP can be reflashed, and there are a variety of images available for it, but reflashing can be a complicated and frustrating process since the company that made it is long since gone and the flashing tools and software repositories are now hosted only on archive sites.

I successfully reflashed one of my CHIPs yesterday (after fighting with it for about a week) and this post is a description of what worked for me, here in 2023.

Downloads

I used three downloaded archives from the CHIP Flash Collection at the Internet Archive.

  • CHIP-SDK.zip
  • CHIP-tools.zip
  • flash-collection.zip

I also used the sunxi-tools repository at Github, though you should be able to git clone it, and don’t need to download it with the zip archives.

I used a Live USB flash drive loaded with Ubuntu 14.04 and a spare computer capable of running it as a live (read: not installed) system. I used a second USB flash drive to hold the downloaded files. You may be able to keep the extracted archives on the 2nd flash drive or you may need to copy the relevant directories to the live operating system. The CHIP-tools directory should be placed within the CHIP-SDK directory, and one directory from the flash-collection archive should also be placed within the CHIP-SDK directory (each directory in flash-collection is a separate CHIP image – you’ll need to select which one you want).

Make sure you reserve a USB 2.0 port for the CHIP on the computer you’ll use to run the Live USB. It doesn’t seem to play nice with USB 3.0 ports, so if you only have one of each, you’ll need to plug the Live USB into the 3.0 port and use the 2.0 first to transfer the tools directories and flash image to the live OS, then remove the file-transfer USB and use the 2.0 port to connect the CHIP.

# File structure
CHIP-SDK
|- CHIP-tools (directory)
|- [flash image dir] (directory)
|- README.md
|- setup_ubuntu1404.sh
|- Vagrantfile

Preparation

Upon loading up Ubuntu 14.04, I added universe repositories to the apt list so I’d have access to two applications the flasher needs.

# file: /etc/apt/sources.list

..
deb http://us.archive.ubuntu.com/ubuntu/ trusty universe
deb-src http://us.archive.ubuntu.com/ubuntu/ trusty universe
deb http://us.archive.ubuntu.com/ubuntu/ trusty-updates universe
deb-src http://us.archive.ubuntu.com/ubuntu/ trusty-updates universe

Most of the commands that come after here are taken from the setup_ubuntu1404.sh script. I’m not going to direct you to use the actual script because we need to build a different version of sunxi-tools than what’s most recent.

# update apt and install prerequisite applications
apt update
apt install -y \
build-essential \
 git \
 mercurial \
 cmake \
 curl \
 screen \
 unzip \
 device-tree-compiler \
 libncurses-dev \
 ppp \
 cu \
 linux-image-extra-virtual \
 u-boot-tools \
 android-tools-fastboot \
 android-tools-fsutils \
 python-dev \
 python-pip \
 libfdt-dev \
 libusb-1.0-0-dev \
 libz-dev \
 g++-arm-linux-gnueabihf \
 pkg-config \
 libacl1-dev \
 zlib1g-dev \
 liblzo2-dev \
 uuid-dev

If (and only if) you’re running 32-bit, also install:

apt install -y libc6-i386 lib32stdc++6 lib32z1

Make sure the user is permitted to communicate via USB serial connections:

sudo usermod -a -G dialout $(logname)
sudo usermod -a -G plugdev $(logname)

echo -e 'SUBSYSTEM=="usb", ATTRS{idVendor}=="1f3a", ATTRS{idProduct}=="efe8", GROUP="plugdev", MODE="0660" SYMLINK+="usb-chip"
SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="1010", GROUP="plugdev", MODE="0660" SYMLINK+="usb-chip-fastboot"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1f3a", ATTRS{idProduct}=="1010", GROUP="plugdev", MODE="0660" SYMLINK+="usb-chip-fastboot"
SUBSYSTEM=="usb", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", GROUP="plugdev", MODE="0660" SYMLINK+="usb-serial-adapter"
' | sudo tee /etc/udev/rules.d/99-allwinner.rules

sudo udevadm control --reload-rules

Build the sunxi-tools

# Clone the sunxi-tools repository
git clone https://github.com/linux-sunxi/sunxi-tools.git

# checkout v1.3 of sunxi-tools
cd sunxi-tools
git checkout tags/v1.3

# make the tools. Note that it may throw some warnings.
# If these commands throw errors about missing libraries, 
# you'll need to find them and install them, 
# then try these next two commands again
make
make misc

# add the sunxi-tools directory to PATH
# modify the path to the sunxi-tools directory if it's different
# from what is listed here
PATH=/home/ubuntu/sunxi-tools:$PATH

Now is the time to insert a jumper wire between the FEL and GND pins, and connect the CHIP to the USB 2.0 port. Make sure you’re using a USB cable that is capable of data transfer.

# If you want to make sure the CHIP is connected, it should appear
# in the output list when you do
lsusb

# enter the CHIP-tools directory
cd CHIP-tools

# run the flashing script
# note that the final path should point to the flash image directory
# which in this example is the one named "stable-pocketchip-b126"
FEL='sudo sunxi-fel' FASTBOOT='sudo fastboot' SNIB=false ./chip-update-firmware.sh -L ../stable-pocketchip-b126

If everything goes smoothly, what you’ll see is a series of tests followed by a few minutes’ worth of terminal output that reports progress of writing UBI data. Once it’s successfully done, it will say, “CHIP is ready to roll!”

At that point you can disconnect the CHIP and remove the jumper. If your CHIP has a Pocket, you can re-seat it into the Pocket and turn it on. You’ll still need to do some setup (keyboard, etc) but the OS should boot for you. Note that jessie has been retired to the archive.debian.org repository server, so that will matter when you go to update /etc/apt/sources.list on your CHIP.

You can let me know how it went for you by leaving a comment here, posting a pingback reply, or by mentioning me @cordelya on any ActivityPub-capable server that can federate with toots.cordelya.net.

A $90 DIY Weather Station with Air Quality Monitoring

About a month ago, I built a weather station to put on my front porch (where all the good shade lives). I hadn’t done a write-up yet, but since this weather station includes a Particulate Matter sensor and we live in these times where suddenly Air Quality is important for quite a lot of people who didn’t need to notice it previously, I’m doing that write-up now.

This weather station captures the following metrics:

  • Temperature
  • Atmospheric Pressure
  • Relative Humidity
  • VOC (note that this is mostly useless unless running the board in Arduino mode, for which no code is supplied)
  • Particulate Matter (PM1.0, PM2.5, PM10, Particles per 0.1L air at < 0.3, <0.5, <5.0, and <10.0 microns particle size)

The Hardware

I can’t guarantee that these parts will be available forever – if this article is old, you may find you need to substitute some parts. Listed prices are USD.

  • Feather S3 by Unexpected Maker – $22
  • PMSA003i PM sensor with STEMMA QT I2C Connector – $45
  • BME680 sensor with STEMMA QT I2C Connector – $19
  • 2 x STEMMA QT cables – $1 each
  • Enclosure – custom enclosure STL files are available in the Gitlab repo for this project (see link in next section), or you can make your own any way you like. It needs to be ventilated, shaded, and protected from precipitation.
  • USB-C cable – for programming the Feather S3, a cable capable of data transfer is needed. Once programmed, a power-only cable is sufficient.
  • Optional: a LiPo battery. The Feather S3 board has on-board battery management and a connector. A battery will enable you to move the station without it losing power, and will allow it to survive short power outages without restarting. A large enough battery will allow it to be placed in otherwise un-powered locations, possibly with solar panel support.
  • Optional: a graphical display. This could be in the form of a FeatherWing, a separate board with a STEMMA QT connector, or a board with basic GPIO pins requiring a custom connection. The enclosure does not support a graphical display as-is, and you will need to write in the code to connect to and display the data on the display.

The Project

For the complete code that is running on my weather station, please visit my Weather Station Gitlab Repository. Because not everyone will want to use MQTT as the data transport mechanism, I will also provide some resources below to help you modify the code to fit your needs.

Secrets

This script comes with a file named secrets-example.py. You should edit this file to include the relevant secrets (at minimum you’re likely going to need wifi credentials) and save it as secrets.py. You can also add additional secrets to the file to meet your needs.

External Libraries

This script makes use of some CircuitPython libraries that are not part of CircuitPython’s core. You’ll need to grab a copy of the CircuitPython bundle that matches your board’s CircuitPython version. The easiest way to confirm your board’s CircuitPython version is to connect to the board’s serial console and enter the REPL. The version will be printed in the welcome line.

If you’re not sure how to connect to the serial console, check Connecting to the Serial Console in the Adafruit Learning Portal’s Welcome to CircuitPython tutorial.

The libraries you will need are:

  • adafruit_bme680
  • adafruit_minimqtt
  • adafruit_pm25

These libraries should be copied into the lib directory on the board’s USB drive. If there’s no lib directory, make one at the top level. Some libraries have their own directory, while others are single .mpy files.

MQTT

If you want to use the code as-is, you will need an MQTT broker. You can run your own MQTT broker service or subscribe to an already-established service – which one you choose is beyond the scope of this article.

Once you have MQTT and WiFi credentials, enter them into secrets.py and you should be good to run the script.

What do I do with the Data?

Once the data from my weather station reaches my MQTT broker, I pull it into OpenHAB and display it in a weather dashboard along with data pulled from a weather API. I also poll the temperature data using a Huginn agent for other Huginn agents to act on depending on the temperature value (sends Pushover notifications when the temperature crosses freezing/not freezing and open-the-windows/close-the-windows thresholds).

Data Transport Alternatives

In the event that you do not want to use MQTT as your data transport mechanism, here are a few alternatives.

  • http api – serve up individual datapoints in JSON via http using the CircuitPython http server
  • prometheus – serve up all datapoints on one plaintext document via http using Prometheus Express (NB: the last meaningful update to that repository was made about 3 years prior to this article’s publication date)
  • Direct to connected display – make this a completely portable solution by adding a LiPo battery and a display for on-the-go air quality information. Put it in an enclosure so you don’t damage the electronics or scare the normies. Add some buttons and button-press handling code to allow rotating through the different datapoints. Readings can be logged to a file on the board’s USB drive as long as it’s not mounted to a computer. Or, add an I2C SD card board and log your data there.
  • Using the on-board RGB LED – add in AQI calculation (see next section) and use the Feather S3’s on-board RGB LED to communicate the AQI by official color for an extremely low-res visual indication

Calculating the Air Quality Index

The weatherstation.py script does not currently calculate the Air Quality Index, but I do have an AQI calculation script for the PMSA003i that I originally wrote for the MagTag, which could be adapted and incorporated into weatherstation.py. I wrote this script using the EPA’s Technical Assistance Document for the Reporting of Daily Air Quality – The Air Quality Index (AQI) resource. This document details how the US Air Quality Index (used, for example, by AirNow.gov) is calculated.

You may alternately choose to use Patrick Ferraz’s airquality Python library, which does the same thing but encloses the calculations within a library function and can handle calculations for more pollutants than PM2.5 and PM10.0.

If you’re using MQTT, you could easily run a separate Python script on a separate machine to calculate the AQI using your local readings and report them back over to your MQTT broker.

What About Indoor Air Quality?

You could choose to run this weather station indoors, but if your home’s air filtration is up to par, the PMSA003i will yield extremely low readings and probably won’t be worthwhile. A more useful sensor for an indoor air quality monitor is one that reads CO2 concentration. CO2 concentration is commonly used to determine whether an indoor space’s ventilation is adequate.

Conclusion

Manufactured outdoor weather stations usually don’t include a particulate matter sensor. PM sensors can be purchased as add-on modules for some systems. Chances are good that you’ll spend several hundred dollars on such solutions. If you’re DIY-inclined, this weather station may be a good low-cost alternative.

If you find an error in this article or within the linked Gitlab repository, please let me know by submitting a comment here or you may contact me via ActivityPub.

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.

GIF of monitor screen changes demonstrating the sparkline
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
A bare mini TFT screen with the CO2 Monitor script output displayed
A bare mini TFT screen with the CO2 Monitor script output displayed

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!

Meanwhile…

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.

Trouble

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

GIF of monitor screen changes demonstrating 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).

Editor’s note: as of late 2022/early 2023, my household no longer purchases Raspberry Pi products. We’ve switched to using Libre Computers’ single-board offerings and have also branched out to the Feather line of microboards for things that don’t need a full blown server.