ESP32C3 RSSI Saturation Issue: Main ESP32 flooding local Sniffer

Hi everyone,

I am working on a STEAM project called "Silent Whistle & Direction Finding Car". The goal is to determine the direction and relative distance of another vehicle using RSSI measurements.

  • Hardware Setup
    +Main Unit (ESP32):Controls the display, reads FSR sensor, and handles ESP-NOW communication.
    +Ear Units (2x ESP32C3 SuperMini):Used as RF Sniffers to measure the RSSI of the other vehicle's signal.
    +Connection: The C3 units are connected to the Main ESP32 via UART (Serial1 & Serial2) to send RSSI data back. They are powered via USB-C independently.

  • The Problem
    I am facing a severe RSSI Saturation / Blocking issue on the ESP32C3 units.

  1. Independent Test (Success): When I test the C3 separately (powered by USB-C, disconnected from the Main ESP32) against the other vehicle's Main Unit, the RSSI measurements are perfect. The values range from approximately -20 dBm (close) to -100 dBm (far), giving me a clear dynamic range of ~80dB.
  2. Integrated Test (Failure): When I connect the C3 back to the Main ESP32 (via UART, even with a 40cm long wire and independent power), the RSSI values get stuck between -20 dBm and -30 dBm.
  • Even when the other vehicle is 5 meters away, the local C3 still reports -25 dBm.
  • It seems the Main ESP32's RF output (or noise) is saturating the C3's receiver, making it "deaf" to the remote signal I actually want to measure.

-What I have tried so far

+Lowered TX Power: Set Main ESP32 to WIFI_POWER_2dBm.
+Power Isolation: Powered C3 with a completely separate USB-C power bank (no shared power rails).
+Physical Separation: Tried using a 40cm long Dupont wire to move the C3 away from the Main ESP32.
+MAC Filtering:Verified the C3 is filtering out the Main's MAC address, so it shouldn't be counting the Main's own packets, but the physical interference seems to bypass the software logic.

I suspect the UART wires (or the proximity) are acting as an antenna, conducting strong RF noise from the Main ESP32 into the C3, or the sheer proximity is causing Receiver Desensitization (Blocking).

Is there a way to prevent the local Main ESP32 from desensitizing the ESP32C3 Sniffer?
Is this a known hardware limitation of placing a Sniffer next to a Transmitter on the same robot?
Do I need hardware filtering (ferrite beads) on the UART lines?
Or is the only solution to physically separate the C3 far away (e.g., 1 meter+) from the Main ESP32?

Source Code

  1. ESP32C3 Sniffer Code (Wi-Fi Promiscuous Mode) This code listens for packets from the other car's MAC address.
#include <WiFi.h>
#include <esp_wifi.h>

#define LED_PIN 8
#define SERIAL_TX_PIN 8 

// MAC Address of the TARGET CAR (The one we want to find)
uint8_t targetMAC[6] = {0x14, 0x33, 0x5C, 0x04, 0x1B, 0x24}; 

// MAC Address of MY CAR (To ignore self-noise)
uint8_t selfMAC[6] = {0x2C, 0xBC, 0xBB, 0x07, 0x31, 0xA0};

// Variables for RSSI Smoothing
float emaAlpha = 0.2; 
float currentEma = -100;

volatile int newRSSI = -100;
volatile bool gotPacket = false;
unsigned long lastPacketTime = 0;

void wifi_sniffer_cb(void *buf, wifi_promiscuous_pkt_type_t type) {
  if (type != WIFI_PKT_MGMT && type != WIFI_PKT_DATA) return;

  const wifi_promiscuous_pkt_t *pktptr = (wifi_promiscuous_pkt_t *)buf;
  
  // Extract Source MAC from packet
  uint8_t *payload = (uint8_t *)pktptr->payload;
  uint8_t srcMac[6];
  memcpy(srcMac, payload + 10, 6);

  // FILTER 1: Ignore packets from MYSELF (Local Main Unit)
  if (memcmp(srcMac, selfMAC, 6) == 0) return;

  // FILTER 2: Only accept packets from TARGET CAR
  if (memcmp(srcMac, targetMAC, 6) == 0) {
    newRSSI = pktptr->rx_ctrl.rssi; // Capture RSSI
    gotPacket = true;
    lastPacketTime = millis();
  }
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH); // Turn off LED initially (Active Low logic)

  Serial1.begin(9600, SERIAL_8N1, -1, SERIAL_TX_PIN); // Send data to Main ESP32

  // Initialize Wi-Fi Sniffer
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  esp_wifi_set_promiscuous(true);
  esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_cb);
  esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE); // Must match Main channel
  
  Serial1.println("C3 Sniffer Started");
}

void loop() {
  unsigned long currentMillis = millis();

  // Smooth RSSI value (EMA Filter)
  if (gotPacket) {
    if (currentEma < -99) currentEma = (float)newRSSI;
    currentEma = (emaAlpha * newRSSI) + ((1 - emaAlpha) * currentEma);
    gotPacket = false;
  }

  // Decay value if no packet received (Simulate signal loss)
  if (currentMillis - lastPacketTime > 200) {
    currentEma = (currentEma * 0.9) - 1.0; 
    if (currentEma < -100) currentEma = -100;
  }

  // Send to Main ESP32
  static unsigned long lastSend = 0;
  if (currentMillis - lastSend > 50) {
    if (currentEma > -100 && currentEma < -20) {
      Serial1.println((int)currentEma);
    }
    lastSend = currentMillis;
  }
}
  1. Main ESP32 (Reading Data) Relevant snippet from Main Unit reading Serial:
// Main ESP32 Loop - Reading Serial from C3
void loop() {
  // ... other code ...  
  while (sLeft.available()) {
    char c = sLeft.read();
    if (c == '\n') { 
      rssiLeft = inputLeft.toInt(); // Update RSSI variable
      inputLeft = ""; 
    } else {
      inputLeft += c;
    }
  }
  // Update UI logic here...
}

Any advice on hardware shielding, filtering, or architecture changes would be greatly appreciated!

Edit your post so that the code tag looks like the following

your code

Can you teach me to do it , i try my best but its not looks good at all. Sorry, I'm new to this page

Back tick, it's tha top eft key with the ~ and `

1 Like

You need to use the IDE Tools menu Auto Format first, delete all the code , and paste the formatted code so it is readable.

Done! thank you for teach me

Good work, sorry I can't help with your problem, not enough coffee yet

Where did you get the code from?

I use a AI named z.ai to build the project, it gave me the code but it's not work correctly

Learn to write your own code, I have yet to see an AI write any code of consequence correctly. Check out Faraday Cage.

Welcome to the real world of RF. Learn about shielding and filtering to reduce the stray RF.

3 Likes