Skip to content

Forced to sleep mode after a while? #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexisicte opened this issue Nov 6, 2019 · 7 comments
Closed

Forced to sleep mode after a while? #41

alexisicte opened this issue Nov 6, 2019 · 7 comments

Comments

@alexisicte
Copy link

alexisicte commented Nov 6, 2019

Hello,
Configuration: Arduino ble 33 nano, cutted 3.3V jumper in order to supply with 3.3v direct to 3.3pin, soldered vusb jumper in order to have serial debug and re-flushing.

Here is my sketch:

#include <ArduinoBLE.h>
#include "LSM9DS1.h"
//Services
BLEService BatteryService("180F");
BLEService SensorService("92a041f8-69de-48ae-a610-6d2e54854fe0");
//Characteristics
BLEUnsignedCharCharacteristic batteryLevelChar("2A19", BLERead | BLENotify);
BLEStringCharacteristic accelerometer_data("abb6f371-c8d4-4c65-9470-140b686698bd", BLERead | BLENotify, 48);
BLEStringCharacteristic gyroscope_data("f1abb263-686f-4a5b-8a8f-39690d3f3020", BLERead | BLENotify, 48);
BLEStringCharacteristic debug_system("f1abb263-686f-4a5b-8a8f-39690d3f3020", BLERead | BLENotify, 48);

String values_to_send = " ";
float x_accel, y_accel, z_accel, x_gyro, y_gyro, z_gyro;
float x_accel_f, y_accel_f, z_accel_f, x_gyro_f, y_gyro_f, z_gyro_f = 0;
String debug_to_send = " ";

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

  pinMode(LED_PWR, OUTPUT);
  digitalWrite(LED_PWR, LOW);
  
  if (!lsm9ds1.begin()) {
    Serial.println("Failed to initialize lsm9ds1!");
    while (1);
  }
  lsm9ds1.init();// initialize sensors and parameters
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  // set advertised local name and service UUID:
  BLE.setLocalName(SENSOR_NAME);
  BLE.setAdvertisedService(BatteryService);
  BLE.setAdvertisedService(SensorService);
  // add the characteristic to the service
  BatteryService.addCharacteristic(batteryLevelChar);
  SensorService.addCharacteristic(accelerometer_data);
  SensorService.addCharacteristic(gyroscope_data);
  SensorService.addCharacteristic(debug_system);
  // add services
  BLE.addService(BatteryService);
  BLE.addService(SensorService);
  // start advertising
  BLE.advertise();
  Serial.println("BLE Peripheral");
}

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

  // if a central is connected to peripheral:
  if (central) {
    Serial.print("Connected to central: ");Serial.println(central.address());
    Serial.print("Acceleration binary status: "); Serial.println(lsm9ds1.read_accel_status(), BIN);
    Serial.print("Gyroscope binary status: "); Serial.println(lsm9ds1.read_gyro_status(), BIN);
    // print the central's MAC address:
    Serial.println(central.address());

    // while the central is still connected to peripheral:
    while (central.connected()) {
      if (lsm9ds1.accelerationAvailable()) {
        lsm9ds1.readAcceleration(x_accel, y_accel, z_accel);
        // set alpha to zero if you don't want to apply the low pass filter
        accelerometer_data.writeValue(low_pass_filter(x_accel, y_accel, z_accel, 0.01, 0));
      }
      if (lsm9ds1.gyroscopeAvailable()) {
        lsm9ds1.readGyroscope(x_gyro, y_gyro, z_gyro);
        gyroscope_data.writeValue(low_pass_filter(x_gyro, y_gyro, z_gyro, 0.01, 1));
      }
      updateBatteryLevel();
      update_temperature();
    }
    // when the central disconnects, print it out:
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
  BLE.advertise(); // start advertising again 
}
void updateBatteryLevel() {
  int batteryLevel = map(analogRead(A0), 612, 815, 0, 100);//815 is analog max
//  Serial.print("analogRead(A0): ");Serial.println(analogRead(A0));
//  Serial.print("batteryLevel: ");Serial.println(batteryLevel);
//  delay(250);
  batteryLevelChar.writeValue(batteryLevel);  // and update the battery level characteristic
}
void update_temperature() {
  debug_to_send = " ";
  lsm9ds1.read_system_temperature();
  debug_to_send += String(lsm9ds1.temperature) + "|";
  debug_to_send += String(analogRead(A0));
  debug_system.writeValue(debug_to_send);
}

String low_pass_filter(float x_axis, float y_axis, float z_axis, float alpha, int sensor) {
  values_to_send = " ";// re initialize array
  if (!sensor) { // sensor = accelerometer
    x_accel_f = alpha * x_accel_f + (1 - alpha) * x_axis;
    y_accel_f = alpha * y_accel_f + (1 - alpha) * y_axis;
    z_accel_f = alpha * z_accel_f + (1 - alpha) * z_axis;
    values_to_send += String(x_accel_f) + "|";
    values_to_send += String(y_accel_f) + "|";
    values_to_send += String(z_accel_f);
  }
  else {
    x_gyro_f = alpha * x_gyro_f + (1 - alpha) * x_axis;
    y_gyro_f = alpha * y_gyro_f + (1 - alpha) * y_axis;
    z_gyro_f = alpha * z_gyro_f + (1 - alpha) * z_axis;
    values_to_send += String(int(x_gyro_f)) + "|";
    values_to_send += String(int(y_gyro_f)) + "|";
    values_to_send += String(int(z_gyro_f));
  }
  return values_to_send;
}

In short the sketch creates services and characteristics and advertises it self. When a central is connected, i write some values on the characteristics. I am using nrf connect android app to debug the procedure.

Everything running smoothly expects when waiting for a central for "too long". I cannot specify "too long" time period yet, but i can say that is about 20-30 minutes.
When this time period exceeds, while my device still adverises and seeking for a connection, despite the fact that the device is discoverable and connectable, the central device cannot read its services. More specifically, it seems that the connection is made (i am assuming that because the application let me to disconnect from the device ) and tries to read the advertised services without a success. After a few seconds the connection is lost.

Bellow are the logs from the application. The error is "Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST"
Screenshot_20191107_092548_no nordicsemi android log

I am assuming that this is not a bug from the application because the same thing happens with other apps too. I believe that the device is going to sleep mode by default (i have to prove that by measuring the current). Despite that, the "library" should interact with radio signal and quit from sleep mode, if this is the case.

Does anyone experienced something similar?
Is it true that the device is forced to sleep mode? and if yes why central's cannot read its services?

P.S. I know that i have to power with 3.3v to 3.3v pin, but i am connecting 3.3v pin direct to lipo battery (4.2-3.2 V). I dont have a clue that this is the problem.

---------------UPDATE--------------
When the device is attached to usb the above problem never occurs.

@sandeepmistry
Copy link
Contributor

but i am connecting 3.3v pin direct to lipo battery (4.2-3.2 V). I dont have a clue that this is the problem.

This is not recommended at all from my knowledge! @pnndra @agdl any thoughts on this?

@sandeepmistry
Copy link
Contributor

When the device is attached to usb the above problem never occurs.

Have you tried to remove all the Serial.print statements in your sketch?

@alexisicte
Copy link
Author

alexisicte commented Nov 12, 2019

but i am connecting 3.3v pin direct to lipo battery (4.2-3.2 V). I dont have a clue that this is the problem.

This is not recommended at all from my knowledge! @pnndra @agdl any thoughts on this?

If i am reading the nano 33 ble board layout correctly, the 3.3v trace is "created" from the mpm3610 ic. The output pins from mpm3610 ic are generating the N$16 trace which is by default connected to 3.3v pin. But as i said at the beginning my configuration is "cutted 3.3V jumper". Therefore, i can say that the 3.3v pin is not actually 3.3v but unregulated battery voltage.

n$16_33v

Please correct me if i am reading in a wrong way the board layout.

Both nina module and lsm9ds1 sensor can be powered up to 3.6v regarding their datasheets. So, i am powering the board with max 4.2 down to 3.2. Powering the board with 3.2v the device is quite unstable but i can not say the same for 4.2v.
There is an 0.6v offset, which is for sure not recommended but the device seems to work properly. Therefore, i do believe that this is not the case here.

@alexisicte
Copy link
Author

alexisicte commented Nov 12, 2019

When the device is attached to usb the above problem never occurs.

Have you tried to remove all the Serial.print statements in your sketch?

Yes, i just try without any Serial method. Still the same error: Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST

-----------------UPDATED-------------
i have i clue that while(central.connected) is not working properly. If the connection goes down due to range issues or the central device crashes the arduino nano 33 ble is not "get" that.
I updated the sketch in order to force disconnect when while(central.connected) becomes false.

void loop() {
  BLE.advertise(); // start advertising again
  BLEDevice central = BLE.central();

  // if a central is connected to peripheral:
  if (central) {
    digitalWrite(LED_PWR, LOW);
    Serial.print("Connected to central: ");Serial.println(central.address());
    //Serial.print("Acceleration binary status: "); Serial.println(lsm9ds1.read_accel_status(), BIN);
    //Serial.print("Gyroscope binary status: "); Serial.println(lsm9ds1.read_gyro_status(), BIN);
    BLE.stopAdvertise();
    Serial.println("Stop advertising...");
    // while the central is still connected to peripheral:
    while (central.connected()) {
      if (lsm9ds1.accelerationAvailable()) {
        lsm9ds1.readAcceleration(x_accel, y_accel, z_accel);
        // set alpha to zero if you don't want to apply the low pass filter
        is_value_send = accelerometer_data.writeValue(low_pass_filter(x_accel, y_accel, z_accel, 0.01, 0));
      }
      if (lsm9ds1.gyroscopeAvailable()) {
        lsm9ds1.readGyroscope(x_gyro, y_gyro, z_gyro);
        gyroscope_data.writeValue(low_pass_filter(x_gyro, y_gyro, z_gyro, 0.01, 1));
      }
      update_battery_level();
      update_temperature();
    }
    central.disconnect();
    delay(100);
    // when the central disconnects, print it out:
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  } 
}

The strange thing is that the device advertise its self again (code line 2), which means that while(central.connected()) is false as it should be, but when a central device tries to connect, error 22 occurs. So, my assumption that the arduino doesn't understand that the connection is over, it is not correct, but at this stage the device is not able to make a connection again. This problem occurs also with usb attached.
It seems that the above is reported here, despite the fact that on this thread is mentioned only power loss.

Enabling BLE.debug(Serial) on normal procedures while disconnecting i get

15:51:11.032 -> HCI EVENT RX <- 04050400000013
15:51:11.076 -> HCI COMMAND TX -> 010A200101
15:51:11.076 -> HCI EVENT RX <- 040E04010A2000

which is missing when the connection goes down from range issues or central device crash or forced shut down.

@sandeepmistry
Copy link
Contributor

@alexisicte ok, so do you think this is a duplicate of issue #33 now?

@pnndra
Copy link

pnndra commented Nov 15, 2019

Hi,
Powering the board directly from battery is not correct. The maximum operating voltage is 3.6v and while this is more or less the voltage a battery will output most of the time, the 4.2v voltage of a fully charged battery WILL damage the board and produce unpredictable results.
Note also that when battery is at or below 3.3v it is basically deleted. This means that drawing current from it will likely damage it in the long term. In any case, when the battery is discharged it won't be able to withstand current spikes and when these happen the voltage will drop significantly. With a multimeter you won't see this as it averages measurements but while Nina usually consumes almost nothing when idle, it will require requires several mA for a very short time and this will likely cause voltage to drop enough to go below allowed voltage.
If you plan to have a very low power application I would recommend using a ldo with low quiescent current so that most of the time it won't consume almost anything (Nina can go down to about 5uA which makes less than 5 uW, not including ldo's iq) it won't impact battery life significantly but will stabilize the board. I would also recommend using a voltage monitor that cuts off battery when voltage drops below 3.3v as this will save your battery from overdischarge.

@alexisicte
Copy link
Author

@pnndra , @sandeepmistry Many thanks for your input and advices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants