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

How to get NRF_DRV_SAADC_EVT _CALIBRATEDONE.

Related to the following Q & A
https://devzone.nordicsemi.com/f/nordic-q-a/70355/saadc_task_calibrateoffset

In the process of checking the operation, we created the following two types of code (A) and (B).

Inquiry items

  • Q1 Regarding (B) below, I would like to know if the correction method is correct. If it is wrong, I would like to know the correct correction method.
  • Q2 I would like to know how to obtain NRF_DRV_SAADC_EVT_CALIBRATEDONE for (B) below.

Explanation of (A)

To check the operation of nrf_drv_saadc_calibrate_offset() on nRF52810
https://github.com/NordicPlayground/nRF52-ADC-examples saadc_low_power
Ported to nRF5_SDK_15.3.0_59ac345\examples\peripheral\saadc. Reference: Code(A)
1.65V is applied to AIN0.

NRF_DRV_SAADC_EVT_CALIBRATEDONE occurs, but the AD value cannot be obtained from the second time onward.
The return value of nrf_drv_saadc_calibrate_offset () does not become NRF_SUCCESS. Reference: Code(A)log

We speculate that the following errata are related.
[237] SAADC: TASKS_CALIBRATEOFFSET shall only be used before TASKS_START or after EVENTS_END

Explanation of (B)

Corrected (A) with reference to the errata. Reference: Code(B)
The AD value can now be obtained repeatedly.

However, NRF_DRV_SAADC_EVT_CALIBRATEDONE cannot be obtained. Reference: Code(B)log


Code(A)

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "boards.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "app_util_platform.h"
#include "nrf_pwr_mgmt.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define SAMPLES_IN_BUFFER 5
volatile uint8_t state = 1;

static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t     m_ppi_channel;
static uint32_t              m_adc_evt_counter;
static bool                    m_saadc_calibrate = false;      


void timer_handler(nrf_timer_event_t event_type, void * p_context)
{

}


void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 400ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}


void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);

    APP_ERROR_CHECK(err_code);
}
#define SAADC_CALIBRATION_INTERVAL 5              //Determines how often the SAADC should be calibrated relative to NRF_DRV_SAADC_EVT_DONE event. E.g. value 5 will make the SAADC calibrate every fifth time the NRF_DRV_SAADC_EVT_DONE is received.
#define SAADC_SAMPLES_IN_BUFFER 1                 //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.


void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;

        if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0)               //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
        {
            m_saadc_calibrate = true;                                           // Set flag to trigger calibration in main context when SAADC is stopped
        }

        int i;
        NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);

        for (i = 0; i < SAMPLES_IN_BUFFER; i++)
        {
            NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
        }

        if(m_saadc_calibrate == false)
        {
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
            APP_ERROR_CHECK(err_code);
        }

        m_adc_evt_counter++;
    }
    else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
    {
        NRF_LOG_INFO("CALIBRATE DONE");
    }
}


#define SAADC_CHANNEL_AN0 (0)

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_drv_saadc_config_t saadc_config;
    nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);

    //Configure SAADC
    saadc_config.low_power_mode = true;                       //Enable low power mode.
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;     //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=4096 (when input voltage is 3.6V for channel gain setting of 1/6).
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;  //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;   //Set SAADC interrupt to low priority.
	
    channel_config.reference = NRF_SAADC_REFERENCE_VDD4;      // VDD/4
    channel_config.acq_time = NRF_SAADC_ACQTIME_40US ;
    channel_config.gain = NRF_SAADC_GAIN1_4 ;

    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL_AN0, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();

    ret_code_t ret_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(ret_code);

    saadc_init();
    saadc_sampling_event_init();
    saadc_sampling_event_enable();
    NRF_LOG_INFO("SAADC HAL simple example started.");

    while (1)
    {
        if(m_saadc_calibrate == true)
        {
            nrf_drv_saadc_abort();                                  // Abort all ongoing conversions. Calibration cannot be run if SAADC is busy
            NRF_LOG_INFO("SAADC calibration starting...");    //Print on UART

            while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task
            m_saadc_calibrate = false;

        }
        nrf_pwr_mgmt_run();
        NRF_LOG_FLUSH();
    }
}


/** @} */


Code(A) Log

<info> app: SAADC HAL simple example started.
<info> app: ADC event number: 0
<info> app: 2023
<info> app: 2027
<info> app: 2028
<info> app: 2032
<info> app: 2043
<info> app: SAADC calibration starting...
<info> app: CALIBRATE DONE
<info> app: ADC event number: 1
<info> app: 24576
<info> app: 8192
<info> app: 885
<info> app: 0
<info> app: 861
<info> app: ADC event number: 2
<info> app: 24576
<info> app: 8192
<info> app: 885
<info> app: 0
<info> app: 861
<info> app: ADC event number: 3
<info> app: 24576
<info> app: 8192
<info> app: 885
<info> app: 0
<info> app: 861
<info> app: ADC event number: 4
<info> app: 24576
<info> app: 8192
<info> app: 885
<info> app: 0
<info> app: 861
<info> app: ADC event number: 5
<info> app: 24576
<info> app: 8192
<info> app: 885
<info> app: 0
<info> app: 861
<info> app: SAADC calibration starting...
<info> app: CALIBRATE DONE

No log is output after that.


Code(B)

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "boards.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "app_util_platform.h"
#include "nrf_pwr_mgmt.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define SAMPLES_IN_BUFFER 5
volatile uint8_t state = 1;

static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t     m_ppi_channel;
static uint32_t              m_adc_evt_counter;
static bool                    m_saadc_calibrate = false;      


void timer_handler(nrf_timer_event_t event_type, void * p_context)
{

}


void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 400ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}


void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);

    APP_ERROR_CHECK(err_code);
}
#define SAADC_CALIBRATION_INTERVAL 5              //Determines how often the SAADC should be calibrated relative to NRF_DRV_SAADC_EVT_DONE event. E.g. value 5 will make the SAADC calibrate every fifth time the NRF_DRV_SAADC_EVT_DONE is received.
#define SAADC_SAMPLES_IN_BUFFER 1                 //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.


void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;

        if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0)               //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
        {
            m_saadc_calibrate = true;                                           // Set flag to trigger calibration in main context when SAADC is stopped
        }

        int i;
        NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);

        for (i = 0; i < SAMPLES_IN_BUFFER; i++)
        {
            NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
        }

        if(m_saadc_calibrate == false)
        {
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
            APP_ERROR_CHECK(err_code);
        }

        m_adc_evt_counter++;
    }
    else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
    {
        NRF_LOG_INFO("CALIBRATE DONE");
    }
}


#define SAADC_CHANNEL_AN0 (0)

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_drv_saadc_config_t saadc_config;
    nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);

    //Configure SAADC
    saadc_config.low_power_mode = true;                       //Enable low power mode.
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;     //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=4096 (when input voltage is 3.6V for channel gain setting of 1/6).
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;  //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;   //Set SAADC interrupt to low priority.
	
    channel_config.reference = NRF_SAADC_REFERENCE_VDD4;      // VDD/4
    channel_config.acq_time = NRF_SAADC_ACQTIME_40US ;
    channel_config.gain = NRF_SAADC_GAIN1_4 ;

    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL_AN0, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();

    ret_code_t ret_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(ret_code);

    saadc_init();
    saadc_sampling_event_init();
    saadc_sampling_event_enable();
    NRF_LOG_INFO("SAADC HAL simple example started.");

    while (1)
    {
        if(m_saadc_calibrate == true)
        {
            NRF_LOG_INFO("SAADC calibration starting...");    //Print on UART

            nrf_drv_saadc_abort();
            while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task

            nrf_drv_saadc_uninit(); //ADD(B)
            saadc_init();           //ADD(B)
            m_saadc_calibrate = false;

        }
        nrf_pwr_mgmt_run();
        NRF_LOG_FLUSH();
    }
}


/** @} */


Code(B)Log

<info> app: SAADC HAL simple example started.
<info> app: ADC event number: 0
<info> app: 2613
<info> app: 1487
<info> app: 2651
<info> app: 1551
<info> app: 2655
<info> app: SAADC calibration starting...
<info> app: ADC event number: 1
<info> app: 1228
<info> app: 2369
<info> app: 1316
<info> app: 2166
<info> app: 1473
<info> app: ADC event number: 2
<info> app: 2102
<info> app: 1668
<info> app: 1969
<info> app: 1865
<info> app: 2012
<info> app: ADC event number: 3
<info> app: 1947
<info> app: 2369
<info> app: 1316
<info> app: 2166
<info> app: 1473
<info> app: ADC event number: 4
<info> app: 2031
<info> app: 1668
<info> app: 1969
<info> app: 1865
<info> app: 2012
<info> app: ADC event number: 5
<info> app: 1934
<info> app: 2369
<info> app: 1316
<info> app: 2166
<info> app: 1473
<info> app: SAADC calibration starting...
<info> app: ADC event number: 6
<info> app: 2022
<info> app: 1905
<info> app: 2008
<info> app: 1917
<info> app: 2004
<info> app: ADC event number: 7
<info> app: 2022
<info> app: 1986
<info> app: 2007
<info> app: 1963
<info> app: 2056
<info> app: ADC event number: 8
<info> app: 1953
<info> app: 1905
<info> app: 2008
<info> app: 1917
<info> app: 2004
<info> app: ADC event number: 9
<info> app: 2025
<info> app: 1986
<info> app: 2007
<info> app: 1963
<info> app: 2056
<info> app: ADC event number: 10
<info> app: 1987
<info> app: 1905
<info> app: 2008
<info> app: 1917
<info> app: 2004
<info> app: SAADC calibration starting...

After that, log output continuously.
NRF_DRV_SAADC_EVT_CALIBRATEDONE cannot be obtained.

Parents
  • Looking at code (A) I would suggest that you comment out the 'if(m_saadc_calibrate == false)' in saadc_callback(). This should ensure that you always set the buffer using nrf_drv_saadc_buffer_convert() on NRF_DRV_SAADC_EVT_DONE. Have you tried this?

    The only thing missing from (A) should then be to call nrf_drv_saadc_calibrate_offset() from main() by checking the m_saadc_calibrate as you already do. I do not see any need to nrf_drv_saadc_abort(), nrf_drv_saadc_uninit() and saadc_init() when calling nrf_drv_saadc_calibrate_offset() from main(), since you will be calling nrf_drv_saadc_calibrate_offset() in any case between the 400ms period.Have you tried this?

  • Thank you for your reply.


    For code (A), I tried the following two lines of commenting out.

    (1). Line 100 ”// if (m_saadc_calibrate == false)”

    (2). Line 171 ”// nrf_drv_saadc_abort ();”

    As a result, log output has stopped. Reference: Code (A)-2 log

    It seems that "NRF_DRV_SAADC_EVT_DONE" is always occurring.

    Code (A)-2 log

    <info> app: SAADC HAL simple example started.
    <info> app: ADC event number: 0
    <info> app: 2037
    <info> app: 2056
    <info> app: 1999
    <info> app: 2043
    <info> app: 2046

    No output after this.


    In addition to (1) and (2) above, I commented out the following lines.

    (3). Line174 "// while (nrf_drv_saadc_calibrate_offset ()! = NRF_SUCCESS);"

    When I commented out (1), (2), and (3), the log is now output continuously. Reference: Code (A)-3 log

    Code (A)-3 log

    <info> app: SAADC HAL simple example started.
    <info> app: ADC event number: 0
    <info> app: 1996
    <info> app: 2045
    <info> app: 2041
    <info> app: 2036
    <info> app: 2023
    <info> app: ADC event number: 1
    <info> app: 2032
    <info> app: 2036
    <info> app: 2042
    <info> app: 2031
    <info> app: 2037
    <info> app: ADC event number: 2
    <info> app: 2045
    <info> app: 2045
    <info> app: 2041
    <info> app: 2036
    <info> app: 2023
    <info> app: ADC event number: 3
    <info> app: 2037
    <info> app: 2036
    <info> app: 2042
    <info> app: 2031
    <info> app: 2037
    <info> app: ADC event number: 4
    <info> app: 1999
    <info> app: 2045
    <info> app: 2041
    <info> app: 2036
    <info> app: 2023
    <info> app: ADC event number: 5
    <info> app: 2047
    <info> app: 2036
    <info> app: 2042
    <info> app: 2031
    <info> app: 2037
    <info> app: ADC event number: 6
    <info> app: 2036
    <info> app: 2045
    <info> app: 2041
    <info> app: 2036
    <info> app: 2023
    <info> app: ADC event number: 7
    <info> app: 2038
    <info> app: 2036
    <info> app: 2042
    <info> app: 2031
    <info> app: 2037
    <info> app: ADC event number: 8
    <info> app: 2039
    <info> app: 2045
    <info> app: 2041
    <info> app: 2036
    <info> app: 2023
    <info> app: ADC event number: 9
    <info> app: 1979
    <info> app: 2036
    <info> app: 2042
    <info> app: 2031
    <info> app: 2037
    <info> app: ADC event number: 10
    <info> app: 2014
    <info> app: 2045
    <info> app: 2041
    <info> app: 2036
    <info> app: 2023
    <info> app: ADC event number: 11
    <info> app: 2042
    <info> app: 2036
    <info> app: 2042
    <info> app: 2031
    <info> app: 2037
    

    Log is output continuously.


    From the above results, I presume that "nrf_drv_saadc_calibrate_offset ()" is blocking the log output.

    I think the following errata may be related to this "Code (A)-2 log" behavior.

    Erratta [237] SAADC: TASKS_CALIBRATEOFFSET shall only be used before TASKS_START or after EVENTS_END

    How can I enable calibration and get NRF_DRV_SAADC_EVT _CALIBRATEDONE?

    Best regards

  • Hi,

    I modified your code so that it can work. The problem was related to the double buffering (which made it difficult to run calibrate in a safe manner), however since you have a 400ms sample period I don't expect using single buffer will be a problem.

    Hope it helps,
    Kenneth

    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "nrf_drv_timer.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define SAMPLES_IN_BUFFER 5
    volatile uint8_t state = 1;
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
    static nrf_saadc_value_t     m_buffer_pool[1][SAMPLES_IN_BUFFER];
    static nrf_ppi_channel_t     m_ppi_channel;
    static uint32_t              m_adc_evt_counter;
    static bool                  m_saadc_calibrate = false;      
    
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 400ms */
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              timer_compare_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void saadc_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    
        APP_ERROR_CHECK(err_code);
    }
    #define SAADC_CALIBRATION_INTERVAL 5              //Determines how often the SAADC should be calibrated relative to NRF_DRV_SAADC_EVT_DONE event. E.g. value 5 will make the SAADC calibrate every fifth time the NRF_DRV_SAADC_EVT_DONE is received.
    #define SAADC_SAMPLES_IN_BUFFER 1                 //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        ret_code_t err_code;
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0)               //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
            {
                m_saadc_calibrate = true;                                           //Set flag to trigger calibration in main context when SAADC is stopped            
            }
            else         
            {
                err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
                APP_ERROR_CHECK(err_code);
            }
    
            int i;
            NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {            
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
    
            m_adc_evt_counter++;
        }
        else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {
            NRF_LOG_INFO("CALIBRATE DONE");
    
            err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    #define SAADC_CHANNEL_AN0 (0)
    
    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_drv_saadc_config_t saadc_config;
        nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
        //Configure SAADC
        saadc_config.low_power_mode = true;                       //Enable low power mode.
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;     //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=4096 (when input voltage is 3.6V for channel gain setting of 1/6).
        saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;  //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
        saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;   //Set SAADC interrupt to low priority.
    	
        channel_config.reference = NRF_SAADC_REFERENCE_VDD4;      // VDD/4
        channel_config.acq_time = NRF_SAADC_ACQTIME_40US ;
        channel_config.gain = NRF_SAADC_GAIN1_4 ;
    
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL_AN0, &channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        ret_code_t ret_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(ret_code);
    
        saadc_init();
        saadc_sampling_event_init();
        saadc_sampling_event_enable();
        NRF_LOG_INFO("SAADC HAL simple example started.");
    
        while (1)
        {
            if(m_saadc_calibrate == true)
            {
                NRF_LOG_INFO("SAADC calibration starting...");    //Print on UART
    
                while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task
                m_saadc_calibrate = false;
            }
            nrf_pwr_mgmt_run();
            NRF_LOG_FLUSH();
        }
    }
    
    
    /** @} */

Reply
  • Hi,

    I modified your code so that it can work. The problem was related to the double buffering (which made it difficult to run calibrate in a safe manner), however since you have a 400ms sample period I don't expect using single buffer will be a problem.

    Hope it helps,
    Kenneth

    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "nrf_drv_timer.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define SAMPLES_IN_BUFFER 5
    volatile uint8_t state = 1;
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
    static nrf_saadc_value_t     m_buffer_pool[1][SAMPLES_IN_BUFFER];
    static nrf_ppi_channel_t     m_ppi_channel;
    static uint32_t              m_adc_evt_counter;
    static bool                  m_saadc_calibrate = false;      
    
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 400ms */
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              timer_compare_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void saadc_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    
        APP_ERROR_CHECK(err_code);
    }
    #define SAADC_CALIBRATION_INTERVAL 5              //Determines how often the SAADC should be calibrated relative to NRF_DRV_SAADC_EVT_DONE event. E.g. value 5 will make the SAADC calibrate every fifth time the NRF_DRV_SAADC_EVT_DONE is received.
    #define SAADC_SAMPLES_IN_BUFFER 1                 //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        ret_code_t err_code;
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0)               //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
            {
                m_saadc_calibrate = true;                                           //Set flag to trigger calibration in main context when SAADC is stopped            
            }
            else         
            {
                err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
                APP_ERROR_CHECK(err_code);
            }
    
            int i;
            NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {            
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
    
            m_adc_evt_counter++;
        }
        else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {
            NRF_LOG_INFO("CALIBRATE DONE");
    
            err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    #define SAADC_CHANNEL_AN0 (0)
    
    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_drv_saadc_config_t saadc_config;
        nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
        //Configure SAADC
        saadc_config.low_power_mode = true;                       //Enable low power mode.
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;     //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=4096 (when input voltage is 3.6V for channel gain setting of 1/6).
        saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;  //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
        saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;   //Set SAADC interrupt to low priority.
    	
        channel_config.reference = NRF_SAADC_REFERENCE_VDD4;      // VDD/4
        channel_config.acq_time = NRF_SAADC_ACQTIME_40US ;
        channel_config.gain = NRF_SAADC_GAIN1_4 ;
    
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL_AN0, &channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        ret_code_t ret_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(ret_code);
    
        saadc_init();
        saadc_sampling_event_init();
        saadc_sampling_event_enable();
        NRF_LOG_INFO("SAADC HAL simple example started.");
    
        while (1)
        {
            if(m_saadc_calibrate == true)
            {
                NRF_LOG_INFO("SAADC calibration starting...");    //Print on UART
    
                while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task
                m_saadc_calibrate = false;
            }
            nrf_pwr_mgmt_run();
            NRF_LOG_FLUSH();
        }
    }
    
    
    /** @} */

Children
  • Hi, Kenneth

    Thank you for fixing the code.
    I feel very reassuring.
    I ran the code you provided and confirmed that "NRF_DRV_SAADC_EVT_CALIBRATEDONE" was occurring.

    I modified the provided code for experimentation. Reference: Code(C)

    The following setting(a) works the same as the code you provided.
    when I ran setting(c), the result was similar to setting(a).

    Also, when the following setting(b) was executed in my environment,
    the AD value was different from the setting (a) and (c),
    and an average offset of about -30 was obtained.

    If "nrf_drv_saadc_calibrate_offset()" returns NRF_SUCCESS and NRF_DRV_SAADC_EVT_CALIBRATEDONE occurs
    Is it okay to determine that the offset calibration is working properly?

    Best regards


    setting(a)

    #define USE_CALIBRATION     1
    #define RESET_ADC           0
    #define WAIT_CALIBRATE_DONE 0

    setting(b)

    #define USE_CALIBRATION     1
    #define RESET_ADC           1
    #define WAIT_CALIBRATE_DONE 0

    setting(c)

    #define USE_CALIBRATION     1
    #define RESET_ADC           1
    #define WAIT_CALIBRATE_DONE 1

    Code(C)

    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "nrf_drv_timer.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    //0: not use calibration
    //1: use calibration
    #define USE_CALIBRATION 1
    
    //0: not reset adc
    //1: reset adc
    #define RESET_ADC 0
    
    //0: not wait NRF_DRV_SAADC_EVT_CALIBRATEDONE
    //1: wait NRF_DRV_SAADC_EVT_CALIBRATEDONE
    #define WAIT_CALIBRATE_DONE 0
    
    #define SAMPLES_IN_BUFFER 5
    volatile uint8_t state = 1;
    
    
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
    static nrf_saadc_value_t     m_buffer_pool[1][SAMPLES_IN_BUFFER];
    static nrf_ppi_channel_t     m_ppi_channel;
    static uint32_t              m_adc_evt_counter;
    static bool                  m_saadc_calibrate = false;      
    
    #if WAIT_CALIBRATE_DONE == 1
    static bool                  m_saadc_calibrate_done = false;    
    #endif //WAIT_CALIBRATE_DONE
    
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 400ms */
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              timer_compare_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void saadc_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    
        APP_ERROR_CHECK(err_code);
    }
    #define SAADC_CALIBRATION_INTERVAL 5              //Determines how often the SAADC should be calibrated relative to NRF_DRV_SAADC_EVT_DONE event. E.g. value 5 will make the SAADC calibrate every fifth time the NRF_DRV_SAADC_EVT_DONE is received.
    #define SAADC_SAMPLES_IN_BUFFER 1                 //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        ret_code_t err_code;
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            m_adc_evt_counter++;
    
            if((m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0)               //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
            {
    #if USE_CALIBRATION == 1
                m_saadc_calibrate = true;                                           //Set flag to trigger calibration in main context when SAADC is stopped            
    #else
                err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
                APP_ERROR_CHECK(err_code);
    #endif //USE_CALIBRATION
            }
            else         
            {
                err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
                APP_ERROR_CHECK(err_code);
            }
    
            int i;
            //NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
            {            
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
        }
        else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {
            NRF_LOG_INFO("CALIBRATE DONE");
    
    #if RESET_ADC == 0
            err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
            APP_ERROR_CHECK(err_code);         
    #endif //RESET_ADC
    
    #if WAIT_CALIBRATE_DONE == 1
            m_saadc_calibrate_done = true;
    #endif 
        }
    }
    
    
    #define SAADC_CHANNEL_AN0 (0)
    
    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_drv_saadc_config_t saadc_config;
        nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
        //Configure SAADC
        saadc_config.low_power_mode = true;                       //Enable low power mode.
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;     //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=4096 (when input voltage is 3.6V for channel gain setting of 1/6).
        saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;  //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
        saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;   //Set SAADC interrupt to low priority.
    	
        channel_config.reference = NRF_SAADC_REFERENCE_VDD4;      // VDD/4
        channel_config.acq_time = NRF_SAADC_ACQTIME_40US ;
        channel_config.gain = NRF_SAADC_GAIN1_4 ;
    
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL_AN0, &channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        ret_code_t ret_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(ret_code);
    
        saadc_init();
        saadc_sampling_event_init();
        saadc_sampling_event_enable();
        NRF_LOG_INFO("SAADC HAL simple example started.");
    
        while (1)
        {
            if(m_saadc_calibrate == true)
            {
    #if RESET_ADC == 1
                nrf_drv_saadc_abort();
    #endif //RESET_ADC
    nrf_drv_saadc_abort();
    #if USE_CALIBRATION == 1
                NRF_LOG_INFO("SAADC calibration starting...");    //Print on UART
                while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task
    #endif //USE_CALIBRATION
    
    #if WAIT_CALIBRATE_DONE == 1
                while(m_saadc_calibrate_done == false);
                m_saadc_calibrate_done = false;
    #endif //WAIT_CALIBRATE_DONE
    
    #if RESET_ADC == 1
                nrf_drv_saadc_uninit();
                saadc_init();           
    #endif //RESET_ADC
    
                m_saadc_calibrate = false;
            }
            nrf_pwr_mgmt_run();
            NRF_LOG_FLUSH();
        }
    }
    
    
    /** @} */

    Setting(a)Log

    <info> app: SAADC HAL simple example started.
    <info> app: 2004
    <info> app: 2003
    <info> app: 2005
    <info> app: 1976
    <info> app: 2006
    <info> app: SAADC calibration starting...
    <info> app: CALIBRATE DONE
    <info> app: 2007
    <info> app: 2001
    <info> app: 2011
    <info> app: 2011
    <info> app: 2009
    <info> app: SAADC calibration starting...
    <info> app: CALIBRATE DONE

    Setting(b)Log

    <info> app: SAADC HAL simple example started.
    <info> app: 2012
    <info> app: 2004
    <info> app: 2022
    <info> app: 2005
    <info> app: 2004
    <info> app: SAADC calibration starting...
    <info> app: 1963
    <info> app: 1981
    <info> app: 1975
    <info> app: 1980
    <info> app: 1975
    <info> app: SAADC calibration starting...

    Setting(c)Log

    <info> app: SAADC HAL simple example started.
    <info> app: 2002
    <info> app: 2001
    <info> app: 2007
    <info> app: 2008
    <info> app: 2004
    <info> app: SAADC calibration starting...
    <info> app: CALIBRATE DONE
    <info> app: 2013
    <info> app: 2012
    <info> app: 2009
    <info> app: 2005
    <info> app: 2007
    <info> app: SAADC calibration starting...
    <info> app: CALIBRATE DONE

  • Hi,

    The offset calibration seems to work as intended here, the reason why it may do a small "hop" in values when doing offset calibration is that it may be between two calibration steps.

    Best regards,
    Kenneth

  • Hi, Kenneth

    Thanks for the reply.

    I will try the useful information you have given me.

Related