3.2.2.1. ADC
Introduction
An analog-to-digital converter (abbreviated ADC) is a device that uses sampling to convert a continuous quantity to a discrete time representation in digital form.
The ADC is a 12-bit, 8-channel, general purpose ADC with a sample rate of 4 MSPS (Megasamples per second or millions of samples per second). The ADC sits idle until a Start of Conversion (SOC) pulse allows the it to start conversion. The ADC samples the analog signal when “start of conversion” signal is high and continues sampling 1 clock cycle after the falling edge. It captures the signal at the end of sampling period and starts conversion. It uses 13 clock cycles to digitize the sampled input; then an “end of conversion” signal is enabled high indicating that the digital data ADCOUT<11:0> is ready for SW to consume. A new conversion cycle can be initiated after the previous data is read. Please note that the ADC output is positive binary weighted data.
Convert Analog voltage to Digital
To cross verify the digital values read use,
D = Vin * (2^n - 1) / Vref
Where:
D = Digital value
Vin = Input voltage
n = No of bits
Vref = reference voltage
Ex: Read value on channel AIN4 for input voltage supplied 1.01:
Formula:
D = 1.01 * (2^12 -1 )/ 1.8
D = 2297.75
Accessing ADC Pins on TI EVMs
On AM64x platform, there is a 20-pin connector (J3) of part number “TSW-110-07-S-D” for connecting ADC signals. The connector includes ADC0_AIN0-7, VDDA_ADC connections and ground connections. For ADC connector (J3) Pin-Out go to the “AM64x User Guide” found here, or see the ADC schematic (PROC101A(001)_SCH) found here.
Driver Configuration
You can enable ADC driver in the kernel as follows.
Device Drivers --->
[*] Industrial I/O support --->
[*] Enable buffer support within IIO
Analog to digital converters --->
<*> TI's AM335X ADC driver
Should the entry “TI’s AM335X ADC driver” be missing the MFD component —>
Device Drivers --->
Multifunction device drivers --->
<M> TI ADC / Touch Screen chip support
Building as Loadable Kernel Module
In-case if you want to build the driver as module, use <M> instead of <*> during menuconfig while selecting the drivers (as shown below). For more information on compiling and installing kernel modules, refer to the Kernel User’s Guide . For more information on loadable modules refer to Loadable Module HOWTO .
Device Drivers --->
[M] Industrial I/O support --->
[*] Enable buffer support within IIO
Analog to digital converters --->
<M> TI's AM335X ADC driver
Use “make modules” during kernel build to build the ADC driver as module. The module should be present in
drivers/iio/adc/ti_am335x_adc.ko
.The driver should autoload on filesystem boot. If not, load the driver using
modprobe ti_am335x_adc
Device Tree
ADC device tree data is added in
file(arch/arm64/boot/dts/ti/am642-evm.dts
) as shown below.
&tscadc0 {
status = "okay";
adc {
ti,adc-channels = <0 1 2 3 4 5 6 7>;
};
};
The parameter “ti,adc-channels” needs to hold data related to which channels you want to use for ADC; the example above is using channels CH0-CH7.
You can find the source code for ADC in the kernel sources at
drivers/iio/adc/ti_am335x_adc.c
.
Usage
To test ADC, Connect a DC voltage supply to each of the AIN0 through AIN7 pins (based on your channel configuration), and vary voltage between 0 and 1.8v reference voltage.
CAUTION Make sure that the voltage supplied does not cross 1.8v
On loading the module you would see the IIO device created
root@arago-armv7:~# ls -al /sys/bus/iio/devices/iio\:device0/
drwxr-xr-x 5 root root 0 Nov 1 22:06 .
drwxr-xr-x 4 root root 0 Nov 1 22:06 ..
drwxr-xr-x 2 root root 0 Nov 1 22:06 buffer
-r--r--r-- 1 root root 4096 Nov 1 22:06 dev
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage0_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage1_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage2_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage3_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage4_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage5_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage6_raw
-rw-r--r-- 1 root root 4096 Nov 1 22:06 in_voltage7_raw
-r--r--r-- 1 root root 4096 Nov 1 22:06 name
lrwxrwxrwx 1 root root 0 Nov 1 22:06 of_node -> ../../../../../../firmware/devicetree/base/ocp/tscadc@44e0d000/adc
drwxr-xr-x 2 root root 0 Nov 1 22:06 power
drwxr-xr-x 2 root root 0 Nov 1 22:06 scan_elements
lrwxrwxrwx 1 root root 0 Nov 1 22:06 subsystem -> ../../../../../../bus/iio
-rw-r--r-- 1 root root 4096 Nov 1 22:06 uevent
Modes of operation
When the ADC sequencer finishes cycling through all the enabled channels, the user can decide if the sequencer should stop (one-shot mode), or loop back and schedule again (continuous mode). If one-shot mode is enabled, then the sequencer will only be scheduled one time (the sequencer HW will automatically disable the StepEnable bit after it is scheduled which will guarantee only one sample is taken per channel). When the user wants to continuously take samples, continuous mode needs to be enabled. One cannot read ADC data from one channel operating in One-shot mode and and other in continuous mode at the same time.
One-shot Mode
To read a single ADC output from a particular channel this interface can be used.
root@arago-armv7:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw
645
This feature is exposed by IIO through the following files:
in_voltageX_raw: raw value of the channel X of the ADC
Continuous Mode
Overview
Important folders in the iio:deviceX directory are:
buffer
enable
: get and set the state of the bufferlength
: get and set the length of the buffer.
root@charlie:~# ls -l /sys/bus/iio/devices/iio\:device0/buffer/
total 0
-rw-r--r-- 1 root root 4096 Nov 3 22:53 enable
-rw-r--r-- 1 root root 4096 Nov 3 22:53 length
-rw-r--r-- 1 root root 4096 Nov 3 22:53 watermark
Scan_elements directory contains interfaces for elements that will be captured for a single sample set in the buffer.
root@arago-armv7:~# ls -al /sys/bus/iio/devices/iio\:device0/scan_elements/
drwxr-xr-x 2 root root 0 Jan 1 00:00 .
drwxr-xr-x 5 root root 0 Jan 1 00:00 ..
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage0_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage0_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage0_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage1_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage1_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage1_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage2_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage2_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage2_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage3_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage3_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage3_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage4_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage4_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage4_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage5_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage5_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage5_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage6_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage6_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage6_type
-rw-r--r-- 1 root root 4096 Jan 1 00:02 in_voltage7_en
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage7_index
-r--r--r-- 1 root root 4096 Jan 1 00:02 in_voltage7_type
root@arago-armv7:~#
scan_elements
exposes 3 files per channel:
in_voltageX_en: is this channel enabled?
in_voltageX_index: index of this channel in the buffer’s chunks
in_voltageX_type : How the ADC stores its data. Reading this file should return you a string something like below:
root@arago-armv7:~# cat /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage1_type
le:u12/16>>0
Where:
le represents the endianness, here little endian
u is the sign of the value returned. It could be either u (for unsigned) or s (for signed)
12 is the number of relevant bits of information
16 is the actual number of bits used to store the datum
0 is the number of right shifts needed.
How to set it up
To read ADC data continuously we need to enable buffer and channels to be used.
Set up the channels in use (you can enable any combination of the channels you want)
root@arago-armv7:~# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage0_en
root@arago-armv7:~# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage5_en
root@arago-armv7:~# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage7_en
Set up the buffer length
root@arago-armv7:~# echo 100 > /sys/bus/iio/devices/iio\:device0/buffer/length
Enable the capture
root@arago-armv7:~# echo 1 > /sys/bus/iio/devices/iio\:device0/buffer/enable
/dev/iio:device0
To stop the capture, just disable the buffer
root@arago-armv7:~# echo 0 > /sys/bus/iio/devices/iio\:device0/buffer/enable
Userspace Sample Application
The source code is located under kernel sources at
tools/iio/iio_generic_buffer.c
.
How to compile:
$ make -C <kernel-src-dir>/tools/iio ARCH=arm
The iio_generic_buffer
application does all the ADC channel “enable”
and “disable” actions for you. You will only need to specify the IIO
driver. Application takes buffer length to use (256 in this example)
and the number of iterations you want to run (3 in this example). By
just enabling the buffer ADC switches to continuous mode.
root@charlie:~# ./iio_generic_buffer -?
Usage: generic_buffer [options]...
Capture, convert and output data from IIO device buffer
-a Auto-activate all available channels
-A Force-activate ALL channels
-c <n> Do n conversions
-e Disable wait for event (new data)
-g Use trigger-less mode
-l <n> Set buffer length to n samples
--device-name -n <name>
--device-num -N <num>
Set device by name or number (mandatory)
--trigger-name -t <name>
--trigger-num -T <num>
Set trigger by name or number
-w <n> Set delay between reads in us (event-less mode)
For example:-
root@charlie:~# ./iio_generic_buffer -N 0 -g -a
iio device number being used is 0
trigger-less mode selected
Enabling all channels
Enabling: in_voltage7_en
Enabling: in_voltage4_en
Enabling: in_voltage6_en
Enabling: in_voltage5_en
525.000000 924.000000 988.000000 1039.000000
754.000000 986.000000 1071.000000 1117.000000
877.000000 1067.000000 1150.000000 1169.000000
1003.000000 1143.000000 1230.000000 1226.000000
1078.000000 1222.000000 1298.000000 1286.000000
1139.000000 1286.000000 1372.000000 1343.000000
...
...
1863.000000 1954.000000 2031.000000 2074.000000
1858.000000 1959.000000 2023.000000 2083.000000
1852.000000 1958.000000 2024.000000 2076.000000
1866.000000 1964.000000 2029.000000 2083.000000
1850.000000 1952.000000 2026.000000 2074.000000
Disabling: in_voltage7_en
Disabling: in_voltage4_en
Disabling: in_voltage6_en
Disabling: in_voltage5_en
ADC Driver Limitations
This driver is based on the IIO (Industrial I/O subsystem), however this driver has limited functionality:
“Out of Range” not supported by ADC driver.