TS-7250-V3 ADC

From embeddedTS Manuals
Revision as of 16:02, 6 July 2021 by Mark (talk | contribs)

This board supports 5 channels of 12-bit ADC using an integrated ADC in the i.MX6UL CPU. All channels can sample 0-30VDC, but channels 1-3 can optionally sample 0-20mA as a current loop. To minimize noise, the ADC pins use a dedicated analog ground available on the even pins of the header. See the #ADC Header section for more details.

These ADCs are accessed through the IIO layer in Linux. This provides ADC samples up to 6ksps between all channels. The simplest API for slow speed acquisition is through /sys/:

cat /sys/bus/iio/devices/iio\:device0/in_voltage{0,1,5,8,9}_raw
ADC Header Pin Schematic Name IIO device IIO name Voltage Current loop
1 AN_CH1 iio:device0 voltage0 0-30VDC 0-20mA
3 AN_CH2 iio:device0 voltage1 0-30VDC 0-20mA
5 AN_CH3 iio:device0 voltage5 0-30VDC 0-20mA
7 AN_CH4 iio:device0 voltage8 0-30VDC N/A
8 AN_CH5 iio:device0 voltage9 0-30VDC N/A

The current loops are enabled/disabled with GPIO:

gpioset 4 7=0 # AN_CH1 voltage
gpioset 4 8=0 # AN_CH2 voltage
gpioset 4 9=0 # AN_CH3 voltage

gpioset 4 7=1 # AN_CH1 current
gpioset 4 8=1 # AN_CH2 current
gpioset 4 9=1 # AN_CH3 current

The libiio library provides simple access to the IO. The fastest API is in C which will get about 6ksps.

/* Build with gcc adc-test.c -o adc-test -liio 
 * Gets ~6ksps
 * At the time of writing this does not support the buffer interface */

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <iio.h>

uint32_t scale_mv(uint32_t raw)
{
	/* fractions $((330+22)) 22 2500 4095 */
	uint32_t val = raw * 9;
	val += (raw * 629) / 819;

	return val;
}

int main(int argc, char **argv)
{
	static struct iio_context *ctx;
	static struct iio_device *dev;
	static struct iio_channel *chn[5];
	int i, ret;
	long long sample;

	ctx = iio_create_default_context();
	assert(ctx);
	dev = iio_context_find_device(ctx, "2198000.adc");
	assert(dev);

	chn[0] = iio_device_find_channel(dev, "voltage0", false);
	chn[1] = iio_device_find_channel(dev, "voltage1", false);
	chn[2] = iio_device_find_channel(dev, "voltage5", false);
	chn[3] = iio_device_find_channel(dev, "voltage8", false);
	chn[4] = iio_device_find_channel(dev, "voltage9", false);

	for (i = 0; i < 5; i++) {
		ret = iio_channel_attr_read_longlong(chn[i], "raw", &sample);
		assert(!ret);
		printf("AN_CH%d_mv=%d\n", i, scale_mv((uint32_t)sample));
	}

	return 0;
}

The python bindings currently achieve about 2ksps with similar code.

#!/usr/bin/env python3

import iio

ctx = iio.Context('local:')
dev = ctx.find_device('2198000.adc')

scan_channels = ["voltage0", "voltage1", "voltage5", "voltage8", "voltage9"]
i = int(0)
for chan_name in scan_channels:
	chn = dev.find_channel(chan_name)
	raw = int(chn.attrs['raw'].value)

	# Scale 0-4095 to 0-2500(mV)
	scaled = raw * (2.5/4095)

	# Scale voltage divider on the pin
	r1 = 330
	r2 = 22
	v = scaled / (r2 / (r1 + r2))

	i += 1
	print('AN_CH{}_V={:.3f}'.format(i, v))