
Ridge3-lite
offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.
Canary is an open-source printed circuit board by offgridevices, from the offgridevices/offgrid-hardware repository on GitHub, published under the CERN-OHL-S-2.0 licence. It is a 2-layer board of 60 × 40 mm with 52 parts on 38 nets, routed with 360 tracks and 82 vias.
It is built around the ATMEGA328P-AU, SGP40-D-R4 and SHT40-AD1B-R2, with the AP2112K-3.3TRG1, SCD41-D-R2 and CL21A106KAYNNNE among its other parts. Its parts include 14 resistors, 13 capacitors, 5 ICs, 5 diodes and 3 connectors. It belongs with the AVR (ATmega, ATtiny) boards of this library.

Status: designed and verified in simulation, not yet built. Every gate below passes on this revision; no board has been assembled or powered yet.
This folder always holds the latest revision; an ordered revision stays at
its order tag (docs/versioning.md).
| Revision | What changed | Status | Order tag |
|---|---|---|---|
| 1.0 | first design: SGP40 + SCD41 + SHT40 + NTC tab, ATmega328P, 100 dB sounder, 60 × 40 mm, 2 layers | designed and simulation-verified, not yet built | — |
A 60 × 40 mm board you put next to (or on) an e-bike or scooter battery while it charges. It watches for the first vent — the moment a failing cell boils off electrolyte as solvent vapour and CO₂ — which comes before self-heating, thermal runaway and smoke. A smoke alarm reacts at the end of that chain; Canary is built to react near its start.
Grid storage and EV packs already carry off-gas detectors (Honeywell BES, Li-ion Tamer). The battery charging in a hallway has nothing. Canary is that detector as an open, cheap, USB-powered board you can order fully assembled.
It fuses three kinds of evidence and needs two at once to alarm:
| Evidence | Sensor | Fires on | Alone it means |
|---|---|---|---|
| Gas | Sensirion SGP40 MOX (on the isolated sensor head) | raw signal ≥ 700 ticks below its learned clean-air baseline (strong ≥ 2500) | WARN (cleaning spray, solvents) |
| CO₂ | Sensirion SCD41 photoacoustic | rise ≥ 250 ppm/min or ≥ 1500 ppm over baseline (strong ≥ 1200 ppm/min or ≥ 4000 ppm) | WARN (someone breathing on it) |
| Heat | NTC on the thermal tab (or remote probe) | ≥ 50 °C, or ≥ 1 °C/min above 35 °C (strong: ≥ 65 °C, or ≥ 3 °C/min above 30 °C) | WARN; strong heat alone → ALARM |
ALARM = gas and CO₂ (one strong), or heat and any gas evidence, or strong heat alone; held 3 s before it sounds, latched for at least 60 s. Outputs: green breathing (watching), amber (one kind of evidence), red flashing + 100 dB 4 kHz sounder in the smoke-alarm T3 pattern. The button self-tests in normal state and hushes for 2 minutes in alarm — the hush ends early if the evidence gets worse.
Product video: a narrated 4-minute explainer, built by video/ and
published rather than committed (video/README.md).
The real firmware, on a simulated ATmega328P with virtual sensors, catching
a vent at 400 s (alarm 7.6 s later) — sim/hil/:

| Requirement | How it is checked | Met? |
|---|---|---|
| Order from PCBWay, arrive assembled and working | Gerbers + PCBWay BOM + CPL + firmware HEX in production/; all parts on top; every part has an MPN | Yes (files); hardware not yet built |
| Parts in production today | Distributor check 2026-10-14, docs/sourcing-2026-10-14.md | Yes — one NRND part replaced (NTC) |
| Latest KiCad | KiCad 10.0.6 (kicad/kicad:10.0.6-full), current stable | Yes |
| Schematic clean | kicad-cli sch erc: 0 violations | Yes |
| Board clean, fab's limits | kicad-cli pcb drc --schematic-parity --severity-all: 0 errors, 0 warnings, 0 unconnected against PCBWay 2-layer limits (with margin) | Yes |
| Clean copper, wide enough for its current | check_geometry.py: no corner sharper than 45° (the router's six right angles mitered by miter.py); every power track ≥ 2.4× its IPC-2221 width at a 10 °C rise | Yes |
| Schematic = circuit = board = firmware | check_netlist.py (27 nets, 0 mismatches), DRC parity, check_pins.py (11 pins, 0 mismatches) | Yes |
| Detects a vent within seconds, ignores single-cause events | HIL simulation of the real firmware: vent → ALARM in 7.6 s; spray, breath → no alarm; still detecting after 100 min of charging; 65/65 checks across 9 scenarios | Yes, in simulation |
| Sounder driver safe | ngspice: drain clamped at 5.4 V on 5 V, clamp diode ≤ 0.34 A, VBUS dip ≥ 4.95 V, for 0.5–4 mH coils | Yes |
| Pack temperature good enough at the thresholds | Tolerance stack-up: ≤ 1.24 °C worst case at 65 °C; rate quantum 0.2 °C/min | Yes |
| Runs from any USB charger | 23.5 mA watching, ~520 mA worst-case peak in alarm | Yes (≤ 900 mA) |
production/canary-gerbers.zip.
production/canary-bom-pcbway.csv (MPN, maker, LCSC # for reference, notes)production/canary-cpl.csv; drawing: production/canary-assembly.pdfproduction/canary.hex to U2 (ATmega328P) through the Tag-Connect TC2030
pads (J2, standard 6-pin AVR ISP pinout), with fuses
lfuse 0xE2, hfuse 0xD9, efuse 0xFD (internal 8 MHz, no clock divider,
brown-out 2.7 V). To do it yourself: a USBasp + TC2030-IDC-NL cable, then
make -C firmware flash.enclosure/print/canary-v1-bumper.stl is an optional printed frame (PLA/PETG, no
supports, 64 × 44 × 5 mm). The board presses in from below; its underside
stays flush with the frame's so the thermal tab still lies on the pack, and
the USB-C, probe connector and the sensor head's air path stay open.

t= st= tp= ... sraw= co2= rate= dtdt= e= f=).firmware/src/detect.h may move.src/models3d.py (KiCad 10.0.6 ships none).| Path | What |
|---|---|
production/ | Gerber zip, PCBWay BOM, CPL, netlist, assembly + schematic PDFs, firmware HEX |
canary.kicad_sch, canary.kicad_pcb, canary.kicad_pro | KiCad 10 design (generated) |
src/ | the design source: circuit.py (every part and net), schematic.py, board.py, miter.py, finish.py, fab.py, checks |
firmware/ | AVR C firmware (detect.c is the detector logic) |
sim/hil/ | simavr hardware-in-the-loop harness + scenarios |
sim/spice/, sim/analysis/ | sounder driver SPICE, NTC/power/I²C analyses |
video/ | the scripts that build the narrated product video (the MP4 is published, not committed) |
web/ | the interactive bench page (build_page.py → one HTML file); its detector is a port of detect.c checked equal to the firmware second by second |
mechanical/ | STEP model (zipped) |
enclosure/ | 3D-printable bumper: bumper.scad, and print/canary-v1-bumper.stl |
TESTS.md, docs/decisions.md | every test with results; the trade-offs |
Needs docker (kicad/kicad:10.0.6-full), Java + xvfb (Freerouting 1.9.0 at
/opt/fr/freerouting-1.9.0.jar or FREEROUTING_JAR), avr-gcc, Python 3.
python3 src/make.py # schematic, ERC, netlist gate, place, route, DRC gate, fab
python3 src/make.py sch finish fab # without re-routing (the routed board in out/ is reused)
make -C firmware # firmware only
cd sim/hil && gcc -O2 -I<simavr>/simavr/sim ... && python3 scenarios.py # see sim/hil/README.mdRouting is done by Freerouting and is not bit-for-bit repeatable, so the
committed canary.kicad_pcb is the design of record: CI rebuilds the
fab outputs from it and checks they match what is committed.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 8 | 100n | Capacitor_SMD:C_0603_1608Metric | C3, C4, C5, C6, C8, C10, C11, C12 |
| 4 | 10u | Capacitor_SMD:C_0805_2012Metric | C1, C2, C9, C13 |
| 3 | 1k | Resistor_SMD:R_0603_1608Metric | R8, R11, R12 |
| 3 | Fiducial | Fiducial:Fiducial_1mm_Mask2mm | FID1, FID2, FID3 |
| 2 | 10k | Resistor_SMD:R_0603_1608Metric | R3, R14 |
| 2 | 10k 0.1% | Resistor_SMD:R_0603_1608Metric | R6, R7 |
| 2 | 4.7k | Resistor_SMD:R_0603_1608Metric | R4, R5 |
| 2 | 5.1k | Resistor_SMD:R_0603_1608Metric | R1, R2 |
| 2 | M2 | MountingHole:MountingHole_2.2mm_M2 | H1, H2 |
| 1 | 100 | Resistor_SMD:R_0603_1608Metric | R9 |
| 1 | 100k | Resistor_SMD:R_0603_1608Metric | R10 |
| 1 | 10k B3380 | Resistor_SMD:R_0603_1608Metric | TH1 |
| 1 | 1u | Capacitor_SMD:C_0603_1608Metric | C7 |
| 1 | 470 | Resistor_SMD:R_0603_1608Metric | R13 |
| 1 | AO3400A | Package_TO_SOT_SMD:SOT-23 | Q1 |
| 1 | AP2112K-3.3 | Package_TO_SOT_SMD:SOT-23-5 | U1 |
| 1 | ATmega328P-AU | Package_QFP:TQFP-32_7x7mm_P0.8mm | U2 |
| 1 | Amber | LED_SMD:LED_0603_1608Metric | D4 |
| 1 | B5819W | Diode_SMD:D_SOD-123 | D2 |
| 1 | CMT-8504 | Buzzer_Beeper:MagneticBuzzer_CUI_CMT-8504-100-SMT | BZ1 |
| 1 | GND | TestPoint:TestPoint_Pad_D1.0mm | TP3 |
| 1 | Green | LED_SMD:LED_0603_1608Metric | D3 |
| 1 | ISP (Tag-Connect) | Connector:Tag-Connect_TC2030-IDC-NL_2x03_P1.27mm_Vertical | J2 |
| 1 | Probe | Connector_JST:JST_PH_S2B-PH-SM4-TB_1x02-1MP_P2.00mm_Horizontal | J3 |
| 1 | RXD | TestPoint:TestPoint_Pad_D1.0mm | TP2 |
| 1 | Red | LED_SMD:LED_0603_1608Metric | D5 |
| 1 | SCD41 | Sensor:Sensirion_SCD4x-1EP_10.1x10.1mm_P1.25mm_EP4.8x4.8mm | U5 |
| 1 | SGP40 | canary:Sensirion_DFN-6_2.44x2.44mm_P0.8mm_SGP40 | U3 |
| 1 | SHT40 | Sensor_Humidity:Sensirion_DFN-4_1.5x1.5mm_P0.8mm_SHT4x_NoCentralPad | U4 |
| 1 | SMF5.0A | Diode_SMD:D_SMF | D1 |
| 1 | TEST / HUSH | Button_Switch_SMD:SW_SPST_TL3342 | SW1 |
| 1 | TXD | TestPoint:TestPoint_Pad_D1.0mm | TP1 |
| 1 | USB-C power | Connector_USB:USB_C_Receptacle_GCT_USB4125-xx-x-0190_6P_TopMnt_Horizontal | J1 |
It measures 60 × 40 mm and has 2 copper layers, 1.6 mm thick.
52 parts, built around the ATMEGA328P-AU, SGP40-D-R4, SHT40-AD1B-R2 and AP2112K-3.3TRG1. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the offgridevices/offgrid-hardware repository on GitHub, at the commit this page was made from: the board is products/canary/canary.kicad_pcb and its schematic products/canary/canary.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the CERN-OHL-S-2.0 licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.

offgridevices/offgrid-hardware
Open hardware from OffGrid Devices. One folder per board. CERN-OHL-S.


hydazz/iasis
An optional Raspberry Pi Compute Module 5 carrier for Iasis. It plugs into the main board's HubPD population and carries Ethernet, NVMe storage, an accessory USB-C port and a service USB-C port.

benjamincrockett/Weather-Feather-Wing
A circuit board incorporating temperature, humidity, atmospheric pressure, and CO2 sensors into an Adafruit Feather Wing form factor with Stemma QT connectors.



obra/space-banana
https://twitter.com/erinbeess/status/1503424797224677376?s=20&t=_vethJano1TXJZ3IsSkWwQ

