BLE service + connect not working on all devices

Good day.

I have the following code which I want to use on a xenon as peripheral device to update batt voltage to an Argon. The problem is it only runs on Argons the service does not show up on Xenons. I have also noticed it does not run on all Argons I have a few of them all with 1.4.4 but some of them I cant conenct to or they dont show up on the list. It does not run at all on the new OS 1.5-RC1 (goes into safe mode) . It is based on the HTM example which I see is also not working on all devices. Is there something missing,

#include "Particle.h"

float battVoltage;//holds the local battery voltage
SerialLogHandler logHandler(LOG_LEVEL_TRACE);

const unsigned long UPDATE_INTERVAL_MS = 2000;
unsigned long lastUpdate = 0;
float getTempC();
uint32_t ieee11073_from_float(float temperature);

const char* xenonBattService = "b4250400-fb4b-4746-b2b0-93f0e61122c6"; //service
BleUuid xenonBattBleService(xenonBattService);
BleCharacteristic batteryMeasurementCharacteristic("bat", BleCharacteristicProperty::NOTIFY, BleUuid(0x2A19), xenonBattService);

void setup() {

  (void)logHandler; // Does nothing, just to eliminate the unused variable warning
  BLE.on();
  //BLE.setAdvertisingTimeout(500); // 1000 * 10 ms // time period of the the detonation period (how long it get transmitted)
  Particle.keepAlive(20);
  Serial.begin(115200);
  
  pinMode(BATT, INPUT); // argon battery 
  BLE.setTxPower(0); // Use lower power // Use lower power -20, -16, -12, -8, -4, 0, 4, 8.
  // set initial IO states
  
  pinMode(BATT, INPUT);

    BLE.addCharacteristic(batteryMeasurementCharacteristic);
    BleAdvertisingData advData;
    advData.appendServiceUUID(xenonBattService);
    BLE.advertise(&advData);
}
void loop() {
    if (millis() - lastUpdate >= UPDATE_INTERVAL_MS) {
        lastUpdate = millis();

       if (BLE.connected()) {
            uint8_t buf[6];
              battVoltage = analogRead(BATT) * 0.0011224;
            //battVoltage = analogRead(BATT) * 0.0011224 / 3.7 * 100; /// in percentage
             buf[0] = 0x01;
             memcpy(&buf[1], &battVoltage, 5);
             batteryMeasurementCharacteristic.setValue(buf, sizeof(buf));

       }
    }
}

From nRF connect I get the following

Invalid handle
BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION

There are a few problems with your code.

  1. You need to put in SYSTEM_MODE(MANUAL); after the #include “Particle.h”. Otherwise the Xenon (and the Argon) will be looking to connect to a Mesh network and a WiFi network and will be flash green on the LED and blocking getting out of setup().

  2. The battery level characteristic reports a percentage 0-100 as a single byte and not a float. I put in something like this:

      uint8_t value;
      value = (uint8_t) (analogRead(BATT) * 0.0011224 * 100 / 4.2);   //battery voltage as a float as a percentage of 4.2V typecast to an unsigned 8-bit int
      batteryMeasurementCharacteristic.setValue(&value, 1);
  1. If you want to send back battery voltage then maybe a custom service and characteristic? You will need to read the battery voltage as a float and then convert into a 4 byte array to send. Maybe you had not included but you would also need to define the float conversion function.
uint32_t ieee11073_from_float(float temperature)
{
  // This code is from the ARM mbed temperature demo:
  // https://github.com/ARMmbed/ble/blob/master/ble/services/HealthThermometerService.h
  // I'm pretty sure this only works for positive values of temperature, but that's OK for the health thermometer.
  uint8_t  exponent = 0xFE; // Exponent is -2
  uint32_t mantissa = (uint32_t)(temperature * 100);

  return (((uint32_t)exponent) << 24) | mantissa;
}

It works fine, ie. the battery level as a percentage on a Xenon on 1.4.4 and 1.5.0-rc.1.

Note: there is an error with the enumerator value for battery service - I believe the value should be 0x180F. The code that works for me is below.

#include "Particle.h"

SYSTEM_MODE(MANUAL);                        //to stop mesh connection blocking

const unsigned long UPDATE_INTERVAL_MS = 2000UL;
unsigned long lastUpdate = 0;

// The battery level service allows the battery level to be monitored 0x180F
BleUuid batteryLevelService(0x180F);

// The battery_level characteristic shows the battery level of
BleCharacteristic batteryLevelCharacteristic("battery level", BleCharacteristicProperty::READ, BleUuid(0x2A19), batteryLevelService);

void setup()
{
  Serial.begin();
  Serial.println("BLE battery level example");
  BLE.on();
  BLE.addCharacteristic(batteryLevelCharacteristic);
  BleAdvertisingData advData;
  advData.appendServiceUUID(batteryLevelService);
  BLE.advertise(&advData);
}

void loop()
{
  if (millis() - lastUpdate >= UPDATE_INTERVAL_MS)
  {
    lastUpdate = millis();
    if (BLE.connected())
    {
      uint8_t value;
      value = (uint8_t) (analogRead(BATT) * 0.0011224 * 100 / 4.2);   //battery voltage as a float as a percentage of 4.2V typecast to an unsigned 8-bit int
      if (value > 100) value = 100;
      Serial.printlnf("Battery Level %% %i", value);
      batteryLevelCharacteristic.setValue(&value, 1);
    }
  }
}
1 Like

Thanks Will.

I discovered the following. From a batch of 4 Argons and 10 Xenons I found the code dit not work on 1 Argon and also did not work on 3 Xenons. These came back with , BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION

Closer investigation lead me to the following. All the particles when put into listening mode with the COM port open returns a Device ID, Device secret and serial no, they are all working

The ones that are not working only show device is as per below.

image

I did at some stage experiment with Segger and the Nordic SDK, I unbricked them using https://www.jaredwolff.com/how-to-unbrick-particle-mesh-using-jlink/#! procedure.

I am very sure these that are not connecting are the ones that at some stage had the Nordic SDK installed. Is this possible?

As for v1.5.0-rc

Im also at a loss when compile in VS Particle Workbench if I compile and stay on the tab “Welcome to particle workbench” after selecting “configure for device” I receive error below

openthread/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_imm_ack_generator.c:72:1: fatal error: opening dependency file …/…/build/target/openthread/platform-12-/./openthread/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_imm_ack_generator.o.d: No such file or directory
}
^
compilation terminated.

If go to “Project.INO” tab and then compile it compiles successfully. The code however does not run.

Thanks again for any assistance given.

Have a look at the particle serial inspect output of the misbehaving devices and compare with a working one.
They might require a SoftDevice update.

1 Like

I had some issue with RF Connect app, Adafruit BLE app worked better. I also did a full load of the Device OS including SoftDevice.

Tried the suggestions. particle serial inspect shows differences on
User Module one is v5 (misbehaving) and one v6 (working)
NCP module one is v 5 (misbehaving) and the other v3 (working)

. Adafruit BLE has the same results it does not connect to the misbehaving devices. Both apps does show the batt service but as soon as you connect it disconnects with invalid handle.
using OS v1.4.4

I ran particle update I dont know if this updates the soft device as well

Decided to compare using nrf_Programmer. Definitely not the same. Once I copied the working hex file across I can connect again. I will try the same with the Xenons tonight. Thank you for the assistance.

Morning. Looks like im back at square 1. Copying the code from working Xenons and Argons did not revive the misbehaving ones. I did notice this morning that I can connect to the misbehaving ones when they are in listening mode. In listening mode strangely they all show the Batt service and the char value of the batt.
image