For those not in the know, WipperSnapper is Adafruit's plug-and-play firmware, which runs on their IO (think IOT) platform, offering free* data history(feeds) with graphs, dashboards, and automatic actions/triggers (along with integrating with other platforms like IFTTT). There is a paid upgrade for longer history, unlimited devices, SMS alerts, etc.
I love it because it's super quick and easy to test a sensor works, and to just get some data recording quickly.
Goto a web-page, flash over usb, add sensors via control panel (feeds + graphs are automatic), done.
Under the hood it's an arduino sketch, so adding additional sensors via github pull requests is surprisingly easy (I've added a few because it makes my future tasks easier).
For this project I'm testing the Sensirion SEN55, which senses Nitrous Oxides (NOx), Volatile Organic Compounds (VOCs), with temperature and relative humidty as a reference (uses SGP40/41 inside), and measures particle counts at <1.0 micron, <2.5, <4.0, and <10.0 micron. The other models of this sensor have less features (SEN54: no NOx, SEN50: no NOx/VOC/Relative Humidity+Temp - only Particulate Counts).
From the standard drivers(arduino/Pi) created by Sensirion we can retrieve the typical particle size, along with the raw particle counts (or in SI units ug/m3), the temperature and humidity, and then two indexes for NOx and VOC.
The NOx index has a baseline of 1.0, and if you hide the sensor under an upside down saucepan and use a lighter under the saucepan before sealing it back up then you will see a rise in the NOx index and then a return to baseline (1).
The VOC index is instead based at 100. You can detect VOC events from many things, the human breath can even be a source. I tested mine with a jar of clear nail varnish, but anything which you can smell, or smells chemically, is probably going to affect the sensor.
Connectivity-wise, it uses I2C, or other methods (UART?) which are as yet unpublished. The connector requires a JST-GHR 1.25mm 6 Pin compatible cable. The development kits include such a cable, but are heavily marked up cost-wise, like an additional 150% (£50 for kit, £20 for bare sensor). I advise getting a bare version with an additional cable from elsewhere (coolcomponents have a cable under £2). There is also a Grove connector version from seeedstudio.
Initially, we simply connect the cables as ordered in the sensor datasheet, as the device is 3volt logic tolerant then the only requirement we need to satisfy is a 5volt supply, which if your microcontroller is plugged in via USB then should be available. If 5volts is not available then see the later section using the Qwiic Boost converter.
Choose a microcontroller board that is supported by wippersnapper, I have a QTPY ESP32-S2 with double-headers attached for flexible prototyping. Goto the wippersnapper page and create a new device, you'll be instructed to add the wippersnapper firmware and then apply your wifi and secret key to the settings file. Alternatively you may select an existing device.
Connect the cable to the microcontroller, like the datasheet suggests, you will need space for two ground pins! (The second ground is connected to pin 5 on the SEN5x, to Select Interface as I2C, as per the datasheet)
At this point we need to connect to the same I2C pins as wippersnapper is expecting. On boards with a StemmaQT / Qwiic connector then those are the expected pins. Check your boards datasheet.
In my case I cheated during testing and changed the wippersnapper SEN55 code to use the other pins (arduino Wire instead of Wire1), but after finishing the testing I moved to using the Qwiic connector and jumper cables.
You would find it easier using a Qwiic cable with dupont jumpers on the other end, and then you can breadboard your circuit more easily.
Once the cable is connected to the board and sensor, plug the board into the computer and watch the serial console using the Serial Monitor option in the Arduino IDE or another tool. You should see the onboard LED flash if it is working, or be solid ON if the secrets file needs setting up.
Assuming it's flashed away then gone green and then off, it should be online!
Goto wippersnapper's devices page https://io.adafruit.com/wippersnapper and verify that you seen your device online, then go into that device and you will see there is an option for I2C Scan at the top of the devices page, along with New Component (like the screenshot at the top of the guide) buttons.
Add a component by clicking the button, follow the instructions, (currently the sensor SEN55 is marked as In-Development so you need to enable that checkbox option at the top right of the Choose Components page) enabling Dev components if needed, then if it's detected as attached it will ask how frequently to record the sensor's values for each value offered. And that's it!
My luck was flying high this festive period, as LadyAda released another product that makes the whole process a lot safer and easier, the Adafruit QT 3V to 5V Level Booster Breakout - STEMMA QT / Qwiic (https://www.adafruit.com/product/5649).
On the product page it mentions the board is for converting 3volt I2C signals to 5volt, along with offering a voltage booster with 250ma max current. It also says it's perfect for the SEN54. We simply solder our 6Pin JST-GHR cable straight to the breakout board, the 5volt side, then use StemmaQT / Qwiic cables to connect to the microcontroller.
(supports battery running by boosting Vcc to 5V for the SEN5x or other i2c devices)
Setup some action or connected device to be triggered when the air quality reaches a certain level? Wippersnapper can send a message or alert when a value is reached, and then you get something else to react to that. I've tried using IFTTT.com and NodeRed, as both allow connecting to other platforms and devices (like my Sonoff + Tapo switches), but anything that supports MQTT indirectly can be made to work. I've got a clean-air message sent when it gets to dirty... Maybe you want an email or SMS to open the window?
Of course we need to stick it in a case, but there are crucial guidance / application notes to follow if you're designing a proper device or want the best accuracy, on the manufacturers product page. I found the mechanical design-in guidance for the SEN55 particularly useful. There is a printable clip / duct that is provided on the manufacturers website, and I've adapted that further to begin integrating a screen, plus the Sensirion SCD41 (CO2 sensor) which also has some invaluable application notes.
You can find my work in progress at Onshape.com where you can do free* CAD, *if the designs are public. I love it because I can change one variable (e.g. material thickness) and my entire design updates, and the free support is excellent. I do occasionally find things break (usually when I have chosen poor reference points to a context) and cannot be easily fixed, rather replace and move forwards more quickly.
I'm using the LilyGo T-Display S3 (ESP32-S3 with 8mb ram, 16mb flash), and adafruit esp32s2/s3 reverse tft feathers (and similar display featherwings/bonnets), and probably a Raspberry Pi e-ink/tft version too. As per usual I've already started over-complicating it and added a distance/gesture sensor to wake the screen at appropriate moments (as a user is approaching or about to pass, catch their eye).
Here's a photo of an old prototype just to test pin length and fitment, the flimsy orange 90degree supports are purely illustrative. The newer design is clip together and modular for different screens, along with the modular sensor drawer for the SCD41.
Accurate Useful readings once you seal it in a box
First things first: the readings wont be the same as if taken at ambient temperature and no box, unless we set a temperature offset or use forced ventilation / large amounts of passive cooling like heatsinks. To do that the box has to change a little as fans currently wouldn't fit very well...
So along the way I tried a few different software platforms (adding support to Tasmota for the SEN5x, and circuitpython and then just about to do csharp - nanoframework when the pull request landed from another user - good timing!), to increase the value/understanding/applicability of the project for myself and other STEM users. While learning techniques with my CAD designs, I ended up trying to do a laser cut box. Mainly because of boxes.py which is a box generator script, kindly hosted at https://www.festi.info/boxes.py/ and is well worth taking a browse through. Generate a few and imagine them cut out, or just look at the gallery section (some don't have previews) and one of them (console2) looks like an old-school nuclear reactor console (control terminal) and has some interesting clip and spring and bolt designs.
As a result I learnt about the laser-joint tool in onshape, and the auto-layout (for creating a laid out cutting sheet). Then I bought some self-adhesive veneer and learnt to use the Sheet Metal tools in onshape (calculating bend radius and specifying parameters / cut points). It worked really well, except for never really being happy with the buttons (I tried some flex designs that adhered to the adafruit esp32-s2 reverse tft feather buttons, but they weren't comfortable for pressing (too small). I also set myself the challenge of making the device as compact as possible (to make the CAD harder), which was interesting but ultimately foolish (for heat management and therefore accuracy of air quality sensors).
See here for some good project photos to illustrate the pieces and assembly of the laser cut design:
I tested a few materials (mdf/plywood/old-wardrobe/acrylic), and breathing holes. I knew I'd need some as the esp32 gets warm at least, and there will be a display which also generates heat. I then did lots of testing with 3 devices running the code continuously reporting online. There was one hard-fault so I had to add logging to the code (now CircuitPython at this point) and automatic reboots (another rabbit hole, but valuable, look at safemode.py in circuitpython)
Anyway, having rebuilt the design that was for 3d printing, to now be similar to the console2 box and the previous cube design, I then needed to keep the sun off the co2 sensor / device and built a sun hat version (which could have a nice RGB LED underneath as the stilts were brass rods) and tested for days / weeks. I knew the more sealed designs would show readings of differing levels regarding temperature, but it was impressively different. I also had one unboxed test rig in the same location to compare without any trapped heat.
I was able to show the most holey design with over 75% surface area as holes still had a degree and a half at most (the co2 sensor and ppm sensor have separate temp readings) above ambient readings from the unboxed setup. The most sealed design (no air holes as I was testing the veneer / sheet metal design and wrapped an mdf box) had over 3degrees celcius above ambient. This increased temperature causes all the other metrics to be invalid / less accurate (readings for Humidity / Carbon Dioxide on the SCD41, and Humidity/VOC/Particulates on the SEN54 depend on temperature).
I had already followed the many design notes for the Sensirion SEN5x and SCD41. The mechanical design-in / installation guides were very valuable. All the literature is worth perusing. The guides mention protecting from strong winds, sunlight, internal enclosure heat (MCUs / displays), ensuring good exposure to air, sealing the front face to avoid air pathways (sen5x). They offer a 3d model for a clip on faceplate / retaining-case among the SEN5x technical downloads, and it has indentations to achieve a tight coupling/fit. I used it initially for the 3d-printed design. If we are using a flat interface against the face of the SEN5x (like a laser cut faceplate) then we need a gasket or manifold or wadding or interface layer, basically something to compress a little to smooth out the difference between high and low points, and in our case to stop the flow of air except through the port / vent holes on the SEN5x. I have used various things, but this 2mm closed cell foam seems to be the best.
Unfortunately even with centimetres of space between the sensors and the heat-source (esp32s2 with display) it was not enough. I debated a fan, and heat shield (wall between sensors+esp) but feared the enclosure will still transfer a large amount of warmth to the affixed scd41 at the top of the case with the laser cut designs.
I decided to try a test rig that was vertical, and to practise using assembly and contexts in onshape (so I can move the fan/display and change angle or move either sensor and all elements update), with an air pathway past the sensors and then through a fan and over the back of the esp and display before exiting though large grilles in the top of the case by the USB.
Successfully built, for the Adafruit ESP32-S2 ReverseTFT Feather, I then tried to move the fan to accommodate the LilyGo T-Display S3 instead of the Feather, but this caused another minor redesign / fix and now I have two!
I've also chosen to fill the air pathway with extra sensors (obstructions bad, but more sensors good, to be improved...).
Upside down CAD image:
The way the USB-C port on the LilyGo T-DisplayS3 is located means the top can't be a complete piece (unlike with the previous display - adafruit reverse tft s2/s3), as you can see on the paper beneath the model where a second top piece is shown, instead I used hot glue to bridge the gap and seal the top to the T-Display.
Open this image in a new tab (CTRL or right click menu on image then Open image in new tab) if you want to see the glue joint, or wire hole separating compartments (bigger with this design as not easy to use StemmaQT connector due to location by USB)
The original plan was to use aluminium foil tape to act as some kind of heat reflector. I'm not entirely sure that it won't just increase the conduction into the case, but on the other hand it will also act as a very quick heat transfer plate for the moving air from the fan, allowing very large surface area and quick heat dissipation. My second thought was a heat deflector separate from the internal heat partition wall. I did not add/build this bit yet, but it would be interesting to see what difference a cooling wing / heat deflector in the central space at the top would create, and how that would perform / influence the case heating. I think attaching / embedding temp sensors (DS18b20's) into the partition wall would be of interesting value and aid the comparison. Also another good excuse to get the phone I want with thermal camera :D
There was not a lot of surprise with the initial usage of the Thermal Camera, and it's inaccurate as you'd expect (+/-2degrees Celsius). It highlighted the power circuitry, the display / backlight, and the MCU as the main heat sources. It also showed how the tiniest power transformation chip still generates a fair old chunk of heat (metric term).
Sadly I have no images of the initial exploration, I keep getting too caught in the moment and either keep fiddling around or just gawping with excitement at the problem it's just highlighted. Too often though it's just a tool to me, I suddenly get a thought that it would help the situation, unlock phone and boot app (5seconds, just about acceptable before losing thought/focus/moment), glance at problem and identify heat (either way too much, or just an interesting amount) leading to a quick next step, at which point the phone is dashed down to pick up a soldering iron or quickly yank out a power supply from a smouldering electronics project.
*Todo* Add images, highlight warmth generated to surroundings, show SEN5X generated heat, 5v to 3v heat, etc. Have old designs warmed up for comparison
I love new things, can't help it, it's something unexplored for my brain to digest...analysing the features, form, failings, future possibilities, I can't help myself and it took years to stop giving my thoughts aloud immediately!
So in this case, I'd finally decided to get my model a bit better from the off, I wanted it to support 3 similar sized screen/MCU combinations, have a ported fan from a clean air path for the sensors into the warm screen/MCU area and then vented over both and out the far side.
The main features I was curious to use were already known, but never used correctly (still now writing this I have more to do in that department), the Configuration options/inputs/variables and Contexts. For example supporting variable Extrusion width and depth (layer height) for 3d printing, as driving the wall thickness from a multiple of those will give the best layer adhesion / strength when 3d printed.
Let's say this journey like the last has not gone "well" in the traditional sense (no finished design yet - it's printable but not good enough), but a heap of learning and design variation, also the way I've thought about designing keeps improving. Mostly I found myself continuously adding more boards to the design, so other users could benefit (and an excuse to play with new models/ideas), eventually even sticking a full sized Raspberry Pi 5 in there to see how big it would make the design. (It's big...even enough to add a front exhaust fan, although I'd lose the current battery/relay compartment)
Why is the first image screen facing down? Well mostly it's that way to illustrate the air pathway (that grey channel that ends up rising through the fan which is cyan coloured) that drags the air over the sensors then round the curved riser through the fan and over the CPU and display screen.
This next image shows the model from the left-back corner, looking at the air channel entrance closest (bottom middle of the image), with the double relay occupying dead-space in the unit. Also to the right, a panel with the configuration options.
Pi5, just because...🥧
It's technically possible, and with this larger increase in width and height I now have space for an 8way relay unit under the air-pathway (grey channel). In reality I'll probably never print this, instead opting for a Pi Zero 1/2W, but then again never say never...
Silly, but an enjoyable extension to the design experiment!
I did print it (well the Qualia+3.2inch version), and it just fits on the smallest printer bed that I have, which is 125mm x 125mm x 125mm approximately. As far as fastenings go, I planned to make a single central vent hole on each side be used for a single screw (two screws total except the mounting of the MCU), although originally I desired magnetic snap close imagining the side wall pegs would contain magnets with matching magnets in the main case.
I was going to use supports, or print vertically (right hand side wall at the bottom), but decided to try a first go unaided and uninhibited on the small printer that has an uneven bed and ready loaded PETG waiting (wasn't expecting great tolerances on the display, more a test of the parameters for that printer as the last print was not great).
Printer didn't like this one, uncovering more than one issue with my setups (I perform no regular/preventative maintenance), although surprisingly the holes and display cut-out faired well.
I also knew I'd been stingy with the tolerance anyway setting the variable at 0.1mm offset to all faces of the display, again as more of a printer test. Initially 0.3 made sense and I'll go as far as 1mm if needed, but I think 0.6 would allow good wiggle room. This display has adhesive backing tape, but those that don't could have some added, even using excess at the sides as filler if needed.
This is an image of the design that was missing the holes on the right hand side of the main case, but illustrates what I was printing (just the main outer shell and left side panel full of slots and holes)
This is an educational journey, not a money making scheme. So yes, I spent £25 and I got some heat-set inserts, a heat-set-insert soldering iron + tip set, and also a set of tips for cleaning 3d prints...and some magnets used for tiny models :D
The magnets still remain unused, although designed in with a configuration option for screws or magnets, but to be honest the fit of the side panel to the main case was already nice and tight (it had pegs to help align and hold it - friction not interlocking). I tested a screw hole, and it worked beautifully, and then I got fool-hardy and attempted to move the case design from one onshape document into another where it had some references. This broke the design, and there is not much to be retrieved, except inspiration! I can still modify some elements, and have made further changes, but it needs a rebuild or fixing by Onshape Support. Also I'd already built the first prototype, and the screen fits, and I only have one of those screens, so for now that will have to do. On to the next! Also I totally forgot that I'd enlarged the width for the Raspberry Pi, but forgot to add a configuration option, ah well...
Meanwhile at work I had to do some testing on WipperSnapper supported boards, so have recently obtained the PyPortal and PyPortal Titano (both M4's with ESP32 coprocessors running Nina-FW), which have a lovely touch screen built in, so perfect for the next design remix.
So I broke my largest 3d printer (3-in-1 fdm/laser/cnc), power-cycling it rapidly with a failed use of google-home automation web site (home.google.com). It turned out their interface(new beta) is designed for triggering based on a condition and it keeps triggering, so after setting up an ON action and it working but not allowing Off, I assumed I could create an Off option too. It then proceeded to play off and on continuously. PITA. Here's a screenshot of the interface, at least there's some auto-generation, but that probably led to the confusion in the first place.
Pretty glad the design fits on the other smaller printers too after that incident, I had to use one for the second print of the main body (with screw retainer). Could have been worse, £65 replacement controller unit for the Snapmaker A350, after a weekend of diagnosis and manual reading, then 4weeks wait, but also a good excuse (free shipping threshold) to get some high-flow(speed) TPU filament, which I'd not seen before.
It was a fun diagnosis, using usb-serial to attempt communication (boot messages received but no TX acknowledgement) and reading exported logs from the touchscreen controller, measuring resistances and voltages of various bits, and finally looking at thermistor datasheets to do a hot-fix of my bed after finding there's no replacements worldwide (stock after xmas). That last bit was related to the new controller also not liking my heated-bed, which I thought I might have to replace, but turns out it thinks 0.6degrees celcius is unreasonable for printing (I quite agree) - a quick hot-water bottle solution which may turn into a smart-switch controlled hair-dryer longer-term.
DisplayIO, PortalBase, and dreams of Responsive Design on embedded...
I got totally distracted with the software. Having had a version for the Adafruit ESP32S2/S3 Reverse TFT, I now need a bit more remixing of the software for other display ratios, etc. I can't have the Qualia running no code, that feels like a travesty the longer it goes on. It's also a good time to move up from the simple indicator and terminal display, to a more menu-driven customisable version with charts plus a few bells and whistles.
I need to write the display and menu changes, plus I've had to familiarise myself with the Adafruit_Circuitpython_Qualia library, which is based on PortalBase (for the PyPortal and MatrixPortal devices), exposing convenience functions and peripherals. A fascinating distraction in itself for a few weekends.
Most of the libraries used were exactly what I've used for previous experiments, with a couple of exceptions. I particularly liked progressing to the PyPortal and testing similar code. I'm now half way through adapting the CO2 project to run on about 8 different options, including plain python.
I also want to deviate and add the menu options (which is a whole can of worms), and the charts, but mostly some touch responsiveness, along with responsive display code. I figure for the responsive layout it will be stepped like media-breakpoints in html, with hard-coded list of known screen physical dimensions, touchscreen presence and orientation, and optimal built-in buttons, in addition to built-in resolution. This will allow me to have different scale values / breakpoints if the screen is physically small with a high resolution (and the opposite situation).
Distractions cleaning up software 📄🧹📃 (SEN5x driver) for CircuitPython
On another tangent I finally cleaned up the github repositories for the circuitpython drivers to have sphinx documentation generated and published to github pages. I'd been putting it off for months after bashing my head against it on first attempt, so it was a motivating win to get that done relatively easily this round. This was also a precursor to releasing the libraries to the community in a more accessible form (like the circuit python community bundle?).
However cool feature was recently enabled for circup (package manager for circuitpython), to allow specifying dependencies that have not been published to pypi (like mine due to fear of trademarks), and another feature to allow adding custom bundles to circup. So that same weekend when I felt motivated I went further down the rabbit hole... I added dependencies from the sensirion-i2c-driver to the SEN5x driver. I also updated the CO2 project repository to specify dependencies on the libraries for the SEN5x. I then created a custom circuitpython library bundle, with my two libraries in, and tested it worked. Amazing.
Pynt version yet)
It's new case time, the printers are quiet and that's always an icky feeling, particularly as I have a couple of very slow printers. I think it's only fair I consider a PyPortal version in the next iteration, although I do have my eye on some new screen for the Qualia board (I'm deeply concerned that I'll break the 3.2" bar display while prototyping and I only ordered one :facepalm: ).