TS-7180 CPU ADC
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
# | '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))