arduino / ArduinoCore-primo

Arduino core for nrf52 cpu
39 stars 34 forks source link

Indications stop working shortly after starting #62

Open ghost opened 6 years ago

ghost commented 6 years ago

I wasn't sure which repo to log this against. I've logged the same issue against the BLEPeripheral API here:

https://github.com/sandeepmistry/arduino-BLEPeripheral/issues/204

To repeat: I'm using a Primo and I'm transmitting temperature measurement characteristic values as indications. Consistently however, the first few calls to setValue return true, the client receives and ACKs the indication and I see the packets in flight. After a few successes (7 in my most recent test) however, setValue starts to return false and does not return to true responses unless I disconnect and reconnect.

Examples:

Protocol analyser showing 7 indications sent and ACKed

image

Serial monitor tracing indication values and API responses:

image

What could be causing indications to stop and is there a recommended way of getting to the root cause?

ghost commented 6 years ago

I wrote a very simple sketch to try to isolate this problem, with temperature measurement values simulated. Nothing is connected to any of the Arduino Primo pins during testing. I find that after 7 indications have been successfully transmitted and acknowledged, the setValue API starts to return false, meaning it failed and the connected client (nRF Connect) no longer receives indications. This happens completely consistently after 7 indications, every time I test.

Here's the code:

/*
Implements a test version of the health thermometer profile
Temperature measurements are simulated
Purpose is to allow investigation of https://github.com/sandeepmistry/arduino-BLEPeripheral/issues/204
*/
#include <SoftwareSerial.h>

int thermistorPin = 2;

// temperature
int temperature_subscribed = 0;
float celsius = 0.00;
int celsius_times_10;
unsigned long timestamp;

// bluetooth
#if defined(ARDUINO_ARC32_TOOLS)
// Arduino 101 Bluetooth library
#include <CurieBLE.h>
#elif defined(ARDUINO_NRF52_PRIMO)
// Arduino Primo Bluetooth library
#include <BLEPeripheral.h>
#else
// Other - defaulting to BLEPeripheral.h which may or may not work. If you're using a board other than Primo or 101 you
// may need to do some tinkering.
#include <BLEPeripheral.h>
#endif

// BLE objects
BLEPeripheral blePeripheral;

// GAP properties
char device_name[] = "THERM";

// Characteristic Properties
unsigned char HealthThermometer_TemperatureMeasurement_props = BLEIndicate | 0;

// Services and Characteristics
BLEService HealthThermometer("1809");
BLECharacteristic HealthThermometer_TemperatureMeasurement("2A1C", HealthThermometer_TemperatureMeasurement_props, 20);

float simulateTemperature()
{
  celsius = celsius + 0.1;
  return celsius;
}

void setup(void)
{
  Serial.begin(115200);
  Serial.println(F("Arduino setup"));

  // set advertising packet content
  blePeripheral.setLocalName(device_name);
  blePeripheral.setDeviceName(device_name);
  blePeripheral.setAdvertisedServiceUuid("1809");

  // add services and characteristics
  blePeripheral.addAttribute(HealthThermometer);
  blePeripheral.addAttribute(HealthThermometer_TemperatureMeasurement);

  // establish event handlers for indication subscription/unsubscription
  HealthThermometer_TemperatureMeasurement.setEventHandler(BLESubscribed, temperatureSubscribed);
  HealthThermometer_TemperatureMeasurement.setEventHandler(BLEUnsubscribed, temperatureUnsubscribed);

#if defined(ARDUINO_NRF52_PRIMO)
  // Arduino Primo Bluetooth library
  removeDfuService(true);
#endif

  // begin advertising
  blePeripheral.begin();
  Serial.println("advertising");

  // set timestamp which we use for periodic temperature indications
  timestamp = millis();

}

void loop()
{
  // listen for BLE peripherals to connect:
  BLECentral central = blePeripheral.central();

  // if a central is connected to peripheral:

  if (central) {
    // while the central is still connected to peripheral:
    while (central.connected()) {
      if (temperature_subscribed == 1) {
        if ((millis() - timestamp) >= 1000) {
          celsius = simulateTemperature();
          celsius_times_10 = celsius * 10;
          timestamp = millis();
          unsigned char value[5] = {0,0,0,0,0};
          value[4] = 0xFF; // exponent of -1
          value[3] = (celsius_times_10 >> 16) & 0xFF;
          value[2] = (celsius_times_10 >> 8) & 0xFF;
          value[1] =  celsius_times_10 & 0xFF;
          Serial.print(value[0]);
          Serial.print(",");
          Serial.print(value[1]);
          Serial.print(",");
          Serial.print(value[2]);
          Serial.print(",");
          Serial.print(value[3]);
          Serial.print(",");
          Serial.print(value[4]);
          Serial.println(",");

          Serial.print(celsius);
          Serial.println(" degrees C");
          int res = HealthThermometer_TemperatureMeasurement.setValue(value,5);
          Serial.print("setValue response=");
          Serial.println(res);
        }
      }
    }
    celsius = 0.00;
  }
}

void temperatureSubscribed(BLECentral& central, BLECharacteristic& characteristic) {
  Serial.println(F("subscribed to temperature indications"));
  temperature_subscribed = 1;
}

void temperatureUnsubscribed(BLECentral& central, BLECharacteristic& characteristic) {
  Serial.println(F("unsubscribed from temperature indications"));
  temperature_subscribed = 0;
}

and here's the serial monitor content:

subscribed to temperature indications
0,1,0,0,255,
0.10 degrees C
setValue response=1
0,2,0,0,255,
0.20 degrees C
setValue response=1
0,3,0,0,255,
0.30 degrees C
setValue response=1
0,4,0,0,255,
0.40 degrees C
setValue response=1
0,5,0,0,255,
0.50 degrees C
setValue response=1
0,6,0,0,255,
0.60 degrees C
setValue response=1
0,7,0,0,255,
0.70 degrees C
setValue response=1
0,8,0,0,255,
0.80 degrees C
setValue response=0
0,9,0,0,255,
0.90 degrees C
setValue response=0
0,10,0,0,255,
1.00 degrees C
setValue response=0
0,11,0,0,255,
1.10 degrees C
setValue response=0
0,12,0,0,255,
1.20 degrees C
setValue response=0
0,13,0,0,255,
1.30 degrees C
setValue response=0
unsubscribed from temperature indications
ghost commented 6 years ago

Bump!

Is this library supported or not?

honnet commented 6 years ago

If you look at the commits by the organisation, nothing seems to have happened since the acquisition of arduino-org by arduino-cc. It was probably the best arduino (hardware & software), but it was maintained by a company, not a community, so they're probably nor going to support it anymore, sadly... ...but you can clone it and maintain it !

ghost commented 6 years ago

Thanks @honnet , good observation. Disappointing though!

honnet commented 6 years ago

The version maintained by @sandeepmistry & co is good, it looks like you know it but here is the link for others who don't: https://github.com/sandeepmistry/arduino-nRF5 They're open to discussion and it seems more reliable than a company ;)

ghost commented 6 years ago

Excellent, thank you. I'll give it a try.

ghost commented 6 years ago

https://github.com/sandeepmistry/arduino-nRF5 does not suffer from this issue (for anyone else having problems).