> ## Content Index
> Fetch the complete content index at: https://blog.wildwanderer-vr.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Turning my GitHub Universe badge into an environmental monitor
- URL: https://blog.wildwanderer-vr.com/github-universe-badge-environment-sensors/
- Published: 2026-10-05T18:03:22.000Z
- Updated: 2026-10-05T18:03:22.000Z
- Description: Two I2C sensors, a badge app and a 3D-printed mount. The first platform was too big; the final version fits above the screen and keeps the wiring underneath.
- Author: Wild Wanderer
- Tags: Hardware, 3D Printing, MicroPython, AI-assisted

My GitHub Universe 2025 badge has a new job. It now shows temperature, humidity, dew point and relative VOC and NOx indexes from two little sensor boards connected to its I2C port.

Getting numbers onto the screen was one part of the build. The other was finding a tidy way to attach the boards without covering the GitHub name or the display. That took a first print that was too big, some revised measurements, and a smaller red-and-white platform with the spare wiring tucked underneath.

![Finished GitHub Universe 2025 badge with two exposed sensor boards mounted above a five-card environmental dashboard](https://blog.wildwanderer-vr.com/content/images/2026/10/2026-10-05-finished-badge.jpg)

The finished fit. The sensor boards stay exposed to room air, while the mount hides the surplus cable.

## Two sensor boards, one bus

The temperature and humidity board uses a [Sensirion SHT41](https://sensirion.com/products/catalog/SHT41?ref=blog.wildwanderer-vr.com). The other uses an [SGP41](https://sensirion.com/products/catalog/SGP41?ref=blog.wildwanderer-vr.com), a metal-oxide sensor with separate VOC and NOx raw signals.

Both boards share the badge's external Qw/ST I2C bus. On my 2025 badge, the firmware's SDA and SCL aliases map to GPIO4 and GPIO5\. The app uses controller 0 at 100 kHz and reads the SHT41 at address 0x44 and the SGP41 at 0x59\. The scan also found another device at 0x51, which the app leaves alone.

The four-wire connections are visible in the photos. Electrically, I2C is a shared bus; the cable running between the boards doesn't mean the software reads one sensor through the other. I haven't identified the exact manufacturer or connector specification of these particular breakout boards, so I wouldn't use their appearance as a substitute for checking another board's pinout or voltage rating.

## Making the gas readings understandable

The first version of the app displayed raw VOC and NOx numbers. Those are useful for checking that the sensor responds, but they don't tell somebody looking at the badge much about the room.

The app now uses [Sensirion's official Gas Index Algorithm](https://github.com/Sensirion/gas-index-algorithm?ref=blog.wildwanderer-vr.com). Its unmodified fixed-point implementation is compiled into a small native MicroPython module. That lets it run on the badge without replacing the firmware or pretending that raw sensor ticks are a gas concentration.

Both indexes run from 1 to 500\. The VOC algorithm learns the background conditions and puts the usual level around 100\. For NOx, the background is around 1\. The captions compare the current index with those documented baselines: Below usual, Usual, Above usual or Background.

**These are relative indexes, not ppm, CO2 readings, a regulatory air-quality index or a safety alarm.** A low number doesn't certify that the air is safe to breathe. The algorithm learns from recent conditions, so the meaning depends on that history too.

The app uses current temperature and humidity readings from the SHT41 to compensate the SGP41 measurements. It also calculates dew point with the Magnus approximation. Measurements are taken at roughly one-second intervals, and both sensors' responses are checked with Sensirion's CRC-8.

## A screen I can read without thinking about the sensors

The badge draws at 160 by 120 logical pixels, doubled onto its 320 by 240 screen. There isn't much room, so the dashboard has five simple cards: Temp, Humidity, Dew point, VOC Index and NOx Index.

Metric is the default. Button A selects Celsius and button C selects Fahrenheit for temperature and dew point. Humidity stays a percentage, and the gas indexes don't change with the unit setting. The permanent A=Met C=Imp hint at the top saves having to remember the controls.

I removed the routine sensor-status lines, but errors still replace the affected readings. Long captions can scroll within their own box. A compact five-pixel font keeps the captions and footer smaller than the headings and values.

That last detail took a correction. An attempt to shrink rendered text using off-screen images stopped the app opening on this firmware. It was replaced with a native pixel font rather than leaving an image-resizing workaround in the startup path. The updated app opened correctly on the physical badge.

On launch, the SGP41 gets approximately nine seconds of conditioning, within its maximum ten-second limit. The algorithm then has an initial blackout of about 45 seconds. During that time the cards show Warming up, not an apparently valid zero. The learned baseline continues adapting over hours. Reopening the app resets that state.

## The first platform was too big

Each of my breakout boards measures 18 by 25.4 mm. I wanted them stacked, with their sensing faces on show and the loose cable hidden underneath a lid. The first design provided that arrangement, but it took up too much of the badge face and was deeper than I wanted.

![First oversized sensor platform positioned on the badge and obscuring part of the GitHub branding](https://blog.wildwanderer-vr.com/content/images/2026/10/2026-10-05-first-fit.jpg)

The first fit check made the problem obvious: the mount was using space needed by the badge name and display.

A CAD preview didn't make that as obvious as putting a real print against the badge. The larger version started at a 52 by 54 mm footprint. I also reduced the depth and the size of the cable passages during the revisions.

![Side view of the early red-base and white-lid platform showing its depth and cable routing](https://blog.wildwanderer-vr.com/content/images/2026/10/2026-10-05-first-side-view.jpg)

The early side view. The base, lid, posts and spare cable all needed to be considered together.

At one point I wanted the platform to be only 35 mm tall. Two stacked 18 mm boards already need 36 mm before leaving a gap or an edge border. Keeping the same arrangement meant that target simply wasn't going to work. The final height became 39 mm, with a 1 mm gap between the boards and a small border above and below them.

## The final print stores the wires, not the sensors

The final platform has a red tray base and a white lid. Its nominal OpenSCAD dimensions are 52 mm wide by 39 mm tall. The base is 7 mm deep and the lid is 2 mm, making the closed box 9 mm deep before the sensor posts. The posts add another 2 mm to the underside of the boards.

Those are CAD dimensions, not a caliper survey of the finished print. PCB thickness, component height, screws and the attachment to the badge add to the final projection.

The shallow cavity holds spare wire. Small side notches let short cable tails reach the visible connectors. I removed the original rectangular openings through the lid, so the wiring space stays underneath while the boards sit outside.

Both boards now use all four corner screws. The sensor posts are part of the lid, and four more screws hold the lid onto the base. The blind pilot holes are shallow, so screw length matters; this isn't a design where a longer screw is automatically a better choice.

![Finished sensor mount viewed from the side, with the red cable-storage base, white lid and exposed boards](https://blog.wildwanderer-vr.com/content/images/2026/10/2026-10-05-final-side-view.jpg)

The finished side profile: wiring space under the lid, exposed sensor boards above it.

The new footprint is about 28% smaller in face area than the original 52 by 54 mm version. More importantly, it fits between the GitHub name and the screen cover. I kept the sensor arrangement I wanted without shifting the problem onto the display.

![Opposite-side view of the completed mount showing short cable loops and clear access to the badge screen](https://blog.wildwanderer-vr.com/content/images/2026/10/2026-10-05-final-cable-routing.jpg)

The opposite side shows the short external loops and where the rest of the wiring disappears.

## What I've checked, and what I haven't

The boards fit, the assembly is attached, and the badge displays live readings. The app has synthetic tests for CRC checking, compensation, startup timing, unit switching and display behavior. The official fixed-point algorithm was also exercised with synthetic inputs to check its warm-up and relative index behavior.

I haven't calibrated this assembly against a reference thermometer, humidity instrument or controlled gas source. The exposed mounting doesn't eliminate possible effects from nearby electronics, the gas sensor's hotplates, handling or airflow. I also haven't measured battery runtime with both boards attached.

This is an experimental environmental display. It is useful to watch changes, but it isn't a substitute for certified smoke, carbon-monoxide or other safety alarms.

## Code and compatibility

I've submitted the application as a [draft contribution to the GitHub badge repository](https://github.com/badger/home/pull/107?ref=blog.wildwanderer-vr.com), with its native-module source, licensing notices and rebuild instructions. It's a proposal for review, not a merged upstream feature.

The tested target is the **GitHub Universe 2025 badge**. Newer badge documentation describes different graphics and button APIs. The I2C protocol code can be reused, but another badge needs its UI adapted and its CPU and MicroPython native-module compatibility checked. I wouldn't claim support for every future badge from this one successful build.

## The AI-assisted parts

I supplied the boards, measurements, fit requirements, photographs and physical printing and assembly. ChatGPT/Codex helped develop and revise the parametric OpenSCAD platform. GitHub Copilot helped write the badge application, package the official gas-index implementation and work through the display changes.

The first print hiding the name, and the text-resizing change breaking startup, were both useful reminders that generated code and models still need to be checked against the actual thing. The finished badge is the result of those checks and revisions, not just the first output.