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

SAADC calibration on nRF52840

Hi,

I am using the SAADC (AIN2) to get temperature values from a Pt1000, and I am experiencing sometimes strange behaviour after the offset calibration is done.I have quite  simple requirements (only one analog value, repeat sampling every 2 ms until I have 50 samples, than stop). Wait for some time, than repeat. This is my initialization:

nrfx_saadc_config_t nrfConfig;
nrf_saadc_channel_config_t nrfChannelConfig;

nrfConfig.resolution = NRF_SAADC_RESOLUTION_12BIT;
nrfConfig.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
nrfConfig.interrupt_priority = APP_IRQ_PRIORITY_LOW;
nrfConfig.low_power_mode = false;
err = nrfx_saadc_init(&nrfConfig, &pt1000EventHandler);

if (err != NRFX_SUCCESS) { ... }

 nrfChannelConfig.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
 nrfChannelConfig.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
 nrfChannelConfig.gain = NRF_SAADC_GAIN1_5;
 nrfChannelConfig.reference = NRF_SAADC_REFERENCE_INTERNAL;
 nrfChannelConfig.acq_time = NRF_SAADC_ACQTIME_40US;
 nrfChannelConfig.mode = NRF_SAADC_MODE_SINGLE_ENDED;
 nrfChannelConfig.pin_p = NRF_SAADC_INPUT_AIN3;
 nrfChannelConfig.pin_n = NRF_SAADC_INPUT_DISABLED;
 nrfChannelConfig.burst = NRF_SAADC_BURST_DISABLED;
 err = nrfx_saadc_channel_init(0, &nrfChannelConfig);

if (err != NRFX_SUCCESS) { ... }

I start by doing one calibration and getting one measurement if the internal temperature sensor. While normal operation is going on, I repeat the temperature measurement every minute, and if the temperature has changed more then 10°C, I repeat the calibration and store the temperature value for later comparison.

The 10°C threshold is taken from the  recommendation in the PS 1.1, 6.23.8.

To test temperature stability, I connect a 1kOhm resistor to my circuit and start heating up my device. I expected to see some drift, countered by the calibrations occurring when temperature has been changed by more then 10K. What I found was little drift, but changes of up to11 digits after calibration (see excel sheet) .The values from column C are calculated by aggregating 50 values as mentioned above and than converted to °C according to the circuity. Than they are sampled to my PC every 30 seconds. The first calibration is not visible in the graph, because it is done directly after startup, the second calibration pushes the measured values up by 0.6K (about 11 ADC digits), the third calibration pulls the measured values down by 0.4K (about 7 ADC digits) and the third calibration has no visible effect. I should add, that this effect does not occur on every test run. I do not get any error code on calling nrfx_saadc_calibrate_offset(), and I always get the NRFX_SAADC_EVT_CALIBRATEDONE event delivered to the event handler.

To me it looks a bit like the second calibration miscalculated a too large offset, and the third calibration then corrected the error.

Is there any explanation of this behaviour? Do I overlook something simple? I am also missing some more detailed explanation, what this calibration really does. What reference is used internally to determine an offset? I could not find a register where I can observe the calculated offset. Would it help to do the calibration more often (either by time interval or by reducing the temperature threshold from 10 K to maybe 1-2 K)?

Regards

  Dirk

temperatur-2020-04-02-13-58-42.xlsx

  • The analog reference used in the automatic offset calibration is a bit temperature-sensitive and not really suited in designs with high accuracy requirements. 

    What you can do is a digital offset calibration: 

    1. Connect positive and negative inputs to the same signal, f.ex VDD/4.

    2. Take a sample.

    3. Subtract the sample value from all future samples (until you calibrate again). 

    This will reduce the offset further and have less variation in offsets between calibrations, but it will require a float or integer operation extra. 

    I also strongly recommend that you enable oversampling, at least 4-8X as there can be a fair bit of transient noise in the power supply for the thermistor. 

    You can also turn on the HFXO for a further increase in accuracy. 

  • I find neither an indication of the temperature drift of the internal reference nor a description of how the calibration works.
    Where can I find a functional description?
    How big is the jump that occurs after a calibration?

  • Hi,

    thank you for the reply. I was using HFXO already. I have activated oversampling as suggested, and it does reduce the noise a bit. But it does not influence the strange calibration behaviour, i.e. sudden unexpected shifts of the values after calibration task has been executed. I have tried to increase the calibration rate by doing it time-dependent instead of temperature-dependent, but that only seems to increase the rate of value shifts. So do I understand you right I should completely avoid the the built-in calibration and instead do a digital offset calculation as described in step 1-3? My question would be still what is happening exactly if I use the built-in calibration and how I can observe the calculated offset.

    Regards Dirk

  • dzabel said:
    I should completely avoid the the built-in calibration and instead do a digital offset calculation as described in step 1-3?

      Yes, I recommend it for your application. 

    dzabel said:
    what is happening exactly if I use the built-in calibration and how I can observe the calculated offset.

     The built-in calibration uses an analog reference to compensate for the offset, but this reference is susceptible to thermal noise that will give a slightly different offset each time. 

  • harti said:
    Where can I find a functional description?

    I'm sorry but that's proprietary information. 
     

    harti said:
    How big is the jump that occurs after a calibration?

     The calibration DAC is around +-2 LSB10b (+-8 LSB12b)

Related