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

Adding Second SAADC increases sleep current to go greater 380uA

SDK 16.0 and SDK 17.0 (tried both versions)

nrf52832

Segger Embedded Studio

Windows 10

When Adding an additional ADC the sleep current increases to greater than 380uA (from one to two).  When I comment out either of the two ADCs (see below) the sleep current returns to less than 2uA.

I've been working on this for several days and have gone through all of the DevZone examples I could find on the subject (perhaps not), enough where I was coming back to the same ticket multiple times.  

Here's the code:

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    ret_code_t err_code;
     uint8_t value[SAADC_SAMPLES_IN_BUFFER*2];
     uint16_t adc_value;
     uint32_t        tempVoltage_u32 = 0 ;

if (p_event->type == NRF_DRV_SAADC_EVT_DONE) //Capture offset calibration complete event {
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
                        
        for (int i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
        {
            adc_value = p_event->data.done.p_buffer[i];
            value[i*2] = adc_value;
            value[(i*2)+1] = adc_value >> 8;

            tempVoltage_u32 += p_event->data.done.p_buffer[i] ;
        }
        m_adc_evt_counter++;
        }
}

void saadc_init (void){
ret_code_t err_code; nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
saadc_config.low_power_mode = true; nrf_saadc_channel_config_t channel_0_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD); channel_0_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED; //Disable pullup resistor on the input pin channel_0_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED; //Disable pulldown resistor on the input pin channel_0_config.gain = NRF_SAADC_GAIN1_6; //Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V channel_0_config.reference = NRF_SAADC_REFERENCE_INTERNAL; //Set internal reference of fixed 0.6 volts channel_0_config.acq_time = NRF_SAADC_ACQTIME_10US ; //Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz. Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS. channel_0_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; //Set SAADC as single ended. This means it will only have the positive pin as input, and the negative pin is shorted to ground (0V) internally. channel_0_config.burst = NRF_SAADC_BURST_ENABLED; channel_0_config.pin_p = NRF_SAADC_INPUT_VDD;//NRF_SAADC_INPUT_AIN0; //Select the input pin for the channel. AIN0 pin maps to physical pin P0.02. channel_0_config.pin_n = NRF_SAADC_INPUT_DISABLED; //Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally. nrf_saadc_channel_config_t channel_1_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5); channel_1_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED; //Disable pullup resistor on the input pin channel_1_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED; //Disable pulldown resistor on the input pin channel_1_config.gain = NRF_SAADC_GAIN1_6; //Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V channel_1_config.reference = NRF_SAADC_REFERENCE_VDD4; //Set internal reference of fixed 0.6 volts channel_1_config.acq_time = NRF_SAADC_ACQTIME_10US ; //Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz. Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS. channel_1_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; //Set SAADC as single ended. This means it will only have the positive pin as input, and the negative pin is shorted to ground (0V) internally. //channel_1_config.burst = NRF_SAADC_BURST_ENABLED; channel_1_config.burst = NRF_SAADC_BURST_DISABLED; // channel_1_config.pin_p = NRF_SAADC_INPUT_AIN1; //Select the input pin for the channel. AIN0 pin maps to physical pin P0.02. channel_1_config.pin_n = NRF_SAADC_INPUT_DISABLED; //Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally. err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback); APP_ERROR_CHECK(err_code);
// ********************************************************************************

//Comment out to lower sleep current (next two lines) err_code = nrf_drv_saadc_channel_init(0, &channel_0_config); APP_ERROR_CHECK(err_code);

// Or
// comment out to lower sleep current (next two lines) err_code = nrf_drv_saadc_channel_init(1, &channel_1_config); APP_ERROR_CHECK(err_code);

// ******************************************************************************** err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAADC_SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAADC_SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code);
}

END

Also - Placing the following code in the call back function the micro resets (so it's not being used):
        nrf_drv_saadc_uninit();
NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos); NVIC_ClearPendingIRQ(SAADC_IRQn);

I had hopes for this solution but nrf_drv_saadc_unit() causes a reset.
https://devzone.nordicsemi.com/f/nordic-q-a/65477/multi-channel-saadc-disable-in-nrf52832

Also, even though running:
volatile uint32_t temp1;
    volatile uint32_t temp2;
    volatile uint32_t temp3;

    ret_code_t err_code;

    temp1 = *(volatile uint32_t *)0x40007640ul;
    temp2 = *(volatile uint32_t *)0x40007644ul;
    temp3 = *(volatile uint32_t *)0x40007648ul;

    *(volatile uint32_t *)0x40007FFCul = 0ul; 
    *(volatile uint32_t *)0x40007FFCul; 
    *(volatile uint32_t *)0x40007FFCul = 1ul;

    *(volatile uint32_t *)0x40007640ul = temp1;
    *(volatile uint32_t *)0x40007644ul = temp2;
    *(volatile uint32_t *)0x40007648ul = temp3;


Will drop the current back to ~2uA, I'm only able to re-init one channel ( nrf_drv_saadc_channel_init(1, &channel_1_config) ).

attempting to stop (code directly above) and starting the second ADC causes a reset.

I have no float variables or functions.

In conclusion, all I'm attempting to do is use two ADCs and have low sleep current.

Thank you in advance for your assistance.

Peter





Parents
  • For Carl Richard - 

    I attempted to work through the  code you provided.  Unfortunately, the code:

                    
            nrf_drv_saadc_uninit();                                                                   //Unintialize SAADC to disable EasyDMA and save power
            NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);               //Disable the SAADC interrupt
            NVIC_ClearPendingIRQ(SAADC_IRQn);                                                         //Clear the SAADC interrupt if set
            m_saadc_initialized = false;                                                              //Set SAADC as uninitialized
        }

    at the end of the callback causes the micro to reset (I noticed this in other samples as well)

    Peter

    BTW - I was not able to reply directly to your response - thank you for any additional information you

    could provide.

Reply
  • For Carl Richard - 

    I attempted to work through the  code you provided.  Unfortunately, the code:

                    
            nrf_drv_saadc_uninit();                                                                   //Unintialize SAADC to disable EasyDMA and save power
            NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);               //Disable the SAADC interrupt
            NVIC_ClearPendingIRQ(SAADC_IRQn);                                                         //Clear the SAADC interrupt if set
            m_saadc_initialized = false;                                                              //Set SAADC as uninitialized
        }

    at the end of the callback causes the micro to reset (I noticed this in other samples as well)

    Peter

    BTW - I was not able to reply directly to your response - thank you for any additional information you

    could provide.

Children
Related