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!

Gerafftes

@Gerafftes

Joined June 2nd, 2026

  • 42Devlogs
  • 3Projects
  • 0Ships
  • 0Votes
hi.
Open comments for this post

9h 24m 53s logged

DEVLOG #38

RX2 is finally delivering a lot more matching CSI data. After installing the new firmware, the rate went from about 1.9 to 31.9 frames per second. A longer, half-hour capture averaged around 30. The firmware now fixes Wi-Fi bandwidth at 20 MHz and guards against invalid CSI callbacks.

One annoying catch: the long capture only recorded RX2 because some device endpoints were outdated or mixed up. I’ve prepared a stricter preflight so an incomplete group can’t silently become a four-receiver test again.

I also corrected the offline window analysis. A valid frame with a different format no longer ruins an entire otherwise usable window. The UI code now separates format exclusions from unexplained sequence gaps instead of calling everything “loss”. The host fixes are tested locally, but aren’t active on the running server yet.

Next: complete a proper simultaneous four-RX capture, then implement the RX1 <-> RX4 peer profile for testing. Tracking and full-system acceptance are still open.

0
0
45
Open comments for this post

9h 48m 15s logged

DEVLOG #37

I narrowed down the RX2 and mmWave2 issues from the failed run. Still no hardware fix, but the picture is getting clearer.

The surprising part is that RX2 was still sending valid CSI packets during its apparent dropout. They just weren’t the 128-subcarrier frames the current evaluation needs. mmWave2, on the other hand, really did have gaps in packets reaching the host. I’m looking into its send-and-acknowledgement path, but haven’t proven the cause yet.

I also found a parser mistake. A supposedly damaged RX packet was actually a valid warning message. That’s corrected in the isolated diagnostic tools, which now also distinguish device timeouts from requests the collector skipped or cancelled.

New diagnostic firmware candidates for TX1, RX2 and mmWave2 are built locally to help trace where things stop moving. They aren’t installed yet, and the TX send errors are still unresolved.

The UI is less misleading now, too: an ESP being reachable doesn’t mean radar data is arriving, and old readings no longer keep disconnected devices looking active.

Next: review the diagnostic candidates, then use a short, controlled hardware run to investigate the remaining errors. The last full acceptance is still a FAIL.

0
0
16
Open comments for this post

9h 31m 34s logged

DEVLOG #36

The first full TX1 acceptance run is done now and it failed, but at least I finally have a much clearer picture of what is still going wrong…

The common setup passed: all seven expected participants were visible, and 22 complete snapshots kept the shared basis valid for more than 20 seconds. Then Scope A ran its three 120-second windows. All three failed. There were 14 new TX send errors, and the diagnostic counters placed them in the wifi_handoff ENOMEM stage. That tells me where the error was recorded, but not yet why it happens or whether it is fixed. MMWAVE2 also became stale in parts of the run, and several RX requests were missing, so none of the historical comparisons could count as a valid PASS.

Scope B stopped itself at the safety gate when the source binding became inconsistent and RX2 was already 5.044 seconds old. This is frustrating, but the guard did exactly what it was supposed to do, it refused to turn an incomplete 120-second window into a result.

Next: decide how to continue the ENOMEM and source-binding issues before starting another acceptance run.

0
0
50
Open comments for this post

10h 9m 20s logged

DEVLOG #35

I fixed two concrete TX1 firmware bugs. An authentication check that ran too late and an HTTP task with too little stack space.

The status endpoint could lose the request headers before checking authorization. I moved that check ahead of the response. I also increased the HTTP task’s stack from 4 KB to 8 KB after confirming that some call paths could exceed the old limit.

Two independent builds matched byte for byte. After taking fresh backups, I installed the candidate and verified the complete 16 MiB flash against the expected image. That part passed.

The UDP/ENOMEM errors are not yet proven fixed.

Next: investigate the reset path, complete a clean controlled boot, then check the matching server setup, authentication, all participants, and the measurement windows.

0
0
74
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
87
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
89
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
65
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
87
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
58
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
110
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
94
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
96
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
95
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
Loading more…

Followers

Loading…