This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE Button low power

Hello fellow developers,

I am new to BLE applications and I am trying to do a very simple device with three buttons that informs a Android smartphone when one has been pressed. So far, I got everything running: the android part, the nRF51822 application on mbed (BLE_Button) and so far everything connects and every time I press the button the application shows the notification :-D

The problem comes with the power consumption: it's around 0.60 uA when advertising (which seems OK to me) and rises to 160-200 uA when the device is paired with the Android application. I wonder if there is a way to drop that consumption when the device is connected to lower values as it seems to be pretty high to me.

Is there a way to configure the device to sleep as much as possible, while keeping the communication channel open and wake up only to send the notification? Should that configuration be done in the Android part or in the nRF51 code?

If it's not possible to lower the power consumption when connected: would it be a better solution to sleep the device and wake up to send Beacons/GAP to the central device and then sleep again. The information I have to transmit is little enough to fit in that model, I just don't know if it is a valid solution architecture (delivery is not guaranteed).

I have tried by reducing the latency but I did not get any changes. Maybe I need to change something on the Android application? Should these parameters be changed before starting the advertisement or when the device has been connected?

Gap::ConnectionParams_t new_params;

ble.gap().getPreferredConnectionParams(&new_params);

new_params.minConnectionInterval = BLE_GAP_CP_MIN_CONN_INTVL_MAX;
new_params.maxConnectionInterval = BLE_GAP_CP_MAX_CONN_INTVL_MAX;
new_params.slaveLatency = BLE_GAP_CP_SLAVE_LATENCY_MAX;
new_params.connectionSupervisionTimeout = BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX;

ble.gap().setPreferredConnectionParams(&new_params);

Thanks all for your time. Best regards,

P/S: I am not tied to mbed development and I'm OK with trying different APIs or examples if you think that the power consumption would be lower (how little should it be? around 10 uA?).

  • 0.6 uA is only achievable in SYSTEM OFF. In this state the chip can only be woken up from a pin change, by the LPCOMP, or from a reset. It will not go to SYSTEM OFF between advertisements. In SYSTEM ON the minimum current you should see between advertisements should be something like 2.6 uA. In your second comment you talk about using a button to start advertising, this button can be used to go from SYSTEM OFF to SYSTEM ON, then 0.6 uA is achievable. From a power consumption perspective you solution is very valid, if your application can live with the latency.

  • If you don't enter a connection you need to put your data into advertising/scan response packets. These will not be acknowledged. Then you need to build your ack mechanism into your application. I'm not sure you are familiar with scan request/scan response. Anyways, if the central does active scanning it sends scan requests when it receives an advertising packet, then the peripheral can send a scan response with additional data. You may be able to use this to make an ack mechanism, where an advertising packet is acked with a scan request, but I don't recommend doing this. I'm not sure if you are doing bonding now, but if not, I would look into that, so that the GATT client on the central avoids doing a service discovery on every connection.

  • I've been playing a little with a Linux machine and gatttool, hcitool, and hcidump and I have done some great progress. As Petter pointed out, the problem was in the connection intervals. The hcidump output when connected to my device showed:

    2015-07-27 13:58:47.398017 < HCI Command: LE Create Connection (0x08|0x000d) plen 25
        bdaddr C3:C5:C1:B5:CE:6B type 1
        interval 96 window 48 initiator_filter 0
        own_bdaddr_type 0 min_interval 40 max_interval 56
        latency 0 supervision_to 42 min_ce 0 max_ce 0
    

    Then with the hcitool lecup commands described in this comment I was able to update the connections lowering the current consumption. After that, I changed the mbed code to update the parameters when it connects.

  • Now I have some problems with the connection parameters, sometimes I get an OUT_OF_RANGE error and I don't get why. The following works:

    new_params.minConnectionInterval = 304 ;
    new_params.maxConnectionInterval = 320;
    new_params.slaveLatency = 5;
    new_params.connectionSupervisionTimeout = 600;
    

    But this one doesn't:

    new_params.minConnectionInterval = BLE_GAP_CP_MIN_CONN_INTVL_MAX; //0xC80
    new_params.maxConnectionInterval = BLE_GAP_CP_MAX_CONN_INTVL_MAX; //0xC80
    new_params.slaveLatency = BLE_GAP_CP_SLAVE_LATENCY_MAX; //0x1F3
    new_params.connectionSupervisionTimeout = BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX; //0xC80
    

    If I lower the Latency to 2 it works but it always disconnects after 32 seconds. I guess there are some formulae that I'm missing for validating the parameters. It seems that the key is in the latency, I would like it to be as high as possible.

  • Answering to myself. According to this mbed Wiki Page the constrain is: (conn_sup_timeout * 8) >= (max_conn_interval * (slave_latency + 1)) However, it seems to refer to softdevice S110 while in mbed IDE it seems to be using S130. In S130 I can't find any reference to this constrain, but it seems that it's been changed to conn_sup_timeout * 4 instead of conn_sup_timeout * 8, but it's an empirical finding. So far, it's good to me. When I have something more stable (and less ugly) I'll share both an mbed and Android projects.

Related