SAADC Oversampling and Event monitoring using limits

i need help.

We use nrf52840 and DK17.0.2

Using  saadc with oversampling  x8 ,  Single-ended mode.

Question

When Event monitoring using limits , Is the timing at which the conversion results are compared after averaging?
Or will it be compared for each sampling?

Processing to exclude when it is out of range even once before being averaged thinking about.

Best Regards,

take.

  • Hi,

    The Limit event is not generated until after averaging (when END event is generated).

    I just verified this using the following code (modified from https://github.com/andenore/NordicSnippets/blob/master/examples/saadc/main.c):

    /**
     * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup nrf_adc_example main.c
     * @{
     * @ingroup nrf_adc_example
     * @brief ADC Example Application main file.
     *
     * This file contains the source code for a sample application using ADC.
     *
     * @image html example_board_setup_a.jpg "Use board setup A for this example."
     */
    
    #include <nrf.h>
    
    int main(void)
    {
      volatile int16_t result = 0;
      static int16_t sample_count = 0;
      volatile float precise_result = 0;
    
      // Start HFCLK from crystal oscillator, this will give the SAADC higher accuracy
      NRF_CLOCK->TASKS_HFCLKSTART = 1;
      while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
      NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    
      // Configure SAADC singled-ended channel, Internal reference (0.6V) and 1/6 gain.
      NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_6    << SAADC_CH_CONFIG_GAIN_Pos) |
                                (SAADC_CH_CONFIG_MODE_SE         << SAADC_CH_CONFIG_MODE_Pos) |
                                (SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
                                (SAADC_CH_CONFIG_RESN_Bypass     << SAADC_CH_CONFIG_RESN_Pos) |
                                (SAADC_CH_CONFIG_RESP_Bypass     << SAADC_CH_CONFIG_RESP_Pos) |
                                (SAADC_CH_CONFIG_TACQ_10us        << SAADC_CH_CONFIG_TACQ_Pos);
    
      // Configure the SAADC channel with VDD as positive input, no negative input(single ended).
      NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0 << SAADC_CH_PSELP_PSELP_Pos;
      NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    
      NRF_SAADC->CH[0].LIMIT = (3000 << SAADC_CH_LIMIT_HIGH_Pos) | (500 << SAADC_CH_LIMIT_LOW_Pos);
    
      // Configure the SAADC resolution.
      NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_12bit << SAADC_RESOLUTION_VAL_Pos;
      NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Over8x << SAADC_OVERSAMPLE_OVERSAMPLE_Pos;
    
      // Configure result to be put in RAM at the location of "result" variable.
      NRF_SAADC->RESULT.MAXCNT = 1;
      NRF_SAADC->RESULT.PTR = (uint32_t)&result;
    
      // No automatic sampling, will trigger with TASKS_SAMPLE.
      NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;
    
      // Enable SAADC (would capture analog pins if they were used in CH[0].PSELP)
      NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos;
    
      // Calibrate the SAADC (only needs to be done once in a while)
      NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
      while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0);
      NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
      while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy <<SAADC_STATUS_STATUS_Pos));
    
      // Start the SAADC and wait for the started event.
      NRF_SAADC->TASKS_START = 1;
      while (NRF_SAADC->EVENTS_STARTED == 0);
      NRF_SAADC->EVENTS_STARTED = 0;
    
      NRF_SAADC->EVENTS_CH[0].LIMITH = 0;
      NRF_SAADC->EVENTS_CH[0].LIMITL = 0;
      NRF_SAADC->EVENTS_DONE = 0;
    
      // Do a SAADC sample, will put the result in the configured RAM buffer.
      while(NRF_SAADC->EVENTS_CH[0].LIMITH == 0 && NRF_SAADC->EVENTS_CH[0].LIMITL == 0)
      {
        NRF_SAADC->TASKS_SAMPLE = 1;
        while(NRF_SAADC->EVENTS_DONE == 0);
        sample_count++;
        NRF_SAADC->EVENTS_DONE = 0;
      }
      while (NRF_SAADC->EVENTS_END == 0);
      sample_count = sample_count;
      NRF_SAADC->EVENTS_END = 0;
    
      // Convert the result to voltage
      // Result = [V(p) - V(n)] * GAIN/REFERENCE * 2^(RESOLUTION)
      // Result = (VDD - 0) * ((1/6) / 0.6) * 2^14
      // VDD = Result / 4551.1
      precise_result = (float)result / 4551.1f;
      precise_result; // to get rid of set but not used warning
    
      // Stop the SAADC, since it's not used anymore.
      NRF_SAADC->TASKS_STOP = 1;
      while (NRF_SAADC->EVENTS_STOPPED == 0);
      NRF_SAADC->EVENTS_STOPPED = 0;
    
    
      while (1)
      {
        __WFE();
      }
    }
    

    The sample_count variable is 8 after the LIMITH/LIMITL events is generated, if the input pin is connected to GND or VDD before running the application.

    Best regards,
    Jørgen

  • I'm sorry for the late reply.

     I understand.
    Thank you very much.

Related