我希望能帮助我解决这个问题,我在我的项目,我新的工作与蓝牙通信和BLE模式的ESP32,所以我感谢您的理解,如果我做的基本错误
我有2个esp32,一个设置为ble通知模式,另一个设置为客户端,esp32在通知模式下,读取2个ADC和1个数字输入,并使用不同UUID在3个特性上公布它们,此代码运行明显良好,因为当我使用nrf连接应用程序时,它检测到esp32 ble,我可以与它连接并查看服务,3个特性和每个特性的值。问题是当我在另一个esp32上运行客户端代码时,因为它可以获得2个ADC读数(ejex和ejey),但数字输入(boton)读取错误,事实上,我获得了正确的数字输入值,但它被最后一次ADC读取的值覆盖(ejeychar)
1)Client reading proof2)Client reading proof
接下来是esp32通知代码
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h> //descriptor para la configuración del cliente que tiene un UUID de 0X2902
const int pinJoyX = 32;
const int pinJoyY = 35;
const int pinJoyButton =33;
int ejex=0;
int ejey=0;
int boton=0;
//Nombre del servidor BLE
#define bleservername "control RBKT"
//Variables de tiempo
unsigned long lastime=0;
unsigned long timerdelay=50;
bool deviceconnected=false;
#define service_uuid "91bad492-b950-4226-aa2b-4ede9fa42f59"
BLECharacteristic ejeXCharacteristics("cba1d466-344c-4be3-ab3f-189f80dd7518", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor ejeXDescriptor(BLEUUID((uint16_t)0x2902));
BLECharacteristic ejeYCharacteristics("f78ebbff-c8b7-4107-93de-889a6a06d408", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor ejeYDescriptor(BLEUUID((uint16_t)0x2901));
BLECharacteristic SWCharacteristics("ca73b3ba-39f6-4ab3-91ae-186dc9577d99", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor SWDescriptor(BLEUUID((uint16_t)0x2903)); //0x2903
//Setup callbacks onConnect and onDisconnect
class MyServerCallbacks: public BLEServerCallbacks
{
void onConnect(BLEServer* pServer)
{
deviceconnected = true;
};
void onDisconnect(BLEServer* pServer)
{
deviceconnected = false;
}
};
void setup()
{
Serial.begin(115200);
pinMode(pinJoyButton ,INPUT_PULLUP);
//Crea dispositivo BLE
BLEDevice::init(bleservername);
//Crea servidor BLE
BLEServer *pServer=BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks);
//Crea el servicio BLE
BLEService *axisservice=pServer->createService(service_uuid);
//Crea caracteristica y descriptor BLE de los ejes
axisservice->addCharacteristic(&ejeXCharacteristics);
ejeXDescriptor.setValue("Posicion Eje X");
ejeXCharacteristics.addDescriptor(new BLE2902());//&ejeXDescriptor
axisservice->addCharacteristic(&ejeYCharacteristics);
ejeYDescriptor.setValue("Posicion Eje Y");
ejeYCharacteristics.addDescriptor(new BLE2902());
axisservice->addCharacteristic(&SWCharacteristics);
SWDescriptor.setValue("BOTON");
SWCharacteristics.addDescriptor(new BLE2902());//new BLE2902()
// inicamos el servicio
axisservice->start();
//iniciamos a publicar
BLEAdvertising *pAdvertising=BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(service_uuid);
pServer->getAdvertising()->start();
Serial.println("Esperando conexion de cliente para notificar");
}
void loop()
{
if(deviceconnected)
{
if((millis()-lastime)>timerdelay)
{
ejex=analogRead(pinJoyX);
delay(50); //es necesaria una pequeña pausa entre lecturas analógicas
ejey=analogRead(pinJoyY);
boton=digitalRead(pinJoyButton);
Serial.print("Eje X:");
Serial.println(ejex);
Serial.print("Eje Y:");
Serial.println(ejey);
Serial.print("SW:");
Serial.println(boton);
static char EJEX[4];
dtostrf(ejex,4,0,EJEX);
ejeXCharacteristics.setValue(EJEX);
ejeXCharacteristics.notify();
static char EJEY[4];
dtostrf(ejey,4,0,EJEY);
ejeYCharacteristics.setValue(EJEY);
ejeYCharacteristics.notify();
static char SW[1];
dtostrf(boton,1,0,SW);
SWCharacteristics.setValue(SW);
SWCharacteristics.notify();
lastime=millis();
}
}
}
这是我的esp32客户端
#include <BLEDevice.h>
// nombre del otro esp32 en modo servidor
#define bleservername "control RBKT"
//UUID del servicio que buscaremos
static BLEUUID carserviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
static BLEUUID ejeXUUID("cba1d466-344c-4be3-ab3f-189f80dd7518");
static BLEUUID ejeYUUID("f78ebbff-c8b7-4107-93de-889a6a06d408");
static BLEUUID SWUUID("ca73b3ba-39f6-4ab3-91ae-186dc9577d99");
static boolean doConnect=false;
static boolean connected=false;
static BLEAddress *pserveraddress;
//caracteristicas que queremos leer
static BLERemoteCharacteristic* ejeXCharacteristics;
static BLERemoteCharacteristic* ejeYCharacteristics;
static BLERemoteCharacteristic* SWCharacteristics;
//Activar notificacion
const uint8_t notificationOn[] = {0x1, 0x0};
const uint8_t notificationOff[] = {0x0, 0x0};
//variables para almacenar valores del joystick
char* ejexchar;
char* ejeychar;
char* swchar;
int ejex=0;
int ejey=0;
int swbt=0;
//banderas si hay nueva lectura disponible
boolean newejex=false;
boolean newejey=false;
boolean newsw=false;
//Connect to the BLE Server that has the name, Service, and Characteristics
bool connectToServer(BLEAddress pAddress)
{
BLEClient* pClient = BLEDevice::createClient();
// Connect to the remove BLE Server.
pClient->connect(pAddress);
Serial.println(" - Conectando al servidor");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(carserviceUUID);
if (pRemoteService == nullptr)
{
Serial.print("Error en encontrar el servicio ");
Serial.println(carserviceUUID.toString().c_str());
return (false);
}
ejeXCharacteristics=pRemoteService->getCharacteristic(ejeXUUID);
ejeYCharacteristics=pRemoteService->getCharacteristic(ejeYUUID);
SWCharacteristics=pRemoteService->getCharacteristic(SWUUID);
if(ejeXCharacteristics==nullptr || ejeYCharacteristics==nullptr || SWCharacteristics==nullptr)
{
Serial.println("Error en encontrar la caracteristica");
}
Serial.println("Caracteristicas encontradas");
//Asignacion de llamados para las caracteristicas
ejeXCharacteristics->registerForNotify(axisXNotifyCallback);
ejeYCharacteristics->registerForNotify(axisYNotifyCallback);
SWCharacteristics->registerForNotify(SWNotifyCallback);
return true;
}
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.getName() == bleservername) //checa si los nombres coinciden
{
advertisedDevice.getScan()->stop(); //Scan can be stopped, we found what we are looking for
pserveraddress = new BLEAddress(advertisedDevice.getAddress()); //Address of advertiser is the one we need
doConnect = true; //Set indicator, stating that we are ready to connect
Serial.println("Dispositivo encontrado, conectando...");
}
}
};
static void axisXNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{
//store temperature value
ejexchar=(char*)pData;
ejex=atoi(ejexchar);
newejex=true;
}
static void axisYNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{
//store temperature value
ejeychar=(char*)pData;
ejey=atoi(ejeychar);
newejey=true;
}
static void SWNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,uint8_t* pData, size_t length, bool isNotify)
{
//store temperature value
swchar=(char*)pData;
//swbt=atoi(swchar);
newsw=true;
}
void setup()
{
Serial.begin(115200);
Serial.println("Iniciando sistema v0.1...");
//Se inicializa dispositivo BLE
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 30 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(30);
}
void loop()
{
if(doConnect==true)
{
if(connectToServer(*pserveraddress))
{
ejeXCharacteristics->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);
ejeYCharacteristics->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);
SWCharacteristics->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);
connected=true;
Serial.print("si esta conectado");
}
else
{
Serial.println("Error al conectarse al servidor");
}
doConnect=false;
}
Serial.print("EJE X:");
Serial.println(ejex);
Serial.print("EJE Y:");
Serial.println(ejey);
Serial.print("Boton:");
Serial.println(swchar);
delay(2000);
}
我的代码所基于的代码参考是Randomnnerdtutorials esp32 ble server client教程
1条答案
按热度按时间olmpazwi1#
所以总的来说你的代码设计很糟糕,你发送负载的方式效率很低,3个通知服务在你的用例中不合理。但是如果这让你的工作完成得不是最好的方式,那么我想这也没关系。
我没有运行你的代码,因为我没有两个esp 32与我,和问题,我认为是竞态条件必须接收多个通知值一次。虽然我也应该声明,ble堆栈理想地支持多个通知一次。
为什么我认为它的比赛是因为你自己说nrfConnect接收数据刚刚好,但在esp 32中,你订阅3个通知在客户端以及发送他们在服务器端,几乎一次。
据我所知,以下三件事中的任何一件都可以做,希望解决您的问题:-
1.逐个通知每个服务-一旦您从每个服务的一个通知值中收到值,通过在通知回调函数中禁用通知来禁用同一服务。例如:-
1.您可以只使用一个通知服务,一次发送所有三个值
1.在三个服务notify()之间的服务器代码上添加延迟。
当然,可以做很多事情来调整你的代码,但希望任何这些理论上应该工作。