Arduino-esp32: BLE_Server setValue float ?

Created on 11 Jan 2018  路  1Comment  路  Source: espressif/arduino-esp32

Please fill the info fields, it helps to get you faster support ;)

Hardware:

Board: ESP32 Dev Module
Core Installation/update date: 11/JAN/2018
IDE name: Arduino IDE
Flash Frequency: 40Mhz
Upload Speed: 115200

Description:

I'm trying to create BLE server that set values and notify changes
all my values are floats but setValue function is not clear what optio can be used to set a float
do i need to convert double values or floats values to unint ?
any help would be great

Sketch:

#include <Wire.h>
#include "MutichannelGasSensor.h"
#include <SPI.h>
#include <BLE2902.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include "Adafruit_HDC1000.h"
#include <math.h>
#include "EmonLib.h"


Adafruit_HDC1000 hdc = Adafruit_HDC1000();
EnergyMonitor emon1;

#define LED_PIN  5

#define PRE_HEAT_TIME   1

const float reference_vol = 0.500;
unsigned char clear_num = 0; //when use lcd to display
float R = 0;
float voltage = 0;


// See the following for generating UUIDs:

//#define aqService        "CCC0"
//#define allCharacteristic "CCC1"
//#define nh3Characteristic "CCCa"
//#define coCharacteristic  "CCC2"
//#define no2Characteristic "CCC3"
//#define c3h8Characteristic "CCC4"
//#define c4h10Characteristic "CCC5"
//#define ch4Characteristic "CCC6"
//#define h2Characteristic "CCC6"
//
//#define aqService2 "DDD0"
//#define c2h5ohCharacteristic "DDD1"
//#define tempCharacteristic  "DDD2"
//#define humCharacteristic "DDD3"
//
//#define aqService3 "EEE0"
//#define power1Characteristic "EEE1"
//#define power2Characteristic "EEE2"
//
//#define getService "19b10000e8f2537e4f6cd104768a1214"
//#define switchCharacteristic "19b10001e8f2537e4f6cd104768a1214"
//#define calibCharacteristic "19b10001e8f2537e4f6cd104768a1215"

BLEDescriptor allDescriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor nh3Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor coDescriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor no2Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor c3h8Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor c4h10Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor ch4Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor h2Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor c2h5ohDescriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor tempDescriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor humDescriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor power1Descriptor(BLEUUID((uint16_t)0x2901));
BLEDescriptor power2Descriptor(BLEUUID((uint16_t)0x2901));

BLECharacteristic allCharacteristic("CCC1", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic nh3Characteristic("CCCa", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic coCharacteristic("CCC2", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic no2Characteristic("CCC3", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic c3h8Characteristic("CCC4", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic c4h10Characteristic("CCC5", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic ch4Characteristic("CCC6", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic h2Characteristic("CCC7", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic c2h5ohCharacteristic("DDD1", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic tempCharacteristic("DDD2", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic humCharacteristic("DDD3", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic power1Characteristic("EEE1", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic power2Characteristic("EEE2", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic switchCharacteristic("19b10001e8f2537e4f6cd104768a1214", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
BLECharacteristic calibCharacteristic("19b10001e8f2537e4f6cd104768a1215", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);


volatile bool readFromSensor = false;
volatile bool readFromSensor2 = false;
volatile bool readFromSensor3 = false;
volatile bool readFromSensor4 = false;

float lastTempReading;
float lastHumidityReading;



void setup() {

  Serial.begin(115200);
    pinMode(LED_PIN, OUTPUT);

  digitalWrite(LED_PIN, HIGH);
  Serial.println("Starting BLE work!");

  BLEDevice::init("AirQuality");

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();

  // Create the BLE Service
  BLEService *pService = pServer->createService(BLEUUID((uint16_t)0xCCC0));

  allDescriptor.setValue("All");
  nh3Descriptor.setValue("NH3");
  coDescriptor.setValue("CO");
  no2Descriptor.setValue("NO2");
  c3h8Descriptor.setValue("C3H8");
  c4h10Descriptor.setValue("C4H10");
  ch4Descriptor.setValue("CH4");
  h2Descriptor.setValue("H2");
  c2h5ohDescriptor.setValue("C2H5OH");
  tempDescriptor.setValue("temp");
  humCharacteristic.setValue("hum");
  power1Descriptor.setValue("current");
  power2Descriptor.setValue("power");


  allCharacteristic.addDescriptor(&allDescriptor);
  nh3Characteristic.addDescriptor(&nh3Descriptor);
  coCharacteristic.addDescriptor(&coDescriptor);
  no2Characteristic.addDescriptor(&no2Descriptor);
  c3h8Characteristic.addDescriptor(&c3h8Descriptor);
  c4h10Characteristic.addDescriptor(&c4h10Descriptor);
  ch4Characteristic.addDescriptor(&ch4Descriptor);
  h2Characteristic.addDescriptor(&h2Descriptor);
  c2h5ohCharacteristic.addDescriptor(&c2h5ohDescriptor);
  tempCharacteristic.addDescriptor(&tempDescriptor);
  humCharacteristic.addDescriptor(&humDescriptor);
  power1Characteristic.addDescriptor(&power1Descriptor);
  power2Characteristic.addDescriptor(&power2Descriptor);

  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  allCharacteristic.addDescriptor(new BLE2902());
  nh3Characteristic.addDescriptor(new BLE2902());
  coCharacteristic.addDescriptor(new BLE2902());
  no2Characteristic.addDescriptor(new BLE2902());
  c3h8Characteristic.addDescriptor(new BLE2902());
  c4h10Characteristic.addDescriptor(new BLE2902());
  ch4Characteristic.addDescriptor(new BLE2902());
  h2Characteristic.addDescriptor(new BLE2902());
  c2h5ohCharacteristic.addDescriptor(new BLE2902());
  tempCharacteristic.addDescriptor(new BLE2902());
  humCharacteristic.addDescriptor(new BLE2902());
  power1Characteristic.addDescriptor(new BLE2902());
  power2Characteristic.addDescriptor(new BLE2902());
  switchCharacteristic.addDescriptor(new BLE2902());
  calibCharacteristic.addDescriptor(new BLE2902());



  pService->addCharacteristic(&allCharacteristic);
  pService->addCharacteristic(&nh3Characteristic);
  pService->addCharacteristic(&coCharacteristic);
  pService->addCharacteristic(&no2Characteristic);
  pService->addCharacteristic(&c3h8Characteristic);
  pService->addCharacteristic(&c4h10Characteristic);
  pService->addCharacteristic(&ch4Characteristic);
  pService->addCharacteristic(&h2Characteristic);
  pService->addCharacteristic(&c2h5ohCharacteristic);
  pService->addCharacteristic(&tempCharacteristic);
  pService->addCharacteristic(&humCharacteristic);
  pService->addCharacteristic(&power1Characteristic);
  pService->addCharacteristic(&power2Characteristic);
  pService->addCharacteristic(&switchCharacteristic);
  pService->addCharacteristic(&calibCharacteristic);

  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();

  Serial.println(F("BLE AirQ Sensor"));
  Serial.println("power on!");
  digitalWrite(LED_PIN, LOW);
  Serial.println("power on, and pre-heat");
  gas.begin(0x04);//the default I2C address of the slave is 0x04
  gas.powerOn();
  delay(60);
  hdc.begin();
}

void getallVal() {
  float t;
  float h;
  float a;
  String r;

  t = hdc.readTemperature();
  r += String(t) + ",";
  h = hdc.readHumidity();
  r += String(h) + ",";
  a = gas.measure_NH3();
  r += String(a) + ",";
  a = gas.measure_CO();
  r += String(a) + ",";
  a = gas.measure_NO2();
  r += String(a) + ",";
  a = gas.measure_C3H8();
  r += String(a) + ",";
  a = gas.measure_C4H10();
  r += String(a) + ",";
  a = gas.measure_CH4();
  r += String(a) + ",";
  a = gas.measure_H2();
  r += String(a) + ",";
  a = gas.measure_C2H5OH();
  r += String(a) + ",";
  Serial.print(r);
  //  char *b ;
  //  b  = string2char(r);
  //  allCharacteristic.setValue(b);
  //   char b[20] ;
  //  r.toCharArray(b, 20);
  //  allCharacteristic.setValue((unsigned char*)b);
}

void calibrate() {

  for (int i = 60 * PRE_HEAT_TIME; i >= 0; i--)
  {
    Serial.print(i / 60);
    Serial.print(":");
    Serial.println(i % 60);
    delay(1000);
  }

  Serial.println("Begin to calibrate...");
  gas.doCalibrate();
  Serial.println("Calibration ok");
  delay(60);
}

void setPowerVal() {
  double Irms = emon1.calcIrms(1480);  // Calculate Irms only
  double Power = Irms * 230.0 / 1000;
  power1Characteristic.setValue(Irms);
  power2Characteristic.setValue(Power);
  power1Characteristic.notify();
  power2Characteristic.notify();
  Serial.print(F("I: ")); Serial.print(Irms); Serial.println();
  Serial.print(F("P: ")); Serial.print(Power); Serial.println();
  //emon1.calcVI(20,2000);         // Calculate all. No.of wavelengths, time-out
  //emon1.serialprint();           // Print out all variables
}

void setTempHumVal() {
  float t;
  float h;


  t = hdc.readTemperature();
  h = hdc.readHumidity();
  tempCharacteristic.setValue(t);
  humCharacteristic.setValue(h);
  tempCharacteristic.notify();
  humCharacteristic.notify();
  Serial.print(F("T: ")); Serial.print(t); Serial.println();
  Serial.print(F("H: ")); Serial.print(h); Serial.println();
}
void setNH3CharacteristicValue() {

  float a;
  a = gas.measure_NH3();
  nh3Characteristic.setValue(a);
  nh3Characteristic.notify();
  Serial.print(F("NH3: ")); Serial.print(a); Serial.println();
}

void setCOCharacteristicValue() {

  float a;
  a = gas.measure_CO();
  coCharacteristic.setValue(a);
  coCharacteristic.notify();
  Serial.print(F("CO: ")); Serial.print(a); Serial.println();
}

void setNO2CharacteristicValue() {

  float a;
  a = gas.measure_NO2();
  no2Characteristic.setValue(a,);
  no2Characteristic.notify();
  Serial.print(F("NO2: ")); Serial.print(a); Serial.println();
}

void setC3H8CharacteristicValue() {

  float a;
  a = gas.measure_C3H8();
  c3h8Characteristic.setValue(a);
  c3h8Characteristic.notify();
  Serial.print(F("C3H8: ")); Serial.print(a); Serial.println();
}

void setC4H10CharacteristicValue() {

  float a;
  a = gas.measure_C4H10();
  c4h10Characteristic.setValue(a);
  c4h10Characteristic.notify();
  Serial.print(F("C4H10: ")); Serial.print(a); Serial.println();
}

void setCH4CharacteristicValue() {

  float a;
  a = gas.measure_CH4();
  ch4Characteristic.setValue(a);
  ch4Characteristic.notify();
  Serial.print(F("CH4: ")); Serial.print(a); Serial.println();
}

void setH2CharacteristicValue() {

  float a;
  a = gas.measure_H2();
  h2Characteristic.setValue(a);
  h2Characteristic.notify();
  Serial.print(F("H2: ")); Serial.print(a); Serial.println();
}

void setC2H5OHCharacteristicValue() {

  float a;
  a = gas.measure_C2H5OH();
  c2h5ohCharacteristic.setValue(a);
  c2h5ohCharacteristic.notify();
  Serial.print(F("C2H5OH: ")); Serial.print(a); Serial.println();
}

void setEMPTYCharacteristicValue() {
  float a;
  a = gas.measure_C2H5OH();
  c2h5ohCharacteristic.setValue(a);
  c2h5ohCharacteristic.notify();
  Serial.print(F("C2H5OH: ")); Serial.print(a); Serial.println();
}

boolean significantChange(float val1, float val2, float threshold) {
  return (abs(val1 - val2) >= threshold);
}

void loop() {
  // put your main code here, to run repeatedly:
   if (readFromSensor) {
    //getallVal();
    digitalWrite(LED_PIN, HIGH);
    setNH3CharacteristicValue();
    setCOCharacteristicValue();
    setNO2CharacteristicValue();
    setC3H8CharacteristicValue();
    setC4H10CharacteristicValue();
    readFromSensor = false;
    delay(10000);
    digitalWrite(LED_PIN, LOW);
  }

  if (readFromSensor2) {
    digitalWrite(LED_PIN, HIGH);
    setCH4CharacteristicValue();
    setH2CharacteristicValue();
    setC2H5OHCharacteristicValue();
    setTempHumVal();
    readFromSensor2 = false;
    delay(10000);
    digitalWrite(LED_PIN, LOW);
  }
  if (readFromSensor3) {
    digitalWrite(LED_PIN, HIGH);
    setPowerVal();
    readFromSensor3 = false;
    digitalWrite(LED_PIN, LOW);
  }
  if (readFromSensor4) {
    calibCharacteristic.setValue(0);
    digitalWrite(LED_PIN, HIGH);
    calibrate();
    readFromSensor4 = false;
    digitalWrite(LED_PIN, LOW);
    calibCharacteristic.setValue(1);
  }
}

void switchCharacteristicWritten() {
  // central wrote new value to characteristic, update LED
  Serial.print(F("Characteristic event, writen: "));
  Serial.print(switchCharacteristic.getValue());
  if ( switchCharacteristic.getValue() == "1" ) {
    timerHandler();
  }
  if ( switchCharacteristic.getValue() == "2" ) {
    timer2Handler();
  }
  if ( switchCharacteristic.getValue() == "3" ) {
    timer3Handler();
  }
  if ( switchCharacteristic.getValue() == "4" ) {
    timer4Handler();
  }
}

void timerHandler() {
  readFromSensor = true;
}

void timer2Handler() {
  readFromSensor2 = true;
}

void timer3Handler() {
  readFromSensor3 = true;
}
void timer4Handler() {
  readFromSensor4 = true;
}
char* string2char(String command) {
  if (command.length() != 0) {
    char *p = const_cast<char*>(command.c_str());
    return p;
  }
}

Debug Messages:

Arduino/BLE_server_esp32/BLE_server_esp32.ino: In function 'void setPowerVal()': BLE_server_esp32:247: error: no matching function for call to 'BLECharacteristic::setValue(double&)' power1Characteristic.setValue(Irms); ^ In file included from /Documents/Arduino/hardware/espressif/esp32/libraries/BLE/src/BLEDescriptor.h:14:0, from /Documents/Arduino/hardware/espressif/esp32/libraries/BLE/src/BLE2902.h:13, from /Documents/Arduino/BLE_server_esp32/BLE_server_esp32.ino:8: /Documents/Arduino/hardware/espressif/esp32/libraries/BLE/src/BLECharacteristic.h:75:7: note: candidate: void BLECharacteristic::setValue(uint8_t*, size_t) void setValue(uint8_t* data, size_t size);

Most helpful comment

@gesaleh a BLE value is either an array of bytes or a String.
If you look at BLE characteristic Temperature

Temperature

Information:
Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius
Unit:
org.bluetooth.unit.thermodynamic_temperature.degree_celsius
Exponent:聽Decimal,聽-2

and BLE characteristic Humidty

Humidity

Information:
Unit is in percent with a resolution of 0.01 percent
Unit:
org.bluetooth.unit.percentage
Exponent:聽Decimal,聽-2

you can see that both temperature and humidity are uint16 values. Temperature and humidity are both defined with 2 digits after the decimal point (the mantissa). The uint16 values are transferred in the sequence LSB first, MSB last.
_Of course you can disregard the BLE definitions and transfer your temperature and humidity values with a higher precision. But you have to convert the float value into an array of bytes still._
Here is my code that I use to convert temperature and humidity into values conform with the BLE specifications for temperature and humidity:

// get float values from DHT sensor
float temperature = dht.getTemperature();
float humidity = dht.getHumidity();
// convert float value into 16 bit integer value (LSB first MSB last)
uint8_t tempData[2];
uint16_t tempValue;
// multiply by 100 to get 2 digits mantissa and convert into uint16_t
tempValue = (uint16_t)(temperature *100);
// set  LSB of characteristic
tempData[0] = tempValue;
// set MSB of characteristic
tempData[1] = tempValue>>8;
// set characteristic value
pCharacteristicTemp->setValue(tempData, 2);
// convert float value into 16 bit integer value (LSB first MSB last)
// multiply by 100 to get 2 digits mantissa and convert into uint16_t
tempValue = (uint16_t)(humidity *100);
// set  LSB of characteristic
tempData[0] = tempValue;
// set MSB of characteristic
tempData[1] = tempValue>>8;
// set characteristic value
pCharacteristicHumid->setValue(tempData, 2);
// notify client about new temperature value
pCharacteristicTemp->notify();
// notify client about new humidity value
pCharacteristicHumid->notify();

I use this in my ESP32 Weatherstation application

>All comments

@gesaleh a BLE value is either an array of bytes or a String.
If you look at BLE characteristic Temperature

Temperature

Information:
Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius
Unit:
org.bluetooth.unit.thermodynamic_temperature.degree_celsius
Exponent:聽Decimal,聽-2

and BLE characteristic Humidty

Humidity

Information:
Unit is in percent with a resolution of 0.01 percent
Unit:
org.bluetooth.unit.percentage
Exponent:聽Decimal,聽-2

you can see that both temperature and humidity are uint16 values. Temperature and humidity are both defined with 2 digits after the decimal point (the mantissa). The uint16 values are transferred in the sequence LSB first, MSB last.
_Of course you can disregard the BLE definitions and transfer your temperature and humidity values with a higher precision. But you have to convert the float value into an array of bytes still._
Here is my code that I use to convert temperature and humidity into values conform with the BLE specifications for temperature and humidity:

// get float values from DHT sensor
float temperature = dht.getTemperature();
float humidity = dht.getHumidity();
// convert float value into 16 bit integer value (LSB first MSB last)
uint8_t tempData[2];
uint16_t tempValue;
// multiply by 100 to get 2 digits mantissa and convert into uint16_t
tempValue = (uint16_t)(temperature *100);
// set  LSB of characteristic
tempData[0] = tempValue;
// set MSB of characteristic
tempData[1] = tempValue>>8;
// set characteristic value
pCharacteristicTemp->setValue(tempData, 2);
// convert float value into 16 bit integer value (LSB first MSB last)
// multiply by 100 to get 2 digits mantissa and convert into uint16_t
tempValue = (uint16_t)(humidity *100);
// set  LSB of characteristic
tempData[0] = tempValue;
// set MSB of characteristic
tempData[1] = tempValue>>8;
// set characteristic value
pCharacteristicHumid->setValue(tempData, 2);
// notify client about new temperature value
pCharacteristicTemp->notify();
// notify client about new humidity value
pCharacteristicHumid->notify();

I use this in my ESP32 Weatherstation application

Was this page helpful?
0 / 5 - 0 ratings