Bluetooth module
The AirMobile sensor will communicate with the smartphone using a Bluetooth module. The obvious choice for an application that harvest energy from wasted heat should be to use a module that supports Bluetooth LE technology. However, because of the some difficulties in hardware design and because my smartphone is a bit old and does not support Bluetooth 4.0, I decided to use a common Roving RN42 module, which is easy to interface to an MCU thanks its UART interface
In order to optimize power consumption, I made some changes to the power management parameters
There are 5 methods to reduce power consumption:
Methods | Bluetooth states | Advantages | Disadvantages |
Optimize Inquiry (discovery) and Page (connection) window | Idle (Not Connected)or ActiveConnection | The current can be reduced from morethan 20 mA to less than 5 mA (combiningthis method with Sniff mode uses lessthan 3 mA). | Causes additional latencywhen pairing or connecting. |
Sniff Mode | TransmitActive Connection | This mode can be combined with theOptimize Inquiry (Discovery) and Page(Connection) Window or Enable DeepSleep methods for lower power consumption. | |
Enable Deep Sleep | Idle (Not Connected) | With this method, current is reduced to
| This method can causelatency issues and may dropthe first byte if the devicewakes on RX data. It alsocauses a loss of performance/power when thedevice wakes frequently. |
Disable Output Drivers | Idle (Not Connected)or ActiveConnection | This method is simple to use. However, itdepends on the load: if the device is notconnected there are no power savings.This method is required for Roving Networksevaluation boards to measurepower accurately. | External components drivenby GPIO pins may not work
|
Lower TransmitPower | Idle (Not Connected)or ActiveConnection | This method lowers power consumptionduring Txmt and active mode by reducingradio output power. | The device has a shortereffective range. |
Before selecting the proper approach for power saving, I had to define a bit more in details the protocol between the AirMobile sensor and the smartphone app.
I finally decided for a very simple protocol where (when connected) the AirMobile sensor sends out the value it got from the sensor. No buffering is going to be implemented if the app is not listening, because the AirMobile sensor has no way to provide neither a timestamp nor a location information. A value without such information is of no significance as it cannot be located anywhere in time and space and it will be simply be discarded
With this in mind, it's clear that
- the connection and pairing time is not very relevant
- the AirMobile sensor does not have to be actively listening for commands from AirMobile app and so it can be put to sleep when it has nothing to transmit
From this analysis, I chose to use the following methods
Optimize Inquiry (discovery) and Page (connection) window
In slave mode, there are two timers that can be used to lower radio power radio while idle. When not connected, the Bluetooth radio is active when listening for other devices. Other devices can discover (inquire) or connect (page) to the device. The amount of time the radio listens is called the window, and the interval at which the process repeats is called the interval.
For Roving Networks devices, the inquiry and page window is fixed at is 0x1000 (2.56 seconds). The default window is 0x0100 (160 ms) or a 6.25% duty cycle. By lowering the window values, you can save power at the expense of possibly missing an inquiry or page request. Because the host usually retries many times automatically, the only downside is a delay in discovery or connection time.
You adjust the inquiry scan window using the SI command. The minimum window for inquiry or page is 0x0012 (11.25 ms), which corresponds to about a 0.5% duty cycle.
You adjust the page scan window using the SJ command. The minimum window for inquiry or page is 0x0012 (11.25 ms), which corresponds to about a 0.5% duty cycle.
Thus, you can reduce the average power from more than 20 mA to less than 5 mA in standard mode and less than 3 mA in Sniff mode.
It is also possible (and desirable for security reasons) to completely disable inquiry. Once a host has found and installed a device, inquiry is not required, only page is used to make a connection. To disable inquiry while still allowing connections, set the inquiry timer to 0 with the SI,0000 command.
To obtain an extreme power saving, I decided to completely disable the inquiry. Also, I decreased the page window to the minimum allowed (11.25 ms)
Sniff mode
Sniff mode, a Bluetooth power conservation method, only pertains to an active connection. In Roving Networks devices, Sniff mode is disabled by default and the radio is active continuously when connected (about 25 to 30 mA). In Sniff mode, the radio wakes up at specific intervals and sleeps in very low power mode (around 2 mA) the rest of the time. With Sniff mode, the power savings can be quite dramatic. To enable Sniff mode, use the SW,<hex value> command. For example to set a 20 ms sniff mode timer, the command to enter is
SW,20
(0x20 is 32 decimal, and 32 decimal * .625 = 20 ms)
When a connection is made, both master and slave must support Sniff mode and agree to the Sniff window, otherwise, the radio remains in full active mode.
Because AirMobile sensor never acts as a master, this setting cannot be used.
Enable deep-sleep
- You can use deep sleep mode to obtain extremely low power operation. In this mode, the device shuts down completely and only draws about 300 μA of current. To enable deep sleep, set the high-order bit of the Sniff word to 0x8000. This bit is NOT used to determine the sleep interval, it is only used as a flag to enable deep sleep. For example:
SW,8320 // ½ second sleep (0x0320), with deep sleep enabled
In normal low-power sleep (not deep sleep) the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops running some tasks. For example, the LEDs only update about once per second. There are 3 ways to wake the radio from sleep mode:
- Send a character to the UART.
- Transition the RX pin. The worst-case wake time is 5 ms. Therefore, the radio generally loses the first character sent. A better way to wake the radio is to toggle the CTS line from low to high, wait 5 ms, and then send data.
- The radio can wake automatically every <hex value> slot times (1 slot time is 625 μs) as defined previously. The radio wakes and listens to see if the other side of the connection has anything to send. This wake time is typically about 5 ms (8 slots) even if no data is to be transferred.
Once the radio is awake, it stays active for exactly 1 second of inactivity, and then sleeps again.
Although enabling deep sleep mode could look a great way to reduce power consumption, I actually experienced a lot of issue due to packet drops and bytes losses. So I finally made up my mind not to use this feature
Disabling output drivers
Because I'm not going to use any GPIO, I used the S%,1000 command to set all GPIO pins (0 to 11) to inputs and thus disabling all output drivers
Lower transmit power
I decided not to change the transmit power because the environment where the sensor will be installed is harsh (lot of metal all around the Bluetooth module) so I think it's better to use the maximum transmitting power
Low-power connect mode
The low-power connect mode command disables the Bluetooth radio and LED timers while not connected, where <value> is a 4-digit number made up of two 1-byte intervals. The first interval is the off period and the second the on period. Both are in hex seconds (not decimal). The maximum value for either interval is 20 seconds. The default is 0000, which indicates always actively waiting for a connection. When this option is set, the module cycles between active (discoverable and connectable) and low-power deep sleep. This setting can save considerable power when the module is waiting for a long time without a connection. The trade off is additional latency when connecting or pairing.
After some tests, I found out a good trade off in keeping the radio switched off for 3 seconds and active for 1 second. This makes discovery operations enough responsive from the smartphone app's point of view
Initialization sequence
After some experiments, I found this initialization sequence works well as long as the AirMobile sensor is concerned
$$$ // enter command mode
S∼,0 // select SPP profile
S%1000 // set all GPIOs as input
SI,0000 // disable enquiry
SJ,0012 // set page window to 11.25 ms
S|,0301 // when not connected, stays off for 3 seconds and on for 1 second
--- // enter command mode
Power consumption
I measured the power consumption of the Bluetooth module with the default settings and with the new settings. I averaged current consumptions over a 10 seconds period. Here are the results
Condition | Original settings | Optimized settings |
Idle | 17 mA | 2 mA |
Connected | 25 mA | 20 mA |
The most of the savings are unfortunately when the Bluetooth module is in not connected, due to the fact that it stays on only 25% of the time. I say "unfortunately" because if the AirMobile sensor is on, it means that the car is running and thus the driver's smartphone is nearby and possibly connected.
To obtain greater savings, I should enable the deep sleep mode, but this would require a more complex handling of the data flow sent to the Bluetooth module. I will get back to this if I will have some time before the challenge ends