ArduinoCore-arc32 icon indicating copy to clipboard operation
ArduinoCore-arc32 copied to clipboard

Jira 906 Device locks up using CurieIMU

Open khanning opened this issue 8 years ago • 15 comments

While testing the new 2.0.0/2.0.1 corelibs I have encountered a bug using the Curie IMU module. With the 101 in peripheral mode, if a BLE characteristic is written to from an external central device while using the IMU, the device will occasionally lock up requiring a reset.

I put together a simple test case by modifying the led example sketch to read from the IMU periodically. You can use the included ledtest.js node script to communicate with the Arduino.

led.ino ledtest.js

To test:

  1. Upload the led.ino to the Arduino 101 using either 2.0.0 or 2.0.1 corelibs
  2. Run npm install noble in the same directory as the ledtest.js file
  3. Execute node ledtest.js and wait for the device to lockup

Please let me know if you require any additional information.

khanning avatar Mar 23 '17 19:03 khanning

Thanks @khanning, we'll take a look.

Side Note: you don't need to handle the timing of CurieIMU reads, anymore-- there is a dataReady() method you can use now, e.g.

CurieIMU.dataReady(ACCEL);               // returns true if a new accel sample is available
CurieIMU.dataReady(GYRO);                // returns true if a new accel sample is available
CurieIMU.dataReady(ACCEL | GYRO);  // returns true if both are available......

eriknyquist avatar Mar 23 '17 20:03 eriknyquist

I was able to reproduce the issue using your peripheral sketch running with an Arduino101 central

russmcinnis avatar Mar 23 '17 20:03 russmcinnis

@eriknyquist @russmcinnis thanks for confirming the issue and for the note on the dataReady() method. Please let me know if there is anything else I can do to help with the issue.

khanning avatar Mar 24 '17 12:03 khanning

works with the dataReady() but we can still reproduce it with the change. I will see what Erik thinks.

russmcinnis avatar Mar 24 '17 16:03 russmcinnis

@russmcinnis

Did you observe any BLE advertisement prior to the lock up? You may need the Ellisys to monitor this... If you can't see any Adv Data packets, you may want to modify the sketch to have control over when the IMU starts. Let see how the two modules affect each other. Thanks.

SidLeung avatar Mar 24 '17 16:03 SidLeung

@khanning @eriknyquist @SidLeung I have the test running with the Ellisys scanning. I am using our latest corelibs and I haven't been able to reproduce the failure. It was failing within a few minutes last week on previous corelibs. I will let this run for a while longer and report back.

russmcinnis avatar Mar 31 '17 18:03 russmcinnis

issue495.zip

Finally crashed it. Ellisys trace attached. @khanning @eriknyquist @SidLeung The peripheral that crashed has address: 98:4F:EE:0C:0E:DE and local name LED. Looks like the write request packet is missing from the last write transaction. The test was just staying connected and alternating writiing 0x0 and 0x1 every 1 second from the central to the peripheral that is using IMU and BLE.

russmcinnis avatar Mar 31 '17 19:03 russmcinnis

tracked by jira 906

russmcinnis avatar Mar 31 '17 19:03 russmcinnis

I have been checking this issue and the workaround I have found is to use interruptions. Unfortunately, it's not suitable for my case.

The arduino sketch and test can be found at: imu_ble.ino

~~I have also try to read the IMU values surrounded by noInterrupts() and interrups() but no luck.~~

Hope this information rings a bell to someone :)

aitorhh avatar Apr 19 '17 18:04 aitorhh

I did some more experiments with IMU and BLE, but anyway, here are some ?conclusions?:

  • noInterrups()/interrupts() helps to postpone the crash

Here is the code I used for the testing, arduino sketch and nodejs script.

Sampling control with setAccelerometerRate()/setGyroRate() without protecting the readMotionSensor() with noInterrupts()/`interrupts():

  • Sampling rate == 25 Hz no crash within
  • Sampling rate > 25 Hz, crash in less than ~10s (1, 3, 11, 3, 3 s)

Sampling control with setAccelerometerRate()/setGyroRate() with protecting the readMotionSensor() with noInterrupts()/`interrupts():

  • Sampling rate <= 100 Hz no crash within at least 15h (900min)
  • Sampling rate > 200 Hz crash in less than ~1s

Using CurieTimer to trigger readMotionSensor() and handle on ISR:

  • Sampling rate <= 100 Hz no crash within at least 10min
  • Sampling rate > 200 Hz crash in less than ~1s

The problem on my previous comment was that I wasn't changing the sampling rate :S.

aitorhh avatar Apr 27 '17 15:04 aitorhh

Hi, @khanning,

The fact that the pre-release JSON is in staging, it is not ready for public consumption yet. The good news is that the release will soon be available.

SidLeung avatar May 04 '17 23:05 SidLeung

I'm having the same issue with a similar setup using BLE + IMU. I tried updating core-libs to 2.1.0 but I haven't seen big improvements; after a while, the 101 hangs and I have to force the reset.

I have the feeling that it stops working when too many events are called.

Here my code for reference:

#include <CurieBLE.h>
#include <Adafruit_NeoPixel.h>
#include "CurieIMU.h"


const int ledPin = 13; // set ledPin to on-board LED


BLEService accelerometerService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service

// create switch characteristic and allow remote device to read and write
BLECharCharacteristic shake_event_Characteristic("19B10011-E8F2-537E-4F6C-D104768A1214",BLERead | BLENotify);


void setup() {
  Serial.begin(9600);

   BLE.begin();

  // set the local name peripheral advertises
   BLE.setLocalName("curie");
  
  // set the UUID for the service this peripheral advertises
  BLE.setAdvertisedService(accelerometerService);

  // add the characteristic to the service
  accelerometerService.addCharacteristic(shake_event_Characteristic);

  // add service
  BLE.addService(accelerometerService);

  Serial.println("Bluetooth device active, waiting for connections...");

  shake_event_Characteristic.setValue(0);

  // start advertising
  BLE.advertise();

  CurieIMU.begin();
  CurieIMU.attachInterrupt(eventCallback);

  /* Enable Shock Detection */
  CurieIMU.setDetectionThreshold(CURIE_IMU_SHOCK, 1500); // 1.5g = 1500 mg
  CurieIMU.setDetectionDuration(CURIE_IMU_SHOCK, 50);   // 50ms
  CurieIMU.interrupts(CURIE_IMU_SHOCK);

  Serial.println("IMU initialisation complete, waiting for events...");
}

void loop() {
  BLE.poll();

}

static void eventCallback(void){
  if (CurieIMU.getInterruptStatus(CURIE_IMU_SHOCK)) {
      Serial.println("shake");
      shake_event_Characteristic.setValue(1);
   digitalWrite(ledPin, HIGH);
   delay(10);
   digitalWrite(ledPin, LOW);
  }
}




lorenzoromagnoli avatar May 05 '17 08:05 lorenzoromagnoli

Hi @SidLeung,

I just tried the 2.1.0 corelibs with the latest Arduino IDE (1.8.2) and the device still locked up within a few minutes using the led.ino and ledtest.js scripts above.

I did receive the message about the core being updated when I uploaded the led.ino script.

ATTENTION: RTOS firmware is being flashed
DO NOT DISCONNECT THE BOARD
. . . . . 
SUCCESS: Sketch will execute in about 5 seconds.

Please let me know if I can provide any more information.

Thank you.

khanning avatar May 05 '17 16:05 khanning

@SidLeung I am having the same issue, any updates on this?

PiotrDabkowski avatar Oct 13 '18 12:10 PiotrDabkowski

For the record the solution:

noInterrupts();
CurieIMU.readMotionSensor(aix, aiy, aiz, gix, giy, giz);
interrupts();

seems to work for me - I have not observed a single crash for ~1h and I am using 800Hz IMU update frequency. I am using it for a quadcopter so I hope it does not crash mid-air (especially that the PWM output stays the same!).

PiotrDabkowski avatar Oct 13 '18 13:10 PiotrDabkowski