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

SAADC Offset Calibration errors and input resistance

nrf52832.

SDK14.2

Segger ES V3.34a

With an initial prototype batch of 30, we have noticed 4 modules that have incorrect voltage readings, reading low ("Bad Modules").

Normally we implement the calibration routine for the offset, but found when we disabled this routine the 4 low reading parts improved in performance, but still had errors.  This lead to debugging and capturing the ADC readings with/without the calibration routine enabled and comparing bad modules with good modules.

We noted the ADC Counts from three of the ADC pins  An0, An1, An2

On the bad module we noticed the following.

The calibration offset was made worse by ~300 steps after calibration.

The input impedance w.r.t 0V for Ain0 was lower on a bad module which affected the potential divider reading.

 Ain2 s/c to 0V had a greater negative offset to start with compared with a good module, (prior to calibration)

Settings on both modules

//set configuration for saadc channel 0
channel_0_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
channel_0_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
channel_0_config.gain = NRF_SAADC_GAIN1_5;
channel_0_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
channel_0_config.acq_time = NRF_SAADC_ACQTIME_3US;

channel_0_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
channel_0_config.pin_p = (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN0);
channel_0_config.pin_n = NRF_SAADC_INPUT_DISABLED;


//set configuration for saadc channel 1
channel_1_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
channel_1_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
channel_1_config.gain = NRF_SAADC_GAIN1_5;
channel_1_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
channel_1_config.acq_time = NRF_SAADC_ACQTIME_3US;
channel_1_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
channel_1_config.pin_p = (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN1);
channel_1_config.pin_n = NRF_SAADC_INPUT_DISABLED;

//set configuration for saadc channel 2
channel_2_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
channel_2_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
channel_2_config.gain = NRF_SAADC_GAIN1_5;
channel_2_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
channel_2_config.acq_time = NRF_SAADC_ACQTIME_3US;
channel_2_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
channel_2_config.pin_p = (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN2);
channel_2_config.pin_n = NRF_SAADC_INPUT_DISABLED;

//Configure SAADC

/saadc_config.low_power_mode = False; //Disable low power mode.
saadc_config.resolution = NRF_SAADC_RESOLUTION_14BIT; //Set SAADC resolution to 14-bit.
saadc_config.oversample = NRF_SAADC_OVERSAMPLE_32X; //Set oversample to 32x. 

We are using 0.1% resisters for the p.d.

Ain0 - p.d with 82.5K and 7.5K

Ain1 - LM61

An2 - 100K pull down to 0V

Results

Applied voltage constant to Ain0 and Ain1  'with and without' calibration for comparison

Bad module -

Ain                        No CAL                                          WITH  CAL                       DIFF

0                            5857                                                   5532                            -325     

1                            4714                                                   4438                            -276

2                            -20                                                       -330                            -310

Good module - 

Ain                       No CAL                                          WITH  CAL                       DIFF

0                            5699                                                 5704                              5  

1                            4830                                                 4836                              6

2                            -8                                                       -2                                  7

Are there any chip revisions that could cause such a loading of the A/D input and also cause the calibration routine to make things worse.

What is done internally to carry out the calibration routine?

Any help suggestions or thoughts?

Parents
  • Hi,

    As previously mentioned in this thread, one should have Tacq > 10 due to some Errata's. I see that you have already tried increasing it, could you try: Apply STOP task after calibration, before sampling. CALIBRATEOFFSET -> CALIBRATEDONE -> STOP -> STOPPED -> START

    Best regards

    Jared 

  • Hi Jared,

    Thanks for looking into this...

    First i do this in my "call back"

    //set the do calibration flag.
    if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0 && p_event->type == NRF_DRV_SAADC_EVT_DONE && m_saadc_calibrate_done == false ) //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency

    {
    nrf_drv_saadc_abort(); // Abort all ongoing conversions. Calibration cannot be run if SAADC is busy
    while(NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos))

    m_saadc_calibrate = true; // Set flag to trigger calibration in main context when SAADC is stopped
    }

    then I do this in main

    if(m_saadc_calibrate == true)
    {

    //Workaround
    //Calibration should follow the pattern STOP -> STOPPED -> CALIBRATEOFFSET -> CALIBRATEDONE -> STOP -> STOPPED -> START.
    NRF_LOG_INFO("SAADC calibration starting now... \r\n"); //
    m_saadc_calibrate = false;
    while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task

    nrf_saadc_disable();
    while(NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos))
    {}
    nrf_saadc_enable();
    while(NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos))
    {}
    m_saadc_calibrate_done = true;


    }

    The weird thing is the loading of our potential divider.  The reading across it is way out of specification for our 0.1% resisters.

    sorry for the poor formatting

    also the die is  nRF5283-QFAA-E00 for both examples

  • I'm suspecting that the issue might be a HW issue, more specially ground bounce on the PCB.

    • Could you share the schematic and layout files of the prototype?
    • Do you have the possibility of using differential mode and see if you're still observing the issue?

    Best regards

    Jared 

Reply Children
No Data
Related