SmartDB v2 system firmware
One PlatformIO project using ESP-IDF, with two firmware targets:
Target |
Board |
Responsibilities |
|---|---|---|
|
SmartDB v2 ESP32-S3-WROOM-1-N16R8 |
AC current, thermal sensing, local cutoff, configuration/event storage, RGB–thermal fusion, HTTP status and HTTPS telemetry |
|
Separate AI Thinker ESP32-CAM + USB programmer base |
Fresh QVGA JPEG capture over Wi-Fi |
|
Same S3, optional demonstration |
Synthetic fusion, relay always disabled; not another required board |
PlatformIO compiles and links the source files automatically. Flash one image per board, not one file at a time. J6 supplies the external camera’s USB power; image data uses Wi-Fi. The MLX90640 connects to the S3 over I²C. The existing older SD-card camera experiment is separate from this project.
This implements the isolated low-voltage AC monitoring bench scope, up to 1 A. The PCB logic supply remains DC; do not apply AC to its DC power input. Relay contact voltage/current ratings and the selected load must be checked against the actual relay BOM. This is not a mains protection firmware or a validated protective device.
Manual build and flash (optional)
The menu performs these operations for you; these commands remain available for development:
pio run -e smartdb_s3
pio run -e esp32cam
If pio is not on PATH, use the PlatformIO terminal or, on this workstation,
/home/chheng-lydia/.platformio/penv/bin/pio in its place. The first build downloads dependencies.
Build targets sequentially: ESP-IDF’s shared managed-component lock is target-specific.
The platform and direct component versions are pinned in platformio.ini and
main/idf_component.yml (ESP-IDF 6.0.1 with espressif32 7.0.1).
Use a data-capable USB cable and list ports:
pio device list
pio run -e smartdb_s3 -t upload --upload-port /dev/ttyUSB0
pio device monitor -e smartdb_s3 --port /dev/ttyUSB0
Then connect the camera’s programmer base and use its actual port:
pio run -e esp32cam -t upload --upload-port /dev/ttyUSB1
pio device monitor -e esp32cam --port /dev/ttyUSB1
The port names above are examples; a board may use /dev/ttyACM0, another USB number,
or a Windows COM port. Close the serial monitor before uploading. In VS Code, the same
actions are under PlatformIO → Project Tasks → target → Build / Upload / Monitor.
If automatic download mode fails, hold BOOT/IO0, tap RESET, start upload, then release BOOT/IO0 once it connects. After upload, release IO0 and reset to run. The camera base’s buttons and automatic reset circuitry vary by supplier. Holding the S3 BOOT button during reset selects ROM download mode; runtime re-arm is a different action described below.
PlatformIO uploads the matching bootloader, partition table, and application together.
Generated application images are .pio/build/smartdb_s3/firmware.bin and
.pio/build/esp32cam/firmware.bin; do not flash either onto the other board. Uploading normally
preserves NVS configuration/trip history; erasing flash removes them. No board has been flashed
as part of this implementation.
The shared partitions.csv reserves a 2 MiB application slot on both boards and keeps the
previous NVS/PHY offsets. It does not add OTA support or erase saved configuration.
Local sensing and protection
The v2 pin map is the source for GPIO assignments:
Function |
Connection |
|---|---|
Relay drive |
GPIO4, active high; starts low |
Buzzer drive |
GPIO5 via Q2 |
RGB status LED |
Red GPIO6, green GPIO7, blue GPIO8 |
I²C |
SDA GPIO10, SCL GPIO2, 400 kHz |
ADS1115 |
Address |
MLX90640 |
Address |
Local button |
BOOT GPIO0, active low |
The SCT-013-000 is AC-only, nominal 2000:1, with the board’s 18 Ω burden. The ADS1115
uses ±0.256 V range and 860 SPS conversion setting in single-shot mode. Actual sampling is
slower because each conversion is polled over the shared bus. RMS uses a 200 ms sample
window with DC offset removed; nominal scaling is 2000 / 18 = 111.1111 A/V. Clipping,
I²C failures, insufficient samples and long sample gaps invalidate the window. Accuracy at
sub-amp currents and under simultaneous MLX traffic requires bench characterization and
calibration; a 100 A CT is not intrinsically a precision sub-amp sensor. An unplugged CT can
look like zero current and cannot be diagnosed reliably by this circuit.
Protection runs in a dedicated 10 ms task on core 1, independently of networking/fusion. It uses native thermal maximum, not bicubic pixels. Current older than 500 ms or thermal data older than 1.5 s is invalid. An armed unit trips on invalid sensors, overcurrent, overtemperature, or storage failure. This is windowed monitoring, not instantaneous short-circuit protection; the 10 ms task period is not an end-to-end cutoff guarantee. The control task is watched by the 10-second ESP-IDF task watchdog with panic/restart enabled.
Startup is always open. Default configuration is uncommissioned, 0.8 A and 60 °C limits.
Use Change protection limits in the menu, or read /config and PUT all five fields
with a strictly greater version; save a calibrated
current_scale_a_per_v, limits and commissioned: true when the installation is ready.
Configuration changes open the relay and require local re-arm. Current limit is capped at
1 A; temperature range is 20–100 °C. Persistence failures prevent arming.
To re-arm while running: release BOOT first, hold it for at least two seconds, then release. Both sensors must have remained valid and below recovery thresholds for two seconds (current below 90% of limit, temperature at least 5 °C below limit). The same gesture opens an armed relay. A trip remains latched until a qualifying local gesture; no network endpoint can close/re-arm the relay. Reset/power loss never automatically closes it.
LEDs show blue disarmed, green armed and red tripped. Buzzer drive defaults off because
BZ1’s active/passive type is not resolved. Set SMARTDB_ACTIVE_BUZZER=1 only for a verified
active buzzer; it pulses on a trip. Passive buzzer PWM is not implemented.
The last 16 transitions and trip flag persist in NVS through a background writer after GPIO cutoff. A power loss before that write can lose the newest event, but reboot still starts open. The event list is a bounded diagnostic history, not an unlimited durable audit log.
RGB–thermal fusion
The camera serves JPEGs captured after its request arrives. The S3 decodes RGB, pairs the request interval with the MLX capture interval using its own monotonic clock, and requires their combined span to fit 500 ms. It does not compare unsynchronized board clocks. Images expire after two seconds. Stale or missing imagery never blocks local protection.
config/calibration.h starts disabled. Actual sensor alignment cannot be inferred from
the PCB or a product photograph. For fixed cameras viewing a near-planar target, provide at
least six spread-out corresponding pixel centers in a JSON file:
{
"version": "panel-1-v1",
"rgb_size": [320, 240],
"thermal_size": [32, 24],
"points": [
{"rgb": [0, 0], "thermal": [0, 0]},
{"rgb": [319, 0], "thermal": [31, 0]},
{"rgb": [0, 239], "thermal": [0, 23]},
{"rgb": [319, 239], "thermal": [31, 23]},
{"rgb": [160, 0], "thermal": [15.54858934, 0]},
{"rgb": [160, 239], "thermal": [15.54858934, 23]}
],
"regions": [{"id": "panel", "rect": [0, 0, 319, 239], "min_samples": 4}]
}
These example points are synthetic, only showing file format. Replace every point and region with real correspondences; do not deploy this example as installation calibration.
python3 tools/calibrate.py measured-points.json config/calibration.h
pio run -e smartdb_s3
The tool checks fit residual, geometry and region bounds. Independently validate other targets afterwards. The runtime does not undistort the JPEG or compensate changing depth; use a lens/scene where the planar mapping is adequate, or add and validate lens correction before using it for more demanding geometry. Recalibrate after changing either camera pose, focus, resolution, mirror/flip setting or target distance.
Bicubic interpolation smooths the display only, with local overshoot clamping. Native 32×24 samples provide region maximum/mean/rise rate. Invalid/factory-bad samples are excluded. Boundary pixels and ambiguous overlapping region assignments are rejected; regions with too few native samples are unsupported. Interpolation cannot recover small hotspots the sensor never resolved. This implementation uses configured component regions; it does not include a trained YOLO detector or a learned risk score.
For a demonstration without sensor data, build smartdb_s3_demo. It marks output synthetic,
uses a synthetic mapping/hotspot, and forces the relay disabled. The browser at the S3’s IP
shows the fused image and status after entering the token.
Firebase integration
The implemented Firebase API and team handoff provide device credentials, persistent telemetry/history, in-app alerts and command acknowledgements. The S3 consumes pending commands from accepted telemetry responses and persists the last result for retry handling. Cloud limits preserve local commissioning and calibration, open the relay and require physical re-arm. No remote close command exists.
Fresh fused previews upload at most once per 30 seconds, or at the telemetry interval if
longer, to the companion /fusion/frame endpoint. Failed preview uploads are dropped.
The backend retains one timestamped BMP per device, separate from numerical native-sample
measurements. The frontend team owns the user dashboard; dashboard/ is a developer console.
Postman and telemetry
Use the existing Postman folder:
smartdb_api/firmware contains status, configuration, relay-open, BMP and JPEG requests.
Set firmware_url, camera_url, and the local firmware_token variable. /status is available
even with no valid fused image; /fused.bmp returns 503 until calibrated fresh fusion exists.
Optional telemetry setup in the menu takes the full HTTPS URL matching
POST /api/v1/devices/{device_id}/telemetry and a separate telemetry bearer token.
The camera does not receive the cloud telemetry token. The older SMARTDB_TELEMETRY_URL
and SMARTDB_TELEMETRY_TOKEN defines remain fallback defaults for the S3.
The publisher verifies the server certificate using ESP-IDF’s certificate bundle, rejects
redirects, sends every five seconds by default (configurable to 5–60 seconds) and expects HTTP 202. It retries the same sample_id
with 5–60 s backoff; a server should deduplicate it. A 12-entry RAM queue discards the oldest
waiting telemetry under prolonged outages. Queued telemetry is lost at reboot; NVS event
history is included in subsequent snapshots. The server implementation lives in cloud/;
run its emulators locally or deploy the API to a reachable HTTPS endpoint. Persistent 4xx responses
need credentials/contract correction and hold up the upload queue.
No voltage sensor exists in this pin map: voltage and power are null. Invalid current or
temperature is null; UTC timestamp is null until the clock is set by SNTP, with monotonic
uptime still supplied. Sensor values and vision readiness are independent. No fabricated
arc-detection score is published. Local camera/control HTTP is bearer-authenticated but
unencrypted; keep it on the isolated bench network. Production CoAP/DTLS, signed configuration,
OTA, cloud AI, application push alerts and production credential provisioning remain separate
architecture work and are not claimed by this bench firmware.
Verification and source layout
python3 -m pip install -r test/requirements.txt
pio run -e smartdb_s3 -e smartdb_s3_demo -e esp32cam
sh tools/check.sh
Host tests cover protection state transitions, AC RMS conversion, stale data, calibration,
bounded cubic interpolation, ROI ambiguity, BMP encoding, the MLX invalid-auxiliary regression,
Postman request/schema consistency, USB response correlation, setup field validation,
profile file permissions, settings persistence/recovery and credential redaction. Build once
before host tests to fetch the pinned cJSON dependency. Tests produce test/build/fused-demo.bmp. Firmware
builds and host tests do not establish real sensor accuracy, frame timing, relay behavior,
thermal calibration, electrical ratings or electromagnetic immunity. No hardware tests have
been performed in this design-only session.
Files |
Purpose |
|---|---|
|
Target-specific application entry points |
|
Board drivers, protection integration, NVS and local control |
|
Wi-Fi, authentication and telemetry |
|
Persistent connection settings and bounded USB setup protocol |
|
Interactive setup/build/flash menu |
|
Portable fusion, measurement and protection logic |
|
Pinned Melexis driver with documented auxiliary-error patch |
|
Installation settings and calibration |
|
Calibration generation and host verification |
Driver references: Espressif camera, Melexis MLX90640, TI ADS1115 datasheet. USB implementation references: ESP-IDF UART and pySerial API.