# Key Outcomes
200
Mesh Nodes
10cm
UWB Accuracy
2ยตA
Idle Current
5yr
Battery Life
80%
False Alarm โ
99.7%
Uptime
# Problem & Solution
The Problem
- Large automotive plant couldn't track $2M of tooling across 10,000 mยฒ floor
- Wi-Fi RSSI positioning had ยฑ3m accuracy โ too coarse for individual workstation tracking
- Existing LoRa sensors couldn't carry environmental + energy data simultaneously
- Plant IT mandated Matter 1.2 for future Google Home / Apple HomeKit integration
- Battery replacement cost for 200 nodes was unsustainable if life < 2 years
The Solution
- ESP32-C6 native Zigbee + IEEE 802.15.4 mesh โ self-heals around failed nodes
- UWB DW1000 two-way ranging โ 10 cm accuracy, works through metal shelving
- Matter 1.2 coordinator (ESP32-S3) bridges Zigbee mesh to any Matter controller
- Deep-sleep duty cycle: 58 s sleep / 2 s awake โ 2 ยตA average โ 5yr on 2ร AA
- TFLite Micro occupancy model runs on coordinator โ reduces motion false alarms 80%
# Firmware Architecture (Sample)
zigbee_node.c โ ESP32-C6 Zigbee End Device with deep-sleep duty cycle
/* ESP32-C6 Zigbee sensor node โ 58s deep sleep, 2s active window Publishes: temperature, humidity, CO2, energy_wh, motion event */ #include "esp_zigbee_core.h" #include "esp_sleep.h" #include "scd41_driver.h" #include "cs5490_driver.h" #define SLEEP_DURATION_US (58 * 1000 * 1000) #define ZIGBEE_CHANNEL 15 typedef struct { int16_t temp_cdC; /* ยฐC ร 100 */ uint16_t humidity_pc; /* % ร 100 */ uint16_t co2_ppm; uint32_t energy_wh; /* cumulative */ uint8_t motion; uint8_t battery_pc; } node_report_t; void app_main(void) { /* Woke from deep sleep โ collect and transmit in <2s */ node_report_t report = {0}; scd41_wake_and_read(&report.temp_cdC, &report.humidity_pc, &report.co2_ppm); cs5490_read_energy(&report.energy_wh); report.motion = pir_read(); report.battery_pc = adc_read_battery_pct(); /* Join Zigbee network (already paired โ fast rejoin <150ms) */ esp_zb_init(&cfg); esp_zb_set_primary_network_channel_set(1 << ZIGBEE_CHANNEL); zigbee_transmit_report(&report); /* Schedule next UWB ranging if coordinator requests it */ if (rtc_mem_read_uwb_flag()) { uwb_dw1000_range_and_report(); rtc_mem_clear_uwb_flag(); } /* Back to deep sleep โ wake on timer OR motion PIR GPIO */ esp_sleep_enable_timer_wakeup(SLEEP_DURATION_US); esp_sleep_enable_ext0_wakeup(GPIO_PIR_INT, 1); esp_deep_sleep_start(); }
uwb_ranging.c โ DW1000 two-way ranging for 10cm asset positioning
/* Two-Way Ranging (TWR) with DW1000 UWB module via SPI Achieves <10cm RMS error in industrial metal-dense environment */ #define SPEED_OF_LIGHT 299702547.0 /* m/s in air */ #define DW_TIME_UNIT (1.0/499200000/128) /* ~15.65ps */ float uwb_measure_distance_m(uint8_t anchor_id) { uint64_t t_poll_tx, t_poll_rx, t_resp_tx, t_resp_rx, t_final_tx, t_final_rx; /* Phase 1: Tag sends POLL */ dwt_writetxfctrl(12, 0, 1); dwt_starttx(DWT_START_TX_IMMEDIATE); t_poll_tx = dwt_readtxtimestamp(); /* Phase 2: Wait for anchor RESPONSE (timeout 5ms) */ if (!dwt_wait_rx(5000)) return -1.0f; t_resp_rx = dwt_readrxtimestamp(); /* Phase 3: Tag sends FINAL */ dwt_writetxdata(&final_msg, sizeof(final_msg), 0); dwt_starttx(DWT_START_TX_IMMEDIATE); t_final_tx = dwt_readtxtimestamp(); /* Receive RESULT from anchor (contains its timestamps) */ if (!dwt_wait_rx(5000)) return -1.0f; dwt_readrxdata(&result, sizeof(result), 0); t_poll_rx = result.t_poll_rx; t_resp_tx = result.t_resp_tx; t_final_rx = result.t_final_rx; /* Compute ToF using asymmetric double-sided TWR formula */ double Ra = (double)(t_resp_rx - t_poll_tx); double Rb = (double)(t_final_rx - t_resp_tx); double Da = (double)(t_resp_tx - t_poll_rx); double Db = (double)(t_final_tx - t_resp_rx); double tof_ticks = (Ra * Rb - Da * Db) / (Ra + Rb + Da + Db); return (float)(tof_ticks * DW_TIME_UNIT * SPEED_OF_LIGHT); }
Security Note: All nodes boot with Secure Boot V2 + flash AES-256 encryption using ESP32-C6's hardware key manager. The OTA signing key never leaves the CI/CD HSM โ devices reject unsigned firmware at the ROM bootloader stage.
# Full Tech Stack
Hardware (per node)
ESP32-C6-MINI-1
DW1000 UWB Module
SCD41 COโ/Temp/RH
CS5490 Energy IC
PIR Motion Sensor
2ร AA Li-SOClโ
2-layer PCB (KiCad)
IP54 Enclosure
Firmware & Cloud
ESP-IDF v5.2
Zigbee Stack (ESP-Zigbee)
Matter 1.2 SDK
TFLite Micro (INT8)
Secure Boot V2
AWS Greengrass v2
React + WebSocket Dashboard
FastAPI + TimescaleDB
# Project Timeline
Weeks 1โ2
Node Hardware & Zigbee Stack
PCB design (node + coordinator), ESP-Zigbee end-device role, deep-sleep power profiling, OTA signing pipeline
Weeks 3โ4
UWB Ranging & Sensor Drivers
DW1000 SPI driver, asymmetric TWR algorithm, SCD41 IยฒC driver, CS5490 energy metering driver, battery gauge
Weeks 5โ6
Matter 1.2 & Greengrass
Matter coordinator firmware, Greengrass v2 component deployment, FastAPI backend, TimescaleDB hypertables
Weeks 7โ8
ML Model, Dashboard & Site Deployment
TFLite Micro occupancy model, React floor-map dashboard, RF site survey, 200-node factory deployment
Ready to Digitise Your Factory Floor?
I'll design a custom mesh sensor network for your facility โ from PCB to cloud dashboard โ with any scale from 20 to 1,000+ nodes.