Upper and lower limit interrupt events in [nrfx_saadc_limits_set ]

hi,In SAADC sampling, the upper limit and lower limit of sampling results are set. Interrupt events are generated only when they are less than the lower limit or greater than the upper limit. But in my code, as long as the sampling ends, it will generate an interrupt event. What's the problem?

17.0.2sdk,52833

The general functions are as follows:
1. ADC sampling result > = 500, generates upper limit interrupt event and wakes up;
2. ADC sampling result < = 300, generates lower limit interrupt event and wakes up;
3.300 < ADC sampling result < 500, sleep;


int main(void)
{
	ret_code_t ret;
	
	NRF_UICR->NFCPINS = 0; 				

	gpio_output_voltage_setup_3v3();
 	UART_Init();
	
    log_init();
	printf("\r\n***************************************************\r\n");
	 
	ret = nrf_drv_clock_init();
	APP_ERROR_CHECK(ret);
	nrf_drv_clock_lfclk_request(NULL);
	
    timers_init();

    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
	
    // Start execution.
    NRF_LOG_INFO("Debug logging for UART over RTT started.");
    advertising_start();

	saadc__limit_init();
	#define BAT_ADC_POWER_PIN				NRF_GPIO_PIN_MAP(0,23)
	nrf_gpio_cfg_output(BAT_ADC_POWER_PIN);
	nrf_gpio_pin_set(BAT_ADC_POWER_PIN);	
	

    for (;;)
    {
		nrf_delay_ms(500);

		nrfx_saadc_sample();
		printf("into idle state\n");
		nrf_delay_ms(10);
		idle_state_handle();
    }
}




#define 						SAMPLES_BUFFER_LEN 1
static nrf_saadc_value_t     	m_buffer_pool[2][SAMPLES_BUFFER_LEN];
static uint32_t       			m_adc_evt_counter;


void saadc_callback(nrfx_saadc_evt_t const * p_event)
{
	float  val;  
	  
	if (p_event->type == NRFX_SAADC_EVT_DONE)
    {
        ret_code_t err_code;

		err_code = nrfx_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_BUFFER_LEN);
        APP_ERROR_CHECK(err_code);
        int i;
			  
        printf("\r\nADC event number: %d\r\n", (int)m_adc_evt_counter);

        for (i = 0; i < SAMPLES_BUFFER_LEN; i++)
        {
            
			printf("Sample value: %d    ", p_event->data.done.p_buffer[i]);

			      
			val = p_event->data.done.p_buffer[i] * 3.6 /1024;	
			printf("Voltage = %.3fV\r\n", val);
        }
        
		m_adc_evt_counter++;
    }

	if(p_event->type == NRF_DRV_SAADC_EVT_LIMIT)
	{
		printf("Limit Event\r\n");
	}
}


void saadc__limit_init(void)
{
  ret_code_t err_code;

  nrf_saadc_channel_config_t channel_config =
  NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN3);

  nrfx_saadc_limits_set(0,300,500);
 
  nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
  saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT;
  saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
  saadc_config.low_power_mode = false;
  saadc_config.interrupt_priority = 6;
  err_code = nrfx_saadc_init(&saadc_config, saadc_callback);

  err_code = nrfx_saadc_channel_init(0, &channel_config);
  APP_ERROR_CHECK(err_code);

  err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_BUFFER_LEN);
  APP_ERROR_CHECK(err_code);

  err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_BUFFER_LEN);
  APP_ERROR_CHECK(err_code);
}



In nrfx_ In the SAADC. C document, I have enabled the [nrf_saadc_int_ch3limit nrf_saadc_int_ch3limit] interrupt,see the #if ,

nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config,
                           nrfx_saadc_event_handler_t  event_handler)
{
    NRFX_ASSERT(p_config);
    NRFX_ASSERT(event_handler);
    nrfx_err_t err_code;

    if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
    {
        err_code = NRFX_ERROR_INVALID_STATE;
        NRFX_LOG_WARNING("Function: %s, error code: %s.",
                         __func__,
                         NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }

    m_cb.event_handler = event_handler;
    nrf_saadc_resolution_set(p_config->resolution);
    nrf_saadc_oversample_set(p_config->oversample);
    m_cb.low_power_mode       = p_config->low_power_mode;
    m_cb.state                = NRFX_DRV_STATE_INITIALIZED;
    m_cb.adc_state            = NRF_SAADC_STATE_IDLE;
    m_cb.active_channels      = 0;
    m_cb.limits_enabled_flags = 0;
    m_cb.conversions_end      = false;

    nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
    nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
    nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
    nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);

	#if 1
	nrf_saadc_event_clear(NRF_SAADC_EVENT_CH3_LIMITH);
	nrf_saadc_event_clear(NRF_SAADC_EVENT_CH3_LIMITL);

	#endif
	
    NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, p_config->interrupt_priority);
    NRFX_IRQ_ENABLE(SAADC_IRQn);

#if 1
    nrf_saadc_int_enable(NRF_SAADC_INT_CH3LIMITH|NRF_SAADC_INT_CH3LIMITL);
#else
    nrf_saadc_int_enable(NRF_SAADC_INT_END);

    if (m_cb.low_power_mode)
    {
        nrf_saadc_int_enable(NRF_SAADC_INT_STARTED);
    }
#endif

    nrf_saadc_enable();

    err_code = NRFX_SUCCESS;
    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));

    return err_code;
}

thanks

  • Hello,

    But in my code, as long as the sampling ends, it will generate an interrupt event. What's the problem?

    I am not sure that I understand your issue exactly, could you elaborate what you mean by this? Are you saying that the limit events are being generated as expected, but when you stop the sampling you are still seeing limit events come in?
    If so, we will need to take a look at how you stop the sampling.

    3.300 < ADC sampling result < 500, sleep;

    I do not understand what you mean by this either - should the device go into sleep mode after 3300 SAADC samples?
    Please clarify or elaborate on what you mean by this line.

    I notice in your code that you are using a mix of the nrfx_saadc driver and calls to the saadc HAL directly.
    In general, it is not recommended to do direct register manipulation and/or use HAL functions in combination with the drivers, because this may place the driver in an invalid state or lead to other breakage.
    Please change to either only use HAL functions, or only use the nrfx_saadc driver functions - I recommend the latter, unless there are any specific reasons for opting for the HAL functions.

    Best regards,
    Karl

  • I want to achieve the following functions:
    In 52833sleep mode, SAADC continues to work. When ADC > = 500 or ADC value < = 300, wake up 52833; 300 < ADC < 500, continue sleep.

    I don't know what's wrong with my code。

    thanks.

  • Ok, thank you for elaborating - now I understand what you would like to achieve.
    Could you now detail what you are currently observing? From the start of your ticket I get the impression that you are able to get limit events, is this not the case?
    What do you mean by the following line?

    But in my code, as long as the sampling ends, it will generate an interrupt event.

    can23 said:
    I don't know what's wrong with my code。

    As mentioned you should not use a mix of both HAL and nrfx_driver functions in your program. Accessing the HAL or registers directly may place the driver in an invalid state, or break it.
    Please switch to only using one of the two in your code, and see if this resolves the issue you are seeing. I recommend that you switch to only using the nrfx_driver.

    Best regards,
    Karl

  • hi karl,

    In the [nrf5_sdk_17.0.2_d674dde \ examples \ peripheral \ SAADC \ pca10100] code, threshold sampling is added. When the SAADC value is < = 380 or > = 420, a callback event is generated to wake up 52833. It is found that after each SAADC, no matter what the SAADC value is, a callback event will be generated, and I have closed [nrf_saadc_int_end] in [nrfx_saadc_init] to interrupt, How can I set it so that only the threshold value will generate a callback event, while other values will not?

    thanks

  • can23 said:
    It is found that after each SAADC, no matter what the SAADC value is, a callback event will be generated, and I have closed [nrf_saadc_int_end] in [nrfx_saadc_init] to interrupt, How can I set it so that only the threshold value will generate a callback event, while other values will not?

    From your code in the original ticket you have a sample buffer length of 1, and from the code in the screenshot you just included it seems that you disable all interrupts and then re-enable the interrupts for limits and the end event.
    The end event will be generated when the SAADC has filled up the provided buffer - which in your case is after 1 sample.
    Please try to increase your buffer length, and see if this changes the situation.

    Please also keep in mind that modifying the nrfx_saadc.c driver directly might break it, since other parts of its functionality depends on the range of different events being generated.

    can23 said:
    How can I set it so that only the threshold value will generate a callback event, while other values will not?

    Please also note that the CPU will wake up from SYSTEM_ON sleep whenever an event is generated - regardless of which peripheral generated the event. So, if you have other peripherals running in your application they might also generate an event and wake the CPU at any other time.

    Best regards,
    Karl

Related