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

NRF_DRV_SAADC_EVT_LIMIT is not triggered

Hi all

I want to trigger a limit event on a signal, which I receive on AIN0. Since the signal does not always have the same baseline, I set the limits with the first measurement and change if it is exceeded by 5% in any direction. Once this occurred, the operating mode of my device is changed and the new limits are set again from the new measurement. However, I noticed that NRF_DRV_SAADC_EVT_LIMIT never gets triggered. I read that this is always active and usually just ignored or set to the highest or lowest possible value so it does not interfere. But clearly something is wrong with my code. I would expect that once I exceed the limit shown in the log, I would get a message in the log "NRF_DRV_SAADC_EVT_LIMIT" and some additional messages from my operation_state() function. But this never happens.

Can you help me? Thanks!

My saadc_init:

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

    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

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

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

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    
    err_code = app_timer_start(m_opstate_interval_timer_id, APP_TIMER_TICKS(opstate_interval), NULL);
    APP_ERROR_CHECK(err_code);
}

My saadc_callback:

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    ret_code_t err_code;
    float mean_f;
    uint16_t limit_l, limit_h;
    
    switch (p_event->type)
    {
	case NRF_DRV_SAADC_EVT_DONE:
	    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
	    APP_ERROR_CHECK(err_code);

	    for (uint8_t i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
	    {
		mean_f += p_event->data.done.p_buffer[i] / (float)SAADC_SAMPLES_IN_BUFFER;
		NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
	    }
	    //NRF_LOG_INFO(NRF_LOG_FLOAT_MARKER, NRF_LOG_FLOAT(mean_f));
	    if (saadc_setlimits) 
	    {
		saadc_setlimits = false;
		limit_l = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_LL);
		limit_h = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_HL);
		nrf_saadc_channel_limits_set(NRF_SAADC_INPUT_AIN0, limit_l, limit_h);
		NRF_LOG_INFO("Limits set initially to: %d, %d", limit_l, limit_h);
	    }
	    
	    
	    //m_supply_fb = true;
	break;
	
	case NRF_DRV_SAADC_EVT_LIMIT:
	    NRF_LOG_INFO("NRF_DRV_SAADC_EVT_LIMIT")
	    switch(p_event->data.limit.limit_type)
	    {
		case NRF_SAADC_LIMIT_LOW:
		    if (op_state_on) 
		    {
			for (uint8_t i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
			{
			    mean_f += p_event->data.done.p_buffer[i] / (float)SAADC_SAMPLES_IN_BUFFER;
			}
			
			limit_l = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_LL);
			limit_h = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_HL);
			nrf_saadc_channel_limits_set(NRF_SAADC_INPUT_AIN0, limit_l, limit_h);
			
			operation_state(false);
		    }
		break;
		case NRF_SAADC_LIMIT_HIGH:
		    if (!op_state_on) {
			for (uint8_t i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
			{
			    mean_f += p_event->data.done.p_buffer[i] / (float)SAADC_SAMPLES_IN_BUFFER;
			}
			
			limit_l = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_LL);
			limit_h = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_HL);
			nrf_saadc_channel_limits_set(NRF_SAADC_INPUT_AIN0, limit_l, limit_h);
			
			operation_state(true);
		    }
		break;
	    }
	break;
    }
}

And finally the output of the log:

<info> app: 369
<info> app: Limits set initially to: 350, 387
<info> app: 368
<info> app: 370
<info> app: 369
<info> app: 370
<info> app: 369
<info> app: 368
<info> app: 368
<info> app: 369
<info> app: 370
<info> app: 369
<info> app: 339
<info> app: 280
<info> app: 280
<info> app: 279
<info> app: 338
<info> app: 427
<info> app: 460
<info> app: 458
<info> app: 457
<info> app: 457
<info> app: 397
<info> app: 398
<info> app: 266

Parents Reply Children
  • Thanks, that was it. 

    Also, I noted that NRF_DRV_SAADC_EVT_LIMIT does not provide data, so I had to set a flag to do the limit calculations only on NRF_DRV_SAADC_EVT_DONE. My callback now looks like this:

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        ret_code_t err_code;
        float mean_f;
        uint16_t limit_l, limit_h;
        
        switch (p_event->type)
        {
    	case NRF_DRV_SAADC_EVT_DONE:
    	    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
    	    APP_ERROR_CHECK(err_code);
    
    	    for (uint8_t i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
    	    {
    		mean_f += p_event->data.done.p_buffer[i] / (float)SAADC_SAMPLES_IN_BUFFER;
    		NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
    	    }
    	    //NRF_LOG_INFO(NRF_LOG_FLOAT_MARKER, NRF_LOG_FLOAT(mean_f));
    	    if (saadc_setlimits) 
    	    {
    		saadc_setlimits = false;
    		limit_l = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_LL);
    		limit_h = (uint16_t) (mean_f * OP_STATE_MULTIPLIER_HL);
    		nrf_drv_saadc_limits_set(0, limit_l, limit_h);
    		NRF_LOG_INFO("Limits set to: %d, %d", limit_l, limit_h);
    	    }
    	break;
    	
    	case NRF_DRV_SAADC_EVT_LIMIT:
    	    NRF_LOG_INFO("NRF_DRV_SAADC_EVT_LIMIT")
    	    switch(p_event->data.limit.limit_type)
    	    {
    		case NRF_SAADC_LIMIT_LOW:
    		    operation_state(false);
    		    saadc_setlimits = true;
    		break;
    		case NRF_SAADC_LIMIT_HIGH:
    		    if (!op_state_on) {
    			operation_state(true);
    			saadc_setlimits = true;
    		    }
    		break;
    	    }
    	break;
        }
    }

Related