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

nrf_delay_us and adc conversion time off by ~ 2X

Using nRF52811, Segger SES, and SDK 16.0, I have some times that seem to be off by ~2X.

I'm timing by setting a gpio before and after the event and capturing with a scope.

Using ADC with tacq = 10us, the gpio shows ~23us.

Using nrf_delay_us of 100us, the gpio shows ~230us

nrf_delay_us of 35us, gpio shows ~81us

nrf_delay_us of 10us, gpio shows ~23us.

Using the app timer for waking up from sleep, the delay times are correct.

The SPI clock freq set to 500KHz is also correct.

I've tried both a custom board and the BMD-360 with the same result.

The project is based off the ble_app_template example project.

Any help would be appreciated.  I don't want to just adjust the tacq and nrf_delay_us times to get the correct timing.

  • How do you toggle gpio ? to measure 10us delay you need to toggle 5us to 1 and 5 us to 0.  If you do 10us at 1 and 10u at 0, then you get a 20us period. hence the 2X

  • Using nrf_delay_us/ms for time-measurements will not work very well, especially in applications that use the softdevice and runs BLE advertising/connections. These functions use NOPs to stall the CPU, which means that any interrupt that blocks the main thread from using the CPU will be included in the times you measure. 

    The same can be said for the SAADC, in case of running the softdevice. The softdevice will always have the highest priority and may block handling of ADC events for a period of time. To get accurate results, you need to set the GPIO right before triggering the SAMPLE task and use PPI+GPIOTE to clear the GPIO when the DONE event is generated by the SAADC peripheral. You may also get better results if you test with a non-BLE example. Depending on your configuration of the project and SAADC peripheral/driver, there may be additional delays for starting a single sample conversion.

    I don't want to just adjust the tacq and nrf_delay_us times to get the correct timing.

    Your application should not depend on the timing of these things. I would generally recommend avoiding to use nrf_delay as part of the regular application, using timers or RTC/app_timer is almost always a better option. The only place nrf_delay could be used is if you need to do a short wait for something to be initialized, etc.

    You should set tacq of the SAADC based on this table. By using a larger buffer to hold multiple samples, the overhead of starting and stopping the samples will be reduced. If you have hard timing-requirements on when sampling is triggered, you should trigger the sampling in HW directly from a TIMER/RTC using PPI.

  • Thank you for the reply.  A couple clarifications:

    1.  In terms of nrf_delay, what time period is considered a short wait?

    2.  On the SAADC, will a soft device interrupt interfere with the acquisition time itself, or is it interfering only with the return from, in my case, the call to nrfx_saadc_sample_convert()?  Since I am only doing single acquisitions, does the overhead of the single call explain a 23us time to return from nrfx_saadc_sample_convert() with a tacq of 10us?

    Thank you

  • 1, That is up to you, you can use it as much as you like but don't expect it to be accurate in interrupt-driven applications. The functions keep the CPU active during the wait, so for battery-powered devices, the use of this function can make a great impact on the battery life of the product.

    2. The softdevice will not interfere with the peripheral or acquisition time, only handling of interrupts. nrfx_saadc_sample_convert() is a blocking function with a lot of overhead. You can check if you measure lower time if you set/clear the GPIO before and after these lines (which is where the actual sampling happens). Note that an additional 2 us conversion time (t_CONV) will be added to each sample.

Related