Hello,
I am need to add voltage sampling functionality to existing FreeRTOS framework on a low-power BLE device. When I enable BLE, I get 3mA of current, which stays there permanently . I have read all sorts of posts and guides for low power SAADC with a multi-channel setup but cannot seem to figure out the culprit... I only need to sample this once every 2-5min so the original approach was to my intent is to enable ADC, sample and disable it completely. However, for some reason I cannot turn it off. My code is attached below, wls_adc_start_sample() is triggered by the main task. It runs like it's supposed to, the interrupt gets triggered and I can read correct values. The only issue is extremely high current, which I am having trouble resolving...
/************************************************************************************************
LOCAL VARIABLES
*************************************************************************************************/
static nrf_saadc_value_t m_adc_buffer[SAADC_SAMPLES_IN_BUFFER];
//ADC config
const nrf_drv_saadc_config_t saadc_config = {
.resolution = NRF_SAADC_RESOLUTION_12BIT, \
.oversample = NRF_SAADC_OVERSAMPLE_DISABLED, \
.interrupt_priority = APP_IRQ_PRIORITY_LOW, \
.low_power_mode = true \
};
const nrf_saadc_channel_config_t channel_config_vbat = {
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
.gain = NRF_SAADC_GAIN1_2, \
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
.acq_time = NRF_SAADC_ACQTIME_10US, \
.mode = NRF_SAADC_MODE_SINGLE_ENDED, \
.burst = NRF_SAADC_BURST_DISABLED, \
.pin_p = NRF_SAADC_INPUT_AIN2, \
.pin_n = NRF_SAADC_INPUT_DISABLED \
};
const nrf_saadc_channel_config_t channel_config_3p3v = {
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
.gain = NRF_SAADC_GAIN1_2, \
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
.acq_time = NRF_SAADC_ACQTIME_10US, \
.mode = NRF_SAADC_MODE_SINGLE_ENDED, \
.burst = NRF_SAADC_BURST_DISABLED, \
.pin_p = NRF_SAADC_INPUT_AIN0, \
.pin_n = NRF_SAADC_INPUT_DISABLED \
};
const nrf_saadc_channel_config_t channel_config_vcc = {
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
.gain = NRF_SAADC_GAIN1_2, \
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
.acq_time = NRF_SAADC_ACQTIME_10US, \
.mode = NRF_SAADC_MODE_SINGLE_ENDED, \
.burst = NRF_SAADC_BURST_DISABLED, \
.pin_p = NRF_SAADC_INPUT_AIN3, \
.pin_n = NRF_SAADC_INPUT_DISABLED \
};
/************************************************************************************************
FLAGS
*************************************************************************************************/
static bool m_saadc_initialized = false;
/************************************************************************************************
FUNCTIONS
*************************************************************************************************/
void wls_adc_deinit( void );
/************************************************************************************************
************************************************************************************************
* @name saadc_callback
*
* @description initialize WLS ADC drivers
*
* @param[in] *p_event - event passed to the callback
*
* @return none
************************************************************************************************
************************************************************************************************/
void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
// ret_code_t err_code;
TaskMsg msg;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
//process ADC data
msg.type = APP_EVENT_PROCESS_ADC;
msg.msg = p_event->data.done.p_buffer;
msg.val = NULL;
//Send to App queue
xQueueSendFromISR(App_EventQueue, &msg, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
//Turn off power to resistor dividers
nrf_gpio_pin_clear(ADC_V_CHECK_EN);
//turn off ADC
wls_adc_deinit();
}
/************************************************************************************************
************************************************************************************************
* @name wls_adc_deinit
*
* @description Turn off WLS ADC
*
* @param[in] none
*
* @return none
************************************************************************************************
************************************************************************************************/
void wls_adc_deinit( void )
{
//De-init ADC
nrfx_saadc_uninit();
m_saadc_initialized = false;
//Clear interrupts
NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
NVIC_ClearPendingIRQ(SAADC_IRQn);
}
/************************************************************************************************
************************************************************************************************
* @name wls_adc_init
*
* @description Turn on WLS ADC
*
* @param[in] none
*
* @return none
************************************************************************************************
************************************************************************************************/
void wls_adc_init( void )
{
ret_code_t err_code;
//Initialize SAADC
err_code = nrfx_saadc_init(&saadc_config, saadc_callback); //Initialize the SAADC with configuration and callback function. The application must then implement the saadc_callback function, which will be called when SAADC interrupt is triggered
APP_ERROR_CHECK(err_code);
//Initialize SAADC channels
err_code = nrfx_saadc_channel_init(ADC_CHANNEL_VBAT, &channel_config_vbat); //Initialize SAADC channel 0 with the channel configuration
APP_ERROR_CHECK(err_code);
err_code = nrfx_saadc_channel_init(ADC_CHANNEL_V3P3, &channel_config_3p3v); //Initialize SAADC channel 0 with the channel configuration
APP_ERROR_CHECK(err_code);
err_code = nrfx_saadc_channel_init(ADC_CHANNEL_VCC, &channel_config_vcc); //Initialize SAADC channel 0 with the channel configuration
APP_ERROR_CHECK(err_code);
m_saadc_initialized = true;
}
/************************************************************************************************
************************************************************************************************
* @name wls_adc_start_sample
*
* @description Kicks off ADC sampling process
*
* @param[in] none
*
* @return none
************************************************************************************************
************************************************************************************************/
void wls_adc_start_sample( void )
{
ret_code_t err_code;
//Turn on power to resistor dividers
nrf_gpio_pin_set(ADC_V_CHECK_EN);
if(m_saadc_initialized == false)
{
//turn on ADC
wls_adc_init();
}
//create conversion buffer
err_code = nrfx_saadc_buffer_convert(m_adc_buffer, SAADC_SAMPLES_IN_BUFFER); //Set SAADC buffer 1. The SAADC will start to write to this buffer
APP_ERROR_CHECK(err_code);
//start sampling
nrfx_saadc_sample();
}
Any insight on what I might be doing wrong is highly apprciated.
Thanks!