Configuring gain_lock_mode for ESP32-C3 in ESPectre

Configure the GAIN_LOCK_MODE setting in micro-espectre/src/config.py to "auto", "enabled", or "disabled" to control whether the ESPectre firmware attempts hardware gain lock during boot or falls back to CV normalization.

The ESP32-C3 features hardware AGC (Automatic Gain Control) lock support, unlike the ESP32-C6. In the francescopace/espectre repository, the gain-lock mode determines how the motion-detection pipeline calibrates itself during initialization. Proper configuration ensures stable turbulence metrics without manual intervention.

Understanding Gain-Lock Modes on ESP32-C3

ESPectre provides three configurable modes for gain management. Because the ESP32-C3 supports hardware gain lock, all three modes are functional and produce different behaviors:

  • auto (default): Attempts gain lock only if the AGC value is at or above GAIN_LOCK_MIN_SAFE_AGC (30). If the signal is too weak, it skips the lock phase and enables CV normalization automatically.
  • enabled: Forces a gain-lock attempt on every boot. On ESP32-C3 this succeeds under normal conditions, providing hardware-stabilized gain for CSI measurements.
  • disabled: Bypasses the gain-lock phase entirely. The system immediately uses CV normalization (standard deviation/mean) for gain-invariant turbulence metrics, reducing boot time.

Configuration File Location

The primary configuration resides in micro-espectre/src/config.py. Edit these constants to change the behavior:


# Gain Lock Configuration

# Modes: "auto" (skip if signal too strong), "enabled" (always lock), "disabled" (never lock)

GAIN_LOCK_MODE = "auto"       # Recommended: "auto" - skips gain lock if AGC < 30

GAIN_LOCK_MIN_SAFE_AGC = 30   # Minimum safe AGC value (below this, gain lock is skipped in auto mode)

Source: config.py

Boot-Time Handling

The main entry point in micro-espectre/src/main.py reads the mode and initializes the chip-specific logic. For ESP32-C3, the firmware attempts the lock sequence when the mode is "enabled" or "auto" (with sufficient AGC):

if chip == 'ESP32-C3':
    # Hardware gain lock available

    needs_cv_normalization = False  # Will use hardware lock unless mode forces otherwise

If the lock fails or the mode is set to "disabled", the code sets needs_cv_normalization = True to ensure the segmentation pipeline uses the software fallback.

Source: main.py

Segmentation Pipeline Integration

The SegmentationContext class in micro-espectre/src/segmentation.py receives the normalization flag via the use_cv_normalization attribute:


# Default False for chips with gain lock support

# Set to True if gain lock is disabled or unavailable

self.use_cv_normalization = False

When the calibration code detects a missing lock (or the user forces disabled), it flips the flag to True, ensuring the motion detection algorithm uses CV-normalized turbulence metrics.

Source: segmentation.py

Practical Configuration Examples

Forcing Hardware Gain Lock on ESP32-C3

To ensure the firmware always attempts hardware gain lock (useful in stable RF environments):


# micro-espectre/src/config.py

GAIN_LOCK_MODE = "enabled"

Re-build and flash (pio run). The boot log will indicate:


🔒 Gain lock mode: enabled → Attempting hardware lock...
🔒 Gain lock acquired successfully

Disabling Gain Lock for Faster Boot

If you prefer deterministic CV normalization or need faster initialization:


# micro-espectre/src/config.py

GAIN_LOCK_MODE = "disabled"

This bypasses the AGC negotiation entirely, setting use_cv_normalization = True immediately.

Runtime Override via CLI

The Micro-ESPectre CLI accepts command-line arguments to override the config file for a single execution:

python -m src.main --gain-lock-mode enabled

ESPHome YAML Configuration

For production ESPectre deployments using ESPHome, ensure the underlying firmware constants are set before compilation:

esphome:
  name: espectre_c3
  platform: ESP32
  board: esp32-c3

# The gain_lock_mode is set at firmware compile time via config.py

# Ensure GAIN_LOCK_MODE is set to your desired mode before flashing

After flashing, verify in the Home Assistant logs:


[DEBUG] Gain lock enabled – Hardware AGC lock active (ESP32‑C3)

Verification and CSI Packet Flags

Each CSI packet carries a gain-locked bit in micro-espectre/tools/csi_utils.py. For ESP32-C3 with successful hardware lock, this bit is set to 1:

description = f'HT20 {self.label}, gain locked (AGC stable)'

If the lock fails or is disabled, the bit remains 0 and the description notes the fallback method.

Source: csi_utils.py

Summary

  • ESP32-C3 supports hardware gain lock, unlike the ESP32-C6, allowing use of the "enabled" mode for hardware-stabilized measurements.
  • Configure via GAIN_LOCK_MODE in micro-espectre/src/config.py using "auto", "enabled", or "disabled".
  • The segmentation pipeline respects this setting through SegmentationContext.use_cv_normalization, automatically switching between hardware gain control and CV normalization.
  • Verify behavior through boot logs and the gain-locked bit in CSI packets parsed by csi_utils.py.

Frequently Asked Questions

Use "auto" for most deployments. This attempts hardware gain lock when the AGC value is healthy (≥30) but falls back to CV normalization automatically if the signal is too weak, providing the best balance of accuracy and reliability.

Can I use gain lock mode "enabled" on ESP32-C3?

Yes. The ESP32-C3 supports hardware AGC gain lock, so "enabled" mode will attempt to acquire a lock on every boot. This is safe and appropriate for environments with consistent RF conditions where you want guaranteed hardware-stabilized gain.

Why would I disable gain lock on a chip that supports it?

Setting GAIN_LOCK_MODE = "disabled" speeds up boot time by skipping the AGC negotiation phase. It also provides deterministic behavior in testing environments where you want consistent CV-normalized metrics regardless of hardware state.

How do I verify that gain lock is actually working on my ESP32-C3?

Check the serial boot logs for the message Gain lock acquired successfully. Additionally, inspect the CSI packets using csi_utils.py; the gain-locked bit (bit 0) will be set to 1 when hardware lock is active, and the packet description will indicate "gain locked" rather than "no gain lock".

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →