Bluetooth Low Energy sensor

I have some ideas for a low power wireless sensor.  I want something that will last more than a month on 2x rechargeable AA or AAA batteries.  I first tried an esp8266 and then an esp32, but the boards I have all use 3-7mA in "deep sleep".  This is probably mostly the fault of the USB/uart chipset.  I then tried an Adafruit Feather based on the nrf52832 chipset.

The Feather board also has a USB/uart chipset that uses about 3mA.  But if I power the board from the 3.3V pins, the USB/uart chipset is not powered on.  

This chipset can handle a supply voltage between 1.7V-3.6V, so I can just plug my 2x AAA batteries into the 3.3V pins.  They're rechargeable batteries, so the pair should range from 3.0V off the charger to 1.8V near empty.  Putting the batteries directly on the 3.3V pin is dangerous because if USB on the Feather is plugged in at the same time, the voltage regulator will try to charge the batteries (and 3.3V is far too much).  I added a 10 ohm resistor between the batteries and the board to limit the current, but a proper fix would be to remove the 3.3V regulator.  I'm also using that 10 ohm resistor to measure the current the board is using.

To simulate a sensor, I setup a voltage divider connected to the ADC.  It's currently measuring the battery voltage.  I'm using the internal 0.6V voltage reference with a 3x gain.  The official specs are +3%/-4% error on the ADC, and my board is seeing around 1.7%.

I have it read the ADC every second, and then use a bluetooth LE indication to the central when the value is changed.  I used a custom UUID for my data.

Important Arduino Code

define the Service, Characteristic, and Software Timer
call adcSampleCallback every 1s
push the change via indicate

I also changed the default connection (polling) interval to reduce power usage.  It defaults to min=20ms,max=30ms.

Requests polling between 400ms and 1s to save power

Important python code

To receive this data, I'm using a Raspberry Pi 3.  I wrote a simple client program with the python gatt library.  gatt is the term for Bluetooth LE data.

The client looks for the custom service and characteristic

And then, whenever the board updates the data, it gets passed to this client:

Converting from bytes to voltage and percent left

1.769V is my measured internal ADC reference voltage.  4096 because the ADC is in 12 bit mode, and 0.49 is my measured voltage divider ratio.  The percentage equation is my estimate of NiMH discharge voltage.

Measuring power usage

First, I looked at what sort of DC offset my oscilloscope has when it is measuring ground directly.

-15.2mV = ground

Next, I connected my oscilloscope to measure the voltage drop over the 10 ohm resistor.

Power usage during transmission

This is the board waking up and transmitting data using Bluetooth.  Peak current is (126+15.2)/10=14.12 mA here.  I'm using a tx power of +4dBm.

Zooming out to see what power usage looks like, you can see the 1 second bluetooth connection polling interval:

Power usage spikes every 1 second

Looking at the average power usage over 1 second:

Mean voltage drop of -10.4mV

This is (-10.4+15.2)/10= 0.48 mA average power usage.  This is near the measurement made by my multi-meter of 0.4 mA.  Assuming the oscilloscope number is correct, that's around 3 months of battery life.

Results

So far I've left it running for just over 27 hours and the battery voltage is still within 1mV its starting value.  My estimate is that's less than 1% of the battery energy used per day.

The range isn't very far, about 30ft/9m.  But this seems like a decent starting point.

Code: https://github.com/ddrown/bluetoothadc

Part 2 has battery voltage after running for a week