espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.23k stars 7.34k forks source link

BLE_Server setValue float ? #992

Closed gesaleh closed 6 years ago

gesaleh commented 6 years ago

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);```
beegee-tokyo commented 6 years ago

@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