I have two separate breadboards, each with an ESP32 module. One acts as the transmitter, and the other as the receiver. The receiver is connected to a servo motor, along with a few other components that are not relevant for now.
Here’s what I want the servo motor to do:
-
When the RSSI (signal strength) between the two ESP32 modules drops below a certain threshold (e.g., -50 dBm), I want the servo motor to rotate 90 degrees clockwise (from 0° to 90°) and stop there.
-
When the RSSI rises above a different threshold (e.g., -47 dBm), I want the servo motor to rotate 90 degrees counterclockwise (from 90° back to 0°) and stop.
the initial postion of the servo motor is 0°
reciver code:
#include <ESP32Servo.h>
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#define SERVO_PIN 26
#define RED_LED_PIN 32
#define GREEN_LED_PIN 25
#define BUZZER_PIN 27
#define SAMPLES 30
#define DEAD_BAND_SPEED 0.05
#define DEAD_BAND_DISTANCE 0.05
#define BASE_ACTIVATE_RSSI -50
#define BASE_DEACTIVATE_RSSI -47
Servo servo;
bool systemActive = false;
bool overrideActive = false;
bool prevSystemState = false;
float rssiSamples[SAMPLES];
float kalmanFilteredRSSI = 0;
int sampleIndex = 0;
volatile int latestRSSI = 0;
float kalmanRSSI = 0;
float kalmanP = 1;
const float Q = 0.5;
const float R = 2.0;
static float prevRSSI = 0;
static unsigned long prevTime = 0;
bool buzzerActive = false;
unsigned long lastBuzzerTime = 0;
int buzzerFreq = 1000;
bool increasing = true;
struct PacketData {
byte type; // 0 = RSSI, 1 = BUTTON
};
PacketData data;
float kalmanUpdate(float measurement) {
kalmanP = kalmanP + Q;
float K = kalmanP / (kalmanP + R);
kalmanRSSI = kalmanRSSI + K * (measurement - kalmanRSSI);
kalmanP = (1 - K) * kalmanP;
return kalmanRSSI;
}
void promiscuousRxCB(void *buf, wifi_promiscuous_pkt_type_t type) {
if (type == WIFI_PKT_MGMT) {
wifi_promiscuous_pkt_t *pkt = (wifi_promiscuous_pkt_t *)buf;
latestRSSI = pkt->rx_ctrl.rssi;
}
}
void updateSiren() {
if (buzzerActive) {
unsigned long currentMillis = millis();
if (currentMillis - lastBuzzerTime >= 50) {
lastBuzzerTime = currentMillis;
buzzerFreq += increasing ? 100 : -100;
if (buzzerFreq >= 3000) increasing = false;
if (buzzerFreq <= 1000) increasing = true;
tone(BUZZER_PIN, buzzerFreq);
}
} else {
noTone(BUZZER_PIN);
}
}
void activateSystem() {
Serial.println("System Activated");
systemActive = true;
servo.attach(SERVO_PIN);
servo.write(180);
delay(300);
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(GREEN_LED_PIN, LOW);
buzzerActive = true;
}
void deactivateSystem() {
Serial.println("System Deactivated");
systemActive = false;
servo.write(0);
delay(300);
servo.detach();
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(GREEN_LED_PIN, HIGH);
buzzerActive = false;
}
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
memcpy(&data, incomingData, sizeof(data));
if (data.type == 1) { // Override button
overrideActive = !overrideActive;
Serial.print("Override Mode: ");
Serial.println(overrideActive ? "ON" : "OFF");
if (overrideActive) {
prevSystemState = systemActive;
if (!systemActive) activateSystem();
} else {
if (kalmanFilteredRSSI < BASE_ACTIVATE_RSSI) {
if (!systemActive) activateSystem();
} else {
if (prevSystemState && !systemActive) activateSystem();
else if (!prevSystemState && systemActive) deactivateSystem();
}
}
}
if (data.type == 0) { // RSSI packet
rssiSamples[sampleIndex] = latestRSSI;
sampleIndex++;
if (sampleIndex >= SAMPLES) sampleIndex = 0;
float avgRSSI = 0;
for (int i = 0; i < SAMPLES; i++) avgRSSI += rssiSamples[i];
avgRSSI /= SAMPLES;
kalmanFilteredRSSI = kalmanUpdate(avgRSSI);
if (abs(kalmanFilteredRSSI - prevRSSI) < DEAD_BAND_DISTANCE) {
kalmanFilteredRSSI = prevRSSI;
}
unsigned long now = millis();
float deltaT = (now - prevTime) / 1000.0;
float speed = deltaT > 0 ? (kalmanFilteredRSSI - prevRSSI) / deltaT : 0;
prevTime = now;
prevRSSI = kalmanFilteredRSSI;
if (abs(speed) < DEAD_BAND_SPEED) {
speed = 0.0;
}
Serial.print("RSSI:");
Serial.println(kalmanFilteredRSSI);
if (!overrideActive) {
if (kalmanFilteredRSSI < BASE_ACTIVATE_RSSI && !systemActive) {
activateSystem();
} else if (kalmanFilteredRSSI > BASE_DEACTIVATE_RSSI && systemActive) {
deactivateSystem();
}
}
}
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW Init Failed");
return;
}
esp_now_register_recv_cb(OnDataRecv);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(GREEN_LED_PIN, HIGH);
noTone(BUZZER_PIN);
servo.attach(SERVO_PIN);
delay(200);
servo.write(0);
delay(500);
servo.detach();
esp_wifi_set_promiscuous(true);
esp_wifi_set_promiscuous_rx_cb(&promiscuousRxCB);
Serial.println("System ready with RSSI + Override button");
}
void loop() {
updateSiren();
}
transmitter code:
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
uint8_t receiverMacAddress[] = {0x20, 0x43, 0xA8, 0x63, 0x35, 0xA8}; // Update to receiver's MAC
#define LED_PIN 22 // LED connected to pin 22
struct PacketData {
byte switch1Value;
int rssiValue;
};
PacketData data;
bool lastButtonState = false;
bool overrideActive = false;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Failure");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW Init Failed");
return;
}
Serial.println("ESP-NOW Initialized");
esp_now_register_send_cb(OnDataSent);
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiverMacAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
Serial.println("Peer added successfully");
pinMode(15, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
void loop() {
wifi_ap_record_t apinfo;
if (esp_wifi_sta_get_ap_info(&apinfo) == 0) {
data.rssiValue = apinfo.rssi;
} else {
data.rssiValue = -100;
}
bool buttonState = !digitalRead(15);
if (buttonState && !lastButtonState) {
overrideActive = !overrideActive;
data.switch1Value = 1;
digitalWrite(LED_PIN, overrideActive ? HIGH : LOW);
Serial.print("Override State: ");
Serial.println(overrideActive ? "ON" : "OFF");
} else {
data.switch1Value = 0;
}
lastButtonState = buttonState;
esp_err_t result = esp_now_send(receiverMacAddress, (uint8_t *)&data, sizeof(data));
if (result == ESP_OK) {
Serial.print("Packet Sent | RSSI: ");
Serial.print(data.rssiValue);
Serial.print(" dBm | Button: ");
Serial.println(data.switch1Value);
} else {
Serial.println("Send Error");
}
delay(50);
}