Sending Data From ESP32 with ble in my phone

I have this issue :

My code:

/*
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updates by chegewara
*/

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>



#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_TX "beb5483e-36e1-4688-b7f5-ea07361b26a8"


BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
int sensorvalue = 0;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};




void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  BLEDevice::init("Esp Rose");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_TX,
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );

  pCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  pServer->getAdvertising()->start();

}

void loop() {

  if (deviceConnected) {
    sensorvalue = analogRead(A0);

    //in order to send the value we must convert it to characteristic
    char txString[8];
    dtostrf(sensorvalue, 1, 2, txString);
    pCharacteristic->setValue(txString);
    pCharacteristic->notify();
    Serial.println("Sent value : " + String(txString));
  }


  
}

Compiles and runs : i can detect in with nrf connector but i cant connect cuz it keeps rebooting
my serial monitor:

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Starting BLE work!

it keeps spamming this

Any ideas , or anyone can suggest another way to make esp32 a server to only send sensor data to Phone via BLE ?

Note sure this is your issue, but that's likely one to solve:

you have a global BLECharacteristic *pCharacteristic;which you re-declare as a local one in the setup

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_TX,
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );

so in the loop when you do pCharacteristic->setValue(txString);you are calling a method on a NULL pointer

as a side note, sensorvalue is a int (the result of analogRead()), why do you transform it into a floating point cString?

So its better to delete the global BLECharacteristic *pCharacteristic; ? since i declare it in setup .

And here pCharacteristic->setValue(txString); I dont understand what you mean , do you mean i should Declare BLECharacteristic *pCharacteristic; and give it a value so its not a null pointer , so i can store the value i get from analogRead(A0) ??

Also i thought u always had to dtostrf in order to upload to iot or ble devices .

Then i guess a simple pCharacteristic->setValue(sensorvalue); will do

Seems You need to read about variable scope

Just keep the global one, don’t redeclare it locally.

The value for a characteristic is just a "sequence of bytes". These bytes are then stored by the BLE Server and made available to a BLE client that requests them. What the bytes represent is user defined.

There are a number of setValue signatures to hand over the sequence of bytes to the BLE Server as defined in the class

        void setValue(uint8_t* data, size_t size);
	void setValue(std::string value);
	void setValue(uint16_t& data16);
	void setValue(uint32_t& data32);
	void setValue(int& data32);
	void setValue(float& data32);
	void setValue(double& data64);

so a uint16_t would work for an analogeRead()

1 Like

Yes i know it was a bad question , but ok i keep it as a global , i still need to declare the characteristics of my ble device , so should i redeclear all that outside of the setup?
and keep inside the setup the server creation etc?

Hmm so pCharacteristic->setValue(uint16_t& sensorvalue)); to access pointer and put sensorvalue in there ?

Read again I was editing my post when you answered

For declaring it, keep it global since you want to use it both in setup and the loop. You create an instance in the setup, only once, and then That’s the one you use in the loop.

Seems you are not fully getting what’s happening with classes and instances =>You have examples you could study in the library

The & in the signature means they pass by reference. It might mean the data is not duplicated and thus needs to refer to some static data in your app so that the reference stays legit. (I’ve not explored this with the ESP32)

Wait i get it now . I know what's an instance of a class , but really while automating with wifi is piece of cake , BLE is something new for me . So from what i understand J-M-L , i declare the global variable BLECharacteristic* pCharacteristic = NULL; and in the setup i am using pCharacteristic = pService->createCharacteristic( "place things here")

and i pass sensor data to BLE with pCharacteristic->setValue((uint16_t*)&value, sensorvalue);

Have you ever looked into the BLE tutorial from random nerd tuotrial?

by the way "classical blue ttoth seems to be much easier to use.

best regards Stefan

Hey Stefan , yes i ve seen it , but i had to adjust the code anyway because i wanted things to happen inside the loop .
I think i am close to the solution but will test it tomorrow