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

SAADC high current

Hi,

I am working on measuring the voltage on a lithium battery (norminal 3.7V) with a voltage divider on nRF52832. The voltage divider combines a 510K and 360K resistor and a 0.1uF capacitor. We got following findings:

  1. The current raised up to over 6mA after SAADC measurement.
  2. Floating input on SAADC (no lithium battery and voltage divider on pca10040), the current is normal before and after SAADC measurement.

Please kindly help to solve this issue.

Attached below is the program code for your reference.

#include "nrf_drv_ppi.h"

#include "saadc.h"

#include "app_util_platform.h"

#include "softdevice_handler.h"

#define SAADC_CALIBRATION_INTERVAL 	5              			

#define SAADC_SAMPLES_IN_BUFFER 	1                 		

#define SAADC_OVERSAMPLE 		NRF_SAADC_OVERSAMPLE_4X  	

#define SAADC_BURST_MODE 		1                        	

static nrf_saadc_value_t    		m_buffer_pool[2][SAADC_SAMPLES_IN_BUFFER];
static uint32_t                		m_adc_evt_counter = 0;

static nrf_ppi_channel_t    		m_ppi_channel;
bool   m_saadc_initialized 		= false;      

void saadc_init(void)
{
    ret_code_t 				err_code;
    nrf_drv_saadc_config_t 		saadc_config;
    nrf_saadc_channel_config_t 		channel_config;
 
    //Configure SAADC
    saadc_config.resolution 		= NRF_SAADC_RESOLUTION_12BIT;	    
    saadc_config.oversample 		= SAADC_OVERSAMPLE;                 
    saadc_config.interrupt_priority 	= APP_IRQ_PRIORITY_LOW;             
	
    //Initialize SAADC
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);           
    error_check(err_code);
		
    //Configure SAADC channel
    channel_config.reference 		= NRF_SAADC_REFERENCE_INTERNAL;     
    channel_config.gain 		= NRF_SAADC_GAIN1_6;                
    channel_config.acq_time 		= NRF_SAADC_ACQTIME_20US;           
    channel_config.mode 		= NRF_SAADC_MODE_SINGLE_ENDED;      
    channel_config.pin_p 		= NRF_SAADC_INPUT_AIN0;             
    channel_config.pin_n 		= NRF_SAADC_INPUT_DISABLED;         
    channel_config.resistor_p 		= NRF_SAADC_RESISTOR_DISABLED;      
    channel_config.resistor_n 		= NRF_SAADC_RESISTOR_DISABLED;      

    //Initialize SAADC channel
    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    error_check(err_code);

    if(SAADC_BURST_MODE)
        NRF_SAADC->CH[0].CONFIG |= 0x01000000;                              

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAADC_SAMPLES_IN_BUFFER);
    error_check(err_code);
    
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAADC_SAMPLES_IN_BUFFER);
    error_check(err_code);
}

void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    error_check(err_code);
}

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    ret_code_t 	err_code;
    uint32_t 	data;    
    
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE){
        if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0){                                      
            NRF_SAADC->EVENTS_CALIBRATEDONE = 0;                                                        
            nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);                                     
            while(!NRF_SAADC->EVENTS_CALIBRATEDONE);                                                    
            while(NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos));          
        }

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
        error_check(err_code);
        m_adc_evt_counter++;

        nrf_drv_saadc_uninit();                                                                   
        NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);               
        NVIC_ClearPendingIRQ(SAADC_IRQn);							
        m_saadc_initialized = false;                                                            
  
  	data = p_event->data.done.p_buffer[0];   		             
    }
}
Parents
  • 6 mA indicates that the CPU is not able to go to sleep (it may be stuck in an infinite loop somewhere).

    You are mixing register manipulation and saadc SDK driver code. This is not recommended unless you know exactly what you are doing. Manipulating the register in a wrong way with respect to the driver may lead to issues like this.

    Why are you uninitializing the driver? This is not necessary in SDK 12 and later to save power. You can use Low Power mode instead:

    #define SAADC_CONFIG_LP_MODE 1
    

    Calibration can be done using the driver: devzone.nordicsemi.com/.../

Reply
  • 6 mA indicates that the CPU is not able to go to sleep (it may be stuck in an infinite loop somewhere).

    You are mixing register manipulation and saadc SDK driver code. This is not recommended unless you know exactly what you are doing. Manipulating the register in a wrong way with respect to the driver may lead to issues like this.

    Why are you uninitializing the driver? This is not necessary in SDK 12 and later to save power. You can use Low Power mode instead:

    #define SAADC_CONFIG_LP_MODE 1
    

    Calibration can be done using the driver: devzone.nordicsemi.com/.../

Children
No Data
Related