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

I used two channel saadc, but not all the time the same channel adc value has same index.

I used 2 channel saadc, channel 1 and channel 3.

Maybe in the first few minutes, it's done ok,

p_event->data.done.p_buffer[0] is belong channel1 adc value

p_event->data.done.p_buffer[1] is belong channel3 adc value

but, it will run error,

p_event->data.done.p_buffer[0] is belong channel3 adc value

p_event->data.done.p_buffer[1] is belong channel1 adc value

#define SAMPLE_CHANNEL_CNT                                           2
#define SAMPLE_CNT      			                                2

#define ADC_TASK_TIMER                                  APP_TIMER_TICKS(3)
APP_TIMER_DEF(m_adc_task_timer_id);             

/*<adc sample value buffer*/
static nrf_saadc_value_t       m_buffer[SAMPLE_CHANNEL_CNT][SAMPLE_CNT];

static void adc_timeout_handler(void* p_context);
static void saadc_callback(nrf_drv_saadc_evt_t const * p_event);

void saadc_module_init(void)
{
    ret_code_t err_code;
    
    nrfx_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_14BIT;
    saadc_config.interrupt_priority = 1;       
    saadc_config.low_power_mode = false;
    
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);
    
    // do a calibrate
    while (nrf_drv_saadc_calibrate_offset() != NRFX_SUCCESS)
        nrf_delay_ms(10);
    while (nrf_drv_saadc_is_busy())
        nrf_delay_ms(10);
    
    pressure_adc_init();
    battery_saadc_init();
    
    err_code = nrf_drv_saadc_buffer_convert(m_buffer[0], SAMPLE_CNT);
    APP_ERROR_CHECK(err_code);  
    err_code = nrf_drv_saadc_buffer_convert(m_buffer[1], SAMPLE_CNT);
    APP_ERROR_CHECK(err_code);  
    
    err_code = app_timer_create(&m_adc_task_timer_id, APP_TIMER_MODE_REPEATED, adc_timeout_handler);
    APP_ERROR_CHECK(err_code);  
}

void saadc_module_start(void)
{
    ret_code_t err_code;
    
    err_code = app_timer_start(m_adc_task_timer_id, ADC_TASK_TIMER, NULL);
    APP_ERROR_CHECK(err_code);    
}

static void adc_timeout_handler(void* p_context)
{
    ret_code_t err_code;
    
    APP_ERROR_CHECK(nrf_drv_saadc_sample());
}


/**@brief adc module call back
 *
 * @param[in]   p_event   adc module event
 *
 */
static void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    uint32_t                    err_code;
    
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLE_CNT);
        APP_ERROR_CHECK(err_code);
        
        pressure_adc_update(p_event->data.done.p_buffer[0]);
        battery_saadc_update(p_event->data.done.p_buffer[1]);
    }
}

Parents
  • Hello,

    How often are you doing offset calibration? This might be caused by the Errata 237 which can cause an unexpected sample to be written to the RAM. This will shift your buffer, leading to behavior as you describe. Please make sure to have the workaround implemented and try this again, and tell me if this resolves your issue.

    Best regards,
    Karl

  • Hi, i just do adc calibration once.

    I have solved this issue.

    define SAMPLE_CHANNEL_CNT                                           2
    #define SAMPLE_CNT      			                                1
    
    #define ADC_TASK_TIMER                                  APP_TIMER_TICKS(5)
    APP_TIMER_DEF(m_adc_task_timer_id);             
    
    /*<adc sample value buffer*/
    static nrf_saadc_value_t       m_buffer[SAMPLE_CHANNEL_CNT];
    
    static void adc_timeout_handler(void* p_context);
    static void saadc_callback(nrf_drv_saadc_evt_t const * p_event);
    static uint16_t mean_value_calc(int16_t* data_buffer, uint8_t size);
    
    void saadc_module_init(void)
    {
        ret_code_t err_code;
        
        nrfx_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
        saadc_config.resolution = NRF_SAADC_RESOLUTION_14BIT;
        saadc_config.interrupt_priority = 1;        
        saadc_config.low_power_mode = false;
        
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
        
        // do a calibrate
        while (nrf_drv_saadc_calibrate_offset() != NRFX_SUCCESS)
            nrf_delay_ms(10);
        while (nrf_drv_saadc_is_busy())
            nrf_delay_ms(10);
        
        pressure_adc_init();
        battery_saadc_init();
        
        err_code = app_timer_create(&m_adc_task_timer_id, APP_TIMER_MODE_REPEATED, adc_timeout_handler);
        APP_ERROR_CHECK(err_code);  
    }
    
    void saadc_module_start(void)
    {
        ret_code_t err_code;
        
        err_code = app_timer_start(m_adc_task_timer_id, ADC_TASK_TIMER, NULL);
        APP_ERROR_CHECK(err_code);    
    }
    
    static void adc_timeout_handler(void* p_context)
    {
        ret_code_t err_code;
        
        if(!nrf_drv_saadc_is_busy())
        {
            err_code = nrf_drv_saadc_buffer_convert(&m_buffer[0], 1);
            APP_ERROR_CHECK(err_code);  
            err_code = nrf_drv_saadc_buffer_convert(&m_buffer[1], 1);
            APP_ERROR_CHECK(err_code);  
            
            APP_ERROR_CHECK(nrf_drv_saadc_sample());
        }
    }
    
    
    /**@brief adc module call back
     *
     * @param[in]   p_event   adc module event
     *
     */
    static void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        uint32_t                    err_code;
        
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    //        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLE_CHANNEL_CNT);
    //        APP_ERROR_CHECK(err_code);
            
            pressure_adc_update(m_buffer[0]);
            battery_saadc_update(m_buffer[1]);
        }
    }

Reply
  • Hi, i just do adc calibration once.

    I have solved this issue.

    define SAMPLE_CHANNEL_CNT                                           2
    #define SAMPLE_CNT      			                                1
    
    #define ADC_TASK_TIMER                                  APP_TIMER_TICKS(5)
    APP_TIMER_DEF(m_adc_task_timer_id);             
    
    /*<adc sample value buffer*/
    static nrf_saadc_value_t       m_buffer[SAMPLE_CHANNEL_CNT];
    
    static void adc_timeout_handler(void* p_context);
    static void saadc_callback(nrf_drv_saadc_evt_t const * p_event);
    static uint16_t mean_value_calc(int16_t* data_buffer, uint8_t size);
    
    void saadc_module_init(void)
    {
        ret_code_t err_code;
        
        nrfx_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
        saadc_config.resolution = NRF_SAADC_RESOLUTION_14BIT;
        saadc_config.interrupt_priority = 1;        
        saadc_config.low_power_mode = false;
        
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
        
        // do a calibrate
        while (nrf_drv_saadc_calibrate_offset() != NRFX_SUCCESS)
            nrf_delay_ms(10);
        while (nrf_drv_saadc_is_busy())
            nrf_delay_ms(10);
        
        pressure_adc_init();
        battery_saadc_init();
        
        err_code = app_timer_create(&m_adc_task_timer_id, APP_TIMER_MODE_REPEATED, adc_timeout_handler);
        APP_ERROR_CHECK(err_code);  
    }
    
    void saadc_module_start(void)
    {
        ret_code_t err_code;
        
        err_code = app_timer_start(m_adc_task_timer_id, ADC_TASK_TIMER, NULL);
        APP_ERROR_CHECK(err_code);    
    }
    
    static void adc_timeout_handler(void* p_context)
    {
        ret_code_t err_code;
        
        if(!nrf_drv_saadc_is_busy())
        {
            err_code = nrf_drv_saadc_buffer_convert(&m_buffer[0], 1);
            APP_ERROR_CHECK(err_code);  
            err_code = nrf_drv_saadc_buffer_convert(&m_buffer[1], 1);
            APP_ERROR_CHECK(err_code);  
            
            APP_ERROR_CHECK(nrf_drv_saadc_sample());
        }
    }
    
    
    /**@brief adc module call back
     *
     * @param[in]   p_event   adc module event
     *
     */
    static void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        uint32_t                    err_code;
        
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    //        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLE_CHANNEL_CNT);
    //        APP_ERROR_CHECK(err_code);
            
            pressure_adc_update(m_buffer[0]);
            battery_saadc_update(m_buffer[1]);
        }
    }

Children
  • Hello,

    suhaihui said:
    I have solved this issue.

    Great, I am happy to hear that the issue is resolved!
    Did you pinpoint exactly what the issue was here? I see that you have changed your new buffers to be setup in the timeout handler instead of the callback function, is that it?

    I highly recommend that you trigger the SAADC sampling by connecting your TIMER CC event to the SAADC's TASKS_SAMPLE task through PPI, like shown in the SAADC example.
    By triggering it through PPI the CPU does not have to be involved in triggering every sample, which is especially nice if you have a high-priority process running in parallel (like the SoftDevice).

    Best regards,
    Karl

Related