(painlessmesh)ESP32 板在进行 BLE 扫描时未连接到网格

问题描述 投票:0回答:1

我正在尝试使用库 painlessMesh 构建 3 个 ESP32 的网格,这似乎是一个非常智能的工具(https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/ esp-wifi-mesh.html

每个板应连续执行快速 BLE 扫描(约 2 秒),然后通过网格广播结果,直到根节点,以字符串的形式。 然后根节点应该处理扫描数据。

我使用任务调度程序来管理 2 个主要任务(执行扫描、广播结果),使用 TaskScheduler (https://github.com/arkhipenko/TaskScheduler)

首先,我遵循了 RandomNerds 的这个很棒的指南(https://randomnerdtutorials.com/esp-mesh-esp32-esp8266-painlessmesh/):它允许我让 3 个板正常工作,连接非常快并进行广播一条简单的“来自 board X 的问候”消息。

无论如何,当我引入执行 2 秒 BLE 扫描的功能时,突然之间,板子不再能够相互识别。通电后,它们不会连接到网格(假设板 1 和板 2 现在加载了 BLE 扫描代码:它们不会找到彼此。如果板 3 加载了简单的“hello”代码,它可能会识别板1 并连接,但不连接板 2)。

他们很少能够按照预期进行连接和工作,但我不知道为什么。无论如何,几秒钟后他们就会断开连接。

每个板都加载了完全相同的代码,除了用于标识板的字符串 BOARD_NAME(范围 1 到 3)。

抱歉意大利评论

#include "painlessMesh.h" //libreria per usare il protocollo ESP-WIFI-MESH

//direttive per la scansione BLE
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

//dettagli della mesh che stiamo realizzando. la rete si occupa da sola di
//mandare in giro i messaggi per tutta la rete.

#define   MESH_PREFIX     "meshName" //nome della rete
#define   MESH_PASSWORD   "password123" //password per la rete
#define   MESH_PORT       5555 //porta tcp sul quale far girare il server. default: 5555.

String BOARD_NAME = "1"; //nome/numero della board

int scanTime = 2; //BLE Scan duration (seconds)
BLEScan* pBLEScan; //oggetto BLEScan
String jsonString;
bool scanCompleted;


Scheduler userScheduler;
painlessMesh  mesh;  //oggetto rete

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      //Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
    }
};

// User stub
void transmitData() ; //prototipo di sendMessage(), da non rimuovere
void scan(); //prototipo di scan(), da non rimuovere

//TASKS
Task transmit( TASK_SECOND * 4 , TASK_FOREVER, &transmitData ); 
Task bleScan(TASK_SECOND * 3, TASK_FOREVER, &scan); 



void scan() {

  scanCompleted = false;

  Serial.print(F("Board "));
  Serial.print(BOARD_NAME);
  Serial.print(F(" is scanning...\n"));

  BLEScanResults foundDevices = pBLEScan->start(scanTime, false); //salva i risultati della scansione in foundDevices

//creazione array JSON
  StaticJsonDocument<1024> scanResultsJson;
  JsonArray devicesArray = scanResultsJson.to<JsonArray>();

  for (int i = 0; i < foundDevices.getCount(); i++) {         //salva nell-iesima posizione dell'array l'i-esimo device (mac, RSSI)
    BLEAdvertisedDevice device = foundDevices.getDevice(i);
    JsonObject deviceJson = devicesArray.createNestedObject();
    deviceJson["mac_address"] = device.getAddress().toString();
    deviceJson["rssi"] = device.getRSSI();
    deviceJson["boardName"] = BOARD_NAME; //inseriamolo per capire quale board ha fatto il rilevamento
    
    //Serial.printf("Device %d: MAC Address: %s, RSSI: %d\n", i+1, device.getAddress().toString().c_str(), device.getRSSI());
  }

  //"stringhifichiamo" il JSON per spedirlo con la painlessMesh
  serializeJson(scanResultsJson, jsonString);
  scanCompleted = true;

  //Serial.print("JsonString: ");
  //Serial.println(jsonString);

}

void transmitData() {
  

  if (scanCompleted){
    Serial.println(BOARD_NAME + " is trying to broadcast...");
    mesh.sendBroadcast(jsonString);
    jsonString = "";
    pBLEScan->clearResults();
  }
   
}

// Callback necessari per fare in modo che la rete sia sempre up to date
void receivedCallback( uint32_t from, String &msg ) {
  Serial.println("Nuovo messaggio: " + msg);
}

//questa funzione viene eseguita ogni volta che un nuovo nodo si connette alla rete
void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("Nuovo nodo, nodeId = %u\n", nodeId);
}


//questa viene eseguita quando cambia la connessione con un nodo (un nodo entra o lascia la rete)
void changedConnectionCallback() {
  Serial.printf("Cambiamento di rete\n");
}

//questa viene eseguita quando la rete aggiusta il timing, così tutti sono in Sync
void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(115200);

//Scegliere il messaggio di Debug che più aggrada sua maestà sviluppatore

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION | GENERAL );  // set before init() so that you can see mesh startup messages
  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT ); //inizializzazione della mesh con i parametri prima definiti

  //assegniamo ad ogni evento la relativa funzione.
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);


  //BLE Functions
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100); //distanza temporale tra due scansioni, in ms
  pBLEScan->setWindow(99);  // finestra di tempo in cui deve scansionare, tra due scansioni. dev'essere <= al valore della riga sopra per chiare ragioni

  
  //TASKS
  userScheduler.addTask(transmit); //aggiungiamo allo scheduler il compito di trasmettere il msg
  userScheduler.addTask(bleScan);
  bleScan.enable(); 
  transmit.enable();



}

void loop() {
  mesh.update(); //mantiene la mesh in esecuzione ed anche lo scheduler
}

我坚信“扫描”任务中的

BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
是所有邪恶的根源,因为当该任务未启用时一切正常。我知道这个特定的行在进行扫描时“停止”代码,但我不明白为什么它会导致连接问题,也不明白如何解决它。

我已经查过了:

  • 每个网格具有相同的 SSID/密码
  • 足够的距离,这样它们在连接过程中就不会干扰

希望有人可以提供帮助,谷歌搜索我发现其他人在过去几年中也遇到了类似的连接问题。

提前非常感谢大家。

bluetooth-lowenergy esp32 mesh-network
1个回答
0
投票

按照评论中@MichaelKotzjan的建议,我一切都工作得很好。

代码更改:

我添加了一个void函数

void EndofScan() {
    pBLEScan->start(scanTime, EndofScan);
}

并且仅在

void setup(){}
中使用

调用一次
foundDevices = pBLEScan->start(scanTime, true);

其中foundDevices是全局声明的

BLEScanResult
对象,用于包含扫描结果。它是全球性的,因此可以在其他任何地方使用。

通过这样做,我们实现了异步执行的 BLE 扫描。

代码:

#include "painlessMesh.h" //libreria per usare il protocollo ESP-WIFI-MESH

//direttive per la scansione BLE
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>


//dettagli della mesh che stiamo realizzando. la rete si occupa da sola di
//mandare in giro i messaggi per tutta la rete.

#define   MESH_PREFIX     "meshName" //nome della rete
#define   MESH_PASSWORD   "password123" //password per la rete
#define   MESH_PORT       5555 //porta tcp sul quale far girare il server. default: 5555. credo servirà per fare la dashboard finale

String BOARD_NAME = "1"; //nome/numero della board

int scanTime = 3; //BLE Scan duration (seconds). non deve essere maggiore del primo parametro di Task bleScan, altrimenti c'è un conflitto.
BLEScan* pBLEScan; //oggetto BLEScan
String jsonString;
bool scanCompleted;
BLEScanResults foundDevices;
String receivedMessage;


Scheduler userScheduler;
painlessMesh  mesh;  //oggetto rete

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      //Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
    }
};

// User stub
void transmitData() ; //prototipo di sendMessage(), da non rimuovere
void scan(); //prototipo di scan(), da non rimuovere
void EndofScan();

//TASKS
Task transmit( TASK_SECOND * 4 , TASK_FOREVER, &transmitData ); 
Task bleScan(TASK_SECOND * 4, TASK_FOREVER, &scan); 



void scan() {


  Serial.print(F("Board "));
  Serial.print(BOARD_NAME);
  Serial.print(F(" is scanning...\n"));

  

//creazione array JSON
  StaticJsonDocument<1024> scanResultsJson;
  JsonArray devicesArray = scanResultsJson.to<JsonArray>();

  for (int i = 0; i < foundDevices.getCount(); i++) {         //salva nell-iesima posizione dell'array l'i-esimo device (mac, RSSI)
    BLEAdvertisedDevice device = foundDevices.getDevice(i);
    JsonObject deviceJson = devicesArray.createNestedObject();
    deviceJson["mac_address"] = device.getAddress().toString();
    deviceJson["rssi"] = device.getRSSI();
    deviceJson["boardName"] = BOARD_NAME; //inseriamolo per capire quale board ha fatto il rilevamento
    
    //Serial.printf("Device %d: MAC Address: %s, RSSI: %d\n", i+1, device.getAddress().toString().c_str(), device.getRSSI());
  }

  //"stringhifichiamo" il JSON per spedirlo con la painlessMesh
  serializeJson(scanResultsJson, jsonString);

  //Serial.print("JsonString: ");
  //Serial.println(jsonString);

}

void EndofScan() {
    pBLEScan->start(scanTime, EndofScan);
}

void transmitData() {
  
    Serial.println(BOARD_NAME + " is trying to broadcast...");
    mesh.sendBroadcast(jsonString);
    
   
}

const int MAX_SIZE = 150;
String boardScans[MAX_SIZE];



// Callback necessari per fare in modo che la rete sia sempre up to date
void receivedCallback( uint32_t from, String &msg ) {
  Serial.println("Nuovo messaggio: " + msg);
  receivedMessage = msg;
  char lastChar = receivedMessage.charAt(receivedMessage.length() - 1);
  int i = int(String(lastChar));
  boardScans[i] = receivedMessage+"agg: "+String(matistaiaggiornando);
  Serial.println("Nuovo messaggio ricevuto da BOARD "+String(lastChar)+" salvato in receivedMessage");
}



//questa funzione viene eseguita ogni volta che un nuovo nodo si connette alla rete
void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("Nuovo nodo, nodeId = %u\n", nodeId);
}


//questa viene eseguita quando cambia la connessione con un nodo (un nodo entra o lascia la rete)
void changedConnectionCallback() {
  Serial.printf("Cambiamento di rete\n");
}

//questa viene eseguita quando la rete aggiusta il timing, così tutti sono in Sync
void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(115200);

//Scegliere il messaggio di Debug che più aggrada sua maestà sviluppatore

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION | GENERAL );  // set before init() so that you can see mesh startup messages
  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT ); //inizializzazione della mesh con i parametri prima definiti
  mesh.setRoot(true);
  //assegniamo ad ogni evento la relativa funzione.
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);


  //BLE Functions
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(200); //distanza temporale tra due scansioni, in ms
  pBLEScan->setWindow(199);  // finestra di tempo in cui deve scansionare, tra due scansioni. dev'essere <= al valore della riga sopra per chiare ragioni
  foundDevices = pBLEScan->start(scanTime, true); //salva i risultati della scansione in foundDevices
  //TASKS
  userScheduler.addTask(transmit); //aggiungiamo allo scheduler il compito di trasmettere il msg
  userScheduler.addTask(bleScan);
  bleScan.enable(); 
  transmit.enable();

}


void loop() {
  mesh.update(); //mantiene la mesh in esecuzione ed anche lo scheduler
}
© www.soinside.com 2019 - 2024. All rights reserved.