AD7173
AD7173 IIO Sigma-Delta ADC Linux Driver.
Supported Devices
This driver supports the
Evaluation Boards
Description
This is a Linux industrial I/O (Linux Industrial I/O Subsystem) subsystem driver, targeting single channel serial interface ADCs. The industrial I/O subsystem provides a unified framework for drivers for many different types of converters and sensors using a number of different physical interfaces (i2c, spi, etc). See Linux Industrial I/O Subsystem for more information.
Status
Files
Function |
File |
|
|---|---|---|
driver |
||
devicetree bindings |
Devicetree
Analog Devices AD7173 and similar ADCs
Required properties for the AD7173:
compatible: Must be one of
adi,ad7172-2
adi,ad7172-4
adi,ad7173-8
adi,ad7175-2
adi,ad7175-8
adi,ad7176-2
adi,ad7177-2
adi,ad4111
adi,ad4112
adi,ad4114
adi,ad4115
adi,ad4116
reg: SPI chip select number for the device
channel@(hex_identifier): defines channels that use analog input pairs
Channel example:
// AIN0 - AIN1, bipolar encoding, uses the REF+/REF- external reference
channel@0 {
reg = <0>;
bipolar;
diff-channels = <0 1>;
adi,reference-select = "vref";
};
Channel required properties
Selection of analog inputs. Valid combinations:
diff-channels: expects a two value array, will define a channel marked as differential.
single-channel + common-mode-channel: each expects a single value, will define a channel marked as single-ended.
single-channel + adi,current-channel: only single-channel expects a value, will be used to define a current measuring channel on AD411x models with current inputs.
Optional properties
interrupts: maps the interrupts to a pin and a trigger level
Ready: Multiplexed with the DOUT pin, can be used as indication of a finished conversion, should be IRQ_TYPE_EDGE_FALLING. The device tree property is optional for the bindings, the upstream version of the driver is required to have the interrupt defined in order to be functional.
Error: Used to detect if one of the following errors has occurred: ADC_ERROR/CRC_ERROR/REG_ERROR. At the time of writing, this feature is not implemented in the driver.
interrupt-names: The name of the interrupts, order should coincide with the values from the interrupts property.
spi-max-frequency: Max SPI frequency to use see: Documentation/devicetree/bindings/spi/spi-bus.txt.
gpio-controller: Marks the device node as a GPIO controller.
voltage supplies:
vref-supply: external supply REF+/REF-
vref2-supply: external supply REF2+/REF2- (only on applicable models)
avdd-supply: external supply AVDD1
avdd2-supply: external supply AVDD2 (only on applicable models)
iovdd-supply: iovdd supply, used for the chip digital interface
clocks: Phandle to the external clock. If left empty, the internal clock will be used and be available as output on the XTAL2 pin.
clock-names: Name of external clock. Valid values:
ext-clk: External clock source applied to XTAL2 pin. Refer to datasheet for valid frequencies for each model. For example, AD7173-8 expects a 2 MHz clock for specified data rates to be obtained.
xtal: External crystal applied to the XTAL1/XTAL2 pins. Refer to datasheet for valid frequencies for each model. For example, AD7173-8 expects a 16 MHz clock that will be divided internally to 2 MHz.
Channels optional properties
adi,reference-select: selects the reference source for the channel. Will use the internal reference of the ADC if left empty, except for AD7172-4 which does not feature an internal reference. Valid values:
vref: will use the supply connected to REF+/REF- defined at vref-supply
vref2: will use the supply conencted to REF2+/REF2- defined at vref2-supply
refout-avss: will use the internal reference REFOUT/AVSS
avdd: will use the AVDD/AVSS supply defined at avdd-supply
bipolar: If set, the channel will be setup in bipolar mode where the ADC accepts negative differential input voltages, and the output coding is offset binary. If the property is missing, the channel will be set in unipolar mode and the ADC accepts only positive differential voltages, and the coding is straight binary.
Configuration differences between models
Analog inputs differences:
Reference differences:
Note
For more devicetree examples and full bindings documentation, refer to adi,ad7173.yaml
Adding Linux driver support
Configure kernel with make menuconfig (alternatively use make xconfig or
make qconfig)
Note
The AD7173 driver depends on CONFIG_IIO and CONFIG_SPI_MASTER
Linux Kernel Configuration
Device Drivers --->
...
<*> Industrial I/O support --->
--- Industrial I/O support
...
Analog to digital converters --->
...
<*> Analog Devices AD7173 driver
...
...
...
Hardware configuration
The evaluation kits were connected using the exposed digital I/O pins to a Raspberry pi 3B+. Here is an example of connection from the ADC evaluation board to the RPI:
DEVICE HOST RPI
* CS <——————— Pin 24 (GPIO08) SPI_CE0_N
* SCLK <——————— Pin 23 (GPIO11) SPI_CLK
* DIN <——————— Pin 19 (GPIO10) SPI_MOSI
* DOUT/RDY ———————> Pin 21 (GPIO09) SPI_MISO
└───> Pin 22 (GPIO25) GPIO_GEN5 (secondary pin connected to DOUT/RDY for the RDY interrupt)
Driver testing
Each and every IIO device, typically a hardware chip, has a device folder under
/sys/bus/iio/devices/iio:deviceX. Where X is the IIO index of the device. Under
every of these directory folders reside a set of files, depending on the
characteristics and features of the hardware device in question. These files
are consistently generalized and documented in the IIO ABI documentation. In
order to determine which IIO deviceX corresponds to which hardware device, the
user can read the name file /sys/bus/iio/devices/iio:deviceX/name. In case
the sequence in which the iio device drivers are loaded/registered is constant,
the numbering is constant and may be known in advance.
root@analog:~# cd /sys/bus/iio/devices/
root@analog:/sys/bus/iio/devices# ls
iio:device0
root@analog:/sys/bus/iio/devices# cd iio\:device0
root@analog:/sys/bus/iio/devices/iio:device0# ls -l
total 0
drwxr-xr-x 2 root root 0 Feb 10 11:39 buffer
drwxr-xr-x 2 root root 0 Feb 10 11:39 buffer0
-r--r--r-- 1 root root 4096 Feb 10 11:39 dev
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_temp_offset
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_temp_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_temp_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_temp_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage0-voltage1_offset
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage0-voltage1_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage0-voltage1_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage0-voltage1_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage10-voltage11_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage10-voltage11_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage10-voltage11_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage12-voltage13_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage12-voltage13_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage12-voltage13_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage14-voltage15_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage14-voltage15_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage14-voltage15_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage2_offset
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage2_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage2_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage2_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage4-voltage5_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage4-voltage5_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage4-voltage5_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage6-voltage7_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage6-voltage7_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage6-voltage7_scale
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage8-voltage9_raw
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage8-voltage9_sampling_frequency
-rw-r--r-- 1 root root 4096 Feb 10 11:39 in_voltage8-voltage9_scale
-r--r--r-- 1 root root 4096 Feb 10 11:39 name
lrwxrwxrwx 1 root root 0 Feb 10 11:39 of_node -> ../../../../../../../../firmware/devicetree/base/soc/spi@7e204000/adc@0
drwxr-xr-x 2 root root 0 Feb 10 11:39 power
drwxr-xr-x 2 root root 0 Feb 10 11:38 scan_elements
lrwxrwxrwx 1 root root 0 Feb 10 11:39 subsystem -> ../../../../../../../../bus/iio
drwxr-xr-x 2 root root 0 Feb 10 11:39 trigger
-rw-r--r-- 1 root root 4096 Feb 10 11:38 uevent
-r--r--r-- 1 root root 4096 Feb 10 11:39 waiting_for_supplier
Note
The channels above correspond to the following devicetree instance: rpi-ad7173-overlay.dts
Show device name
root@analog:/sys/bus/iio/devices/iio:device0# cat name
ad7173-8
Show channel raw, scale and offset
Description: Scales and offsets to be applied to in_voltagex_voltagey_raw in order to obtain the measured voltage in millivolts.
Compute formula is: (RAW + OFFSET) * SCALE for channels that are configured with bipolar coding within the devicetree. For channels missing the offset property, RAW * SCALE will be used. Example channel configured with AIN0-AIN1, internal reference and bipolar coding:
U = (in_voltage0-voltage1_raw + in_voltage0-voltage1_offset) * cat in_voltage0-voltage1_scale = 517.683236334 mV
root:/sys/bus/iio/devices/iio:device0> cat in_voltage0-voltage1_scale
0.000596046
root:/sys/bus/iio/devices/iio:device0> cat in_voltage0-voltage1_offset
-8388608
root:/sys/bus/iio/devices/iio:device0> cat in_voltage0-voltage1_raw
9257137
Set sampling frequency
Description: The output sampling rate cat be set to each channel individually.
When reading channel values individually or using buffered mode with a single channel enabled, the data rate will coincide with the set value.
When using buffered mode with multiple channels, the effective data rate will be lower and depend on the number of enabled channels and their respective sampling frequency setting.
root:/sys/bus/iio/devices/iio:device0> cat in_voltage0-voltage1_sampling_frequency
6211.000000
root:/sys/bus/iio/devices/iio:device0> echo 10 > in_voltage0-voltage1_sampling_frequency
root:/sys/bus/iio/devices/iio:device0> cat in_voltage0-voltage1_sampling_frequency
10.000000
root:/sys/bus/iio/devices/iio:device0> echo 100.5 > in_voltage2_sampling_frequency
root:/sys/bus/iio/devices/iio:device0> cat in_voltage2_sampling_frequency
100.500000
Calibration
The family supports both internal and system calibrations which can be done at full or zero scale.
* Internal zero scale: removes ADC core offset errors. * Internal full scale: removes ADC core gain errors. * System zero scale: reduces offset error to the order of channel noise. * System full scale: reduces gain error to the order of channel noise.
All voltage channels will undergo an internal zero/full scale calibration at bootup.
System zero/full scale can be done after bootup using the newly created iio interface ‘sys_calibration’ and ‘sys_calibration_mode’
root:/sys/bus/iio/devices/iio:device0> echo 'zero_scale' > sys_calibration_mode
root:/sys/bus/iio/devices/iio:device0> echo 1 > sys_calibration_mode
root:/sys/bus/iio/devices/iio:device0> echo 'full_scale' > sys_calibration_mode
root:/sys/bus/iio/devices/iio:device0> echo 1 > sys_calibration_mode
Openwire detection for AD4111
AD4111 supports openwire detection and will report a fault event through an iio_event when an openwire condition is detected when running a single conversion.
The fault is level triggered, it will keep being sent as long as the condition still exists.
The tool iio_event_monitor found in your kernel sources tools/iio/iio_event_monitor.c can be used to read those events.
Buffer management
The Industrial I/O subsystem provides support for various ring buffer based
data acquisition methods. Apart from device specific hardware buffer support,
the user can chose between two different software ring buffer implementations.
One is the IIO lock free software ring, and the other is based on Linux kfifo.
Devices with buffer support feature an additional sub-folder in the
/sys/bus/iio/devices/deviceX/ folder hierarchy. Called deviceX:bufferY,
where Y defaults to 0, for devices with a single buffer.
Every buffer implementation features a set of files:
- length
Get/set the number of sample sets that may be held by the buffer.
- enable
Enables/disables the buffer. This file should be written last, after length and selection of scan elements.
- watermark
A single positive integer specifying the maximum number of scan elements to wait for. Poll will block until the watermark is reached. Blocking read will wait until the minimum between the requested read amount or the low water mark is available. Non-blocking read will retrieve the available samples from the buffer even if there are less samples then watermark level. This allows the application to block on poll with a timeout and read the available samples after the timeout expires and thus have a maximum delay guarantee.
- data_available
A read-only value indicating the bytes of data available in the buffer. In the case of an output buffer, this indicates the amount of empty space available to write data to. In the case of an input buffer, this indicates the amount of data available for reading.
- length_align_bytes
Using the high-speed interface. DMA buffers may have an alignment requirement for the buffer length. Newer versions of the kernel will report the alignment requirements associated with a device through the
length_align_bytesproperty.- scan_elements
The scan_elements directory contains interfaces for elements that will be captured for a single triggered sample set in the buffer.
root@analog:/sys/bus/iio/devices/iio:device0/scan_elements# ls
in_temp_en in_voltage10-voltage11_index in_voltage14-voltage15_type in_voltage6-voltage7_en
in_temp_index in_voltage10-voltage11_type in_voltage2_en in_voltage6-voltage7_index
in_temp_type in_voltage12-voltage13_en in_voltage2_index in_voltage6-voltage7_type
in_voltage0-voltage1_en in_voltage12-voltage13_index in_voltage2_type in_voltage8-voltage9_en
in_voltage0-voltage1_index in_voltage12-voltage13_type in_voltage4-voltage5_en in_voltage8-voltage9_index
in_voltage0-voltage1_type in_voltage14-voltage15_en in_voltage4-voltage5_index in_voltage8-voltage9_type
in_voltage10-voltage11_en in_voltage14-voltage15_index in_voltage4-voltage5_type
Note
The channels above correspond to the following devicetree instance: rpi-ad7173-overlay.dts
- in_voltageX_en / in_voltageX-voltageY_en / timestamp_en:
Scan element control for triggered data capture. Writing 1 will enable the scan element, writing 0 will disable it
- in_voltageX_type / in_voltageX-voltageY_type / timestamp_type:
Description of the scan element data storage within the buffer and therefore in the form in which it is read from user-space. Form is [s|u]bits/storage-bits. s or u specifies if signed (2’s complement) or unsigned. bits is the number of bits of data and storage-bits is the space (after padding) that it occupies in the buffer. Note that some devices will have additional information in the unused bits so to get a clean value, the bits value must be used to mask the buffer output value appropriately. The storage-bits value also specifies the data alignment. So u12/16 will be a unsigned 12 bit integer stored in a 16 bit location aligned to a 16 bit boundary. For other storage combinations this attribute will be extended appropriately.
- in_voltageX_index / in_voltageX-voltageY_index / timestamp_index:
A single positive integer specifying the position of this scan element in the buffer. Note these are not dependent on what is enabled and may not be contiguous. Thus for user-space to establish the full layout these must be used in conjunction with all _en attributes to establish which channels are present, and the relevant _type attributes to establish the data storage format.