This blog is to mention how to add the battery service and read the VDD through SAADC module. Also, the most important is to optimize the current consumption.
SAADC (Successive approximation analog-to-digital converter)
The SAADC is a differential successive approximation register (SAR) analog-to-digital converter. It supports
up to eight external analog input channels, depending on package variant. It is an analog module. For example, it is the most common used to detect the battery level.
For example, if we need to use SAADC module, it needs to run the HCLK either NRF52832 or NRF52840.
nRF52832 Product Specification

nRF52840 Product Specification

Battery detection on the VDD
By select the SAADC to use the VDD pin as below,


In order to save the current consumption by using the SAADC, the SAADC can be only active when it is running for battery detection.
For example, it creates the app_timer for battery every 120 seconds.
#define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(120000) /**< Battery level measurement interval (ticks). This value corresponds to 120 seconds. */


On every battery handler timeout,

It tries to initialize the SAADC module.

After received the NRF_DRV_SAADC_EVT_DONE, the SAADC would be uninitialized.

Given advertising interval = 1000ms, VDD = 3 V with DCDC enable, we run the firmware at the NRF52840 DK board.
By using the init / uninit approach, the SAADC is only switched on every 120 seconds.

Keep to run the SAADC all the time,

By comparing two difference configurations as above, you can find that around 480 uA keeps to run as the background.
The source code of this example can be found at https://github.com/jimmywong2003/nrf5-ble-bidirection-throughput-test/tree/master/ble_app_its_bas .
Welcome to give any comment on this blog. Please remember to give a like if you think it is good.
Thanks for your interests on my blog. Since 2019, I have created this blog and shared the idea how to do some funny stuffs. I am very pleasure that I get quite a lot of positive feedback. I really hope that this blog helps your own embedded solution development. May I get support from you to keep it in order to maintain the wordpress host service? Your appreciation would be very helpful.
https://jimmywongiot.com/2021/05/26/asking-for-support/

Jimmy, can you please explain in detail what this example does? The blog seems to explain only the battery level measurement and optimization.
LikeLike
What do you plan to know ? The battery measurement is depended on the coincell or external LDO. For example, thingy52 is using the adc pin to measure the voltage with resistor divider and then have a lookup to convert with battery in percentage. If coincell battery, the V battery can directly convert to the percentage.
LikeLike
Hi Jimmy
Great blog – great example.
I am trying to use your example on my nrf5340-DK with sdk 1.9.1 I but can’t seem to find the correct include file to resolve the use of the “nrf_drv_saadc_uninit();”.
You use: #include “nrf_drv_saadc.h”
But it is not found on my SDK. I tried also
#include
but also “nrf_drv_saadc_uninit();”. not resolved.
Even tried #include
with the function nrfx_saadc_uninit();
But also doesn’t work.
How can I resolve this problem?
Thanks!
Gerard
LikeLike
Hi Gerad,
Our SDK version is difference. You may need to find the corresponding HAL file such as nrfx_saadc.h.
Jimmy
LikeLike
Hi Jimmy
Of course I realize that & had already done that.
But it seems to me that in the v1.9.1 SDK & for nrf5340, the saadc uniti() function is no longer supported.
Throws a build error – even though the function appears to exist.
Can you shed any light on that…!
Would really appreciate your experienced insight into this. It has me baffled ! 🙂
Thanks!
Gerard
LikeLike
Hi Gerad,
I think Nordic is still using the nrfx driver on their peripheral at nRF connect SDK.
from the saadc driver, https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_saadc.c
It has the uninit.
void nrfx_saadc_uninit(void)
{
nrfx_saadc_abort();
NRFX_IRQ_DISABLE(SAADC_IRQn);
nrf_saadc_disable(NRF_SAADC);
saadc_channels_disable(m_cb.channels_configured | m_cb.channels_activated);
m_cb.saadc_state = NRF_SAADC_STATE_UNINITIALIZED;
}
I think your problem is to use the generic driver on zephyr but the uninit routine is not exposed at such layer.
You may go through the devzone to get further investigation.
Jimmy
LikeLike