
Project CV
KazimGL/ESP32-PowerIoT-DevBoard
ESP32 battery-powered IoT dev board with Li-ion charging, protection, and sensor support — designed in KiCad

Low-power ESP32 environmental telemetry node. Includes custom KiCad hardware schematics, ESP-NOW protocol broadcasting, custom I2C drivers, and deep sleep power management.
Metsta is an open-source printed circuit board by losneoo, from the losneoo/esp32-wsn-telemetry-node repository on GitHub. It is a 2-layer board of 23.5 × 5 mm with 25 parts on 57 nets, routed with 204 tracks and 24 vias.
It is built around the CH340C, ESP32-WROOM-32E and BME280, with the SGP30 and AP2112K-3.3 among its other parts. Its parts include 10 resistors, 5 ICs, 4 capacitors, 2 diodes and 2 transistors. It belongs with the ESP32 boards of this library.
This repository documents the complete hardware and firmware implementation of an ultra-low-power, custom-designed ESP32 environmental sensor node. I designed this system from scratch from KiCad PCB layout to FreeRTOS C firmware as a comprehensive proof-of-concept for deployable, battery-operated IoT telemetry using the connectionless ESP-NOW protocol.
The system continuously monitors temperature, humidity, barometric pressure, estimated CO2 (eCO2), and battery voltage, broadcasting the data to a central gateway before returning to a deep sleep state.
I designed this wireless station to operate autonomously on battery power for extended periods. It relies on a carefully orchestrated 5-minute wake/sleep cycle. The firmware is written in C using the Espressif IoT Development Framework (ESP-IDF v5+) and FreeRTOS.
The core design philosophy is modularity and power efficiency. The hardware separates the power domain, digital domain, and sensor domain, while the firmware abstracts sensor communication, radio transmission, and sleep management into isolated components.
The complete telemetry payload is structured as follows:
typedef struct __attribute__((packed)) {
uint8_t node_id; // Derived from MAC address
uint32_t message_id; // RTC incremented message counter
float temperature; // °C
float humidity; // %RH
float pressure; // hPa
uint16_t eco2_ppm; // eCO2 in parts-per-million
uint16_t battery_mv; // Calibrated battery voltage (mV)
uint8_t status_flags; // Bitmask for Sensor/Battery errors
} sensor_payload_t;The custom PCB was designed in KiCad. The design files (schematic, layout, and component libraries) are available in the Hardware/ directory.
The board is powered by a lithium-ion battery, regulated to 3.3V by a high-efficiency AP2112K Low Dropout (LDO) regulator. This LDO was chosen for its low quiescent current, which is critical for maximizing battery life during deep sleep.
Battery voltage monitoring is implemented using a simple resistive voltage divider connected to an ADC channel. To ensure accurate readings across the discharge curve, the firmware (battery_adc.c) utilizes the ESP32 internal calibration routines to convert raw ADC readings to precise millivolts.
The node features two primary environmental sensors sharing a single 100kHz I2C bus:
The I2C bus utilizes hardware 4.7kΩ pull-up resistors to ensure crisp signal edges, allowing the firmware to disable internal weak pull-ups for improved reliability.
A modern USB-C receptacle is included for direct flashing and serial debugging. The USB data lines (DP, DN) are routed to a CH340C USB-to-UART bridge, which interfaces with the ESP32 hardware UART0. The auto-reset circuit (utilizing DTR/RTS signals and two NPN transistors) allows seamless firmware uploads via idf.py flash without manual button presses.
The firmware is structured into several modular source components:
| Module | Role |
|---|---|
main.c | Core application logic, sleep management, and payload assembly. |
central_node.c | Gateway application logic for receiving ESP-NOW packets. |
battery_adc.c | ADC initialization, calibration, and voltage calculation. |
bme280.c | BME280 initialization, raw data reading, and compensation math. |
sgp30.c | SGP30 initialization, IAQ reading, and CRC8 validation. |
The primary execution flow in app_main() is strictly linear to minimize active time:
sensor_payload_t and set status flags.To achieve micro-ampere average power consumption, standard Wi-Fi (connecting to an AP, acquiring DHCP, establishing TCP/MQTT connections) is too slow and power-hungry.
I chose ESP-NOW, a connectionless protocol that allows the node to wake up, broadcast its 18-byte payload in milliseconds, and immediately go back to sleep. The node transmits to a broadcast MAC address (FF:FF:FF:FF:FF:FF), which is received by the central gateway device running central_node.c.
I wrote custom, lightweight drivers for both sensors rather than relying on heavy third-party libraries:
bme280.c driver includes the full Bosch integer compensation algorithms, reconstructing the calibration matrix from the sensor's NVM to calculate exact physical values.sgp30.c driver implements strict CRC8 verification on every byte received from the sensor to prevent corrupted IAQ readings.During development, several hardware and firmware interactions required careful resolution:
| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | 10k | Resistor_SMD:R_0805_2012Metric | R5, R6, R7, R8 |
| 2 | 0.1uf | Capacitor_SMD:C_0805_2012Metric | C3, C4 |
| 2 | 100k | Resistor_SMD:R_0805_2012Metric | R9, R10 |
| 2 | 10uf | Capacitor_SMD:C_0805_2012Metric | C1, C2 |
| 2 | 4k7 | Resistor_SMD:R_0805_2012Metric | R3, R4 |
| 2 | 5k1 | Resistor_SMD:R_0805_2012Metric | R1, R2 |
| 2 | D_Schottky | Diode_SMD:D_SOD-123 | D1, D2 |
| 2 | NPN | Package_TO_SOT_SMD:SOT-23 | Q1, Q2 |
| 1 | AP2112K-3.3 | Package_TO_SOT_SMD:SOT-23-5 | U1 |
| 1 | BME280 | Package_LGA:Bosch_LGA-8_2.5x2.5mm_P0.65mm_ClockwisePinNumbering | U3 |
| 1 | CH340C | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U2 |
| 1 | Conn_01x02_Pin | Connector_JST:JST_PH_B2B-PH-K_1x02_P2.00mm_Vertical | J2 |
| 1 | ESP32-WROOM-32E | RF_Module:ESP32-WROOM-32D | U5 |
| 1 | SGP30 | sgp30:SGP30 | U4 |
| 1 | USB_C_Receptacle_USB2.0_16P | Connector_USB:USB_C_Receptacle_GCT_USB4110 | J1 |
It measures 23.5 × 5 mm and has 2 copper layers, 1.6 mm thick.
25 parts, built around the CH340C, ESP32-WROOM-32E, BME280 and SGP30. 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 losneoo/esp32-wsn-telemetry-node repository on GitHub, at the commit this page was made from: the board is Hardware/metsta.kicad_pcb and its schematic Hardware/metsta.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask losneoo before reusing the design.

KazimGL/ESP32-PowerIoT-DevBoard
ESP32 battery-powered IoT dev board with Li-ion charging, protection, and sensor support — designed in KiCad

nkitanov/iaq_board
IAQ Board is a DIY (Do-It-Yourself) device for measuring internal air quality

dustpot/indoor-air-monitor
A battery-powered ESP32 monitor for the non-particulate qualities of indoor air: temperature, humidity, pressure, eCO₂, and TVOC.

LEAT-EDGE/ambient-pcb-dkaiot
The design also provides empty footprints for several other sensors which are not populated in the Ambient variant: - Light sensor (LITEON LTR-303ALS-01) - MEMS microphone (Knowles SPH0645LM4H) - Indoor air quality…


entropia/Teebeutel-Hardware
Teebeutel (eng. Teabag) is an electronic, Entropia themed con-badge for the GPN20, featuring an ESP32 microprocessor running micropython.

aluisioalves123/esp32-env-sensor
Placa de sensor ambiental com ESP32-WROOM-32E projetada do zero no KiCad 9: USB-C com CH340C e auto-program, BME280 e BH1750FVI em I2C, regulacao AMS1117-3.3.
