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
  • Hello,

    Will the following work? val_mv = buf;

    Shouldn't you cast it first, like val_mv = (int32_t)buf;

    Kenneth

  • But buf is already int32_t. I tried your method, and no change in output.

  • Can you change the log output so you print both the raw ADC measurement and the calculated mV value and share it here? This may shed some light to what is occuring.

    Kenneth

  • 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

Reply Children
No Data
Related