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

SAADC scans only one sample

Hello,

I am developing a solution that measures values on 2 AIN channels in scan mode with the following setup:

- differential mode

- no oversampling

- no burst mode

- 10 bit precision

- resistors disabled

The channels are configured standard way using nrf_drv_saadc_channel_init() and nrf_drv_saadc_buffer_convert(). I start conversion by calling nrf_drv_saadc_sample() and set low power mode. This I understood to run several scan samples until buffer lasts.

The callback function checks for p_event->type == NRF_DRV_SAADC_EVT_DONE, makes nrf_drv_saadc_buffer_convert() and copies measured values to a separate array for further processing outside of the callback. I am not doing calibration at this stage, as it requires scan to work.

The problem I am facing is that the callback function is called always when only 1 set of samples is done, i.e. 1 sample for each channel. Regardless of what size buffer I set (tried 2x10, 2x20, 2x30 size).

I want to note that nrf_drv_saadc_sample() is triggered from RTC2 timer interrupt handler, setup for 2 kHz frequency of calls.

I would like to know why I am not getting s full scan of those 2 channels through the whole buffer.

I am using nRF 52832, custom design, also DK PCA10040, SDK 14.2 and SD 132, v5.0.0.

What else I forgot to set for running the scan mode / what can block the scan mode to work? Is the scan mode supported under SD? According to the SD documentation open for SAADC. 

Any advice is very much appreciated.

Thanx.

peter

Parents
  • Hello Haakonsh,

    I understand that eclipse is not the favorite IDE for the nRF. There is not so much support / up to date. I tried to setup debugger but ended up with the device packages not working. Switching to Segger studio is not an option for me at this stage of the project.

    I decided to go other way to get SAADC registers. I implemented a simple function that gets registers values:

    void saadc_get_registers(uint32_t * registers) {
    	uint32_t * p;
    
    	p =  (uint32_t *)NRF_SAADC_BASE;
    
    	registers[0] = p[0];
    	registers[1] = p[1];
    	registers[2] = p[2];
    	registers[3] = p[3];
    
    	p += 0x100;
    
    	registers[4] = p[0];
    	registers[5] = p[1];
    	registers[6] = p[2];
    	registers[7] = p[3];
    	registers[8] = p[4];
    	registers[9] = p[5];
    }
    

    The register values then I print at other point, on the main level. Please, let me know if this approach is viable.

    The other question I would like to ask, is I believe very close related to the SAADC scan. The first thing I am trying to do is calibration. I implemented a simple code:

    ret_code_t saadc_calibrate(void) {
        ret_code_t err_code;
    
        err_code = nrf_drv_saadc_buffer_convert(m_battery_measurement_buffer[0], SAADC_BATTERY_SAMPLE_COUNT); 
    	NRF_LOG_DEBUG("Saadc init 0 %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        err_code = nrf_drv_saadc_buffer_convert(m_battery_measurement_buffer[1], SAADC_BATTERY_SAMPLE_COUNT);
    	NRF_LOG_DEBUG("Saadc init 1 %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        while((err_code = nrf_drv_saadc_calibrate_offset()) != NRF_SUCCESS);
    	NRF_LOG_DEBUG("Saadc calibrate %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        return err_code;
    }
    

    The saadc_calibrate() function is called at the beginning of the main, no library is called before (besides log init) in order to avoid any influences. 

    Surprisingly, I found out that the nrf_drv_saadc_calibrate_offset() always returns NRF_ERROR_BUSY result. I am not sure if that is a result of  the buffer convert called before?

    My understanding is that if calibration doesnt work then also scan doesnt work. This way I may come to the root cause for scan not working?

    Best regards,

    peter

Reply
  • Hello Haakonsh,

    I understand that eclipse is not the favorite IDE for the nRF. There is not so much support / up to date. I tried to setup debugger but ended up with the device packages not working. Switching to Segger studio is not an option for me at this stage of the project.

    I decided to go other way to get SAADC registers. I implemented a simple function that gets registers values:

    void saadc_get_registers(uint32_t * registers) {
    	uint32_t * p;
    
    	p =  (uint32_t *)NRF_SAADC_BASE;
    
    	registers[0] = p[0];
    	registers[1] = p[1];
    	registers[2] = p[2];
    	registers[3] = p[3];
    
    	p += 0x100;
    
    	registers[4] = p[0];
    	registers[5] = p[1];
    	registers[6] = p[2];
    	registers[7] = p[3];
    	registers[8] = p[4];
    	registers[9] = p[5];
    }
    

    The register values then I print at other point, on the main level. Please, let me know if this approach is viable.

    The other question I would like to ask, is I believe very close related to the SAADC scan. The first thing I am trying to do is calibration. I implemented a simple code:

    ret_code_t saadc_calibrate(void) {
        ret_code_t err_code;
    
        err_code = nrf_drv_saadc_buffer_convert(m_battery_measurement_buffer[0], SAADC_BATTERY_SAMPLE_COUNT); 
    	NRF_LOG_DEBUG("Saadc init 0 %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        err_code = nrf_drv_saadc_buffer_convert(m_battery_measurement_buffer[1], SAADC_BATTERY_SAMPLE_COUNT);
    	NRF_LOG_DEBUG("Saadc init 1 %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        while((err_code = nrf_drv_saadc_calibrate_offset()) != NRF_SUCCESS);
    	NRF_LOG_DEBUG("Saadc calibrate %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        return err_code;
    }
    

    The saadc_calibrate() function is called at the beginning of the main, no library is called before (besides log init) in order to avoid any influences. 

    Surprisingly, I found out that the nrf_drv_saadc_calibrate_offset() always returns NRF_ERROR_BUSY result. I am not sure if that is a result of  the buffer convert called before?

    My understanding is that if calibration doesnt work then also scan doesnt work. This way I may come to the root cause for scan not working?

    Best regards,

    peter

Children
  • Try this: 

    ret_code_t saadc_calibrate(void) {
        ret_code_t err_code;
    
        while(nrf_drv_saadc_is_busy())
        {
            nrf_drv_saadc_abort(); // Abort any SAADC activity, puts the driver in NRF_SAADC_STATE_IDLE. 
        }
    
        err_code = nrf_drv_saadc_calibrate_offset();
    	NRF_LOG_DEBUG("Saadc calibrate %s error code: %s", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
    
        while(nrf_drv_saadc_is_busy())
        { 
            // Wait for calibration to complete
        }
        
        return err_code;
    }
    
    
    

    NB: 
    After you've called nrf_drv_saadc_buffer_convert the SAADC driver is in NRF_SAADC_STATE_BUSY as it is waiting for the Sample task to be triggered. The SAADC will be in NRF_SAADC_STATE_BUSY until the buffer has been filled with samples and you've gotten a callback in main. 


Related