In this project, I used the RSSI value (Received Signal Strength Indicator) as a measure of distance between the transmitter and the receiver, using the ESPNOW wireless protocol.
The transmitter is an ESP8266 with the following code:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WifiEspNow.h>
uint8_t receiverMac[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Update with the receiver's MAC
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
pinMode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,HIGH);
WifiEspNow.begin();
}
void loop() {
const char *message = "CascajoLabs";
digitalWrite(LED_BUILTIN,HIGH);
WifiEspNow.send(receiverMac, (uint8_t *)message, strlen(message));
delay(500);
digitalWrite(LED_BUILTIN,LOW);
}
It sends a message every half second. In this case, it operates in unicast mode.
The receiver is an Arduino Nano ESP32.
It features an OLED screen where we can display the RSSI value or, based on that value, show an image of a thermometer (which is what I included in the example). This is its code:
#include <esp_now.h>
#include <WiFi.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include "esp_wifi.h"
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_SDA_PIN 21
#define OLED_SCL_PIN 22
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C //0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int rssi= 0;
int previousRSSI = -150;
typedef struct {
unsigned frame_ctrl: 16;
unsigned duration_id: 16;
uint8_t addr1[6]; /* receiver address */
uint8_t addr2[6]; /* sender address */
uint8_t addr3[6]; /* filtering address */
unsigned sequence_ctrl: 16;
uint8_t addr4[6]; /* optional */
} wifi_ieee80211_mac_hdr_t;
typedef struct {
wifi_ieee80211_mac_hdr_t hdr;
uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */
} wifi_ieee80211_packet_t;
//You need to add the bitmaps of the pictures if you want them to be displayed
//const unsigned char medium_bitmap [] PROGMEM = {};
void promiscuous_rx_cb(void *buf, wifi_promiscuous_pkt_type_t type) {
if (type != WIFI_PKT_MGMT)
return;
const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buf;
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
rssi = ppkt->rx_ctrl.rssi;
}
void onReceiveData(const uint8_t *mac, const uint8_t *incomingData, int len) {
Serial.print("RSSI: ");
Serial.println(rssi);
display.clearDisplay();
display.setRotation(3);
// Change image
/*
if (rssi >= -40) {
display.drawBitmap(0, 0, really_close_bitmap, SCREEN_HEIGHT, SCREEN_WIDTH,WHITE);
} else if (rssi >= -66) {
display.drawBitmap(0, 0, close_bitmap, SCREEN_HEIGHT, SCREEN_WIDTH, WHITE);
} else if (rssi >= -75) {
display.drawBitmap(0, 0, medium_bitmap, SCREEN_HEIGHT,SCREEN_WIDTH, WHITE);
} else if (rssi >= -80) {
display.drawBitmap(0, 0, far_bitmap, SCREEN_HEIGHT, SCREEN_WIDTH, WHITE);
} else {
display.drawBitmap(0, 0, ice_bitmap, SCREEN_HEIGHT, SCREEN_WIDTH, WHITE);
}
*/
previousRSSI = rssi;
display.display();
}
void setup() {
Serial.begin(115200);
delay(1000);
WiFi.mode(WIFI_STA);
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println("SSD1306 failed");
for(;;); // Loop forever if error
}
Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN); //I2C pins
if (esp_now_init() != ESP_OK) {
Serial.println("Error");
return;
}
// Wait a second
delay(1000);
// Print the MAC address (important if the sender is sending unicast)
// Serial.print("MAC Address: ");
// Serial.println(WiFi.macAddress());
esp_now_register_recv_cb(onReceiveData);
esp_wifi_set_promiscuous(true);
esp_wifi_set_promiscuous_rx_cb(&promiscuous_rx_cb);
display.clearDisplay();
display.display();
}
void loop() {
}
This is a very simple test.
The sources I consulted:
https://otroblogdemarcelo.wordpress.com/2021/09/07/esp32-y-el-rssi-del-esp-now/
For images bitmaps: