Hi, I am working with Arduino Nano 33 BLE. I have a code that sends data to an app via Bluetooth successfully but fails after a few reads and gives "error 133(0X85) GATT error".
C++:
//#include "mbed.h"
#include <Arduino_LPS22HB.h>
#include <Arduino_LSM9DS1.h>
#include <PDM.h>
#include <Arduino_APDS9960.h>
#include <Arduino_HTS221.h>
#include "ble/BLE.h"
//#define BLE_ROLE_PERIPHERAL;
//#include "events/EventQueue.h"
using namespace mbed;
/*------------GLOBAL VARIABLES-------------*/
const static char DEVICE_NAME[] = "SMARTSOLE"; // Device name when detected on Bluetooth
static events::EventQueue event_queue(10 * EVENTS_EVENT_SIZE); // Create Event queue
static const uint16_t MAX_ADVERTISING_PAYLOAD_SIZE = 78; // Advertising payload parameter
const ble::phy_set_t CodedPHY(ble::phy_t::LE_CODED); // Creating a Coded Phy set
static const uint16_t uuid16_list[] = {0xFFFF}; //Custom UUID, FFFF is reserved for development
const float analogInPin1 = A0; // change here to read another analog input
const float analogInPin2 = A1;
const float analogInPin3 = A2;
float voltage1, voltage2, voltage3;
float senseAve1,senseAve2,senseAve3;
float vout1,vout2,vout3;
float ForcePos1, ForcePos2, ForcePos3;
float cf = 2032.5203; // calibration factor
float GND_CONTACT_T = millis();
float weight1,weight2,weight3;
uint16_t force2ServiceUUID = 0xA005;
uint16_t forceServiceUUID = 0xA000;
// position1FCharUUID = 0xA001;
//uint16_t position2FCharUUID = 0xA002;
#define POSITION1FCharUUID "1A3AC130-31EE-758A-BC50-54A61958EF81"
#define POSITION2FCharUUID "FE4E19FF-B132-0099-5E94-3FFB2CF07940"
uint16_t position3FCharUUID = 0xA003;
#define BLE_UUID_TEST_SERVICE "9A48ECBA-2E92-082F-C079-9E75AAE428B1"
#define BLE_UUID_ACCELERATION "2713"
//#define BLE_UUID_POSITION1F "1A3AC130-31EE-758A-BC50-54A61958EF81"
//#define BLE_UUID_POSITION2F "FE4E19FF-B132-0099-5E94-3FFB2CF07940"
const char* deviceServiceUuid = "19b10000-e8f2-537e-4f6c-d104768a1214";
/* Set Up custom Characteristics */
static uint8_t readValue[10] = {weight1};
ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(POSITION1FCharUUID, readValue,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
static uint8_t writeValue[11] = {weight2};
WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(POSITION2FCharUUID, writeValue);
/* Set up custom service */
//GattCharacteristic *characteristics[] = {&writeChar};
GattCharacteristic *characteristics[] = {&readChar, &writeChar};
GattService forceService(forceServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
//void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
//{
// BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
//}
class LRDemo : public ble::Gap::EventHandler {
public:
// /* Class constructor */
LRDemo(BLE &ble, events::EventQueue &event_queue) :
_ble(ble), // BLE API Class
_event_queue(event_queue),
_service_uuid("b77a2543-ddc5-4e16-8955-15a29123e4e0"),
_data_service(_service_uuid, _data_service_characteristics, 4),
//_adv_handle(ble::INVALID_ADVERTISING_HANDLE), // Advertising parameter
_adv_data_builder(_adv_buffer),
characteristic1("b77a2543-ddc5-4e16-8955-15a29123e4e4"),
characteristic2("b77a2543-ddc5-4e16-8955-15a29123e4e2"),
characteristic3("b77a2543-ddc5-4e16-8955-15a29123e4e3"),
characteristic4("b77a2543-ddc5-4e16-8955-15a29123e4e4")
{
_data_service_characteristics[0] = &characteristic1;
_data_service_characteristics[1] = &characteristic2;
_data_service_characteristics[2] = &characteristic3;
_data_service_characteristics[3] = &characteristic4;
} // Advertising parameter
/* Class destructor */
~LRDemo() {
if (_ble.hasInitialized()) {
_ble.shutdown();
}
}
void start() {
_ble.gap().setEventHandler(this); // Assign GAP events to this class
_ble.init(this, &LRDemo::eek:n_init_complete); // Initialize Bluetooth
_event_queue.dispatch_forever(); // Wait for event forever
}
private:
/** Callback triggered when the ble initialization process has finished */
void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
if (params->error != BLE_ERROR_NONE) {
Serial.println("Ble initialization failed.");
delay(100);
return;
}
Serial.println("Ble initialized.");
_ble.gattServer().onUpdatesEnabled(
makeFunctionPointer(this, &LRDemo::when_update_enabled));
// _ble.gattServer().onUpdatesDisabled(
// makeFunctionPointer(this, &LRDemo::when_update_disabled));
ble_error_t err = _ble.gattServer().addService(_data_service);
if (err) {
Serial.println("Error %u during demo service registration");
return;
}
//_ble.gap().startScan(ble::scan_duration_t(500));
start_advertising();
}
void when_update_enabled(GattAttribute::Handle_t handle) {
currentCount = 0;
Serial.println("update enabled on handle");
if (_update_sensor_event == 0) {
_update_sensor_event = _event_queue.call_every(
250 /* ms */, callback(this, &LRDemo::update_sensor_value));
Serial.println("BNO Reader started");
delay(250);
}
}
/**
Handler called after a client has cancelled his subscription from
notification or indication.
[USER=120004]@Param[/USER] handle Handle of the characteristic value affected by the change.
*/
void when_update_disabled(GattAttribute::Handle_t handle) {
Serial.println("update disabled on handle");
if (_update_sensor_event != 0) {
_event_queue.cancel(_update_sensor_event);
Serial.println("Counter:");
_update_sensor_event = 0;
}
}
void start_advertising()
{
/* Create advertising parameters and payload */
ble::AdvertisingParameters adv_parameters(
ble::advertising_type_t::CONNECTABLE_NON_SCANNABLE_UNDIRECTED, // Advertising Type here : connectable non scannable undirected = connectable with exetended advertising
ble::adv_interval_t(ble::millisecond_t(500)), // Min Advertising time in ms
ble::adv_interval_t(ble::millisecond_t(500)), // Max Advertising time in ms
false // Legacy PDU : Needed to be OFF in Long Range Mode
);
adv_parameters.setPhy(ble::phy_t::LE_CODED, ble::phy_t::LE_CODED); // Set Advertising radio modulation to LE_CODED Phy (=Long Range)
adv_parameters.setTxPower(8); // Set radio output power to 8dbm (max)
_ble.gap().setPreferredPhys(&CodedPHY, &CodedPHY); // Set preferred connection phy to LE_CODED (=long range)
/* now we set the advertising payload that gets sent during advertising without any scan requests */
//_adv_data_builder.clear();
_adv_data_builder.setFlags();
_adv_data_builder.setName(DEVICE_NAME);
/* Setup advertising */
_ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
_ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
/* Add our custom service */
// _ble.addService(forceService);
//
_ble.gap().startAdvertising();
}
void update_sensor_value() {
HTS.begin();
BARO.begin();
IMU.begin();
APDS.begin();
float pressure = BARO.readPressure();
int numReads = 50;
float senseSum1 = 0;
int senseSum2 = 0;
int senseSum3 = 0;
for(int k = 0; k < numReads; k++) {
senseSum1 += analogRead(A0);
delay(1);
senseSum2 += analogRead(A1);
delay(1);
senseSum3 += analogRead(A2);
delay(1);
}
bool accelAvailable;
float accelX = -1;
float accelY = -1;
float accelZ = -1;
if ((accelAvailable = IMU.accelerationAvailable())) {
IMU.readAcceleration(accelX, accelY, accelZ);
}
bool gyroAvailable;
float gyroX = -1;
float gyroY = -1;
float gyroZ = -1;
if ((gyroAvailable = IMU.gyroscopeAvailable())) {
IMU.readGyroscope(gyroX, gyroY, gyroZ);
}
bool magAvailable;
float magX = -1;
float magY = -1;
float magZ = -1;
if ((magAvailable = IMU.magneticFieldAvailable())) {
IMU.readMagneticField(magX, magY, magZ);
}
float senseAve1 = senseSum1 / numReads;
float senseAve2 = senseSum2 /numReads;
float senseAve3 = senseSum3 /numReads;
vout1 = (senseAve1 * 5.0) / 1056;
vout2 = (senseAve2 * 5.0) / 1056.0;
vout3 = (senseAve3 * 5.0) / 1056.0;
ForcePos1= vout1 * cf ;
ForcePos2 = vout2 *cf;
ForcePos3 = vout3 *cf;
float altitude = 44330 * ( 1 - pow(pressure/101.325, 1/5.255) );
++currentCount;
float first[5];
float second[5];
float third[5];
float forth[5];
first[0] = HTS.readTemperature();
first[1] = HTS.readHumidity();
first[2] = altitude;
first[3] = 0;
second[0] = ForcePos1;
second[1] = ForcePos2;
second[2] = ForcePos3;
second[3] = GND_CONTACT_T;
third[0] = accelX;
third[1] = accelY;
third[2] = accelZ;
third[3] = 0;
forth[0] = magX;
forth[1] = magY;
forth[2] = magZ;
Serial.print("Weight1");
Serial.println (first[ ]);
//memcpy(second, first, sizeof(second));
//memcpy(third, first, sizeof(third));
//memcpy(forth, first, sizeof(forth));
//memcpy(second, first, sizeof(second));
//memcpy(third, first, sizeof(third));
// memcpy(forth, first, sizeof(forth));
characteristic1.set(_ble.gattServer(), first);
characteristic2.set(_ble.gattServer(), second);
characteristic3.set(_ble.gattServer(), third);
characteristic4.set(_ble.gattServer(), forth);
}
private:
// /* Event handler */
void
onConnectionComplete(const ble::ConnectionCompleteEvent &event) override {
//_ble.gap().startScan(ble::scan_duration_t(500));
Serial.print("Connection Interval: %d, Connection Latency: %d, Supervison ");
delay(100);
// "Timeout %d\n");
// Serial.print ( event.getConnectionInterval().valueInMs());
// Serial.print (event.getConnectionLatency().value());
// Serial.print (event.getSupervisionTimeout().valueInMs());
// Serial.println("MIN: Connection Interval: %d, Connection Latency: %d, "
// "Supervison Timeout %d\n");
// Serial.println (event.getConnectionInterval().min().valueInMs());
//// event.getConnectionLatency().min(),
//// event.getSupervisionTimeout().min().valueInMs());
// Serial.println("MAX: Connection Interval: %d, Connection Latency: %d, "
// "Supervison Timeout %d\n");
//// event.getConnectionInterval().max().valueInMs(),
//// event.getConnectionLatency().max(),
//// event.getSupervisionTimeout().max().valueInMs());
//
// auto toConnIntervalTTime = [](int timeInMs) {
// return (timeInMs * 1000) / ble::conn_interval_t::TIME_BASE;
// };
//
// auto err = _ble.gap().updateConnectionParameters(
// event.getConnectionHandle(), event.getConnectionInterval().min(),
// event.getConnectionInterval().min(), event.getConnectionLatency(),
// event.getSupervisionTimeout());
// Serial.println("Error: %d");
// Serial.println( err);
}
void
onDisconnectionComplete(const ble::DisconnectionCompleteEvent &) override {
delay(250);
_ble.gap().startAdvertising();
delay(100);
}
private:
/* Class variables declaration*/
BLE &_ble;
events::EventQueue &_event_queue;
UUID _service_uuid;
GattCharacteristic *_data_service_characteristics[4];
// demo service
GattService _data_service;
GattServer *_server;
int _update_sensor_event = 0;
uint8_t _adv_buffer[MAX_ADVERTISING_PAYLOAD_SIZE]; // Advertising parameters
ble::advertising_handle_t _adv_handle; //
ble::AdvertisingDataBuilder _adv_data_builder;
class NotifyFloatCharacteristic : public GattCharacteristic {
public:
NotifyFloatCharacteristic(const UUID &uuid)
: GattCharacteristic(
/* UUID */ uuid,
/* Initial value */ {0},
/* Value size */ sizeof(float) * 5,
/* Value capacity */ sizeof(float) * 5,
/* Properties */
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | BLE_GATT_CHAR_PROPERTIES_READ,
/* Descriptors */ NULL,
/* Num descriptors */ 0,
/* variable len */ false) {}
ble_error_t set(GattServer &server, const float value[5]) const {
return server.write(getValueHandle(), (uint8_t *)value, sizeof(float) * 5,
false);
}
};
NotifyFloatCharacteristic characteristic1;
//delay(250);
NotifyFloatCharacteristic characteristic2;
//delay(250);
NotifyFloatCharacteristic characteristic3;
//delay(250);
NotifyFloatCharacteristic characteristic4;
//delay(250);
int currentCount = 0;
};
/** Schedule processing of events from the BLE middleware in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
}
/*====================== MAIN CODE ======================*/
int main() {
Serial.begin(9600);
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
Serial.print("Starting BLE Server\n");
LRDemo demo(ble, event_queue);
// Starting delay - 100 msec
// Delay between each evet - 200msec
demo.start();
return 0;
}
void setup(){
/* Setup Debugging */
Serial.begin(9600);
// while(!Serial);
//
// /* Low Power */
// digitalWrite(LED_PWR, LOW); // Turn off power LED
// digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW); // Turn off sensors
// NRF_POWER->DCDCEN = 0x00000001; // Enable DCDC
// /* */
//
// BLE &ble = BLE::Instance(); // Create the BLE object in order to use BLE_API function
// ble.onEventsToProcess(schedule_ble_events); // Set event schedule
//
// LRDemo demo(ble, event_queue); // Create LRDemo Object
// demo.start(); // Start Bluetooth Long Range
// delay(100);
}
void loop(){}
/*=======================================================*/
Last edited by a moderator: