Multiple ADC reading - NCS

Hello everyone!

I'm trying to read 4 channels of ADC, and for future production, I'd have to read all 8.

There is two channels example, yet it isn't scalable. I'm thinking about building a dynamic setup based on the example, but it doesn't go so well due to the limits of specific macros in the given example code.

Parents
  • Hi Tamir

    It sounds a bit odd that the standard example shouldn't be scalable. The way it works is that it goes through all the channels defined in the device tree and configures each channel as required. 

    As an example the nrf52840 overlay can be seen here, where 3 different channels are defined with different settings. In order to add more channels all you have to do is update the overlay, and the sample should handle the rest (just make sure to use each index between 0-7 only once). 

    Best regards
    Torbjørn

  • By trying your method, I'm getting various errors from CMake and a lack of definitions. I'm using NCS V1.9.1.

    I'm attaching the list of errors and my project.

    adc_extended.zip

  • Hi

    This feature was added in v2.1.0 of NCS, and won't work in v1.9.1 unfortunately. 

    In v1.9.1 you would have to look at the battery sample

    Alternatively it is possible to forego the Zephyr driver entirely and use the nrfx driver instead. There are some examples showing how to use the nrfx_saadc driver eavailable here. These are also written for a newer NCS version, but the nrfx drivers haven't changed much in that time API wise so I would expect the samples to run in older versions as well. 

    Best regards
    Torbjørn

  • adc_4.zip

    So I did some googling. It builds well yet suffers from failure while trying to start channel 0. What did I miss here?

  • Hi 

    Which NCS version are you using to build it? 

    I tried in v1.9.1, but it doesn't build. The .channel_cfgs field in the adc_sequence struct can't be found. 

    Best regards
    Torbjørn

  • I updated the code, and now it's compiling well, but when trying to see the nRF Terminal, I'm getting the following logs.

    *** Booting Zephyr OS build v2.7.99-ncs1-1  ***
    Device binded to ADC_0
    [00:00:00.257,568] <err> os: ***** MPU FAULT *****
    [00:00:00.257,568] <err> os:   Instruction Access Violation
    [00:00:00.257,568] <err> os: r0/a1:  0x00000000  r1/a2:  0x20001958  r2/a3:  0x54f7fab5
    [00:00:00.257,568] <err> os: r3/a4:  0x20001958 r12/ip:  0x00000000 r14/lr:  0x00000407
    [00:00:00.257,598] <err> os:  xpsr:  0x61000000
    [00:00:00.257,598] <err> os: Faulting instruction address (r15/pc): 0x54f7fab4
    [00:00:00.257,598] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    [00:00:00.257,629] <err> os: Current thread: 0x20000420 (main)
    [00:00:01.207,336] <err> fatal_error: Resetting system

    The code now:

    adc_4_v3.zip

  • Hi 

    The MPU fault is caused by the way you assign the device pointer. 

    If you want to provide a pointer back to the caller of the function you should pass a pointer to the pointer to the function. In your code you will simply assign the ADC device pointer to the local dev variable in the function, adc_dev will not be updated. 

    Also, on an error you return the ret variable, which is unassigned. This is also incorrect (but not the problem here). 

    The code snippet below corrects these issues:

    static int adc_setup_meh(const struct device **dev)
    {
        //ADC0 setup
        *dev = device_get_binding(ADC_DEVICE_NAME);
    	if (!dev) {
            printk("device_get_binding ADC_0 (=%s) failed\n", ADC_DEVICE_NAME);
            return -1;
        } 
    
        return 0;
    }

    And then you need to call the function like this:

    err = adc_setup_meh(&adc_dev);

    Best regards
    Torbjørn

Reply
  • Hi 

    The MPU fault is caused by the way you assign the device pointer. 

    If you want to provide a pointer back to the caller of the function you should pass a pointer to the pointer to the function. In your code you will simply assign the ADC device pointer to the local dev variable in the function, adc_dev will not be updated. 

    Also, on an error you return the ret variable, which is unassigned. This is also incorrect (but not the problem here). 

    The code snippet below corrects these issues:

    static int adc_setup_meh(const struct device **dev)
    {
        //ADC0 setup
        *dev = device_get_binding(ADC_DEVICE_NAME);
    	if (!dev) {
            printk("device_get_binding ADC_0 (=%s) failed\n", ADC_DEVICE_NAME);
            return -1;
        } 
    
        return 0;
    }

    And then you need to call the function like this:

    err = adc_setup_meh(&adc_dev);

    Best regards
    Torbjørn

Children
Related