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

SAADC nrf52832

hello, I have two questions for SAADC of nrf52832 when we use nrf52832 SAADC for voltage measurement.

The AIN0 is connected to the pin to be measured(the voltage is about 1.5V, use SE mode, so the negative
input will be shorted to ground internally ), the output of SAADC is 850(the result beating frequently between 850 to 856).

my SAADC config is bellow:
NRF_SAADC->CH[channel].CONFIG = ((SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos)|
(SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos)|
(SAADC_CH_CONFIG_GAIN_Gain1_3<< SAADC_CH_CONFIG_GAIN_Pos)|
(SAADC_CH_CONFIG_REFSEL_Internal<<SAADC_CH_CONFIG_REFSEL_Pos)|
(SAADC_CH_CONFIG_TACQ_10us<< SAADC_CH_CONFIG_TACQ_Pos)|
(SAADC_CH_CONFIG_MODE_SE<<SAADC_CH_CONFIG_MODE_Pos) );
NRF_SAADC->CH[channel].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0;
NRF_SAADC->CH[channel].PSELN = SAADC_CH_PSELP_PSELP_NC;
NRF_SAADC->RESULT.MAXCNT = 1;
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_10bit;
NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Bypass;
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos);
NRF_SAADC->INTENSET = SAADC_INTENSET_END_Msk;

then read the result:

NRF_SAADC->TASKS_START = 1;
NRF_SAADC->TASKS_SAMPLE = 1;

uint32_t saadc_timeout = 100000;
while ((NRF_SAADC->EVENTS_END == 0U)&& (saadc_timeout > 0))
{
saadc_timeout--;
}
NRF_SAADC->EVENTS_END = 0;

NRF_SAADC->RESULT.PTR = (uint32_t)saadc_value_data;


My question is :
1) RESULT = [V(P) – V(N) ] * GAIN/REFERENCE * 2(RESOLUTION - m)
RESULT = 850/1024 = 0.83
[V(P) – V(N) ] * GAIN/REFERENCE * 2(RESOLUTION - m) = 1.5V * Gain1_3 / (0.6V * 2) = 0.417, it's not equall to RESULT, why?


2) The SAADC output is beating frequently between 850 to 856(for example 851,853,855...), is it normal?

Parents Reply Children
  • The oversampling is SAADC_OVERSAMPLE_OVERSAMPLE_Over2x

    void nrf_drv_saadc_init(void)
    {
    uint8_t channel = 0;

    NRF_SAADC->CH[channel].CONFIG = ((SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos)|
    (SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos)|
    (SAADC_CH_CONFIG_GAIN_Gain1_3<< SAADC_CH_CONFIG_GAIN_Pos)|
    (SAADC_CH_CONFIG_REFSEL_Internal<<SAADC_CH_CONFIG_REFSEL_Pos)|
    (SAADC_CH_CONFIG_TACQ_10us<< SAADC_CH_CONFIG_TACQ_Pos)|
    (1<< 24)|
    (SAADC_CH_CONFIG_MODE_SE<<SAADC_CH_CONFIG_MODE_Pos) );
    NRF_SAADC->CH[channel].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0;
    NRF_SAADC->CH[channel].PSELN = SAADC_CH_PSELP_PSELP_NC;
    NRF_SAADC->RESULT.MAXCNT = 1;
    NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_10bit;
    NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Over2x;
    NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos);
    NRF_SAADC->INTENSET = SAADC_INTENSET_END_Msk;
    }

    Then read:

    NRF_SAADC->RESULT.PTR = (uint32_t)saadc_value_data;
    NRF_SAADC->TASKS_START = 1;
    while (NRF_SAADC->EVENTS_STARTED == 0U);
    NRF_SAADC->TASKS_SAMPLE = 1;
    //
    uint32_t saadc_timeout = 100000;
    while ((NRF_SAADC->EVENTS_END == 0U)&& (saadc_timeout > 0))
    {
    saadc_timeout--;
    }
    NRF_SAADC->EVENTS_END = 0;
    NRF_SAADC->TASKS_STOP = 1;

  • That looks good. I suggest you increase oversampling to at least 16x. Right now you take the average of two samples which won't improve the variance much. 

Related