Skip to content

[Bug/Enhancement]: Default fall_thresh (500) causing excessive false positives in high-traffic environments #263

Closed

Description

@austinjs471

During testing of a 3-node TDM mesh setup (Node IDs 0, 1, 2) on ESP32-S3 CSI Nodes, the default fall_thresh value of 500 (and in some cases the internal default of 50) triggers constant "Fall Detected" alerts during normal human walking/movement.

Logs
19:31:19.037 -> W (423803) edge_proc: Fall detected! accel=5.0683 > thresh=2.0000
19:31:19.071 -> W (423823) edge_proc: Fall detected! accel=2.4746 > thresh=2.0000

Note: Even when provisioned at 500, the logs show the comparator hitting a much lower threshold (2.0), suggesting the NVS value might not be applying correctly or the default is too low for ADR-039 Edge Intelligence.

Activity

  1. ruvnet commented on Mar 14, 2026

    @ruvnet
    Owner

    Analysis: fall_thresh NVS scaling bug

    You're right — there's a mismatch between the provisioned value and what the firmware uses internally. Looking at the code:

    In provision.py, --fall-thresh is stored as a raw u16:

    writer.writerow(["fall_thresh", "data", "u16", str(args.fall_thresh)])

    In nvs_config.c, it's loaded and divided by 1000:

    uint16_t fall_thresh_val;
    if (nvs_get_u16(handle, "fall_thresh", &fall_thresh_val) == ESP_OK) {
        cfg->fall_thresh = (float)fall_thresh_val / 1000.0f;
    }

    So --fall-thresh 500 → NVS stores 500 → firmware reads 500 / 1000.0 = 0.5 rad/s².

    The Kconfig default (CONFIG_EDGE_FALL_THRESH) is also divided by 1000, but the compiled default when no Kconfig is set is 2.0f:

    cfg->fall_thresh = 2.0f;

    Your logs show thresh=2.0000 which means the NVS override isn't being applied — the firmware is using the compiled default of 2.0. This happens when:

    1. The NVS partition wasn't flashed (provisioning didn't complete)
    2. The NVS namespace csi_cfg doesn't exist yet

    Fix: Re-provision with the latest v0.4.2-esp32 firmware and set a higher threshold:

    # Threshold 500 → 0.5 rad/s², too low for walking
    # Try 5000 → 5.0 rad/s² (only triggers on actual falls)
    python provision.py --port COMX --fall-thresh 5000

    For the default: We should increase the compiled default from 2.0 to 5.0 rad/s² to reduce false positives in standard deployments. I'll add this to the next firmware release.

    Recommendation for your 3-node TDM setup:

    python provision.py --port COMX --fall-thresh 8000 --pres-thresh 100 \
      --node-id 0 --tdm-slot 0 --tdm-total 3

    The 8000 → 8.0 rad/s² threshold should eliminate false positives during normal walking while still catching genuine falls.

  2. ksullivan86 commented on Mar 15, 2026

    @ksullivan86

    During testing of a 3-node TDM mesh setup (Node IDs 0, 1, 2) on ESP32-S3 CSI Nodes, the default fall_thresh value of 500 (and in some cases the internal default of 50) triggers constant "Fall Detected" alerts during normal human walking/movement.

    Logs
    19:31:19.037 -> W (423803) edge_proc: Fall detected! accel=5.0683 > thresh=2.0000
    19:31:19.071 -> W (423823) edge_proc: Fall detected! accel=2.4746 > thresh=2.0000

    Note: Even when provisioned at 500, the logs show the comparator hitting a much lower threshold (2.0), suggesting the NVS value might not be applying correctly or the default is too low for ADR-039 Edge Intelligence.

    How is your mesh setup working? Do you think this is just AI slop os will this eventually work as they claim?

  3. ruvnet commented on Mar 15, 2026

    @ruvnet
    Owner

    Fix submitted in PR #267.

    Root cause: The default fall_thresh was 2.0 rad/s², but normal walking produces phase accelerations of 2.5-5.0+, triggering constant false alerts. Additionally, the provisioning script documented "default: 500" but the NVS stores as u16 divided by 1000 — so --fall-thresh 500 gave 0.5, making it even more sensitive.

    Fixes applied:

    1. Raised default threshold from 2.0 → 15.0 rad/s² — normal movement will no longer trigger
    2. Added consecutive-frame requirement — 3 frames in a row must exceed threshold before alerting (eliminates single-frame noise spikes)
    3. Added 5-second cooldown between fall alerts (prevents alert storms)
    4. Updated provision.py help text to document correct units: --fall-thresh 15000 = 15.0 rad/s²

    To update existing devices, re-provision with a higher threshold:

    python provision.py --port COM7 --fall-thresh 15000

    Or for high-traffic environments, try --fall-thresh 25000 (25.0 rad/s²).

  4. ruvnet commented on Mar 15, 2026

    @ruvnet
    Owner

    Fixed in v0.4.3-esp32 (PR #267).

    What changed:

    • Default fall threshold raised from 2.0 to 15.0 rad/s² (normal walking is 2-5)
    • Added 3-consecutive-frame debounce — a single noise spike no longer triggers an alert
    • Added 5-second cooldown between alerts — no more alert storms

    Verified on real ESP32-S3 hardware (not just simulation): connected to a live WiFi network, captured 1,300+ real CSI frames over 60 seconds — zero false fall alerts. The same test with v0.4.2 firmware produced 7 false alerts in 45 seconds.

    To update: download the new binaries from the release page and reflash, or just re-provision an existing device with a higher threshold:

    python provision.py --port /dev/ttyUSB0 --fall-thresh 15000

    For high-traffic environments (offices, hallways), you can go even higher: --fall-thresh 25000 (25.0 rad/s²).

    Thank you for the detailed logs — the accel=5.07 > thresh=2.0 output made the root cause immediately clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions