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

nrfx_saadc_uninit() do not work when use SAADC's differential mode with SDK17.0.2, nrf52832, using NRFX_SAADC_API_V2

Hi, dear Nordic & all:

I found nrfx_saadc_uninit() did not work when use SAADC's differential mode with SDK17.0.2, nrf52832, the fellowing is saadc init and configuration code:

static nrfx_saadc_channel_t channels[SAADC_CHANNEL_TOTAL_COUNT] = {NRFX_SAADC_DEFAULT_CHANNEL_DIFFERENTIAL(NRF_SAADC_INPUT_AIN0, NRF_SAADC_INPUT_AIN1, 0),
                                                                   NRFX_SAADC_DEFAULT_CHANNEL_DIFFERENTIAL(NRF_SAADC_INPUT_AIN2, NRF_SAADC_INPUT_AIN3, 1)};

void saadc_event_handler(nrfx_saadc_evt_t const * p_event)
{
    float val = 180.0 / 3.14159265358979323846;
	uint32_t err_code;
    if (p_event->type == NRFX_SAADC_EVT_DONE)
    {
        //NRF_LOG_INFO("ADC Values: %6d %6d",p_event->data.done.p_buffer[0], p_event->data.done.p_buffer[1]);

        data = -atan2(p_event->data.done.p_buffer[0], p_event->data.done.p_buffer[1])*val + 180;
        //NRF_LOG_INFO("float data:"NRF_LOG_FLOAT_MARKER"\n",NRF_LOG_FLOAT(data));

        if (data > prev_angle)
        {
            if (prev_angle > 270)
              positive_direction_judge[2] = true;
            else if (prev_angle > 180)
              positive_direction_judge[1] = true;
            else if (prev_angle > 90)
              positive_direction_judge[0] = true;

            if (prev_angle > 355.00 && positive_direction_judge[0] && positive_direction_judge[1] && positive_direction_judge[2])
            {
                m_angle.turns++;
                memset(positive_direction_judge, false, 3);
                memset(negative_direction_judge, false, 3);
                prev_angle = 360;
            }
        
        }

        if (data < prev_angle)
        {
            if (prev_angle < 90)
              negative_direction_judge[2] = true;
            else if (prev_angle < 180)
              negative_direction_judge[1] = true;
            else if (prev_angle < 270)
              negative_direction_judge[0] = true;

            if (prev_angle < 5.00 && negative_direction_judge[0] && negative_direction_judge[1] && negative_direction_judge[2])
            {
                m_angle.turns--;
                memset(positive_direction_judge, false, 3);
                memset(negative_direction_judge, false, 3);
                prev_angle = 0;
            }
        
        }


        m_angle.integer_part = (uint16_t)data; 
        m_angle.decimal_part = (data - m_angle.integer_part) * 100;

        prev_angle = data;

        //NRF_LOG_INFO("turns: %d, integer: %d, decimal: %d", m_angle.turns, m_angle.integer_part, m_angle.decimal_part);
        if(is_frist_time){
        
            x_initial_value = p_event->data.done.p_buffer[0];
            y_initial_value = p_event->data.done.p_buffer[1];

            x_amplitude_max = x_amplitude_min = x_initial_value;
            y_amplitude_max = y_amplitude_min = y_initial_value;
      
            is_frist_time = false;
        }else 
        {
            x_value = p_event->data.done.p_buffer[0];
            y_value = p_event->data.done.p_buffer[1];
          
        
        }
    }	

    //ct310_data_send_schedule();
    nrfx_saadc_uninit();
    /* Applying workaround from Errata 212, otherwise current is stuck at 4-500uA during sleep after first sample. */
//    volatile uint32_t temp1;
//    volatile uint32_t temp2;
//    volatile uint32_t temp3;
//
//    temp1 = *(volatile uint32_t *)0x40007640ul;
//    temp2 = *(volatile uint32_t *)0x40007644ul;
//    temp3 = *(volatile uint32_t *)0x40007648ul;
//
//    *(volatile uint32_t *)0x40007FFCul = 0ul; 
//    *(volatile uint32_t *)0x40007FFCul; 
//    *(volatile uint32_t *)0x40007FFCul = 1ul;
//
//    *(volatile uint32_t *)0x40007640ul = temp1;
//    *(volatile uint32_t *)0x40007644ul = temp2;
//    *(volatile uint32_t *)0x40007648ul = temp3;
}

void saadc_configure_init_and_sample(void * p_event_data, uint16_t event_size)
{
    uint32_t err_code;
    err_code = nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_saadc_channels_config(channels, SAADC_CHANNEL_TOTAL_COUNT);
    APP_ERROR_CHECK(err_code);

	err_code = nrfx_saadc_simple_mode_set((1<<0|1<<1),
                                              NRF_SAADC_RESOLUTION_12BIT,
                                              NRF_SAADC_OVERSAMPLE_4X,
                                              saadc_event_handler);
	APP_ERROR_CHECK(err_code);
	
	err_code = nrfx_saadc_buffer_set(samples, SAADC_CHANNEL_TOTAL_COUNT);
	APP_ERROR_CHECK(err_code);

	err_code = nrfx_saadc_mode_trigger();
	APP_ERROR_CHECK(err_code);

}

and my main function is:

void stop_sample(void)
{

    nrfx_saadc_uninit();

}

int main(void)
{

    bool erase_bonds;

    // Initialize.

//    lfclk_config();
//    rtc_config();

    log_init();
    scheduler_init();

    user_times_init();
    power_management_init();

    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

//    NRF_LOG_INFO("Debug logging for UART over RTT started.");
    advertising_start();

    //user_times_start();

    saadc_configure_init_and_sample(NULL, NULL);
    // Enter main loop.
    for (;;)
    {   
        stop_sample();
        app_sched_execute();
        idle_state_handle();
    }
}

I called just one time before for(;;), then I will call nrfx_saadc_uninit() in saadc_event_handler() to stop it , but It didn't work, So I call this in for(;;) all the time to make sure it is uninited, but It is still don't work, now the power consumption added 7mA, it‘s very high and abnormal!

So, Why  nrfx_saadc_uninit() do not work?

Thanks for your kind suggestion and best regards.

Parents
  • Hi

    I am not sure how well it works to uninitialize the driver in the callback function, and if you do it in the for loop you will try to uninitialize the driver before the first operation is even complete. 

    Could you try to set a flag in the callback function that signals that the ADC operation is complete, and check this flag in the for loop before you uninitialize the ADC?

    Something like this:

    // Declare flag
    static volatile bool adc_operation_completed = false;
    
    // At the end of the adc callback
    adc_operation_completed = true;
    
    // Inside the for loop
    if(adc_operation_completed)
    {
        adc_operation_completed = false;
        stop_sample();
    }

    Alternatively you can schedule the call to stop_sample() from the adc callback by using the app_scheduler, so that the uninit function will not be run from interrupt context. 

    Best regards
    Torbjørn

Reply
  • Hi

    I am not sure how well it works to uninitialize the driver in the callback function, and if you do it in the for loop you will try to uninitialize the driver before the first operation is even complete. 

    Could you try to set a flag in the callback function that signals that the ADC operation is complete, and check this flag in the for loop before you uninitialize the ADC?

    Something like this:

    // Declare flag
    static volatile bool adc_operation_completed = false;
    
    // At the end of the adc callback
    adc_operation_completed = true;
    
    // Inside the for loop
    if(adc_operation_completed)
    {
        adc_operation_completed = false;
        stop_sample();
    }

    Alternatively you can schedule the call to stop_sample() from the adc callback by using the app_scheduler, so that the uninit function will not be run from interrupt context. 

    Best regards
    Torbjørn

Children
No Data
Related