
Atmosmesh bench
konih/atmosmesh
ESP32 indoor air-quality station: PM, climate, and a local OLED — headed for MQTT, Home Assistant, and Grafana.

ESP32 indoor air-quality station: PM, climate, and a local OLED — headed for MQTT, Home Assistant, and Grafana.
Atmosmesh room is an open-source printed circuit board by konih, from the konih/atmosmesh repository on GitHub, published under the MIT licence. It is a 2-layer board of 80 × 60 mm with 44 parts on 45 nets.
Its parts include 7 capacitors and 1 IC. It belongs with the home automation and IoT and sensors and measurement boards and the ESP32 boards of this library.
DO NOT ENERGISE THIS BOARD YET. The controller and every module connector order are now identified, but no supply voltage or output swing has been measured on the 5 V modules. This project is a protected, reviewable starting point, not a wiring approval.
The controller is the ideaspark ESP32 1.14 inch TFT LCD board (ESP32-WROOM-32), confirmed from
docs/hardware/ideaspark-esp32-tft-pinout.png.
Its 30 pins and their order are therefore no longer provisional: pads 1–15 are the left column and
16–30 the right column, both counted from the USB/button end. What remains unmeasured is the
physical row spacing: 25.4 mm is still an assumption, so MEASURE THE ROW SPACING before
cutting a socket or committing a hole pattern.
The integrated display is SPI, not I²C. It occupies GPIO23 (MOSI), GPIO18 (SCLK), GPIO15 (CS), GPIO2 (DC), GPIO4 (RST) and GPIO32 (backlight). GPIO21/22 carry no onboard device, so the carrier supplies the only I²C pull-ups it has.
| File | Purpose |
|---|---|
atmosmesh-room.kicad_pro | KiCad 10 project; open this file |
atmosmesh-room.kicad_sch | Reviewable electrical contract |
atmosmesh-room.kicad_pcb | Parked. Kept only as a netlist/silkscreen cross-check — not the build target |
perfboard.md | The build target: 31×27 hole plan, orientation rules and build order |
atmosmesh-room-perfboard-drawing.svg | Zoomable front, mirrored back and logical wiring planning drawing |
atmosmesh-room-perfboard-drawing.png | Rendered preview of the planning drawing |
validate_room_perfboard.py | Deterministic structural check on the perfboard plan |
room.pretty/, fp-lib-table, sym-lib-table | Local THT library contract |
BOM.csv | Values, fitting policy and verification notes |
wiring.md | Connector contract and staged pre-power checks |
validate_room_carrier.py | Deterministic structural safety check |
generate_project.py | Reproducible project generator; KiCad source remains editable |
requirements-generator.txt | Pinned generator-only Python dependency |
3V3 must never receive 5 V.task flash and task monitor. generate_project.py refuses to emit a net on
any of them and validate_room_carrier.py fails if one appears.R_PU_SDA and R_PU_SCL (3.3 kΩ to 3.3 V) are the bus pull-ups. They are required because the
display is SPI: nothing on the controller board pulls I²C up. They sit on the sensor side of the
330 Ω resistors so the series resistance stays a fault limit rather than part of the pull-up
divider. With both breakouts populated the parallel result is roughly 2.0 kΩ, about 1.6 mA at
3.3 V, inside the I²C 3 mA sink limit, so they stay fitted rather than DNP. Every resistor value
on this board is justified in wiring.md's sizing table.C1, C3, C4
and C7 — the confirmed ceramic stock value, inside D-022's own 47–220 nF range.VIN, 3Vo, GND, SCL, SDA: VIN receives
3.3 V and 3Vo is regulator output and remains NC.JP_PIR_5V which is DEFAULT
OPEN, then a 1N5819. PIR OUT drives a 2N3904 through 10 kΩ; GPIO33 sees only the collector and a
10 kΩ pull-up to 3.3 V. Motion logic is active-low.S/VCC/−. GPIO25 drives S
directly through R_BEEP_S 100 Ω, active HIGH, exactly as AtmosMesh v1 drives the same part. The
low-side NPN and flyback diode are gone because the transducer is self-oscillating inside the
can — the breakout PCB carries no parts, so the middle VCC pin is a no-op and GPIO25 sources
the whole operating current. The evidence is that v1 sounds this part with a bare 50 ms DC
digitalWrite(HIGH), which neither a piezo disc nor a passive coil can do. That type is inferred,
not measured: one ohmmeter reading across S and − settles it, and R_BEEP_S is never
raised — see the table in wiring.md before changing anything.JP_5V_SRC selects where +5V_DOMAIN comes from: the board's VIN (pins 1–2) or an external
bench supply on J_5V_EXT (pins 2–3). A 3-pin header takes exactly one shunt, so the two sources
can never be bridged back into the host's USB port. Use the external, current-limited supply for
first power-up and whenever the SDS011 fan runs.JP_SDS_5V, DEFAULT OPEN, with no series diode: its minimum
is 4.7 V and a Schottky at fan current drops below that. Its UART is crossed — sensor TXD to
GPIO16/RX2, GPIO17/TX2 to sensor RXD — each through a 1 kΩ series resistor that bounds a driver
fight to about 3.3 mA. The generator refuses both a straight-through UART and a diode on that
rail.D_LED_SDS and D_LED_PIR draw through
their own default-open jumpers, so a lit LED is direct evidence that the jumper it reports on is
closed. Use red or green: a blue or white LED's ~3.0 V forward drop leaves too little across
R_LED_3V3 on the 3.3 V rail.docs/elektronik-inventar.md is the 1N47xx series starting at 1N4733 = 5.1 V,
which clamps far too late to protect a 3.3 V GPIO. A 3.3 V part (1N4728) is not held.The operator builds this by hand on a 31 × 27 hole perfboard, so no board is fabricated. The
schematic is the electrical contract and perfboard.md is the build plan.
atmosmesh-room.kicad_pcb is parked: it is still generated from the netlist and still carries
the safety silkscreen, which is why its checks remain in validate_room_carrier.py, but its
placement is not maintained as a fabrication candidate. Do not order it.
The VEML7700 sits at a board edge and must be optically shielded from the TFT backlight. The SHT41 sits at
the opposite ventilated edge, away from the ESP32 regulator, PIR electronics and buzzer. The 5 V
PIR block is fenced at the right edge. The antenna clearance is marked on User.Drawings and silk;
its final copper keepout/overhang cannot be fixed until the exact board orientation is photographed.
Copper is intentionally unrouted because the Ideaspark row spacing and orientation, plus each module connector order, are unverified. This prevents a plausible-looking provisional drawing from being mistaken for a fabrication-ready board. Do not "finish the ratsnest" by assuming a generic ESP32 DevKit image.
The complete net table, double-sided through-hole placement guidance, assembly order, unpowered
checks, staged commissioning and stop conditions are in wiring.md.
From this directory:
python3.12 -m venv .generator-venv
.generator-venv/bin/pip install -r requirements-generator.txt
.generator-venv/bin/python generate_project.py
python3 validate_room_carrier.py
kicad-cli sch erc --severity-all --exit-code-violations \
-o atmosmesh-room-erc.rpt atmosmesh-room.kicad_sch
kicad-cli pcb drc --severity-all --schematic-parity --refill-zones \
-o atmosmesh-room-drc.rpt atmosmesh-room.kicad_pcb
kicad-cli sch export pdf -o atmosmesh-room-schematic.pdf atmosmesh-room.kicad_schDRC reports the deliberately unrouted nets as unconnected; schematic parity must remain clean and there must be no other DRC violation. Routing stays blocked until the exact physical parts are verified.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | 100nF | room:C_Disc_P5.00mm | C1, C3, C4, C7 |
| 4 | 1k | room:R_Axial_P7.62mm | R_LED_PIR, R_LED_SDS, R_SDS_RX, R_SDS_TX |
| 4 | M3 | room:MountingHole_3.2mm_M3 | H1, H2, H3, H4 |
| 2 | 100uF | room:C_Radial_P2.00mm | C2, C5 |
| 2 | 10k | room:R_Axial_P7.62mm | R_PIR_IN, R_PIR_PU |
| 2 | 3.3k | room:R_Axial_P7.62mm | R_PU_SCL, R_PU_SDA |
| 2 | 330R | room:R_Axial_P7.62mm | R_SCL, R_SDA |
| 2 | DEFAULT_OPEN | room:Jumper_2_Open_P2.54mm | JP_PIR_5V, JP_SDS_5V |
| 1 | 100R | room:R_Axial_P7.62mm | R_BEEP_S |
| 1 | 100k | room:R_Axial_P7.62mm | R_PIR_PD |
| 1 | 1N5819 | room:D_Axial_P7.62mm | D_PIR |
| 1 | 2N3904 C/B/E | room:TO92_CBE | Q_PIR |
| 1 | 3V3/GND | room:TestPoint_2Pin_THT | TP_3V3 |
| 1 | 470R | room:R_Axial_P7.62mm | R_LED_3V3 |
| 1 | 470uF | room:C_Radial_P2.00mm | C6 |
| 1 | 5V/GND | room:TestPoint_2Pin_THT | TP_5V |
| 1 | DSUN_PIR GND/OUT/VCC | room:PinHeader_1x03_P2.54mm | J_PIR |
| 1 | EXT 5V IN / GND | room:PinHeader_1x02_P2.54mm | J_5V_EXT |
| 1 | GND/GND | room:TestPoint_2Pin_THT | TP_GND |
| 1 | IDEASPARK_ESP32_1V14_TFT_30PIN | room:Ideaspark_30Pin_Provisional | U1 |
| 1 | KEYES BUZZER S/VCC/- | room:PinHeader_1x03_P2.54mm | J_BEEP |
| 1 | LED PIR 5V LIVE | room:D_Axial_P7.62mm | D_LED_PIR |
| 1 | LED RED 3V3 LIVE | room:D_Axial_P7.62mm | D_LED_3V3 |
| 1 | LED SDS 5V LIVE | room:D_Axial_P7.62mm | D_LED_SDS |
| 1 | SCL/GND | room:TestPoint_2Pin_THT | TP_SCL |
| 1 | SDA/GND | room:TestPoint_2Pin_THT | TP_SDA |
| 1 | SDS011 5V/GND/RXD/TXD | room:PinHeader_1x04_P2.54mm | J_SDS |
| 1 | SELECT: 1-2 USB / 2-3 EXT | room:PinHeader_1x03_P2.54mm | JP_5V_SRC |
| 1 | SHT41 VIN/GND/SCL/SDA | room:PinHeader_1x04_P2.54mm | J_SHT |
| 1 | VEML7700 VIN/3Vo/GND/SCL/SDA | room:PinHeader_1x05_P2.54mm | J_VEML |

konih/atmosmesh
ESP32 indoor air-quality station: PM, climate, and a local OLED — headed for MQTT, Home Assistant, and Grafana.





mudmin/AnotherMaker
This is where I will store code snippets for AnotherMaker Videos

qbancoffee/imac_g3_ivad_board_init
iMac G3 IVAD board initialization with an arduino

Stefan-Olt/MISRC
MISRC Is a multi channel RF capture device for FM RF, S-Video, CVBS RAW capture and anything else, but intended and supported for the decode family of projects vhs-decode, ld-decode, hifi-decode.

It measures 80 × 60 mm and has 2 copper layers, 1.6 mm thick.
44 parts. 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 konih/atmosmesh repository on GitHub, at the commit this page was made from: the board is hardware/kicad/atmosmesh-room/atmosmesh-room.kicad_pcb and its schematic hardware/kicad/atmosmesh-bench/AtmosmeshAqua/AtmosmeshAqua.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).