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

Adc consumption

Hello all,

I am trying to activate ADC to measure a voltage every few seconds using nrf51822. When it is done, I supposedly deactivate ADC so it does not consumes while I don't need it. I find that the consumption increases when I activate the ADC, but it does not decreases when it is finished, so I suppose I am not deactivating well.

Code:

Every few seconds, I run this function:

void measure_voltage(void)
{
	uint32_t err_code;
    // Configure ADC
    NRF_ADC->INTENSET   = ADC_INTENSET_END_Msk;
    NRF_ADC->CONFIG     = (ADC_CONFIG_RES_8bit                        << ADC_CONFIG_RES_Pos)     |
                          (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos)  |
                          (ADC_CONFIG_REFSEL_VBG                      << ADC_CONFIG_REFSEL_Pos)  |
                          (ADC_CONFIG_PSEL_Disabled                   << ADC_CONFIG_PSEL_Pos)    |
                          (ADC_CONFIG_EXTREFSEL_None                  << ADC_CONFIG_EXTREFSEL_Pos);
    NRF_ADC->EVENTS_END = 0;
    NRF_ADC->ENABLE     = ADC_ENABLE_ENABLE_Enabled;

    // Enable ADC interrupt
    err_code = sd_nvic_ClearPendingIRQ(ADC_IRQn);
    APP_ERROR_CHECK(err_code);

    err_code = sd_nvic_SetPriority(ADC_IRQn, NRF_APP_PRIORITY_LOW);
    APP_ERROR_CHECK(err_code);

    err_code = sd_nvic_EnableIRQ(ADC_IRQn);
    APP_ERROR_CHECK(err_code);

    NRF_ADC->EVENTS_END  = 0;    // Stop any running conversions.
    NRF_ADC->TASKS_START = 1;
}

Then, I wait for the handler to come up:

void ADC_IRQHandler(void) 
{
    if (NRF_ADC->EVENTS_END != 0)
    {
        uint8_t     adc_result;

        NRF_ADC->EVENTS_END     = 0;
        adc_result              = NRF_ADC->RESULT;
        NRF_ADC->TASKS_STOP     = 1;
	    NRF_ADC->ENABLE     = ADC_ENABLE_ENABLE_Disabled;
			
	    paquet_advertising[0]=adc_result;
	}
}

Am I missing something?

Thank you very much

  • First, I would assume you have calculated a range of voltage you want to measure. Looking at your configuration for ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling you will get

    1.2 VBG * 3 = 3.6V.

    If your input is exceeding this range you will get extra current draw. For more information I recommend reading nRF51 Reference Manual v 3.0, page 165 onward.

    Second, assume your input voltage is in range, you should consider using a voltage divider to lower the input voltage. It has an added benefit of lowering current draw because you are adding resistance to the ADC pin. This way you need less prescaling, a lower input can lead to much lower current draw during measurement.

    Third, you should be aware of the input impedance on these GPIOs when you design the voltage divider, I would assume you have the knowledge to solve RC circuits, so I will only tell you the values are on Table 313 of Page 167 in the reference manual. Just make sure the impedance is appropriate otherwise you will get very unstable read.

    I hope these points will be helpful to your circuit design.

  • Thank you for your response. I understand I can get an extra current draw in these conditions. But I assume this current draw should appear only when ADC is enabled, right? This does not explain why I don't get the same current draw I had before enabling ADC when I deactivate it.

  • Hi

    The internal ADC model is shown on this thread, where you can see a 0.6V voltage source and an internal resisor R_AIN which has values listed in table 313 in the nRF51 Reference manual 3.0.

    According to my calculations, the maximum current flowing into the ADC AIN pin when sampling and with no voltage divider connected is (3.6V-0.6V)/390kohm=7.7uA with 1/3 input prescaler and (1.2V-0.6V)/130kohm=4.6uA with 1/1 input prescaler. The average current would normally be somewhat smaller and it is only consumed when sampling, which is 20us for 8-bit sampling and 68us for 10-bit single sample. The GPIO is high impedance when not sampling and leak no current. For instance, if you sample with <1kHz frequency, the leakage current into the AIN should always be <1uA. So I assume that in most situations, the leakage current into the AIN pin is not of concern.

    When you have a voltage divider I can agree with that you have less current flow into the ADC AIN pin as you have higher overall impedance in the circuit, but you constantly have the leakage current through the voltage divider, unless you use a switch to stop it when not sampling. But if you have a voltage divider you also need a capacitor to compensate for the voltage drop caused by the high impedance of the voltage divider so you need to have the switch open for a long time in order to recharge the capacitor before sampling again.

    So for the above reasoning, I would generally think that adding a voltage divider would not save current consumption.

  • Hi

    I have generally in the past not found a reason to disable the ADC after sampling is finished. I have obtained low current without it. What current are you seeing when ADC enabled and not sampling?

    I have generally used this code with low current consumption. When there sampling ongoing the current consumption should be around 1mA, as the ADC consumes ~260uA and it needs 16MHz clock to opterate, adding up to the 1mA current consumption. If you have a multimeter to measure current consumption, you would need more low frequency sampling example than the one I just linked to. Here is more relevant example that is made for SDK 8.1.0 and the nRF51-DK where you can also adjust the sampling frequency to a very small value, which will enable you to see the current consumption on a multimeter between sampling events. You should see around ~3uA when not sampling

    rtc0-triggering-adc-sample_nrf51DK.zip

    Make the NRF_RTC0->CC[0] value larger to slow down the sampling frequency

  • I agree, my second point is not true. The only use for a divider is to lower Vin to the range AIN can measure

Related