TS-7180 CPU ADC: Difference between revisions
No edit summary |
(Remove external voltage divider from examples (gives wrong results without a divider)) |
||
Line 1: | Line 1: | ||
The TS-7180 has four channels | The TS-7180 has four ADC channels whose inputs are available on the [[TS-7180#Terminal_Blocks|P3]] connector, as <code>AN_IN_1</code> through <code>AN_IN_4</code>. 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. | ||
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/: | 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 <code>/sys/</code>: | ||
<source lang=bash> | <source lang=bash> | ||
Line 7: | Line 7: | ||
</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 <code>AN_IN_1</code> through <code>AN_IN_4</code> has its own enable, <code>EN_ADC1_10V</code> through <code>EN_ADC4_10V</code>, and these are controlled by GPIO #10 through #13. For example, to switch <code>AN_IN_1</code> to the 10.9V range, run the following command: | ||
<source lang=bash> | <source lang=bash> | ||
gpioset 5 10=1 | gpioset 5 10=1 | ||
Line 14: | Line 14: | ||
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 <code>EN_CL_1</code> through <code>EN_CL_4</code>, and are controlled by GPIO #6 through #9. | ||
<source lang=bash> | <source lang=bash> | ||
# Select 2.5V | # Select 2.5V | ||
Line 69: | Line 69: | ||
uint32_t scale_mv(uint32_t raw) | uint32_t scale_mv(uint32_t raw) | ||
{ | { | ||
/* | /* scale a 0-4095 raw reading to 0-2500 mV */ | ||
uint32_t val = raw * | uint32_t val = raw * 5000 / (4095 * 2); | ||
return val; | return val; | ||
Line 106: | Line 105: | ||
The python bindings currently achieve about 2ksps with similar code. | The python bindings currently achieve about 2ksps with similar code. | ||
<source lang=python> | <source lang=python> | ||
#!/usr/bin/env | #!/usr/bin/env python | ||
import iio | import iio | ||
Line 114: | Line 113: | ||
scan_channels = ["voltage4", "voltage5", "voltage8", "voltage9"] | scan_channels = ["voltage4", "voltage5", "voltage8", "voltage9"] | ||
for chan_name in scan_channels: | for n, chan_name in enumerate(scan_channels, start=1): | ||
chn = dev.find_channel(chan_name) | chn = dev.find_channel(chan_name) | ||
raw = int(chn.attrs['raw'].value) | raw = int(chn.attrs['raw'].value) | ||
# Scale 0-4095 to 0-2500(mV) | # Scale 0-4095 raw value to 0-2500(mV) | ||
scaled = raw * (2.5/4095) | scaled = raw * (2.5/4095) | ||
print('AN_CH{}_V={:.3f}'.format(n, scaled)) | |||
print('AN_CH{}_V={:.3f}'.format( | |||
</source> | </source> |
Revision as of 13:41, 19 April 2022
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.
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))