Analog input jumps above VDD

Hey all :)

My project includes an analogue measure, and in some channels, the input goes over 57000mV in certain, probably random cases.

Of course, it's not a real input because it would fry the MCU. But how can I shield my signal from these spikes, and how do I prevent them totally?

My prj.cfg:

CONFIG_LOG=y
CONFIG_I2C=y
CONFIG_ADC=y #I know this is only the relevant one, but in case this content is worth something.
CONFIG_SFLOAT=y
CONFIG_CBPRINTF_FP_SUPPORT=y
CONFIG_DK_LIBRARY=y

My devicetree overlay:

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



&adc {
	#address-cells = <1>;
	#size-cells = <0>;

	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_AIN0>; /* P0.03 */
		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_AIN1>;
		zephyr,resolution = <12>;
		zephyr,oversampling = <8>;
	};

	channel@2 {
		reg = <2>;
		zephyr,gain = "ADC_GAIN_1_6";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,input-positive = <NRF_SAADC_AIN2>; /* P0.04 */
		zephyr,resolution = <12>;
		zephyr,oversampling = <8>;
	};

	channel@3 {
		reg = <3>;
		zephyr,gain = "ADC_GAIN_1_6";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,vref-mv = <750>;
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,input-positive = <NRF_SAADC_AIN3>; /* P0.30 */
		zephyr,resolution = <12>;
	};	
};

My main code:

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(ADC_Custom_Driver);

#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
	!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
#error "No suitable devicetree overlay specified"
#endif

#define DT_SPEC_AND_COMMA(node_id, prop, idx) \
	ADC_DT_SPEC_GET_BY_IDX(node_id, idx),

/* Data of ADC io-channels specified in devicetree. */
static const struct adc_dt_spec adc_channels[] = {
	DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels,
			     DT_SPEC_AND_COMMA)
};

uint16_t buf;
struct adc_sequence sequence = {
	.buffer = &buf,
	/* buffer size in bytes, not number of samples */
	.buffer_size = sizeof(buf),
};


void adc_custom_channels_setup(void)
{   int err;
	/* Configure channels individually prior to sampling. */
	for (int i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
		if (!device_is_ready(adc_channels[i].dev)) {
			LOG_WRN("ADC controller device not ready\n");
			return;
		}

		err = adc_channel_setup_dt(&adc_channels[i]);
		if (err < 0) {
			LOG_ERR("Could not setup channel #%d (%d)\n", i, err);
			return;
		}
	}
}



int adc_custom_measure_channel(uint8_t idx)
{
	int err;
	uint16_t value;
			(void)adc_sequence_init_dt(&adc_channels[idx], &sequence);

			err = adc_read(adc_channels[idx].dev, &sequence);
			if (err < 0) {
				LOG_ERR("Could not read (%d)\n", err);
				
			} else {
				
				//LOG_INF("%"PRId16, buf);
				value = (uint16_t)buf;
				LOG_DBG("Values.channels[%d] = %d\n", idx, value);
				return value;
			}

	}

int adc_custom_measure_channel_mv(uint8_t idx)
{
	int err;
	int32_t val_mv;
			(void)adc_sequence_init_dt(&adc_channels[idx], &sequence);

			err = adc_read(adc_channels[idx].dev, &sequence);	
				/* conversion to mV may not be supported, skip if not */
			val_mv = buf;
			err = adc_raw_to_millivolts_dt(&adc_channels[idx],
						       &val_mv);
			if (err < 0 || val_mv > 5000) {
				LOG_ERR(" (value in mV not available)\n");
			} else {

				LOG_DBG("Values_mv[%d] = %d mV\n",idx, val_mv);
				return val_mv;
			}
}

I call the setup once and in a loop for the measure / measure_print methods.

Is this bug possible because I configured the functions as int and not uint16?

I'm using nRF52840 / Thingy52 (with proper overlays, of course) and NCS v2.2.0

Parents Reply Children
  • adc_custom_measure_channel_mv(uint8_t idx)
    {
    	int err;
    	int32_t val_mv;
    			(void)adc_sequence_init_dt(&adc_channels[idx], &sequence);
    
    			err = adc_read(adc_channels[idx].dev, &sequence);
    			/* conversion to mV may not be supported, skip if not */
    			val_mv = (int32_t)buf;
    			err = adc_raw_to_millivolts_dt(&adc_channels[idx],
    						       &val_mv);
    			if (err < 0) {
    				LOG_ERR(" (value in mV not available)\n");
    				return -1;
    			} else {
    				LOG_INF("Values_mv[%d] = %d mV, Raw: %d\n",idx, val_mv, buf);
    				return val_mv;
    			}
    }

    Here is the output from this modified version. It looks like the signed bit is interrupting for some odd reason. I tried to mask it to 0x0FFF before, but it returned a constant -4096 output.

    [00:00:00.514,678] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 0
    
    [00:00:01.617,950] <inf> ADC_Driver: Values_mv[2] = 2475 mV, Raw: 2816
    
    [00:00:02.721,252] <inf> ADC_Driver: Values_mv[2] = 2984 mV, Raw: 3396
    
    [00:00:03.824,554] <inf> ADC_Driver: Values_mv[2] = 1518 mV, Raw: 1728
    
    [00:00:04.927,856] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 0
    
    [00:00:06.031,097] <inf> ADC_Driver: Values_mv[2] = 297 mV, Raw: 338
    
    [00:00:07.134,338] <inf> ADC_Driver: Values_mv[2] = 2982 mV, Raw: 3393
    
    [00:00:08.237,579] <inf> ADC_Driver: Values_mv[2] = 2984 mV, Raw: 3396
    
    [00:00:09.340,820] <inf> ADC_Driver: Values_mv[2] = 148 mV, Raw: 169
    
    [00:00:10.444,061] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 0
    
    [00:00:11.547,302] <inf> ADC_Driver: Values_mv[2] = 1559 mV, Raw: 1774
    
    [00:00:12.650,543] <inf> ADC_Driver: Values_mv[2] = 2985 mV, Raw: 3397
    
    [00:00:13.753,784] <inf> ADC_Driver: Values_mv[2] = 2986 mV, Raw: 3398
    
    [00:00:14.857,025] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 1
    
    [00:00:15.960,266] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 0
    
    [00:00:17.063,507] <inf> ADC_Driver: Values_mv[2] = 869 mV, Raw: 989
    
    [00:00:18.166,748] <inf> ADC_Driver: Values_mv[2] = 57598 mV, Raw: 65534
    
    [00:00:19.269,989] <inf> ADC_Driver: Values_mv[2] = 2189 mV, Raw: 2491
    
    [00:00:20.373,229] <inf> ADC_Driver: Values_mv[2] = 2985 mV, Raw: 3397
    
    [00:00:21.476,470] <inf> ADC_Driver: Values_mv[2] = 1278 mV, Raw: 1455
    
    [00:00:22.579,711] <inf> ADC_Driver: Values_mv[2] = 11 mV, Raw: 13
    
    [00:00:23.682,952] <inf> ADC_Driver: Values_mv[2] = 666 mV, Raw: 758
    
    [00:00:24.786,193] <inf> ADC_Driver: Values_mv[2] = 2581 mV, Raw: 2937
    
    [00:00:25.889,434] <inf> ADC_Driver: Values_mv[2] = 2986 mV, Raw: 3398
    
    [00:00:26.992,675] <inf> ADC_Driver: Values_mv[2] = 2451 mV, Raw: 2789
    
    [00:00:28.095,916] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:00:29.199,157] <inf> ADC_Driver: Values_mv[2] = 24 mV, Raw: 28
    
    [00:00:30.302,398] <inf> ADC_Driver: Values_mv[2] = 2846 mV, Raw: 3239
    
    [00:00:31.405,639] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3395
    
    [00:00:32.508,880] <inf> ADC_Driver: Values_mv[2] = 1863 mV, Raw: 2120
    
    [00:00:33.612,121] <inf> ADC_Driver: Values_mv[2] = 57597 mV, Raw: 65533
    
    [00:00:34.715,362] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:00:35.818,603] <inf> ADC_Driver: Values_mv[2] = 1960 mV, Raw: 2231
    
    [00:00:36.921,844] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3394
    
    [00:00:38.025,085] <inf> ADC_Driver: Values_mv[2] = 2986 mV, Raw: 3398
    
    [00:00:39.128,326] <inf> ADC_Driver: Values_mv[2] = 865 mV, Raw: 985
    
    [00:00:40.231,567] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 0
    
    [00:00:41.334,808] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:00:42.438,049] <inf> ADC_Driver: Values_mv[2] = 2257 mV, Raw: 2568
    
    [00:00:43.541,290] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3395
    
    [00:00:44.644,531] <inf> ADC_Driver: Values_mv[2] = 2985 mV, Raw: 3397
    
    [00:00:45.747,772] <inf> ADC_Driver: Values_mv[2] = 1240 mV, Raw: 1411
    
    [00:00:46.851,013] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 1
    
    [00:00:47.954,254] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:00:49.057,495] <inf> ADC_Driver: Values_mv[2] = 1412 mV, Raw: 1607
    
    [00:00:50.160,736] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3395
    
    [00:00:51.263,977] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3394
    
    [00:00:52.367,218] <inf> ADC_Driver: Values_mv[2] = 2457 mV, Raw: 2796
    
    [00:00:53.470,458] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:00:54.573,699] <inf> ADC_Driver: Values_mv[2] = 0 mV, Raw: 0
    
    [00:00:55.676,940] <inf> ADC_Driver: Values_mv[2] = 80 mV, Raw: 92
    
    [00:00:56.780,181] <inf> ADC_Driver: Values_mv[2] = 2984 mV, Raw: 3396
    
    [00:00:57.883,422] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3394
    
    [00:00:58.986,663] <inf> ADC_Driver: Values_mv[2] = 2985 mV, Raw: 3397
    
    [00:01:00.089,904] <inf> ADC_Driver: Values_mv[2] = 149 mV, Raw: 170
    
    [00:01:01.193,145] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:01:02.296,386] <inf> ADC_Driver: Values_mv[2] = 57598 mV, Raw: 65534
    
    [00:01:03.399,627] <inf> ADC_Driver: Values_mv[2] = 2949 mV, Raw: 3356
    
    [00:01:04.502,868] <inf> ADC_Driver: Values_mv[2] = 2984 mV, Raw: 3396
    
    [00:01:05.606,109] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3394
    
    [00:01:06.709,350] <inf> ADC_Driver: Values_mv[2] = 45 mV, Raw: 52
    
    [00:01:07.812,591] <inf> ADC_Driver: Values_mv[2] = 57599 mV, Raw: 65535
    
    [00:01:08.915,832] <inf> ADC_Driver: Values_mv[2] = 200 mV, Raw: 228
    
    [00:01:10.019,073] <inf> ADC_Driver: Values_mv[2] = 2983 mV, Raw: 3394
    
    [00:01:11.122,314] <inf> ADC_Driver: Values_mv[2] = 2985 mV, Raw: 3397

  • Hello,

    It's not possible to do oversampling and scan at the same time. Can you try without oversampling and check again?

    Kenneth

Related