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

saadc with oversampling + burst with multiple channel failing

hello Slight smile

i am working with nrf52832, s132, sdk 16.0

i am trying to init 3 channels with OVERSUMPELING and BURST enabled:

"

    nrf_drv_saadc_config_t saadc_config;

    //Configure SAADC
    saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT; 
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X; 
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;

    nrf_saadc_channel_config_t channel_config_0 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    nrf_saadc_burst_set(0, NRF_SAADC_BURST_ENABLED);
    nrf_saadc_channel_config_t channel_config_1 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
    nrf_saadc_burst_set(1, NRF_SAADC_BURST_ENABLED);
    nrf_saadc_channel_config_t channel_config_2 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    nrf_saadc_burst_set(2, NRF_SAADC_BURST_ENABLED);

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

   SET_TO_BATTERY_ADC_CHECK
   err_code = nrf_drv_saadc_channel_init(0, &channel_config_0);
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_saadc_channel_init(1, &channel_config_1);
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_saadc_channel_init(2, &channel_config_2);
   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);

"

it falls in channel_1 init attempt:

<error> app: ASSERTION FAILED at c:\Nordik SDK\modules\nrfx\drivers\src\nrfx_saadc.c:294<CR><CR><LF>

so 2 questions: 

1. how can i configure and init 3 channels with OVERSAMPLING and BURST enable to be read from the 'saadc_callback' one after the other 

2. if i configure and init only one channel as OVERSAMPLING and BURST can i change the pin in the 'saadc_callback' handler ?

i have tried and it allways falls back to line 294 in the nrfx_saadc.c assertion when i try to init the channel again after uniniting it :

"

     NRF_LOG_INFO("battery: %d", p_event->data.done.p_buffer[0]);
     nrfx_saadc_channel_uninit(0);
     channel_config0.pin_p = NRF_SAADC_INPUT_AIN1;
     err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
     APP_ERROR_CHECK(err_code);

"

best regards

Ziv

Parents
  • From Oversampling
    "Oversampling and scan should not be combined, since oversampling and scan will average over input channels." 

    From nrfx_saadc.c line 293:

    // Oversampling can be used only with one channel.
        NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) || (m_cb.active_channels == 0));


    You have to configure only one channel at a time when you've enabled oversampling or configure all three channels and average in SW. 

  • i have change the nrfx_saadc.c line 294 to 

    NRFX_ASSERT((nrf_saadc_oversample_get() != NRF_SAADC_OVERSAMPLE_DISABLED) ||

    and it works fine

    its very limiting if one needs to use several channels and wants to have oversampling for better accuracy

    if there is no intention of changing that on nordic side it is possible to close this questions

  • Are you sure your sampled values are correct?

    I suggest your tie one of the inputs to VDD, another to GND, and leave the third as is, then compare the results.

  • i have done just that and it worked .. i am not sure this will be the final structire of the code since i actualy wish to have seperate handler and read time for each input but for now it works, there s the code i

    "

    void saadc_init(void)
    {
    ret_code_t err_code;
    nrf_drv_saadc_config_t saadc_config;
    nrf_saadc_channel_config_t channel_config0;

    //Configure SAADC
    saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT; //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=2048 (when input voltage is 3.6V for channel gain setting of 1/6).
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X; //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.
    saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;

    //Configure SAADC channel
    channel_config0.reference = NRF_SAADC_REFERENCE_INTERNAL; //Set internal reference of fixed 0.6 volts
    channel_config0.gain = NRF_SAADC_GAIN1_6; //Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V
    channel_config0.acq_time = NRF_SAADC_ACQTIME_10US; //Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz. Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS.
    channel_config0.mode = NRF_SAADC_MODE_SINGLE_ENDED; //Set SAADC as single ended. This means it will only have the positive pin as input, and the negative pin is shorted to ground (0V) internally.
    channel_config0.pin_p = NRF_SAADC_INPUT_AIN0; //Select the input pin for the channel. AIN0 pin maps to physical pin P0.02.
    channel_config0.pin_n = NRF_SAADC_INPUT_DISABLED; //Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
    channel_config0.resistor_p = NRF_SAADC_RESISTOR_DISABLED; //Disable pullup resistor on the input pin
    channel_config0.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
    channel_config0.burst = NRF_SAADC_BURST_ENABLED;


    //Initialize SAADC
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    // err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
    // APP_ERROR_CHECK(err_code);
    // SET_TO_BATTERY_ADC_CHECK
    err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
    APP_ERROR_CHECK(err_code);
    channel_config0.pin_p = NRF_SAADC_INPUT_AIN1;
    err_code = nrf_drv_saadc_channel_init(1, &channel_config0);
    APP_ERROR_CHECK(err_code);
    channel_config0.pin_p = NRF_SAADC_INPUT_AIN2;
    err_code = nrf_drv_saadc_channel_init(2, &channel_config0);
    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);

    }

    "

    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)
    {
    nrf_pwr_mgmt_run();
    NRF_LOG_FLUSH();
    }
    "

    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;

    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);


    uint16_t battery_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[0])*3600)/1024);
    uint16_t irri_level_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[1])*3600)/1024);
    uint16_t evac_level_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[2])*3600)/1024);

    NRF_LOG_INFO("battery: %d",battery_val);
    NRF_LOG_INFO("irri level: %d", irri_level_val);
    NRF_LOG_INFO("evac level: %d", evac_level_val);
    }
    }

    besicaly i need to be reading one pin as battery input and the other 2 are analog sensors that i am now searching to understand how to use the limit low/high event 

    Ziv :)

Reply
  • i have done just that and it worked .. i am not sure this will be the final structire of the code since i actualy wish to have seperate handler and read time for each input but for now it works, there s the code i

    "

    void saadc_init(void)
    {
    ret_code_t err_code;
    nrf_drv_saadc_config_t saadc_config;
    nrf_saadc_channel_config_t channel_config0;

    //Configure SAADC
    saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT; //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=2048 (when input voltage is 3.6V for channel gain setting of 1/6).
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X; //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.
    saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;

    //Configure SAADC channel
    channel_config0.reference = NRF_SAADC_REFERENCE_INTERNAL; //Set internal reference of fixed 0.6 volts
    channel_config0.gain = NRF_SAADC_GAIN1_6; //Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V
    channel_config0.acq_time = NRF_SAADC_ACQTIME_10US; //Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz. Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS.
    channel_config0.mode = NRF_SAADC_MODE_SINGLE_ENDED; //Set SAADC as single ended. This means it will only have the positive pin as input, and the negative pin is shorted to ground (0V) internally.
    channel_config0.pin_p = NRF_SAADC_INPUT_AIN0; //Select the input pin for the channel. AIN0 pin maps to physical pin P0.02.
    channel_config0.pin_n = NRF_SAADC_INPUT_DISABLED; //Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
    channel_config0.resistor_p = NRF_SAADC_RESISTOR_DISABLED; //Disable pullup resistor on the input pin
    channel_config0.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
    channel_config0.burst = NRF_SAADC_BURST_ENABLED;


    //Initialize SAADC
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    // err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
    // APP_ERROR_CHECK(err_code);
    // SET_TO_BATTERY_ADC_CHECK
    err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
    APP_ERROR_CHECK(err_code);
    channel_config0.pin_p = NRF_SAADC_INPUT_AIN1;
    err_code = nrf_drv_saadc_channel_init(1, &channel_config0);
    APP_ERROR_CHECK(err_code);
    channel_config0.pin_p = NRF_SAADC_INPUT_AIN2;
    err_code = nrf_drv_saadc_channel_init(2, &channel_config0);
    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);

    }

    "

    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)
    {
    nrf_pwr_mgmt_run();
    NRF_LOG_FLUSH();
    }
    "

    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;

    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);


    uint16_t battery_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[0])*3600)/1024);
    uint16_t irri_level_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[1])*3600)/1024);
    uint16_t evac_level_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[2])*3600)/1024);

    NRF_LOG_INFO("battery: %d",battery_val);
    NRF_LOG_INFO("irri level: %d", irri_level_val);
    NRF_LOG_INFO("evac level: %d", evac_level_val);
    }
    }

    besicaly i need to be reading one pin as battery input and the other 2 are analog sensors that i am now searching to understand how to use the limit low/high event 

    Ziv :)

Children
Related