Seb Zuddas

Axiometa Digital Twin

hardware-software digital twins

01

Overview

Live demo: https://sebzuddas.github.io/axiometa-digital-twin/ (interactive 3D building, runs in the browser)

Built at an Axiometa hackathon. Firmware for an Axiometa Genesis Mini ("ENV" node) that reads temperature, humidity, light and a dial, and streams them to a live 3D digital twin of a building.

02

Why it matters: sensing a whole building, cheaply

Most building monitoring is either one thermostat per zone or an expensive, installer-only system. This project goes the other way: a building owner can deploy many identical, low-cost sensor nodes and have each one appear in the twin automatically.

  • One board, one firmware. Every room runs the same Genesis Mini image. Rooms differ only by node ID.
  • No soldering, no custom PCBs. Sensors are Axiometa AX22 modules that click into any of the board's four ports, so changing what a node measures means swapping a module, not redesigning hardware.
  • Scale by repetition. A new room means another node on USB or battery power. It publishes to its own topic (axm/<node-id>/telemetry) and shows up in the viewer with no code changes.
  • See the whole building at once. Rooms are colour-coded by temperature, humidity or light in 3D, so hot spots, stuffy rooms and sunlit zones are visible at a glance.
  • Cheap hardware. An ESP32-S3 board plus a few hobby-grade sensors per room (a DHT11 and an LDR here), so instrumenting every room is realistic, not just a showcase floor.
  • A twin, not just a dashboard. The sensed values feed a building simulation (heat flow, occupants, HVAC control), so owners can ask "what if" as well as "what is".

The demo page lets you click rooms to deploy nodes and watch the building fill in. It is a simulation of the viewer; no hardware is needed.

 sensors ──► Genesis Mini ──USB serial──► serial→MQTT bridge ──► simulation ──► 3D twin
 (DHT11, LDR, encoder)   KEY:value @ 5 Hz                       (Rust)        (three.js)

Status: hackathon prototype. This repo holds the ENV node firmware and the project page. The serial→MQTT bridge, Rust simulation and full spec live in the companion hackathon project (AxiometaHack, not yet published) and are not in this repo.

03

Credits

Built using Axiometa hardware: the Genesis Mini board and AX22 modules. Hackathon project by Seb Zuddas.

04

Hardware

Port Part Pins Signal
P1 DHT11 data on P1_IO1 temperature, humidity
P2 Rotary enc. BTN P2_IO0, CLK P2_IO1, DT P2_IO2 dial (0–100) + button
P3 LDR analog out P3_IO0 (GPIO9, ADC1) light level

Board: ESP32-S3-N4R2 (4 MB flash, 2 MB QSPI PSRAM), custom axiometa_genesis_mini variant so the Px_IOy pin aliases exist.

05

Serial protocol

115200 baud. After boot the board prints READY, then emits one frame every 200 ms (5 Hz), one KEY:value per line:

Key Range / unit Notes
TEMP °C, 1 dp DHT11, sampled every 2 s; 0.0 until first valid read
HUM % RH, 1 dp DHT11, same cadence
SOLAR 0.0–1.0 LDR, mean of 5 ADC reads, 12‑bit. Flip to 1 - x if dark reads bright
ENC 0–100 Encoder dial, starts at 50, clamped. Bridge maps it to outdoor.temp_bias (−10…+10)
BTN 0 / 1 Push switch. Pressing re-centres ENC to 50

The encoder switch is active-HIGH on this board (read with INPUT_PULLDOWN), verified empirically.

Intended MQTT topics (per the firmware comments): axm/env-01/telemetry and twin/set.

06

Build & flash

Requires PlatformIO.

shell
pio run -t upload      # build and flash
pio device monitor     # 115200 baud

Libraries (auto-installed): adafruit/DHT sensor library, adafruit/Adafruit Unified Sensor, mathertel/RotaryEncoder.

Notable config in platformio.ini: pioarduino platform, 4 MB flash with the huge_app.csv partition table (the devkit default assumes 8 MB and won't boot), USB-CDC on boot.

07

Repo layout

src/sketch.ino   active firmware (ENV serial bring-up)
src/main.cpp     PlatformIO template stub   (excluded from build)
src/blink.cpp    P4 blink test              (excluded from build)
platformio.ini   board, flash, libs; build_src_filter selects sketch.ino
docs/            GitHub Pages site (static, no build step)

main.cpp, blink.cpp and sketch.ino each define setup()/loop(), so build_src_filter compiles only sketch.ino for now.

08

Project page

docs/index.html is a single static file: Three.js (pinned to 0.160.0 from jsDelivr) with a simulated building, no build step. It matches the palette of sebzuddas.com.

  • Publish: Settings → Pages → Deploy from a branch → main / /docs.
  • Preview locally: python3 -m http.server -d docs
  • Embed in sebzuddas.com/projects: <iframe src="https://sebzuddas.github.io/axiometa-digital-twin/?embed" style="width:100%;height:560px;border:0" loading="lazy"></iframe>. ?embed hides the surrounding text; ?theme=light|dark forces a theme.
09

Roadmap

  • Interactive Three.js project page (simulated)
  • Publish the serial → MQTT bridge, Rust sim and spec from the hackathon project
  • Connect the page to a live MQTT-over-WebSocket feed
  • Split firmware into roles (replace the build_src_filter workaround)