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

NRF52840 SAADC High Current with FreeRTOS SDK15.2

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!

Related