I'm using two ESP32-C3, the first one to turn on is the one who becomes the master after 3 seconds. The master should initialise NimBLE and then broadcast every second or so a packet called ACK for other ESP32s with esp now. The problem is that when the slave device receives the packet it tries to reply back to the master but the attempt fails. I know for sure that this kind of communication works because I tried it without initialising NimBLE.
(Note: after initialising NimBLE the master ESP is correctly seen by the phone)
(I already tried to ask on Arduino-ESP32 core but didn't replied and I need to finish this code before friday)
I can't figure out what's the problem.
This is the code
Code: Untitled.cpp Select all
#include <NimBLEDevice.h>
#include "ESP32_NOW.h"
#include "WiFi.h"
#include "structs.cpp"
#include <esp_mac.h> // For the MAC2STR and MACSTR macros
/* Definitions */
#define ESPNOW_WIFI_CHANNEL 6
#define BATTERY_PIN 3
/* Global Variables */
uint32_t msg_count = 0;
bool inGroup = false;
bool isMaster = false;
long startupTime, lastBatteryCheckSent, lastACKSent, lastAliveCheck;
bool connectedBLE = false;
/* Functions */
int getCurrentBatterySOT() {
int batteria = map(analogReadMilliVolts(BATTERY_PIN) * 2, 3150, 4150, 0, 100);
batteria = max(1, min(batteria, 100));
return batteria;
}
/* Classes */
// Creating a new class that inherits from the ESP_NOW_Peer class is required.
class ESP_NOW_Broadcast_Peer : public ESP_NOW_Peer {
public:
// Constructor of the class using the broadcast address
ESP_NOW_Broadcast_Peer(uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(ESP_NOW.BROADCAST_ADDR, channel, iface, lmk) {}
// Destructor of the class
~ESP_NOW_Broadcast_Peer() {
remove();
}
// Function to properly initialize the ESP-NOW and register the broadcast peer
bool begin() {
if (!ESP_NOW.begin() || !add()) {
log_e("Failed to initialize ESP-NOW or register the broadcast peer");
return false;
}
return true;
}
// Function to send a message to all devices within the network
bool send_message(const uint8_t *data, size_t len) {
if (!send(data, len)) {
log_e("Failed to broadcast message");
return false;
}
return true;
}
};
class ESP_NOW_Peer_Class : public ESP_NOW_Peer {
public:
// Constructor of the class
ESP_NOW_Peer_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(mac_addr, channel, iface, lmk) {}
// Destructor of the class
~ESP_NOW_Peer_Class() {}
// Function to register the master peer
bool add_peer() {
if (!add()) {
log_e("Failed to register the peer");
return false;
}
return true;
}
// Function to print the received messages from the master
void onReceive(const uint8_t *data, size_t len, bool broadcast) {
Serial.println("The peer received a packet");
if (*data == ACK_PACK_TYPE) return;
if (*data == BATTERY_PACK_TYPE) {
Serial.println("Sending battery information to the master");
BATTERY response = BATTERY(getCurrentBatterySOT());
send_message((uint8_t *)&response, sizeof(BATTERY));
}
Serial.printf("Received a message from master " MACSTR " (%s)\n", MAC2STR(addr()), broadcast ? "broadcast" : "unicast");
Serial.printf(" Message: %s\n", (char *)data);
}
// Function to send a message to the peer
bool send_message(const uint8_t *data, size_t len) {
if (!send(data, len)) {
log_e("Failed to send message to peer %s", MAC2STR(addr()));
return false;
}
return true;
}
};
class ESP_NOW_Slave_Class : public ESP_NOW_Peer {
public:
bool isAlive = true;
int battery = 0;
// Constructor of the class
ESP_NOW_Slave_Class(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) : ESP_NOW_Peer(mac_addr, channel, iface, lmk) {}
// Destructor of the class
~ESP_NOW_Slave_Class() {}
// Function to register the master peer
bool add_peer() {
if (!add()) {
log_e("Failed to register the peer");
return false;
}
return true;
}
// Function to print the received messages from the master
void onReceive(const uint8_t *data, size_t len, bool broadcast) {
isAlive = true;
//Serial.printf("Received message from: (%s), data*: %d\n", MAC2STR(addr()), *data);
if (*data == ACK_PACK_TYPE) return;
if (*data == BATTERY_PACK_TYPE) {
BATTERY *packet = (BATTERY *) data;
battery = packet->batt;
}
}
void onSent(bool success) {
isAlive = success;
Serial.printf("onSent(), %d\n\n", isAlive);
}
bool deinitialise() {
Serial.printf("I'm removing the peer\n");
return remove();
}
// Function to send a message to the peer
bool send_message(const uint8_t *data, size_t len) {
if (!send(data, len)) {
log_e("Failed to broadcast message");
return false;
}
return true;
}
};
// Create a broadcast peer object
ESP_NOW_Broadcast_Peer broadcast_peer(ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);
std::vector<ESP_NOW_Slave_Class> devices;
ESP_NOW_Peer_Class* master = NULL;
// Callback called when an unknown peer sends a message
void register_new_master(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) {
if (memcmp(info->des_addr, ESP_NOW.BROADCAST_ADDR, 6) == 0) {
Serial.printf("Unknown peer " MACSTR " sent a broadcast message\n", MAC2STR(info->src_addr));
if (*data == ACK_PACK_TYPE && !inGroup) {
inGroup = true;
Serial.println("Registering the peer as a master");
master = new ESP_NOW_Peer_Class(info->src_addr, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);
if (!master->add_peer()) {
Serial.println("Failed to register the new master");
return;
}
OK_PACK okPack = OK_PACK();
master->send_message((uint8_t *)&okPack, sizeof(OK_PACK));
}
} else {
if (isMaster) {
log_v("Received a unicast message from " MACSTR, MAC2STR(info->src_addr));
Serial.printf("%d\n", *data);
if (*data == OK_PACK_TYPE) {
ESP_NOW_Slave_Class new_device(info->src_addr, ESPNOW_WIFI_CHANNEL, WIFI_IF_STA, NULL);
devices.push_back(new_device);
if(!devices.back().add_peer()){
Serial.println("\n\nFailed to add the new peer to the device list\n\n");
}
}
} else {
// The slave will only receive broadcast messages
log_v("Received a unicast message from " MACSTR, MAC2STR(info->src_addr));
log_v("Igorning the message");
}
}
}
NimBLEServer* pServer = NULL;
NimBLEService *serviceBattery = NULL;
NimBLECharacteristic *batteryLevelChar = NULL;
#define SERVICE_BATTERY_UUID "180f" //batteria
#define BATTERY_LEVEL_CHARACTERISTIC_UUID "492c2d04-f173-4814-9630-e12aedc4f7f6"
//livello batteria tutti i sensori, 1byte per sensore, max 10 sensori, se sensore non connesso: 0xFF
class ServerCallbacks: public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer) {
Serial.println("Device connected");
connectedBLE = true;
};
void onDisconnect(NimBLEServer* pServer) {
Serial.println("Device disconnected");
connectedBLE = false;
//resart the advertising
BLEDevice::startAdvertising();
}
};
void initBLE() {
NimBLEDevice::init("B_Rainbow");
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
serviceBattery = pServer->createService(SERVICE_BATTERY_UUID);
batteryLevelChar = serviceBattery->createCharacteristic(
BATTERY_LEVEL_CHARACTERISTIC_UUID,
NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ
);
serviceBattery->start();
BLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_BATTERY_UUID);
// pAdvertising->setScanResponse(true);
pAdvertising->setPreferredParams(0x06, 0x12);
NimBLEDevice::startAdvertising();
Serial.println("Finished BLE init");
}
void updateBLEData() {
uint8_t *data = (uint8_t*) malloc(devices.size() + 1);
data[0] = devices.size()+1;
for (int i = 0; i < devices.size(); i++) {
data[i] = devices[i].battery;
}
batteryLevelChar->setValue(data, devices.size()+1);
batteryLevelChar->notify();
free(data);
data = NULL;
}
/* Main */
void setup() {
Serial.begin(115200);
// Initialize the Wi-Fi module
WiFi.mode(WIFI_STA);
WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
while (!WiFi.STA.started()) {
delay(100);
}
// Register the broadcast peer
if (!broadcast_peer.begin()) {
Serial.println("Failed to initialize broadcast peer");
Serial.println("Reebooting in 5 seconds...");
delay(5000);
ESP.restart();
}
ESP_NOW.onNewPeer(register_new_master, NULL);
startupTime = millis();
}
void loop() {
// Broadcast a message to all devices within the network
if (!inGroup && startupTime + 3000 < millis() && !isMaster) {
//diventa il master
isMaster = true;
Serial.println("\n\n\nIM THE MASTER \n\n\n");
initBLE();
}
if (isMaster && lastACKSent + 1000 < millis()) {
ACK pack = ACK();
broadcast_peer.send_message((uint8_t *)&pack, sizeof(ACK));
lastACKSent = millis();
}
if (isMaster && lastBatteryCheckSent + 2000 < millis()) {
BATTERY pack = BATTERY(255);
for (int i = devices.size() - 1; i >= 0; i--) {
devices[i].send_message((uint8_t *)&pack, sizeof(BATTERY));
}
lastBatteryCheckSent = millis();
}
if (isMaster && lastAliveCheck + 1000 < millis()) {
for (int i = devices.size() - 1; i >= 0; i--) {
if (!devices[i].isAlive) {
devices[i].deinitialise();
devices.erase(devices.begin() + i);
}
}
lastAliveCheck = millis();
}
delay(100);
}
Master's Logs
Code: Untitled.txt Select all
============ Before Setup End ============
[ 484][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 18 already has type USB_DM (38) with bus 0x3fc98ed0
[ 485][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 19 already has type USB_DP (39) with bus 0x3fc98ed0
I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
D NimBLEService: >> start(): Starting service: UUID: 0x180f, handle: 0x0000
D NimBLEService: Adding 1 characteristics for service UUID: 0x180f, handle: 0x0000
D NimBLEService: << start()
Finished BLE init
[ 577][V][NetworkEvents.cpp:113] _checkForEvent(): Network Event: 101 - WIFI_READY
[ 581][V][STA.cpp:186] _onStaEvent(): STA Started
[ 581][V][NetworkEvents.cpp:113] _checkForEvent(): Network Event: 110 - STA_START
[ 582][V][STA.cpp:110] _onStaArduinoEvent(): Arduino STA Event: 110 - STA_START
[ 584][V][ESP32_NOW.cpp:18] _esp_now_add_peer(): ff:ff:ff:ff:ff:ff
[ 585][V][ESP32_NOW.cpp:311] add(): Peer added - ff:ff:ff:ff:ff:ff
=========== After Setup Start ============
IM THE MASTER
D NimBLEAdvertising: >> Advertising start: duration=0, dirAddr=NULL
primary service
uuid 0x1800
handle 1
end_handle 5
characteristic
uuid 0x2a00
def_handle 2
val_handle 3
min_key_size 0
flags [READ]
characteristic
uuid 0x2a01
def_handle 4
val_handle 5
min_key_size 0
flags [READ]
primary service
uuid 0x1801
handle 6
end_handle 13
characteristic
uuid 0x2a05
def_handle 7
val_handle 8
min_key_size 0
flags [INDICATE]
ccc descriptor
uuid 0x2902
handle 9
min_key_size 0
flags [READ|WRITE]
characteristic
uuid 0x2b3a
def_handle 10
val_handle 11
min_key_size 0
flags [READ]
characteristic
uuid 0x2b29
def_handle 12
val_handle 13
min_key_size 0
flags [READ|WRITE]
primary service
uuid 0x180f
handle 14
end_handle 17
characteristic
uuid 492c2d04-f173-4814-9630-e12aedc4f7f6
def_handle 15
val_handle 16
min_key_size 0
flags [READ|NOTIFY]
ccc descriptor
uuid 0x2902
handle 17
min_key_size 0
flags [READ|WRITE]
D NimBLEAdvertising: setAdvertisementData: 02 01 06 03 03 0f 18 05 12 06 00 12 00
D NimBLEAdvertising: << Advertising start
Started Advertising
[ 3727][V][ESP32_NOW.cpp:384] send(): ff:ff:ff:ff:ff:ff, data length 1
[ 3829][V][ESP32_NOW.cpp:133] _esp_now_tx_cb(): ff:ff:ff:ff:ff:ff : SUCCESS
[ 3830][I][ESP32_NOW.h:78] onSent(): Message transmission to peer ff:ff:ff:ff:ff:ff successful
.....
Slave's Logs
Code: Untitled.txt Select all
00:00:27.572 ============ Before Setup End ============
00:00:27.676 [ 2279][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 18 already has type USB_DM (38) with bus 0x3fc98ed0
00:00:27.676 [ 2280][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 19 already has type USB_DP (39) with bus 0x3fc98ed0
00:00:27.725 I NimBLEDevice: BLE Host Task Started
00:00:27.728 I NimBLEDevice: NimBle host synced.
00:00:27.730 D NimBLEService: >> start(): Starting service: UUID: 0x180f, handle: 0x0000
00:00:27.735 D NimBLEService: Adding 1 characteristics for service UUID: 0x180f, handle: 0x0000
00:00:27.737 D NimBLEService: << start()
00:00:27.739 Finished BLE init
00:00:27.749 [ 2352][V][NetworkEvents.cpp:113] _checkForEvent(): Network Event: 101 - WIFI_READY
00:00:27.749 [ 2356][V][STA.cpp:186] _onStaEvent(): STA Started
00:00:27.750 [ 2356][V][NetworkEvents.cpp:113] _checkForEvent(): Network Event: 110 - STA_START
00:00:27.750 [ 2357][V][STA.cpp:110] _onStaArduinoEvent(): Arduino STA Event: 110 - STA_START
00:00:27.753 [ 2359][V][ESP32_NOW.cpp:18] _esp_now_add_peer(): ff:ff:ff:ff:ff:ff
00:00:27.754 [ 2359][V][ESP32_NOW.cpp:311] add(): Peer added - ff:ff:ff:ff:ff:ff
00:00:27.754 =========== After Setup Start ============
00:00:27.754 INTERNAL Memory Info:
00:00:27.755 ------------------------------------------
00:00:27.755 Total Size : 272580 B ( 266.2 KB)
00:00:27.755 Free Bytes : 131276 B ( 128.2 KB)
00:00:27.755 Allocated Bytes : 133592 B ( 130.5 KB)
00:00:27.755 Minimum Free Bytes: 131172 B ( 128.1 KB)
00:00:27.755 Largest Free Block: 110580 B ( 108.0 KB)
00:00:27.755 ------------------------------------------
00:00:27.755 GPIO Info:
00:00:27.755 ------------------------------------------
00:00:27.755 GPIO : BUS_TYPE[bus/unit][chan]
00:00:27.755 --------------------------------------
00:00:27.755 18 : USB_DM
00:00:27.755 19 : USB_DP
00:00:27.755 20 : UART_RX[0]
00:00:27.756 21 : UART_TX[0]
00:00:27.756 ============ After Setup End =============
00:00:28.247 [ 2850][V][ESP32_NOW.cpp:112] _esp_now_rx_cb(): Broadcast from d8:3b:da:e3:1c:cc, data length : 1
00:00:28.248 0x00, // .
00:00:28.248 [ 2850][V][ESP32_NOW.cpp:115] _esp_now_rx_cb(): Calling new_cb, peer not found.
00:00:28.248 Unknown peer d8:3b:da:e3:1c:cc sent a broadcast message
00:00:28.248 Registering the peer as a master
00:00:28.248 [ 2853][V][ESP32_NOW.cpp:18] _esp_now_add_peer(): d8:3b:da:e3:1c:cc
00:00:28.248 [ 2856][V][ESP32_NOW.cpp:311] add(): Peer added - d8:3b:da:e3:1c:cc
00:00:28.248 [ 2856][V][ESP32_NOW.cpp:384] send(): d8:3b:da:e3:1c:cc, data length 1
00:00:28.288 [ 2894][V][ESP32_NOW.cpp:133] _esp_now_tx_cb(): d8:3b:da:e3:1c:cc : FAILED
00:00:28.289 [ 2895][I][ESP32_NOW.h:78] onSent(): Message transmission to peer d8:3b:da:e3:1c:cc failed
00:00:29.245 [ 3850][V][ESP32_NOW.cpp:112] _esp_now_rx_cb(): Broadcast from d8:3b:da:e3:1c:cc, data length : 1
00:00:29.245 0x00, // .
00:00:29.245 [ 3851][V][ESP32_NOW.cpp:122] _esp_now_rx_cb(): Checking peer ff:ff:ff:ff:ff:ff
00:00:29.246 [ 3851][V][ESP32_NOW.cpp:122] _esp_now_rx_cb(): Checking peer d8:3b:da:e3:1c:cc
00:00:29.246 [ 3851][V][ESP32_NOW.cpp:125] _esp_now_rx_cb(): Calling onReceive
00:00:29.246 The peer received a packet
00:00:30.345 [ 4950][V][ESP32_NOW.cpp:112] _esp_now_rx_cb(): Broadcast from d8:3b:da:e3:1c:cc, data length : 1
00:00:30.346 0x00, // .
00:00:30.346 [ 4951][V][ESP32_NOW.cpp:122] _esp_now_rx_cb(): Checking peer ff:ff:ff:ff:ff:ff
00:00:30.346 [ 4951][V][ESP32_NOW.cpp:122] _esp_now_rx_cb(): Checking peer d8:3b:da:e3:1c:cc
00:00:30.346 [ 4952][V][ESP32_NOW.cpp:125] _esp_now_rx_cb(): Calling onReceive
00:00:30.346 The peer received a packet