TS-7180 CPU ADC: Difference between revisions
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. | ||
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> | </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> | ||
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. | 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> | <source lang=bash> | ||
# 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
# | '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))