NRF52840 Zephyr ADC read issue

Hello,

I am using nrf52840 on usb dongle  and i would like to measure voltage on a specific ADC input pin.

According to the datasheet, i use P0.02/AIN0.

My problem is that adc_read() function returns -22 error.

I am posting the code and the overlay file. Could you please help me what i am doing wrong here?

Thanks a lot guys!

Thanos

&adc
{   
    status = "okay";
    io-channels = <&adc 0>;
};
#define ADC_RESOLUTION		    12
#define ADC_GAIN			    ADC_GAIN_1
#define ADC_REFERENCE		    ADC_REF_INTERNAL
#define ADC_ACQUISITION_TIME	ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40)
#define ADC_CHANNEL_AIN0       0

#define ADC_IO_LABEL            DT_GPIO_LABEL(DT_ALIAS(gpiocus1), gpios)
#define ADC_IO_PIN	            DT_GPIO_PIN(DT_ALIAS(gpiocus1), gpios)

const struct device *adc_dev;
const struct device *adc_en_dev;


uint32_t sample_buffer[10] = {0};


static struct adc_channel_cfg adcConfig = 
{
	.gain             = ADC_GAIN,
	.reference        = ADC_REFERENCE,
	.acquisition_time = ADC_ACQUISITION_TIME,
	.channel_id       = 1, // gets set during init
	.differential	  = 0,
// #if CONFIG_ADC_CONFIGURABLE_INPUTS
	// .input_positive   = 0, // gets set during init
// #endif
};

const struct adc_sequence sequence = 
{
	    .options     = NULL,				// extra samples and callback
		.channels    = BIT(ADC_CHANNEL_AIN0),		// bit mask of channels to read
		.buffer      = sample_buffer,		// where to put samples read
		.buffer_size = sizeof(sample_buffer),
		.resolution  = ADC_RESOLUTION,		// desired resolution
		.oversampling = 0,					// don't oversample
		.calibrate = 0						// don't calibrate
};
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool adc_init(uint8_t channel)
{
    int adcInitError;
    
    adc_dev = DEVICE_DT_GET(DT_NODELABEL(adc));
    if(adc_dev == NULL)
    {
        return false;
    }

    adc_dev = device_get_binding(DEVICE_DT_NAME(DT_NODELABEL(adc)));
    if(adc_dev == NULL)
    {
        return false;
    }

    adcConfig.channel_id = channel;
    adcInitError = adc_channel_setup(adc_dev, &adcConfig);
    if(adcInitError)
    {
        return false;
    }

    return true;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint32_t readBatteryVoltage(void)
{
    int readBatteryVoltageError = 0;

    readBatteryVoltageError = adc_read(adc_dev, &sequence);
    if(readBatteryVoltageError == 0)
    {
        return sample_buffer[0];
    }

    return 0;
}
CONFIG_ADC=y
CONFIG_ADC_ASYNC=y

Parents
  • Hi Thanos

    From where do you call the readBatteryVoltage() function?

    The adc_read() function can not be called from an interrupt context, so it is important to make sure you call readBatteryVoltage() from thread context for this code to work. 

    Best regards
    Torbjørn

  • Thanks ovrebekk for your anwser.

    I have completed succesfully adc reading, but i am trying to disable it in order to reduce consumption.

    How can i do that?

  • Hi

    Very good question, I have looked around for a power optimized ADC sample but can't seem to find any. 

    I will have to continue my search next week and get back to you Slight smile

    Best regards
    Torbjørn

  • Hi,

    NCS1.9.1, nRF52840DK,Windows10 X64, VSCode,

    i've follow you,and adc_read() function returns -22 error.

    How did you solve this problem? add thread?

    #include <zephyr.h>
    #include <device.h>
    #include <drivers/gpio.h>
    #include <sys/util.h>
    #include <sys/printk.h>
    #include <inttypes.h>
    #include <drivers/adc.h>
    
    
    #define ADC_RESOLUTION		    12
    #define ADC_GAIN			    ADC_GAIN_1
    #define ADC_REFERENCE		    ADC_REF_INTERNAL
    #define ADC_ACQUISITION_TIME	ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40)
    #define ADC_CHANNEL_AIN0       0
    
    #define ADC_IO_LABEL            DT_GPIO_LABEL(DT_ALIAS(gpiocus1), gpios)
    #define ADC_IO_PIN	            DT_GPIO_PIN(DT_ALIAS(gpiocus1), gpios)
    
    const struct device *adc_dev;
    const struct device *adc_en_dev;
    
    
    uint32_t sample_buffer[10] = {0};
    
    
    static struct adc_channel_cfg adcConfig = 
    {
    	.gain             = ADC_GAIN,
    	.reference        = ADC_REFERENCE,
    	.acquisition_time = ADC_ACQUISITION_TIME,
    	.channel_id       = 1, // gets set during init
    	.differential	  = 0,
    // #if CONFIG_ADC_CONFIGURABLE_INPUTS
    	// .input_positive   = 0, // gets set during init
    // #endif
    };
    
    const struct adc_sequence sequence = 
    {
    	    .options     = NULL,				// extra samples and callback
    		.channels    = BIT(ADC_CHANNEL_AIN0),		// bit mask of channels to read
    		.buffer      = sample_buffer,		// where to put samples read
    		.buffer_size = sizeof(sample_buffer),
    		.resolution  = ADC_RESOLUTION,		// desired resolution
    		.oversampling = 0,					// don't oversample
    		.calibrate = 0						// don't calibrate
    };
    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    bool adc_init(uint8_t channel)
    {
        int adcInitError;
        
        adc_dev = DEVICE_DT_GET(DT_NODELABEL(adc));
        if(adc_dev == NULL)
        {
     		printk("adc_init fail 1\n");
           	return false;
        }
    
        adc_dev = device_get_binding(DEVICE_DT_NAME(DT_NODELABEL(adc)));
        if(adc_dev == NULL)
        {
    		printk("adc_init fail 2\n");
            return false;
        }
    
        adcConfig.channel_id = channel;
        adcInitError = adc_channel_setup(adc_dev, &adcConfig);
        if(adcInitError)
        {
    		printk("adc_init fail 3\n");
            return false;
        }
    	printk("adc_init done\n");
    
        return true;
    }
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    uint32_t main(void)
    {
    	adc_init(0);
        int readBatteryVoltageError = 0;
    
        readBatteryVoltageError = adc_read(adc_dev, &sequence);
        if(readBatteryVoltageError == 0)
        {
     		printk("readBatteryVoltage: %d \n",sample_buffer[0]);
    		return sample_buffer[0];
        }
    	printk("readBatteryVoltage error: %d \n",readBatteryVoltageError);
    
        return 0;
    }

    i cant not  find know how to create thread

    Thread protocol — Zephyr Project Documentation (nordicsemi.com)

      

    Best Regards

Reply
  • Hi,

    NCS1.9.1, nRF52840DK,Windows10 X64, VSCode,

    i've follow you,and adc_read() function returns -22 error.

    How did you solve this problem? add thread?

    #include <zephyr.h>
    #include <device.h>
    #include <drivers/gpio.h>
    #include <sys/util.h>
    #include <sys/printk.h>
    #include <inttypes.h>
    #include <drivers/adc.h>
    
    
    #define ADC_RESOLUTION		    12
    #define ADC_GAIN			    ADC_GAIN_1
    #define ADC_REFERENCE		    ADC_REF_INTERNAL
    #define ADC_ACQUISITION_TIME	ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40)
    #define ADC_CHANNEL_AIN0       0
    
    #define ADC_IO_LABEL            DT_GPIO_LABEL(DT_ALIAS(gpiocus1), gpios)
    #define ADC_IO_PIN	            DT_GPIO_PIN(DT_ALIAS(gpiocus1), gpios)
    
    const struct device *adc_dev;
    const struct device *adc_en_dev;
    
    
    uint32_t sample_buffer[10] = {0};
    
    
    static struct adc_channel_cfg adcConfig = 
    {
    	.gain             = ADC_GAIN,
    	.reference        = ADC_REFERENCE,
    	.acquisition_time = ADC_ACQUISITION_TIME,
    	.channel_id       = 1, // gets set during init
    	.differential	  = 0,
    // #if CONFIG_ADC_CONFIGURABLE_INPUTS
    	// .input_positive   = 0, // gets set during init
    // #endif
    };
    
    const struct adc_sequence sequence = 
    {
    	    .options     = NULL,				// extra samples and callback
    		.channels    = BIT(ADC_CHANNEL_AIN0),		// bit mask of channels to read
    		.buffer      = sample_buffer,		// where to put samples read
    		.buffer_size = sizeof(sample_buffer),
    		.resolution  = ADC_RESOLUTION,		// desired resolution
    		.oversampling = 0,					// don't oversample
    		.calibrate = 0						// don't calibrate
    };
    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    bool adc_init(uint8_t channel)
    {
        int adcInitError;
        
        adc_dev = DEVICE_DT_GET(DT_NODELABEL(adc));
        if(adc_dev == NULL)
        {
     		printk("adc_init fail 1\n");
           	return false;
        }
    
        adc_dev = device_get_binding(DEVICE_DT_NAME(DT_NODELABEL(adc)));
        if(adc_dev == NULL)
        {
    		printk("adc_init fail 2\n");
            return false;
        }
    
        adcConfig.channel_id = channel;
        adcInitError = adc_channel_setup(adc_dev, &adcConfig);
        if(adcInitError)
        {
    		printk("adc_init fail 3\n");
            return false;
        }
    	printk("adc_init done\n");
    
        return true;
    }
    
    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    uint32_t main(void)
    {
    	adc_init(0);
        int readBatteryVoltageError = 0;
    
        readBatteryVoltageError = adc_read(adc_dev, &sequence);
        if(readBatteryVoltageError == 0)
        {
     		printk("readBatteryVoltage: %d \n",sample_buffer[0]);
    		return sample_buffer[0];
        }
    	printk("readBatteryVoltage error: %d \n",readBatteryVoltageError);
    
        return 0;
    }

    i cant not  find know how to create thread

    Thread protocol — Zephyr Project Documentation (nordicsemi.com)

      

    Best Regards

Children
No Data
Related