stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

Observatory

  • 34 Devlogs
  • 185 Total hours

An experimental Wi-Fi CSI sensing system for real-time spatial information, indoor positioning, vital sign monitoring, and presence detection.

Open comments for this post

10h 7m 39s logged

DEVLOG #34

The TX1 migration is now 100% verified, but the project is still only around ≈ 70% complete. The third and final boot attempt did not give me the clean result I was hoping for.

Recovery happened within the allowed time, but UART0 showed two app starts. After the first start, an RTC_SW_CPU_RST appeared and the app started again. It eventually reached BOOT_OK, but because of the duplicate start I still cannot accept the boot trace or move on to server activation and measurements. I am currently documenting the exact restart sequence and trying to figure out what caused it.

I also put together a source collection about Wi-Fi sensing and RF-based person detection. GitHub

The separate mmWave freshness test did not reproduce the old MMWAVE2 delay problem, but that does not prove it is fixed.

Next: get one clean TX1 boot, then activate the server and start collecting real measurements.

0
0
83
Open comments for this post

10h 4m 28s logged

DEVLOG #33

The TX1 finally made it all the way to BOOT_OK. After the CHECK_COUNTRY problem from the last update, the new candidate passed the Country20/Power44 and Wi-Fi checks, booted into test mode, and passed the local TX/RX4 checks. I also confirmed the amber LED and both mmWave transport paths.

The previous candidate had stopped because one sampling gap grew to 10.2 seconds. I traced that back to the timing bookkeeping and changed the sampler to schedule from the last real sample completion. The corrected run stayed within the sampling limits. That is a real improvement, but it is not the final acceptance yet. The full coverage result is still blocked by the clock-binding requirement, and the radar window only showed no_target, not a position result.

I also switched to the new diagnostic server in a controlled run. It stayed ready and a separate 61-second capture passed the coverage gate, but the active CSI position setup is still missing, so this does not count as a complete TX-7B or system pass.

The CAD UI got a pretty big upgrade too. MMWAVE1 and MMWAVE2 can now be edited as separate sensors with their own colors, 6 m fields of view, direction arrows, and yaw handles. I added a button to aim them at each other, plus a wall-angle tool that draws the real beam/wall intersection and lets me set the angle directly. Marker labels also move out of the way automatically, and the snap setting survives a refresh.

Next: fix the remaining coverage and clock evidence, activate the sealed CAD/CSI setup, and complete the full TX-7B validation.

0
0
88
Open comments for this post

10h 9m 24s logged

DEVLOG #32

I still do not really have a final result to show, but it has been another ten hours, so I did not want to skip the devlog.

The latest TX1 boot attempt did at least narrow things down. The new firmware now passes the Wi-Fi channel checks: channel 6, HT40 with the secondary channel below, AP-only mode, and the other radio checks all matched the expected profile. It then stops at CHECK_COUNTRY, before reaching BOOT_OK. The TX1 migration is therefore still not accepted, but the failure is much more specific now.

The confusing part is that the Wi-Fi power values do not line up cleanly. The country structure reports a different power field than expected, while the separate power API returns the expected value. This may be an SDK representation or comparison issue rather than a real transmit-power problem, but there is not enough evidence to call it fixed yet. I also corrected related checks for the country bytes, SSID representation, and status getters, and prepared another reproducible candidate offline.

With the move to Python 3.15, I also added the new lazy-import implementation. The official Python documentation describes the new syntax. Eligible imports now use explicit lazy import and lazy from syntax, with a local verifier to keep the behavior consistent.

After the failed candidate boot, I restored the original 16 MiB image and verified the return path. The historical firmware is running again, and RX4 plus both mmWave sensors are sending data.

Next: resolve the country/power comparison, then attempt the candidate boot again under the existing safety gates.

0
0
62
Open comments for this post

9h 52m 23s logged

DEVLOG #31

The mmWave2 connection problem is finally understood. It was caused by a reproducible dependency on the WLAN transmit power: at around 19.5 dBm, the ESP kept running and received probe requests, but its test AP could not be found and connections failed.

At 10 dBm, the AP worked immediately, csi-test connected again, and 360/360 pings succeeded without a disconnect. Raising the limit reproduced the issue, confirming the dependency. Both mmWave sensors now work reliably.

The TX1 migration is also complete. I verified the candidate firmware and baseline, created two identical 16 MiB backups.

The new app was written to app1 together with the NVS merge and OTA selection. A complete readback of all 16,777,216 bytes matched the expected flash image exactly.

Next: Boot the candidate under the existing safety gates, check that TX1 comes up properly, and run the full comparison.

0
0
84
Open comments for this post

9h 3m 48s logged

DEVLOG #30

The replacement ESP for mmWave2 is now soldered and mounted on the previously working breadboard setup. The connection problem has not disappeared, however WiFi still fails, so I uploaded a minimal WiFi test script to isolate the radio and network path before testing the radar or UDP transport.

The mmWave firmware now distinguishes MMWAVE1 and MMWAVE2 with separate build and upload paths, uses 55010 as the default UDP port, and logs the WiFi disconnect reason. These changes are prepared locally; the test image is not yet a confirmed fix, and the complete mmWave2 path is still unvalidated.

In parallel, the TX1 replacement reached a stronger local checkpoint. Reproducible builds from fresh and isolated source copies are byte-identical, and the local test suite passed. The 7A TX1/RX4 baseline still produced no usable measurement data, so the migration remains blocked and 7B is NO-GO.

Next: resolve the WiFi connection on the replacement ESP, verify mmWave2 communication, and continue with two-sensor validation and RX3 calibration.

0
0
56
Open comments for this post

7h 41m 31s logged

DEVLOG #29

The local RX work has expanded, but the two-sensor setup is currently blocked by a connection problem with mmWave2. RX-04 to RX-12 add bounded capture and queue handling, stale-frame rejection, corrected CSI parsing, clearer UDP/server counters, and timing and synchronization metadata. The firmware host tests, standard and raw ESP32-S3 builds, and targeted server checks pass. These are still software and build results. No live RX measurement has yet proven lower frame loss or data age. :(

The 3D-printed part now fits. While investigating the mmWave2 connection, I tried to desolder its ESP, but it could not be removed cleanly. Since the connection problem is not resolved, I ordered a replacement ESP, a new mmWave sensor, and an FH/Fenghua 1206X106K160NT SMD component. The exact cause is still open, and the replacement parts have not been installed or tested yet. The existing TX1 replacement also remains locally tested but unflashed.

Next: rebuild mmWave2 with the replacement parts, identify the connection fault, validate both sensor paths, and continue with RX3 calibration.

1
0
131
Open comments for this post

10h 9m 24s logged

DEVLOG #28

I prepared and locally verified an ESP-IDF replacement candidate for TX1. The firmware builds successfully, and the host-side checks for packet handling, scheduling, boot/OTA variants, and negative compile guards pass. This is still a software-only result. Nothing has been flashed, and TX1 has not been validated on hardware. Before replacing the existing TX1, the old TX1/RX4 baseline and network pre-check must still be completed.

I also tightened the RX data path. Incoming frames are now checked for valid input and correct TX binding before passing through one jitter-tolerant 20 ms admission gate. Invalid or foreign frames no longer consume the timing budget. Callback, queue, UDP, and server-side counters are tracked separately, making it possible to see where loss or delay occurs. The deterministic fixtures and local ESP32-S3 build pass, but no live RX measurement has yet shown an actual reduction in frame loss or data age.

The new 3D print exposed a mechanical error: it is approximately 1 mm too small and does not fit. It needs to be adjusted and printed again.

Next: complete the read-only TX1/RX4 baseline, adjust and reprint the part, then continue with RX3 calibration and validation of both mmWave sensor paths.

0
0
109
Open comments for this post

9h 54m 20s logged

DEVLOG #27

I soldered a second PCB from revision 3, making the hardware for two mmWave sensors available. The software now keeps MMWAVE1 and MMWAVE2 separate through stable node identities and independent sequence, transform, and calibration state.

The mmWave transport also crossed an important milestone. Because best-effort UDP was not enough, firmware 0.1.6 now uses ACK-based retransmission. In a controlled 60-second comparison, sequence loss reached 0.00% and the radar_sequence_loss_free gate passed, compared with 0.70% loss and 84 full ACK timeouts on firmware 0.1.5.

The Tauri desktop shell has been replaced in the active build by a loopback control helper for discovery, provisioning, flashing, OTA, and WASM. I also created a new 3D-print file, which is currently being printed; the mechanical result is not finished yet.

Next: validate both sensor paths together, resolve the RX3 Phase 1 offset, and repeat the full radar preflight.

0
0
152
Open comments for this post

5h 49m 22s logged

DEVLOG #26

I have completed, soldered, and tested the third and hopefully final PCB revision. Everything works, but the ground plane made soldering significantly more difficult than expected. Even with thermal reliefs around the solder pads, the plane acted like a heat sink, dissipating heat across the entire board.

The shift to a browser-centric approach is progressing: the Tauri desktop app and its associated release pipeline are being removed, while hardware control is being moved to a standalone “loopback crate.” This crate handles tasks such as device discovery, serial access, provisioning, flashing, OTA updates, and WASM integration. This work is currently ongoing.

The server now protects the /api/field and /ws/field endpoints using Bearer authentication and keeps auto mode offline until real data is available. An explicit simulated source is required for simulation.

mmWave transmission has been improved but still exhibits a sequence loss rate of 13.1%, causing the radar preflight to remain blocked. The causes of the remaining loss still need to be investigated, particularly regarding channel conditions, the startup process/ARP, and Wi-Fi airtime and scheduling. The calibration offset for “Phase 1” on RX3 also remains unresolved.

Next steps: fixing the RX3 offset, completing the migration to the browser/control setup, and re-running the radar preflight.

0
0
93
Open comments for this post

9h 1m 31s logged

DEVLOG #25

I measured and optimized the mmWave UDP transport, but the radar path still fails the lossless-transmission test (image 1).

The new firmware and server path use one UDP copy without artificial delay, disable Wi-Fi power saving on the mains-powered node, persist the collector target and CAD transform, and separate socket reads from processing. Reordering, sequence validation, deduplication, and rolling metrics expose failures instead of hiding them. Across three 60-second runs, unique arrivals improved by 11.2%, sequence loss fell from 20.6% to 13.1%, duplicates dropped to zero, and arrival P95 improved by 27.8%. Two copies did not reduce loss and only added duplicates, so one copy remains the default.

The transport is better, but not lossless: 13.1% sequence loss still blocks the radar preflight. The 50 ms interval is not the bottleneck; LD2450 frames arrive in bursts and the bridge emits about 2.64 measurements per second, not 20 independent frames per second. Next I will investigate RSSI and channel conditions, ARP and startup behaviour, Wi-Fi retries and airtime, and packet scheduling. RX/CSI stayed offline, so this is not a full Wi-Fi validation.

The server refactor from DEVLOG #24 is now integrated: routes, state, runtime, calibration, recording, model, and system responsibilities moved out of main.rs, with active, legacy, and unavailable-training contracts separated.

Desktop-interface removal remains in progress. Hardware-control modules are moving to a standalone control crate, while loopback-only browser server controls with origin checks are being added. Phase 1 calibration is also getting a longer measurement window and persisted evidence. RX3 currently lands roughly two to three metres from its expected fixed point. I will not consider the calibration valid until the transform, profile binding, or target association causing this offset is understood and corrected.

Next: resolve the RX3 Phase 1 offset (seen in image 2), then repeat the full fixed-point calibration and re-verify the radar preflight.

0
0
51
Open comments for this post

7h 10m 28s logged

DEVLOG #24

I strengthened security for live-sensor operation and started aligning the Observatory UI with backend functionality that actually exists.

Live WebSockets now require Bearer authentication along with strict Origin and Host checks. Browser and Python clients no longer send tokens in the URL. Regression tests cover missing, invalid, and duplicate requests as well as cross-origin access. The complete CAD geometry document is now persisted in SQLite and survives a server restart.

Another issue was in the browser catalog: it listed routes that the active Rust server did not provide. I am separating active routes from legacy compatibility routes, adding the missing model-details contract, and returning unavailable or HTTP 501 when browser-triggered training is not available instead of falsely reporting that it started.

Next: finish and commit the route extraction, then repeat the live mmWave preflight, including calibration.

0
0
53
Open comments for this post

4h 46m 23s logged

DEVLOG #23

The issue encountered during initial startup was a design error: the LD2450 had been mounted rotated by 180°. The UART routing itself was correct.
After rotating the sensor and reflashing the ESP32-C3, everything worked again, though the physical setup doesn’t look very tidy.
I designed PCB-03 based on PCB-02. The LD2450 connector and its wiring have been rotated by 180°.
Everything else remains unchanged. I also added ground planes.
Until the PCB arrives, the breadboard setup will continue to serve as a temporary mmWave configuration.

Next steps: order PCB-03, mount the LD2450 in the marked orientation, and repeat the live radar verification. Continue using the breadboard setup until delivery.

0
0
71
Open comments for this post

6h 47m 7s logged

DEVLOG #22

I fixed the last browser security gap found in the local security review: a page on one local port can no longer reach an unauthenticated service on another local port by default.

The review contained 13 entries. Entries 8 and 11, and entries 12 and 13, were duplicates, leaving 11 unique findings.

The old check trusted the hostname alone, so every localhost port was accepted. I separated browser Origin validation from the existing Host/DNS-rebinding protection. WebSockets and state-changing /api/v1/* requests now require an exact scheme, host, and port.

By default, only http://localhost:<http_port>, http://127.0.0.1:<http_port>, and http://[::1]:<http_port> are allowed. Repeatable --allowed-origin values or the comma-separated SENSING_ALLOWED_ORIGINS variable explicitly replace these defaults. Host-only values, wildcards, null, paths, userinfo, and invalid ports are rejected.

The protection covers /ws/* and /api/v1/stream/pose on both the HTTP and dedicated WebSocket ports. CLI clients without an Origin header remain compatible.

The regression test now returns 403 for an unlisted cross-port UI, while an explicitly allowlisted cross-port UI still works. All 24/24 Origin/Host tests, 471 sensing-server tests (1 ignored), HomeCore server/API/auth/WebSocket tests (18 + 18 + 6 + 5), and 7 Python/firmware security-boundary tests passed. Binary checks, targeted rustfmt, and git diff --check also passed. No flash or OTA action was performed.

The ESP-IDF v5.4 build matrix is still inconclusive: the native ARM64 image is missing a containerd layer, while the AMD64 fallback crashes in the emulated Xtensa compiler inside MbedTLS. I therefore do not count the three firmware builds as passed.

Next: Solder PCB-02 first, then mount the mmWave sensor in the corner.

0
0
95
Open comments for this post

2h 43m 29s logged

DEVLOG #21

The 65-second empty-room calibration failed before it could collect a usable
baseline. The UI showed Samples 0 when I returned, so no calibration ID or
context hash was created.

The failure exposed a design problem in the run itself. A recoverable
outside-room radar target could stop the entire measurement. I’m changing the
workflow so the run always reaches its configured end and evaluates the
evidence afterwards. The final report will mark it valid or invalid with
concrete reasons instead of hiding the failure behind an early stop.

This behavior change is planned, but not yet implemented or validated. No
successful calibration, restored baseline, 10/10 acceptance, position index,
guided room walk, or blind-test result is claimed.

Next: implement and test the non-interrupting run plus the post-run validity
report

0
0
94
Open comments for this post

5h 18m 45s logged

DEVLOG #20

Today I finally found why the four RX streams kept disagreeing: the server was
fusing packets from different transmitter moments. The old path had already
reached 98,126 engine errors with a timestamp spread of about 710 ms.

The first timing fix exposed the deeper problem. The server was simply taking
the latest packet from each receiver, even when those packets did not belong to
the same event. I replaced that with bounded per-RX queues and approximate-time
matching. The existing 60 ms guard stays fail-closed, so an incoherent quartet
is discarded instead of becoming a fake D6 input.

The new tests cover packet loss, reboots, sequence wrap, clock jumps, queue
matching, and host-time fallback. 484/485 tests passed in the sandbox,.

Next: restart the server and verify a stable, error-free 25-second preflight. But for now, time to sleep.

0
0
148
Open comments for this post

4h 39m 28s logged

DEVLOG #19

I activated the new mmWave firmware and got the live 25-second preflight to
pass once, but the first empty-room recording did not complete.

The main work was hardening the transport: the firmware now sends redundant
radar packets, while the server handles reordering, duplicates, short CSI gaps,
and recent diagnostics instead of relying on cumulative counters. The UI also
gained a controlled empty-room countdown.

The remaining failure is intermittent: the sensor stays online and reports no
local UDP send errors, but the server still recorded packets_lost=10 and
packets_rejected=324. The empty-room capture lasted only 4.8 s for radar
and 5.1 s for CSI, so it is not a valid calibration reference.

No calibration, training, or blind position result is claimed yet.

Next: expose the exact reject reason and sequence-gap timing, fix the remaining
transport problem, and repeat the complete empty-room measurement.

0
0
114
Open comments for this post

3h 44m 38s logged

DEVLOG #18

Since the LD2450 first worked, I connected TX, RX1–RX4, and Wi-Fi, positioned
the sensor, sealed setup-v2, and added a calibration preparation phase with a
countdown and a minimum duration of 60 seconds.

The real hardware UI is running on port 8080; port 3002 still shows the
simulation. I started the workflow, but it currently stops at step 4, the
empty-room Wi-Fi baseline
, because radar packets are being lost.

I improved server-side packet sorting and built a new 10 Hz firmware. The OTA
update started, but the device still boots the old firmware from ota_0 at
about 20.6 Hz.

The sensor is online, but calibration is not ready. 63 UI tests pass; one
Rust test mismatch remains. No real D6 calibration or blind validation has
been completed yet.

Next: activate the 10 Hz firmware, resolve the packet-loss blocker, and rerun
the preflight and empty-room baseline.

0
0
64
Open comments for this post

3h 33m logged

DEVLOG #17

I finally verified the complete breadboard mmWave data path with the
HLK-LD2450.

After flashing the known firmware to a new ESP32-C3, it joined csi-test,
received 192.168.4.2, and exposed /ota/status on port 8032. The status
confirmed the expected UART mapping: GPIO20 RX, GPIO21 TX, and 256000 baud in
calibration mode.

The important test was a read-only UDP capture: 224 valid LD2450 datagrams in
20 seconds, followed by 222 more while the setup was powered only from the
normal power supply. Every packet matched ruview.mmwave.ld2450.v1 and
contained a recognized target. This proves that the breadboard wiring, UART
parser, ESP Wi-Fi connection, and UDP transport work together. The reported
coordinates are still sensor-frame data, not a validated room position.

The permanent PCB-02 is still pending. Next I will validate the radar
transform with known room marks, connect the CSI receivers, and continue with
D6 calibration, training, blind tests, and the quality gates.

1
0
123
Open comments for this post

1h 37m 45s logged

DEVLOG #16

The ESP was not the problem

After the original PCB failed during WLAN authentication, I redesigned the mmWave carrier as PCB-02 and isolated the ESP to find the real cause.

PCB-02 replaces the too-small ESP contact pads with proper through-hole header rows, keeps the case-compatible outline, protects the antenna area, and retains the SMD capacitors. The routing and electrical checks passed, and the Gerbers are ready to order.

The important experiment came next. I unsoldered the suspect ESP from the old PCB and powered it by itself. It joined csi-test, answered every ping, and returned HTTP 200 from /ota/status. A second ESP did exactly the same without any PCB attached.

This was the key finding: both ESPs work outside the PCB. The earlier auth → init failure is therefore very unlikely to be a dead ESP. The likely cause is the old PCB assembly, its soldered fly-wires, power delivery, or the antenna/contact area.

The LD2450 UART and radar path are still unverified.

Next: as an interim solution, continue on a breadboard with one known-good ESP and the LD2450 before moving to manufactured PCB-02.

0
0
58
Open comments for this post

1h 54m 17s logged

DEVLOG #15

D4/D5/D6 evidence package

I consolidated every archived D4/D5/D6 recording into one reproducible technical report and a 25-run CSV inventory. I kept historical A/G captures separate because their sample rate and guard settings do not support a direct percentage comparison.

The result is clear: pooled D4 retained 88.4% still recall but produced 75.2% empty-room false presence. Historical D5 replay looked strong at 0.0% false presence and 89.3% recall, but the real D5 live run and D5-abs still-person run both collapsed to 0% recall. D5-abs therefore reduced false presence only by making still presence unusable.

I also audited all five D6 raw CSI files against their sidecars. Every file is complete, has zero recorder drops, includes RX1–RX4, and uses one 2.437 GHz / 1-antenna / 64-subcarrier grid. The current empty-neutral-02 capture is a valid same-setup baseline candidate; the older setup and discovery capture remain separate.

This is technical evidence, not an accuracy claim. No phase yet has independent mmWave ground truth, blind position validation, or a proven live localization path.

Next I will install the heat-set thread inserts in the mmWave case and then check whether everything works as intended before deciding how to proceed.

0
0
53
Open comments for this post

2h 25m 53s logged

DEVLOG #14

Since the last devlog, I published a new Observatory Control Center and a
guided calibration workflow for the D6 experiment.

The setup now includes a CAD-style room editor for the TX and RX1–RX4
positions. It validates room boundaries, duplicate receiver positions, and the
canonical node IDs. The continuous mmWave calibration route is now the primary
workflow; the manual P01–P09 grid remains only as a legacy fallback.

Experiment profiles, run phases, setup hashes, and prediction/truth artifact
hashes are persisted in SQLite. The UI also makes READY, RUNNING, PASS,
OFFLINE, and SOFTWARE-ONLY / UNVALIDATED states explicit, so a simulated
workflow cannot be mistaken for a real sensor result.

I ran 41 UI/Observatory tests and 4 targeted Rust workflow tests; all
passed. This validates the software workflow, but not the real CSI stream,
LD2450 UART/UDP path, calibration data, or position accuracy.

Next: connect the LD2450 to the working ESP on the breadboard, verify UART
bytes and valid radar frames, and then continue with the sealed hardware
workflow and real blind tests.

0
0
27
Open comments for this post

1h 50m 55s logged

DEVLOG #13

I narrowed the Wi-Fi authentication problem down to the original ESP32-C3.
A second ESP running the same firmware connected to csi-test, received an IP
address, and started its HTTP server successfully. This shows that the TX,
credentials, and firmware work in principle—and that the LD2450 is not causing
the current Wi-Fi failure.

The original ESP (ac:a7:04:c2:71:f4) is now the main suspect, possibly because
of its Wi-Fi hardware, power stability, flash state, or an access-point client
entry.

I also planned a breadboard-compatible power setup for testing without the SMD
capacitors: a through-hole 100 nF ceramic capacitor and 10 µF electrolytic
capacitor across 5 V and GND, placed close to the ESP and radar connections.

The radar itself has not passed a UART test yet. Next, I will connect the
unpowered LD2450 to the working ESP and check whether UART bytes and valid radar
frames increase.

0
0
38
Open comments for this post

3h 18m 26s logged

DEVLOG #12

I built a new Observatory Control Center that guides the experiment through
all ten phases—from creating and sealing the setup to calibration, blind tests,
evaluation, and the final report.

Run metadata, setup profiles, phase history, and artifact hashes are now stored
persistently in SQLite, while the raw recordings remain separate files. The UI
shows clear READY, RUNNING, PASS, OFFLINE, and UNVALIDATED states and
keeps software-only demonstrations separate from real measurements.

I also made continuous mmWave-guided calibration the main workflow. The manual
P01–P09 capture grid remains available only as a legacy fallback.

All 29 UI tests and all 4 targeted SQLite/workflow tests pass. This verifies
the software workflow, but does not yet validate the real sensors or position
accuracy
.

Next: connect the finished hardware and run the guided workflow with real data.

0
0
44
Open comments for this post

3h 24m 17s logged

DEVLOG #11

I started assembling the reference-sensor PCB and soldered the available
parts. The SMD capacitors have not arrived yet, and the ESP pads turned out to
be too small for reliable soldering, so I have started connecting the ESP with
wires instead.
On the software side, I added diagnostics for UART bytes, valid radar frames,
UDP transmissions, and errors. The server and UI now display these values and
detect connection or network problems.
I also tested the complete software path synthetically—from radar input through
calibration, position indexing, blind-test gates, and the UI. All relevant tests
passed, including 10/10 UI tests. This confirms the software path, but not the
final live hardware setup.
A read-only CSI check currently receives no RX packets. The last discovery did
find TX and RX1–RX4 with a stable 64-subcarrier grid, although sequence gaps
were around 5–6%.
Next: finish the wiring, add the capacitors, and restore live CSI reception.

0
0
168
Open comments for this post

1h 14m 7s logged

DEVLOG #10

I completed the calibration and evaluation pipeline for WiFi positioning
with an HLK-LD2450 reference sensor.
The new system includes:

  • ESP32-C3 firmware with UART parsing, room coordinates, operating modes,
    Wi-Fi transmission, and protected configuration;
  • persistent coordinate transformation with origin, rotation, and optional
    mirroring;
  • synchronization of mmWave and RX1–RX4 CSI data within 150 ms;
  • a 65-second empty-room reference;
  • automatic room coverage with nine reachable zones (P01–P09) and six
    training blocks per zone;
  • a position index that uses only CSI after calibration;
  • blind evaluation with separated WiFi predictions and mmWave reference data;
  • fixed quality thresholds with automatic acceptance or rejection; and
  • a guided German calibration assistant in the UI.
    The PCB has also arrived. I am checking it carefully before soldering and
    starting the first complete hardware tests.
    Next: verify the PCB, solder the components, and test the full system.
0
0
67
Open comments for this post

1h 19m 29s logged

DEVLOG #09

I 3D-printed the case and a PCB mockup to test the fit. The IKEA Skådis mount
and the retaining posts were slightly too large, possibly because supports
were placed in the wrong areas.
I have already updated the 3D model and will print the revised version
tomorrow.

0
0
83
Open comments for this post

38m 49s logged

DEVLOG #08

I finished the firmware and flashed it onto the ESP32-C3 SuperMini for the
mmWave reference sensor.

It uses the correct UART pins (GPIO20 RX, GPIO21 TX, 256000 baud), parses
all three LD2450 targets using the
official protocol,
and sends timestamped UDP JSON data. It also separates calibration and
reference recordings, supports protected A/B OTA, detects ambiguous
multi-person measurements, and allows configurable radar placement.

The firmware is ready, but the final PCB still needs to arrive. I then need to
solder it before any complete hardware testing can begin. I will also finish
the IKEA-board mount, print the case, and check the PCB fit—especially the
retaining posts.

Next: receive and solder the PCB, print the case, and test everything together.

0
0
65
Open comments for this post

1h 11m 44s logged

DEVLOG #07

I added small retaining posts to hold the PCB securely inside the mmWave
sensor case.
I also designed a holder for mounting the enclosure to an IKEA board. These
details should keep both the electronics and the finished case in place, but
they still need to be printed and tested for fit.
Next: print the parts and check the tolerances.

0
0
43
Open comments for this post

1h 58m 1s logged

DEVLOG #06

I continued redesigning the mmWave reference sensor case and replaced the
honeycomb pattern with cleaner parallel openings.
I also refined the inside of the enclosure by adding two posts and a
rectangular internal feature. The case now has a much cleaner shape, but it is
still a CAD design and has not been printed or tested yet.
Next: check the component fit and prepare the case for printing.

0
0
35
Open comments for this post

1h 58m 52s logged

DEVLOG #05

Redesigning the mmWave reference sensor case

Today

  • Redesigned the 3D-printed enclosure for the mmWave reference sensor.
  • Finish the enclosure and prepare it for printing.

Current Challenge

I am currently working on the honeycomb pattern. The new case is taking shape,
but the pattern still needs to be fixed before the design is complete.
Status: Redesigned, NOT FINISHED, currently focused on the pattern.

0
0
134
Open comments for this post

2h 10m 25s logged

DEVLOG #04

D6 setup and calibration

Today

  • Sealed the 1TX/4RX setup and identified the TX without flashing.
  • Passed the 25-second preflight and recorded 65 seconds of empty-room data.

UI Fix

Camera rotation was replaced with a display-only X-axis mirror:

x_display = room_length - x

Next

  • Record training data at P01–P09
  • Build the position fingerprint index
  • Run blind tests and evaluate both quality thresholds
  1. Complete all nine training positions.
  2. Build the fingerprint model.
  3. Validate before enabling live positioning.

Status: Connected, UNCALIBRATED, setup sealed and unchanged

0
0
69
Open comments for this post

1h 42m 53s logged

DEVLOG #03
Today I finished the 3D-printed case for the reference sensor (mmWave). Its purpose is to measure how accurate the WiFi CSI-based positioning actually is.

0
0
107
Open comments for this post

34m 17s logged

DEVLOG #02

So, I had a big issue today.

I finished my PCB after five hours of work and recorded the entire process
as a timelapse in Lookout. Then I accidentally clicked Discard.
Fortunately, I was able to recover the video on my Mac, including all of its
metadata. Getting the logged time restored now depends on the incredible team
at Hack Club/Laps. I have already asked for help on Slack and sent an email.

The PCB Is Finished

Despite the timelapse issue, the PCB shown below is finished and already
ordered
.
Its purpose is to provide reference data for evaluating how accurately the
Wi-Fi-based tracking system works. The board includes:

  • an ESP32-C3 SuperMini; and
  • an mmWave radar sensor.
0
0
41
Open comments for this post

27h 21m 49s logged

DEVLOG #01

Hi, long time no see.

Over the past few weeks, I have been developing two new approaches to
presence detection. The main issue was that the system could not reliably
distinguish between an empty room and a room with me standing inside :(.
To solve this, I first developed D5 and then D6. D5 is already available on
GitHub. D6 is not available yet because it is still under development and
has not been fully validated with real measurements and blind tests.

D5 — Presence Detection

D5 was designed to determine whether a room is empty or occupied. It compares
current CSI measurements with a previously recorded empty-room reference.
However, D5 mainly evaluated changes in one direction. In practice, a person’s
presence can cause CSI values to either increase or decrease, depending on the
receiver and propagation path. As a result, D5 behaved more like a motion
detector and could miss a person who remained still. While it significantly
improved presence detection, it was not robust enough for reliable real-world
use.

D6 — Presence Detection and Position Classification

D6 builds on D5 by evaluating deviations from the empty-room reference in
both directions, making it much more effective at detecting people who
remain stationary.
Once a person has been detected, D6 attempts to classify their position.
Instead of calculating arbitrary coordinates, it identifies one of nine
predefined locations (P01–P09)
that were previously trained using CSI
recordings.
A position is only reported if:

  • the hardware setup is valid and sealed;
  • all receivers provide fresh and valid CSI data;
  • the correct transmitter has been verified;
  • a person has been detected;
  • a valid position index is available; and
  • the classification result is sufficiently confident.
    If any of these conditions are not met, D6 deliberately reports no
    position
    instead of inventing one.
    The software pipeline is largely complete, but the system still needs to be
    validated using a new sealed setup, fresh training recordings, and independent
    blind tests before D6 can be released on GitHub.

New Interface

I also redesigned the standard RuView interface as a clean, white,
Samaritan-inspired UI based on the AI system from the TV series Person of
Interest
.

1
0
138

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…