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!