TS-7180 CPU ADC: Difference between revisions

From embeddedTS Manuals
No edit summary
No edit summary
Line 1: Line 1:
The TS-7180 has four channels of ADC, and those inputs are available on the [[TS-7180#Terminal_Blocks|P3]] connector, as AN_IN_1 through AN_IN_4.  Each input may be configured to measure voltage in two ranges (0-2.5V and 0-10.9V), or a 20mA current-loop.
The TS-7180 has four channels of ADC, and those inputs are available on the [[TS-7180#Terminal_Blocks|P3]] connector, as AN_IN_1 through AN_IN_4.  Each input may be configured to measure voltage in two ranges (0-2.5V and 0-10.9V), or a 20mA current-loop.


The standard linux kernel offers a simple interface to the ADC that does not require any sort of programming to use. For example, to see the "raw" reading from the AN_IN_1 input, type the following command:
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/:


<source lang=bash>
<source lang=bash>
cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw
cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw
</source>
To convert this raw value to a voltage, it must be multiplied by the "scaling factor", which can be found by typing the following command:
<source lang=bash>
cat /sys/bus/iio/devices/iio\:device0/in_voltage_scale
</source>
The result will be in millivolts.  If you have the '''bc''' utility installed, you can enter the following command:
<source lang=bash>
echo `cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw` \* `cat /sys/bus/iio/devices/iio\:device0/in_voltage_scale` | bc
</source>
</source>


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:
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:
<source lang=bash>
<source lang=bash>
tshwctl -a 10 -w 3
gpioset 5 10=1
</source>
</source>


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.
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. First select the 2.5V range as follows:
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.
<source lang=bash>
tshwctl -a 10 -w 1
</source>
And then set the EN_CL_1 enable high as follows:
<source lang=bash>
<source lang=bash>
tshwctl -a 6 -w 3
# Select 2.5V
gpioset 5 10=0
# Asssert EN_CL_1
gpioset 5 6=1
</source>
</source>


{|class=wikitable
{|class=wikitable
Line 44: Line 31:
| AN_IN_1
| AN_IN_1
| in_voltage4_raw
| in_voltage4_raw
| GPIO 10
| [[#GPIO|gpio bank 5 io 10]]
| GPIO 6
| [[#GPIO|gpio bank 5 io 6]]
|-
|-
| AN_IN_2
| AN_IN_2
| in_voltage5_raw
| in_voltage5_raw
| GPIO 11
| [[#GPIO|gpio bank 5 io 11]]
| GPIO 7
| [[#GPIO|gpio bank 5 io 7]]
|-
|-
| AN_IN_3
| AN_IN_3
| in_voltage8_raw
| in_voltage8_raw
| GPIO 12
| [[#GPIO|gpio bank 5 io 12]]
| GPIO 8
| [[#GPIO|gpio bank 5 io 8]]
|-
|-
| AN_IN_4
| AN_IN_4
| in_voltage9_raw
| in_voltage9_raw
| GPIO 13
| [[#GPIO|gpio bank 5 io 13]]
| GPIO 9
| [[#GPIO|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.}}
{{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 [https://analogdevicesinc.github.io/libiio/ libiio] library provides simple access to the IO.  The fastest API is in C which will get about 6ksps.
<source lang=c>
/* 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[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;
}
</source>
The python bindings currently achieve about 2ksps with similar code.
<source lang=python>
#!/usr/bin/env python3
import iio
ctx = iio.Context('local:')
dev = ctx.find_device('2198000.adc')
scan_channels = ["voltage4", "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))
</source>

Revision as of 16:51, 15 June 2021

The TS-7180 has four channels of ADC, and those inputs are available on the P3 connector, as AN_IN_1 through AN_IN_4. Each input may be configured to measure voltage in two ranges (0-2.5V and 0-10.9V), or a 20mA current-loop.

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)
{
	/* 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[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 python3

import iio

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

scan_channels = ["voltage4", "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))