Open ghost opened 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
Bump!
Is this library supported or not?
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 !
Thanks @honnet , good observation. Disappointing though!
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 ;)
Excellent, thank you. I'll give it a try.
https://github.com/sandeepmistry/arduino-nRF5 does not suffer from this issue (for anyone else having problems).
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
Serial monitor tracing indication values and API responses:
What could be causing indications to stop and is there a recommended way of getting to the root cause?