Skip to the content
4 layers108.5 × 60 mmESP32 BME690, the printed circuit board in 3D

Multi-room ESP32-S3 environmental sensor node that streams air-quality data to a Node.js server over Wi-Fi. Built around the Bosch BME690 with auxiliary light, sound and battery monitoring.

Size
108.5 × 60 mm
Copper layers
4
Thickness
1.6 mm
Parts
98
Nets
101
Pads
385
Tracks, vias
1,073, 117
Pours
1
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
5 May 2026
Updated
4 Jul 2026

Overview

ESP32 BME690 is an open-source printed circuit board by andrewcnjuguna, from the andrewcnjuguna/ESP32_BME690 repository on GitHub. It is a 4-layer board of 108.5 × 60 mm with 98 parts on 101 nets, routed with 1,073 tracks and 117 vias.

It is built around the ESP32-S3-WROOM-1-N8, MCP73871EV and BME690, with the MAX4466EXK+T, W25Q32JVSSIQ and GSD090012SEU among its other parts. Its parts include 38 resistors, 28 capacitors, 8 ICs, 6 diodes and 5 connectors. It belongs with the ESP32 boards of this library.

Main components

12

README

README.md

ESP32_BME690

Multi-room ESP32-S3 environmental sensor node that streams air-quality data to a Node.js server over Wi-Fi. Built around the Bosch BME690 with auxiliary light, sound and battery monitoring.

PCB

Hardware

  • ESP32-S3-WROOM-1 module
  • Bosch BME690 (I2C) — temperature, humidity, pressure, IAQ, CO2eq, bVOC
  • SH1106 0.96" OLED (I2C)
  • TEMT6000 ambient light sensor
  • Analog MEMS microphone (sound level)
  • 1-cell LiPo with 1M/1M voltage divider on the battery rail
  • USB-C power / programming
  • Status LED

KiCad project lives in hardware/kicad/.

Pin map

FunctionGPIO
I2C SDA8
I2C SCL9
Status LED2
Light sensor (TEMT6000)5
Microphone4
VBAT sense1

Firmware

Sketches live in firmware/.

  • ESP32_BME690_usb/ — main node firmware
  • battery_level/, light_sensor_test/, sound_sensor/ — bring-up sketches

Setup

  1. Open firmware/ESP32_BME690_usb/ in the Arduino IDE.
  2. Copy secrets.h.example → secrets.h and fill in your Wi-Fi credentials and server URL. secrets.h is gitignored.
  3. Install required libraries: Adafruit GFX, Adafruit SH110X, BSEC2 (Bosch), ArduinoJson, ArduinoOTA.
  4. Build & flash. The locationID constant in the sketch tags this node's data on the server (e.g. Kitchen, Living_Room).

Node web page (port 80)

Each node runs its own tiny status page at http://<node-ip>/ (auto-refreshes every 5 s). It shows the live BSEC readings, light / sound / battery, WiFi signal (RSSI in dBm, an approximate 0–100 % quality, and a label Excellent/Good/Fair/Weak/Poor), and the SD-log status. If the SD card is mounted it also links http://<node-ip>/datalog.csv to download the full log.

The node's IP is printed on the serial console at boot ([INFO] Web UI at http://...).

WiFi is self-healing: if the router is down at boot (or the link drops later), the node keeps logging to SD and retries the connection every 30 s in the background; OTA and the web page start automatically as soon as the first connection succeeds — no reboot needed.

Data upload

Every 3 s BSEC cycle the node POSTs a JSON snapshot to SERVER_URL (/sensor-data on the dashboard server). The payload includes location, all sensor channels, and the WiFi link quality (rssi in dBm plus a derived wifiPercent). Nodes running older firmware simply omit the WiFi fields — the dashboard shows "not reported (update firmware)" for them.

Server (dashboard)

A small Node/Express app in server/ collects POSTs from each node and serves a per-room dashboard.

bash
cd server
npm install express
node server.js

Then point a browser at http://<host>:3000.

  • POST /sensor-data — nodes push their JSON snapshot here.
  • GET /data — latest snapshot of every room, as JSON.
  • GET / — dashboard. Room boxes are created dynamically from whatever location tags have reported, so adding a node needs no server change. Each box shows the air-quality channels plus battery and WiFi signal quality for that node.

The pi_server notes file documents the systemd / iptables setup used on the home Raspberry Pi.

Data logging & plotting

SD card log

The node averages its 3 s BSEC samples and appends one CSV row per minute to /datalog.csv on the SD card:

text
boot_id,uptime_s,epoch,synced,temp_c,hum_pct,press_hpa,iaq,iaq_acc,
co2_ppm,voc_ppm,lux,sound_db,sound_avg,sound_peak,batt_v,batt_pct
  • boot_id — power-session counter (persisted in EEPROM), groups rows from one uninterrupted run.
  • uptime_s — seconds since boot (monotonic, rollover-safe).
  • epoch / synced — Unix time and whether NTP had synced when the row was written. Rows logged before the sync have epoch=0, but their true time is still recoverable (see below).
  • iaq_acc — BSEC accuracy 0–3; air-quality values below your chosen threshold are warm-up noise.

Grab the file over WiFi from http://<node-ip>/datalog.csv, or pull the card.

Plotting with analysis/plot_datalog.py

bash
pip install pandas matplotlib
python analysis/plot_datalog.py datalog.csv            # plot a local file
python analysis/plot_datalog.py --ip 192.168.0.65      # fetch straight from the node
python analysis/plot_datalog.py datalog.csv -o out.png # save instead of showing
python analysis/plot_datalog.py datalog.csv --last 48  # last 48 h only
python analysis/plot_datalog.py datalog.csv --min-accuracy 3  # strict AQ filter

The script produces six stacked, time-aligned panels: temp+humidity, pressure, IAQ, CO₂eq+VOCeq, light+sound, and battery. Under the hood it:

  1. Reconstructs absolute time. For each boot_id it derives boot_epoch = epoch − uptime_s from the NTP-synced rows, then stamps every row of that session as boot_epoch + uptime_s — so even rows logged before the NTP sync get correct timestamps. Sessions that never synced have no time anchor and are dropped with a warning.
  2. Masks warm-up air-quality data. IAQ/CO₂/VOC are blanked where iaq_acc < --min-accuracy (default 1) so BSEC's calibration period doesn't draw misleading flat lines.
  3. Breaks lines at gaps. Rows are minutely, so a jump larger than --gap-min (default 5 min) means the node was off; a NaN break is inserted so downtime shows as a blank gap instead of a false straight line across it.

Repo layout

text
firmware/   Arduino sketches (main + bring-up)
server/     Node/Express dashboard
analysis/   plot_datalog.py — CSV log plotting
hardware/   KiCad project + design notes
images/     PCB photos

Component datasheets are kept locally only (not redistributable).

Parts

98
QtyValueFootprintReferences
130.1uCapacitor_SMD:C_0805_2012MetricC2, C5, C8, C10, C11, C13, C15, C17, C18, C20, C22, C23, C25
1310kResistor_SMD:R_0805_2012MetricR2, R18, R21, R22, R23, R24, R25, R26, R31, R35, R36, R37, R39
610uCapacitor_SMD:C_0805_2012MetricC1, C6, C26, C28, C29, C30
6470Resistor_SMD:R_0805_2012MetricR7, R8, R9, R10, R14, R15
447Resistor_SMD:R_0805_2012MetricR16, R17, R19, R20
31kResistor_SMD:R_0805_2012MetricR11, R27, R29
3LTST-C170KRKTESP32 Project Footprints:LEDC2012X120NLED1, LED4, LED6
210nCapacitor_SMD:C_0805_2012MetricC19, C21
210uESP32 Project Footprints:T491AC12, C14
21MResistor_SMD:R_0805_2012MetricR28, R30
21uCapacitor_SMD:C_0805_2012MetricC7, C27
24k7Resistor_SMD:R_0805_2012MetricR32, R33
25k1Resistor_SMD:R_0805_2012MetricR3, R4
2BC817Package_TO_SOT_SMD:SOT-23Q2, Q3
2LTST-C170GKTESP32 Project Footprints:LEDC2012X120NLED2, LED5
2USLPT2819DT2TRESP32 Project Footprints:SW_USLPT2819DT2TRS1, S2
10ZCH0110AF2EESP32 Project Footprints:FUSC3226X100NF1
1100kResistor_SMD:R_0805_2012MetricR38
1100pCapacitor_SMD:C_0805_2012MetricC16
120kResistor_SMD:R_0805_2012MetricR5
122k1Resistor_SMD:R_0805_2012MetricR12
122uCapacitor_SMD:C_0805_2012MetricC24
12kResistor_SMD:R_0805_2012MetricR6
135WR100KLFTRESP32 Project Footprints:TRIM_35WR100KLFTRR34
14.7uESP32 Project Footprints:T491AC9
147k5Resistor_SMD:R_0805_2012MetricR13
1AP2112K-3.3Package_TO_SOT_SMD:SOT-23-5U7
1B2B-PH-SM4-TBESP32 Project Footprints:JST_B2B-PH-SM4-TBJ2
1B4B-XH-AM__LF__SN_ESP32 Project Footprints:JST_B4B-XH-AM__LF__SN_J4
1BME690ESP32 Project Footprints:BME690IC1
1CMC-5042PF-ACESP32 Project Footprints:CUI_CMC-5042PF-ACMK1
1CP2102N-Axx-xQFN20Package_DFN_QFN:SiliconLabs_QFN-20-1EP_3x3mm_P0.5mm_EP1.8x1.8mmU4
1Conn_01x10_PinConnector_PinHeader_2.54mm:PinHeader_1x10_P2.54mm_VerticalJ5
1ESP32-S3-WROOM-1RF_Module:ESP32-S3-WROOM-1U2
1FBMJ2125HM330-TESP32 Project Footprints:BEADC2012X105NFB1
1GSD090012SEUESP32 Project Footprints:AMPHENOL_GSD090012SEUJ3
1LTST-C170TBKTESP32 Project Footprints:LEDC2012X120NLED3
1MAX4466EXKESP32 Project Footprints:SOT65P210X110-5NU6
1MCP73871Package_DFN_QFN:QFN-20-1EP_4x4mm_P0.5mm_EP2.5x2.5mmU1
1SS-52400-002ESP32 Project Footprints:BELFUSE_SS-52400-002J1
1TEMT6000X01ESP32 Project Footprints:TRANS_TEMT6000X01Q1
1Test CLKTestPoint:TestPoint_Pad_D1.0mmTP3
1Test CSTestPoint:TestPoint_Pad_D1.0mmTP5
1Test CS_SDTestPoint:TestPoint_Pad_D1.0mmTP4
1Test MISOTestPoint:TestPoint_Pad_D1.0mmTP2
1Test MOSITestPoint:TestPoint_Pad_D1.0mmTP1
1USBLC6-2SC6Package_TO_SOT_SMD:SOT-23-6U5
1W25Q32JVSSIQESP32 Project Footprints:SOIC127P790X216-8NU3

Similar boards

  • 4 layers83 × 53.5 mmESP 32 PCB Project, the printed circuit board in 3D

    ESP 32 PCB Project

    BBIkal/ESP32_IOT_Project

    A compact 4-layer mixed-signal PCB designed in KiCad 9, built around the ESP32-C3 module for IoT sensor applications.

    92 parts
  • 4 layers60.6 × 72.3 mmESP32, the printed circuit board in 3D

    ESP32

    KirtiChickamath/ESP32-IoT-sensor-board

    ESP32- IoT sensor board. 4-layer PCB, designed in KiCad . Features LiPo charging, USB-C, SPI flash, SD card, BME280, and more.

    90 parts2
  • 4 layers107.6 × 55 mmESP32-sensor board, the printed circuit board in 3D

    ESP32-sensor board

    chopda15/ESP32-sensor-board

    Custom-designed ESP32-C3 IoT PCB with integrated Li-ion charging, environmental sensing, data logging, USB-C connectivity, and power-efficient embedded system architecture.

    94 parts
  • 4 layers77.3 × 48.5 mmESP32 IOT, the printed circuit board in 3D

    ESP32 IOT

    WasikeIsaac/ESP32_IOT-PCB-

    ESP32 IoT board: 4-layer KiCad PCB with USB-C, BME280, mic, audio amp, SD card, GPIO breakout. Full custom design from schematic to layout.

    87 parts1
  • 4 layers93 × 56.3 mmKicad 10 ESP32 Demo Project, the printed circuit board in 3D

    Kicad 10 ESP32 Demo Project

    Kaushalyasamantha/ESP32-C3-IoT-Dev-Board

    "A custom 4-layer IoT development board built around the ESP32-C3 in KiCad 9"

    87 parts
  • 4 layers81 × 56 mmEsp32-sensor board, the printed circuit board in 3D

    Esp32-sensor board

    pasensiojimenez/esp32-sensor-board

    4-layer ESP32-C3 IoT development board designed in KiCad 10. Onboard power management (USB-C/LiPo), environmental sensors (BME280, light, sound), and SD/flash storage.

    88 parts

Questions

How big is the ESP32 BME690 PCB?

It measures 108.5 × 60 mm and has 4 copper layers, 1.6 mm thick.

What parts does the ESP32 BME690 use?

98 parts, built around the ESP32-S3-WROOM-1-N8, MCP73871EV, BME690 and MAX4466EXK+T. 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.

Where can I download the ESP32 BME690 KiCad files?

From the andrewcnjuguna/ESP32_BME690 repository on GitHub, at the commit this page was made from: the board is hardware/kicad/ESP32_BME690.kicad_pcb and its schematic hardware/kicad/ESP32_BME690.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the ESP32 BME690 design in my own project?

Its repository states no licence, so its author keeps all rights: ask andrewcnjuguna before reusing the design.