I have a Arduino Nano 33 BLE and I am trying to read the onboard accelerometer quickly (100Hz) and using a mbed::Ticker to control the read of the sensor. The code works as expected when I have a “dummy” routine simulating the accelerometer reading.
The problem occurs as soon as the Ticker callback (named TimerHandler0 in code below) tries to read the accelerometer. Immediately the BLE disconnects and the program hangs. I am out of ideas as to why BLE would disconnect when I try to read the onboard LSM9DS1 accelerometer.
Code below and if you have any ideas to help troubleshoot it would be GREATLY appreciated.
#include <Arduino.h>
#include <ArduinoBLE.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Arduino_LSM9DS1.h>
#define TIMER_INTERRUPT_DEBUG 0
#define _TIMERINTERRUPT_LOGLEVEL_ 3
#include "NRF52_MBED_TimerInterrupt.h"
#include <mbed.h>
//----------------------------------------------------------------------------------------------------------------------
// CONSTANTS
//----------------------------------------------------------------------------------------------------------------------
#define SAMPLE_RATE 100 // ms Delay. How often do we read and update BLE data.
#define TIMER0_DURATION_MS 500 //How often the Timer loop will actually go in and check # of pts read and see if it's done
#define NUMPTS_BURSTMODE 20 //Numer of points to record when in burst mode
#define NUMPTS_BURST_PERSEND 10 //Number of points to send per write to characteristic.
// * because you can't send them all at once with 244 bytes limit per send.
// * normally don't need to change this unless the struct size changes
//----------------------------------------------------------------------------------------------------------------------
// STRUCTURE DEFINITION
// Note: The unpacking in Python needs to match the byte configuration of the struct here.
//----------------------------------------------------------------------------------------------------------------------
typedef struct __attribute__ ((packed)) {
unsigned long timeread;
int ax;
int ay;
int az;
}sensordata ;
sensordata d;
//----------------------------------------------------------------------------------------------------------------------
// TIMER SETUP AND BURST MODE CONFIG
//----------------------------------------------------------------------------------------------------------------------
//Define array of structs for BURST MODE
sensordata burstdata[NUMPTS_BURSTMODE];
sensordata *burstdataptr=&burstdata[0] ;
// Init MBED Timer
mbed::Ticker mytimer;
volatile uint32_t preMillisTimer0 = 0;
volatile u_int16_t ptsread=0; // Initialize pt counter
bool toggle0 = false;
unsigned long lastTimer=0;
unsigned long previousMillis = 0; // last time the reading was done, in ms
// *************** DEFINITION OF MBED TIMER HANDLER ****************
void TimerHandler0(){
//preMillisTimer0 = millis();
if (ptsread<NUMPTS_BURSTMODE) {
// ********************************************************************
// ***** PROBLEM: THE REAL SENSOR READ BELOW FAILS ****
// ********************************************************************
//*burstdataptr=readSensorDataAsStruct();
**// The dummy sensor read works. WHY ??????**
*burstdataptr=dummyread();
//Increment pointer
++burstdataptr;
//Increment points read
++ptsread;
} //end if
}
// ********************** PORTION OF MAIN LOOP **************************************
void loop() {
if (currentopmode==true) {
// Start the timer
// Try MBED Ticker
//Now attach interrupt to MBED so it can start
mytimer.attach(&TimerHandler0, SAMPLE_RATE/1000.);
while (true ){
if (millis()-lastTimer > TIMER0_DURATION_MS){
lastTimer=millis();
if(ptsread==NUMPTS_BURSTMODE){
//ITimer0.stopTimer();
mytimer.detach();
BLE.poll();
//** Write array to bluetooth
// Break Array into chunks to send that are under the max limit of 244 bytes.
int packetbytes=NUMPTS_BURST_PERSEND*sizeof(sensordata);
//Initialize pointer
sensordata *loopptr=&burstdata[0];
sensordata *loopend=loopptr+NUMPTS_BURSTMODE;
//Send update to Bluetooth
//Original command tried to send all data at once.
// * Exceeds the max allowable of 244 bytes per send. Look in github
// * or in source code for MTU and maxlength.
// burstmodestructDataChar.writeValue( (uint8_t *) &burstdata, sizeof(burstdata) );
while (loopptr!=loopend){
//Serial.print("pointer val=");
//Serial.println((int)loopptr);
burstmodestructDataChar.writeValue( (uint8_t *) loopptr, packetbytes );
Serial.print("Burst Mode: Write to: ");
Serial.print((unsigned long)loopptr);
Serial.println(" successful");
//Increment pointer
loopptr+=NUMPTS_BURST_PERSEND;
}//end while
BLE.poll(); //TODO Not sure if this is needed??
//** Reset pointers and counter
ptsread=0;
//loopptr=&burstdata[0];
burstdataptr=&burstdata[0];
//** restart timer
//ITimer0.restartTimer();
mytimer.attach(&TimerHandler0, SAMPLE_RATE/1000.);
}//End Burst mode point check
} //end Time duration check
}//end while NRF52 Run
} // end Burst mode
} //end if Central connected
}// End Loop() function
// ********************** SUPPORT FUNCTIONS **************************************
sensordata readSensorDataAsStruct(){
/* Read the current data values.
Returns a Struct with the data. */
// Initialzie
float ax,ay,az;
unsigned long tnow=millis();
// **********************************************************
// ***** This is the sensor read that appears to cause the issue
// **********************************************************
IMU.readAcceleration(ax,ay,az);
//Declare struct and populate
//The scaler 10000 converts a float so it can be sent as an int.
//It will be decoded back to float on receiving side.
sensordata datareading;
datareading.timeread=tnow;
datareading.ax=(int) (ax*10000);
datareading.ay=(int) (ay*10000);
datareading.az=(int) (az*10000);
return datareading;
}