TS-7180 CPU ADC

From embeddedTS Manuals

The TS-7180 has four ADC channels, whose inputs are available on the P3 connector as AN_IN_1 through AN_IN_4. Each input may be configured to measure voltage in either one of two ranges (0-2.5V and 0-10.9V) or a 20mA current-loop. Voltage measurements outside those ranges can be accomplished by adding an external voltage divider and then also making corresponding adjustments to the scaling applied in the code examples below.

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_voltage4_raw

To switch to the 10.9V input range, the appropriate enable must be set high. Each input AN_IN_1 through AN_IN_4 has its own enable, EN_ADC1_10V through EN_ADC4_10V, and these are controlled by GPIO #10 through #13. For example, to switch AN_IN_1 to the 10.9V range, run the following command:

gpioset 5 10=1

Note that the result must now be multiplied by (10.9/2.5). Note also that the input impedance will now be around 2k ohms.

To switch to the 20mA current-loop mode, the appropriate enable must be set high. These are EN_CL_1 through EN_CL_4, and are controlled by GPIO #6 through #9.

# Select 2.5V
gpioset 5 10=0
# Asssert EN_CL_1
gpioset 5 6=1
ADC Table
# 'raw' 2.5/10.9V Select 20mA Loop Select
AN_IN_1 in_voltage4_raw gpio bank 5 io 10 gpio bank 5 io 6
AN_IN_2 in_voltage5_raw gpio bank 5 io 11 gpio bank 5 io 7
AN_IN_3 in_voltage8_raw gpio bank 5 io 12 gpio bank 5 io 8
AN_IN_4 in_voltage9_raw gpio bank 5 io 13 gpio bank 5 io 9
Note: The four ADC inputs use the CPU ADC inputs 4,5,8, and 9, corresponding with the 'raw' entries in the above table.

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)
{
	/* scale a 0-4095 raw reading to 0-2500 mV */
	uint32_t val = raw * 5000 / (4095 * 2);

	return val;
}

int main(int argc, char **argv)
{
	static struct iio_context *ctx;
	static struct iio_device *dev;
	static struct iio_channel *chn[4];
	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, "voltage4", false);
	chn[1] = iio_device_find_channel(dev, "voltage5", false);
	chn[2] = iio_device_find_channel(dev, "voltage8", false);
	chn[3] = iio_device_find_channel(dev, "voltage9", false);

	for (i = 0; i < 4; 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 python

import iio

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

scan_channels = ["voltage4", "voltage5", "voltage8", "voltage9"]

for n, chan_name in enumerate(scan_channels, start=1):
	chn = dev.find_channel(chan_name)
	raw = int(chn.attrs['raw'].value)

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

	print('AN_CH{}_V={:.3f}'.format(n, scaled))