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

Continuous periodic nRF52840 ADC sampling with Zephyr

Hello, guys.

We are using Zephyr RTOS (NCS v1.4.2) with nRF52840 development kit.

The idea is to have continuous ADC sampling on two ADC channels. So far, I was able to properly initialize the ADC device, and get one single ADC read with the following piece of code:

const struct adc_sequence sequence = {
	.channels = BIT(ADC_1ST_CHANNEL_ID),
	.buffer = m_sample_buffer,
	.buffer_size = sizeof(m_sample_buffer),
	.resolution = ADC_RESOLUTION,
};

ret = adc_read(adc_dev, &sequence);
if (ret) {
    printk("adc_read() failed with code %d\n", ret);
}

There is an issue even with this piece of code because, when I call adc_read(adc_dev, &sequence) function, only the first value of m_sample_buffer is updated, the rest of the m_sample_buffer values remain 0. What I am missing here?

Other than that, is there any way that we configure ADC device to do periodic sampling in the background without our intervention?

Thanks in advance for your time and efforts.

Sincerely,

Bojan.

Parents
  • Hi Bojan,

    You cannot use the Zephyr ADC API if you want to trigger sampling regularly without CPU intervention due to the general nature of the Zephyr APIs. In that case you need to use a TIMER to trigger the SAADC via PPI, and for that you need to use the nrfx drivers directly.

    I do not have an example which does that at hand, but how to use nrfx drivers in general in Zephyr is demonstrated by the nrfx use example. You can combine that with this unofficial SAADC example, which demonstrates using the latest nrfx API to sample multiple channels regularly based on a timer (it is for the nRF5 SDK, but the nrfx API is the same regardless).

    Referring to the example, note that if you do not want to handle the sample set every time you just need to increase the buffer length, as you will get an interrupt ever time the buffer is filled. Also, you may not need to use double buffering as demonstrated, if you have time to process the buffer on time without it.

    Br,

    Einar

  • Hello, Einar.

    I am trying to port your unofficial SAADC example into Zephyr environment.

    As a first goal, I wanted to test only adc_configure() function. According to nrfx use example that shows how to use nrfx drivers in Zephyr, I did the following in my prj.config file:

    CONFIG_ADC=n
    CONFIG_ADC_NRFX_SAADC=y

    I also included nrfx_saadc header file  line in my main.cpp file:

    #include <nrfx_saadc.h>

    When I compile the code, the compiler complains about undefined reference to nrfx_saadc_xxx() functions that are all declared in included nrfx_saadc.h file:

    build/../src/main.cpp:187: undefined reference to `nrfx_saadc_channels_config'
    build/../src/main.cpp:190: undefined reference to `nrfx_saadc_advanced_mode_set'
    build/../src/main.cpp:197: undefined reference to `nrfx_saadc_buffer_set'
    build/../src/main.cpp:200: undefined reference to `nrfx_saadc_buffer_set'
    build/../src/main.cpp:203: undefined reference to `nrfx_saadc_mode_trigger'
    

    Do you have any idea what I am missing here? Do I need to include something more in my prj.config file that will disable the usage of Zephyr ADC APIs and encourage the usage of NRFX SAADC driver?

    Thanks in advance for your time and efforts.

    Sincerely,

    Bojan.

  • Hi Bojan,

    It seems this is not valid C++ code. Perhaps you can just replace nrf_saadc_task_address_get(NRF_SAADC_TASK_SAMPLE) with NRF_SAADC->TASKS_SAMPLE or just a pointer to 0x40007004?

    Einar

  • Hey, Einar.

    I figured it out. In NCS environment, nrf_saadc_task_address_get() function requires two arguments:

    /**
     * @brief Function for getting the address of the specified SAADC task register.
     *
     * @param[in] p_reg Pointer to the structure of registers of the peripheral.
     * @param[in] task  SAADC task.
     *
     * @return Address of the specified SAADC task.
     */
    NRF_STATIC_INLINE uint32_t nrf_saadc_task_address_get(NRF_SAADC_Type const * p_reg,
                                                          nrf_saadc_task_t       task);

    Consequently, what I did in the code is:

        err_code = nrfx_ppi_channel_assign(m_timer_saadc_ppi_channel, 
                                           nrfx_timer_event_address_get(&m_sample_timer, NRF_TIMER_EVENT_COMPARE0),
                                           nrf_saadc_task_address_get((NRF_SAADC_Type *)0x40007000, NRF_SAADC_TASK_SAMPLE));

    and it is now working well.

    Thanks once again, man!

    Cheers,

    Bojan.

  • Ah, of course. I did not catch that the API was changed. Good to hear it works now. Thank you for updating us!

  • Thank YOU for the great support!

    By the way, I am using an official version of nrfx_saadc drivers that can be found under:

    ncs/v1.4.2/modules/hal/nordic/nfrx/drivers/include

    You are playing with version 2 of the nrfx_saadc drivers in your repo (link). I noticed that nrfx_saadc_v2 is already included in nRF SDK 17.2 under:

    SDK_ROOT/modules/nrfx/drivers/include

    What is the difference between version 1 and version 2 of nrfx_saadc drivers? Is this version 2 already included in version 1.5.0 of nRF Connect SDK? Finally, do you recommend using version 2 for production code?

    Cheers,

    Bojan.

  • Hi Bojan,

    bojan said:
    What is the difference between version 1 and version 2 of nrfx_saadc drivers?

    The SAADC driver was completely rewritten, so there are a number of differences. Generally, the version 2 SAADC driver includes more workarounds for HW limitations.,

    bojan said:
    Is this version 2 already included in version 1.5.0 of nRF Connect SDK?

    Yes. nRF Connect SDK includes nrfx 2.4.0.

    bojan said:
    Finally, do you recommend using version 2 for production code?

    For NCS, you should use the one that tis part of the NCS vision you are using (which will be version 2.x.x these days). For the nRF5 SDK 17.x.x you can choose, but I recommend using the V2 API for the SAADC.

    Einar

Reply
  • Hi Bojan,

    bojan said:
    What is the difference between version 1 and version 2 of nrfx_saadc drivers?

    The SAADC driver was completely rewritten, so there are a number of differences. Generally, the version 2 SAADC driver includes more workarounds for HW limitations.,

    bojan said:
    Is this version 2 already included in version 1.5.0 of nRF Connect SDK?

    Yes. nRF Connect SDK includes nrfx 2.4.0.

    bojan said:
    Finally, do you recommend using version 2 for production code?

    For NCS, you should use the one that tis part of the NCS vision you are using (which will be version 2.x.x these days). For the nRF5 SDK 17.x.x you can choose, but I recommend using the V2 API for the SAADC.

    Einar

Children
No Data
Related