52832 adc 2 channels-SDK2.4.2 .If I take the value of each input individualy the reading is correct. When I read both channels at the same time, shows the same value in both channel.

Hi.

I need read the external voltage in input P030, and the battery backup voltage in P031.  

If I read using only one channel,  the P030 (AIN6 ) the value that show is correct 3625 mv (external voltage), and the value is the same like the multimeter measuring the input pin.

If I read using only one channel,  the P031 (AIN7 ) the value that show is correct to 2600 mv (backup battery voltage) , and the same in multimeter. 

The problem occurs when I want to take the reading of both inputs in two channels at the same time, in the while(true) loop. It shows the value of pin P031 on both channels, 2650 mv.  But in the circuit when I measure the voltage , por example  in P030 = 10 mv (without external power) , and P031 2650 mV the value of the battery, But the channel 0 and channel 1 has the same value.

The configuration in nrf52dk_nrf52832.overlay file is

/ {
    zephyr,user {
        io-channels = <&adc 0>, <&adc 1>;
        //io-channels = <&adc 0>;
    };
};

&adc {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";
    channel@0 {
        reg = <0>;
        zephyr,gain = "ADC_GAIN_1_6";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN6>; /* P030 AIN6 for nRF52832 Alim Externa */
        zephyr,resolution = <12>;
    };
    channel@1 {
        reg = <1>;
        zephyr,gain = "ADC_GAIN_1_6";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN7>; /* P031 AIN7 for nRF52832 Bateria */
        zephyr,resolution = <12>;
    };
};

The example was taking from the intermediate course ADC Lession 6

*********************************************************************************

the main.c file is

/
/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

 

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1650


/* Define a variable of type adc_dt_spec for each channel */
//static const struct adc_dt_spec adc_channel = ADC_DT_SPEC_GET(DT_PATH(zephyr_user));
static const struct adc_dt_spec adc_channel0 = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
static const struct adc_dt_spec adc_channel1 = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 1);

/



void main(void){
    int ret, i, aux=0, count=0, err, val0_mv=0, val1_mv=0;
       
    if (!device_is_ready(led.port)) {
        return;
    }

    ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    if (ret < 0) {
        return;
    }
   
    /* Define a variable of type adc_sequence and a buffer of type uint16_t */
    int16_t buf;
    struct adc_sequence sequence = {
        .buffer = &buf,
        /* buffer size in bytes, not number of samples */
        .buffer_size = sizeof(buf),
        // Optional
        //.calibrate = true,
    };

    /* Setup the ADC channel 0 */
    err = adc_channel_setup_dt(&adc_channel0);
    if (err < 0) {
        printk("Could not setup channel0 #%d (%d)", 0, err);
        return;
    }
    /* Initialize the ADC sequence */
    err = adc_sequence_init_dt(&adc_channel0, &sequence);
    if (err < 0) {
        printk("Could not initalize sequnce channel0");
        return;
    }
    /* Setup the ADC channel 1 */
    err = adc_channel_setup_dt(&adc_channel1);
    if (err < 0) {
        printk("Could not setup channel1 #%d (%d)", 1, err);
        return;
    }
    /* Initialize the ADC sequence */
    err = adc_sequence_init_dt(&adc_channel1, &sequence);
    if (err < 0) {
        printk("Could not initalize sequnce channel1");
        return;
    }

    while (1) {
        printk("\nRunning @ %d @\n", aux);
              
              
        /* Read a sample from the ADC Channel 0 */
        err = adc_read(adc_channel0.dev, &sequence);
        //printk("\nError leyendo channel0 (%d)", err);
        if (err < 0) {
            printk("\nCould not read channel0 (%d)", err);
            continue;
        }
        val0_mv = (int)buf;
        printk("\nADC reading 0[%u]: %s, channel %d: Raw: %d", aux, adc_channel0.dev->name, adc_channel0.channel_id, val0_mv);
        /* Convert raw value to mV*/
        err = adc_raw_to_millivolts_dt(&adc_channel0, &val0_mv);
        /* conversion to mV may not be supported, skip if not */
        if (err < 0) {
            printk(" (value in mV not available)\n");
        } else {
            printk(" = %d mV", val0_mv);
        }
               
        /* Read a sample from the ADC Channel 1 */
        err = adc_read(adc_channel1.dev, &sequence);
        //printk("\nError leyendo channel1 (%d)", err);
        if (err < 0) {
            printk("\nCould not read channel1 (%d)", err);
            continue;
        }
        val1_mv = (int)buf;
        printk("\nADC reading 1[%u]: %s, channel %d: Raw: %d", aux, adc_channel1.dev->name, adc_channel1.channel_id, val1_mv);
        err = adc_raw_to_millivolts_dt(&adc_channel1, &val1_mv);
        /* conversion to mV may not be supported, skip if not */
        if (err < 0) {
            printk(" (value in mV not available)\n");
        } else {
            printk(" = %d mV", val1_mv);
        }

        k_msleep(SLEEP_TIME_MS);
        aux++;
    }
}

Thank you in advance

  • Hi,

    The problem seems to be that you have an issue with the sequence of your function calls. With the Zephry API, each channel is sampled separately. So you need to call adc_sequence_init_dt() every time before you call adc_read(). I did a small quick and dirty change to your application so that it looked like this, and that works:

    /*
     * Copyright (c) 2020 Libre Solar Technologies GmbH
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <inttypes.h>
    #include <stddef.h>
    #include <stdint.h>
    
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/adc.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/util.h>
    
    #include <zephyr/drivers/gpio.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS 1650
    
    /* Define a variable of type adc_dt_spec for each channel */
    // static const struct adc_dt_spec adc_channel = ADC_DT_SPEC_GET(DT_PATH(zephyr_user));
    static const struct adc_dt_spec adc_channel0 = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
    static const struct adc_dt_spec adc_channel1 = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 1);
    
    void main(void)
    {
    	int aux = 0, err, val0_mv = 0, val1_mv = 0;
    
    	/* Define a variable of type adc_sequence and a buffer of type uint16_t */
    	int16_t buf;
    	struct adc_sequence sequence = {
    		.buffer = &buf,
    		/* buffer size in bytes, not number of samples */
    		.buffer_size = sizeof(buf),
    		// Optional
    		//.calibrate = true,
    	};
    
    	/* Setup the ADC channel 0 */
    	err = adc_channel_setup_dt(&adc_channel0);
    	if (err < 0) {
    		printk("Could not setup channel0 #%d (%d)", 0, err);
    		return;
    	}
    
    	/* Setup the ADC channel 1 */
    	err = adc_channel_setup_dt(&adc_channel1);
    	if (err < 0) {
    		printk("Could not setup channel1 #%d (%d)", 1, err);
    		return;
    	}
    
    	while (1) {
    		printk("\nRunning @ %d @\n", aux);
    
    		/* Initialize the ADC sequence */
    		err = adc_sequence_init_dt(&adc_channel0, &sequence);
    		if (err < 0) {
    			printk("Could not initalize sequnce channel0");
    			return;
    		}
    
    		/* Read a sample from the ADC Channel 0 */
    		err = adc_read(adc_channel0.dev, &sequence);
    		// printk("\nError leyendo channel0 (%d)", err);
    		if (err < 0) {
    			printk("\nCould not read channel0 (%d)", err);
    			continue;
    		}
    		val0_mv = (int)buf;
    		printk("\nADC reading 0[%u]: %s, channel %d: Raw: %d", aux, adc_channel0.dev->name,
    		       adc_channel0.channel_id, val0_mv);
    		/* Convert raw value to mV*/
    		err = adc_raw_to_millivolts_dt(&adc_channel0, &val0_mv);
    		/* conversion to mV may not be supported, skip if not */
    		if (err < 0) {
    			printk(" (value in mV not available)\n");
    		} else {
    			printk(" = %d mV", val0_mv);
    		}
    
    		/* Initialize the ADC sequence */
    		err = adc_sequence_init_dt(&adc_channel1, &sequence);
    		if (err < 0) {
    			printk("Could not initalize sequnce channel1");
    			return;
    		}
    
    		/* Read a sample from the ADC Channel 1 */
    		err = adc_read(adc_channel1.dev, &sequence);
    		// printk("\nError leyendo channel1 (%d)", err);
    		if (err < 0) {
    			printk("\nCould not read channel1 (%d)", err);
    			continue;
    		}
    		val1_mv = (int)buf;
    		printk("\nADC reading 1[%u]: %s, channel %d: Raw: %d", aux, adc_channel1.dev->name,
    		       adc_channel1.channel_id, val1_mv);
    		err = adc_raw_to_millivolts_dt(&adc_channel1, &val1_mv);
    		/* conversion to mV may not be supported, skip if not */
    		if (err < 0) {
    			printk(" (value in mV not available)\n");
    		} else {
    			printk(" = %d mV", val1_mv);
    		}
    
    		k_msleep(SLEEP_TIME_MS);
    		aux++;
    	}
    }
    

Related