Reading a BLE characteristic on central device

I've been going around in circles here so I'll just ask the experts. I have a Nano 33 BLE Sense as a peripheral device and am successfully sending a value from the temperature sensor which I can read on the Android app "nRF Connect" using the sketch below. What I want to do now is use another Arduino set up as central to read the value being sent by the peripheral. I have been trying for days now and I can connect to the peripheral but cannot find a way to download the data I know it is sending. I keep getting verification errors such as:

request for member 'readValue' in '"2A6E"', which is of non-class type 'const char [5]'

'class BLEDevice' has no member named 'read'

Could someone show me a simple way for the central device to read the data from the peripheral?

#include <ArduinoBLE.h>
#include <Arduino_HTS221.h>
#include <Arduino_LSM9DS1.h>


BLEService sensorService("181A");
BLEIntCharacteristic temperatureSensorLevel("2A6E", BLERead );
BLEIntCharacteristic humiditySensorLevel("2A6F", BLERead );

int oldTemperature = 0;
int oldHumidity = 0;

void setup() {
  Serial.begin(9600);
  //while (!Serial);
  delay(10);
  // set the LEDs pins as outputs
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);

  // turn all the LEDs off
  digitalWrite(LEDR, LOW);
  digitalWrite(LEDG, HIGH);
  digitalWrite(LEDB, HIGH);

  if (!HTS.begin()) {
    Serial.println("Failed to initialize humidity temperature sensor!");
    while (1);
  }

  pinMode(LED_BUILTIN, OUTPUT);

  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  BLE.setLocalName("SteveTempHumidity2");
  BLE.setAdvertisedService(sensorService);
  sensorService.addCharacteristic(temperatureSensorLevel);
  sensorService.addCharacteristic(humiditySensorLevel);
  BLE.addService(sensorService);
  temperatureSensorLevel.writeValue( oldTemperature);
  humiditySensorLevel.writeValue( oldHumidity);

  BLE.advertise();
  Serial.println("Bluetooth device active, waiting for connections");
}

void loop() {
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());
    //digitalWrite(LED_BUILTIN, HIGH);
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDG, HIGH);
    digitalWrite(LEDB, LOW);

    while (central.connected()) {
      //long currentMillis = millis();
      updateHumidityLevel();
      delay (300);
    }

    //digitalWrite(LED_BUILTIN, LOW);
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDB, HIGH);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

void updateHumidityLevel() {
  int temp, hum;
  temp = HTS.readTemperature();
  hum = HTS.readHumidity();


  Serial.print("********");
  Serial.print(temp);

  if (temp != oldTemperature) {
    temperatureSensorLevel.writeValue(temp * 100);

    oldTemperature  = temp;
  }

  if (hum != oldHumidity) {
    humiditySensorLevel.writeValue(hum * 100);
    oldHumidity  = hum;
  }

  Serial.print("Temp = ");
  Serial.print(temp);
  Serial.println("°C");
  Serial.print("Humidity = ");
  Serial.print(hum);
  Serial.println("%");
  delay(1000);
}

Here is an example central sketch reading an integer value. You should be able to modify it for your service and characteristics,

#include <ArduinoBLE.h>

void setup() {

Serial.begin(9600);
while(!Serial);
 
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  Serial.println("BLE Central for Temperature Server");
  //custom sensor service 1101
  BLE.scanForUuid("1101"); 
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();
 
  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();
    BLE.stopScan();
  }
  peripheral.connect();
  while (peripheral)
  {
    peripheral.discoverAttributes();
    BLEService service = peripheral.service("1101");
    Serial.print("Service ");
    Serial.print(service.uuid());
    BLECharacteristic characteristic = service.characteristic("2104");
    readCharacteristicValue(characteristic);
    delay(2000);
  }
}

void readCharacteristicValue(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  // check if the characteristic is readable
  if (characteristic.canRead()) {
    //read the characteristic value
    int16_t temperature = 0;
    characteristic.readValue(&temperature,2);
    Serial.print(", temperature = ");
    Serial.println((float)temperature/100.0);
  }
}
1 Like

Thank you so much! After changing the service and chacteristic codes the sketch works. I will now study it to find out what I was doing wrong.

It seems that what I was missing was the ampersand (&) as in characteristic.readValue(**&**temperature,2);

What exactly is the meaning of the ampersand in this context?

characteristic.readValue(&temperature,2);

It is "the address of" operator. Your search engine of choice can tell you more.

In the .readValue() function, it is storing the read value at the address of the variable "temperature". That variable is a 2 byte integer, and that the reason for the number of bytes to place starting at the specified address.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.