This is an old revision of the document!
This is a Linux industrial I/O (IIO) subsystem driver, targeting Resolver-to-Digital Converters. 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 IIO for more information.
Support for the AD2S1210 is in mainline for kernel v6.7 and is backported to v6.1 of the ADI tree. Some additional features are slated for v6.8. The device was previously supported by a staging driver with a different ABI.
Function | File |
---|---|
driver | drivers/iio/resolver/ad2s1210.c |
devicetree | Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml |
Configure kernel with “make menuconfig” (alternatively use “make xconfig” or “make qconfig”)
The Driver depends on CONFIG_SPI
Linux Kernel Configuration Device Drivers ---> [*] Staging drivers ---> <*> Industrial I/O support ---> --- Industrial I/O support -*- Enable ring buffer support within IIO -*- Industrial I/O lock free software ring -*- Enable triggered sampling support *** Resolver to digital converters *** [--snip--] <*> Analog Devices AD2S1210 driver [--snip--]
To configure the chip, use the attributes according to the device register to IIO ABI mapping below:
Register | Addr | IIO ABI (sysfs) | Units | Notes |
---|---|---|---|---|
DOS Overrange Threshold | 0x89 | events/in_altvoltage0_thresh_rising_value | mV | |
DOS Mismatch Threshold | 0x8A | events/in_altvoltage0_mag_rising_value | mV | |
DOS Reset Maximum Threshold | 0x8B | events/in_altvoltage0_mag_rising_reset_max | mV | |
DOS Reset Minimum Threshold | 0x8C | events/in_altvoltage0_mag_rising_reset_min | mV | |
LOT High Threshold | 0x8D | events/in_angl1_thresh_rising_value | Radians | |
LOT Low Threshold [1] | 0x8E | events/in_angl1_thresh_rising_hysteresis | Radians | |
Excitation Frequency | 0x91 | out_altvoltage0_frequency | Hz | |
Control | 0x92 | *as bit fields* | ||
Phase lock range | D5 | events/in_phase0_mag_rising_value | Radians | |
Hysteresis | D4 | in_angl0_hysteresis | Radians | |
Encoder resolution | D3:2 | *not implemented* | ||
Resolution | D1:0 | *device tree: assigned-resolution-bits* | Bits | 10, 12, 14, or 16 |
Soft Reset | 0xF0 | [2] | ||
Fault | 0xFF | *not implemented* |
[1]: The value written to the LOT low register is high value minus the hysteresis.
[2]: Soft reset is performed when `out_altvoltage0_frequency` is written.
Accessing a list of channels:
This specifies any shell prompt running on the target
analog@setup-2-zed:~ $ iio_attr ad2s1210 -c dev 'ad2s1210', channel 'angl0' (input, index: 0, format: be:U16/16>>0), found 5 channel-specific attributes dev 'ad2s1210', channel 'anglvel0' (input, index: 1, format: be:S16/16>>0), found 3 channel-specific attributes dev 'ad2s1210', channel 'timestamp' (input, index: 2, format: le:S64/64>>0), found 0 channel-specific attributes dev 'ad2s1210', channel 'phase0' (input), found 1 channel-specific attributes dev 'ad2s1210', channel 'altvoltage0' (output), found 3 channel-specific attributes dev 'ad2s1210', channel 'altvoltage2' (input), found 1 channel-specific attributes dev 'ad2s1210', channel 'angl1' (input), found 1 channel-specific attributes dev 'ad2s1210', channel 'altvoltage0' (input), found 1 channel-specific attributes dev 'ad2s1210', channel 'altvoltage1' (input), found 1 channel-specific attributes
For example, to get position channel angl0:
This specifies any shell prompt running on the target
analog@setup-2-zed:~ $ iio_attr ad2s1210 -ci angl0 dev 'ad2s1210', channel 'angl0' (input), attr 'hysteresis', value '1' dev 'ad2s1210', channel 'angl0' (input), attr 'hysteresis_available', value '0 1' dev 'ad2s1210', channel 'angl0' (input), attr 'label', value 'position' dev 'ad2s1210', channel 'angl0' (input), attr 'raw', value '34114' dev 'ad2s1210', channel 'angl0' (input), attr 'scale', value '0.000095874'
Or velocity channel anglvel0:
This specifies any shell prompt running on the target
analog@setup-2-zed:~ $ iio_attr ad2s1210 -ci anglvel0 dev 'ad2s1210', channel 'anglvel0' (input), attr 'label', value 'velocity' dev 'ad2s1210', channel 'anglvel0' (input), attr 'raw', value '0' dev 'ad2s1210', channel 'anglvel0' (input), attr 'scale', value '0.023968449'
Alternatively, you can read data directly from the device path in /sys/bus:
This specifies any shell prompt running on the target
analog@setup-2-zed:~ $ cd /sys/bus/iio/devices/iio\:device1/ analog@setup-2-zed:/sys/bus/iio/devices/iio:device1 $ ls -l total 0 drwxr-xr-x 2 root root 0 Dec 5 16:05 buffer drwxr-xr-x 2 root root 0 Dec 5 16:05 buffer0 -rw-r--r-- 1 root root 4096 Dec 5 16:05 current_timestamp_clock -r--r--r-- 1 root root 4096 Dec 5 16:05 dev drwxr-xr-x 2 root root 0 Dec 5 16:05 events -r--r--r-- 1 root root 4096 Dec 5 16:05 in_altvoltage0_label -r--r--r-- 1 root root 4096 Dec 5 16:05 in_altvoltage1_label -r--r--r-- 1 root root 4096 Dec 5 16:05 in_altvoltage2_label -rw-r--r-- 1 root root 4096 Dec 5 16:05 in_angl0_hysteresis -r--r--r-- 1 root root 4096 Dec 5 16:05 in_angl0_hysteresis_available -r--r--r-- 1 root root 4096 Dec 5 16:05 in_angl0_label -rw-r--r-- 1 root root 4096 Dec 5 16:05 in_angl0_raw -rw-r--r-- 1 root root 4096 Dec 5 16:05 in_angl0_scale -r--r--r-- 1 root root 4096 Dec 5 16:05 in_angl1_label -r--r--r-- 1 root root 4096 Dec 5 16:05 in_anglvel0_label -rw-r--r-- 1 root root 4096 Dec 5 16:05 in_anglvel0_raw -rw-r--r-- 1 root root 4096 Dec 5 16:05 in_anglvel0_scale -r--r--r-- 1 root root 4096 Dec 5 16:05 in_phase0_label -r--r--r-- 1 root root 4096 Dec 5 16:05 name lrwxrwxrwx 1 root root 0 Dec 5 16:05 of_node -> ../../../../../../../../firmware/devicetree/base/axi/spi@e0006000/ad2s1210@0 -rw-r--r-- 1 root root 4096 Dec 5 16:05 out_altvoltage0_frequency -r--r--r-- 1 root root 4096 Dec 5 16:05 out_altvoltage0_frequency_available -r--r--r-- 1 root root 4096 Dec 5 16:05 out_altvoltage0_label drwxr-xr-x 2 root root 0 Dec 5 16:05 power drwxr-xr-x 2 root root 0 Dec 5 16:05 scan_elements lrwxrwxrwx 1 root root 0 Dec 5 16:05 subsystem -> ../../../../../../../../bus/iio drwxr-xr-x 2 root root 0 Dec 5 17:42 trigger -rw-r--r-- 1 root root 4096 Dec 5 16:05 uevent -r--r--r-- 1 root root 4096 Dec 5 16:05 waiting_for_supplier analog@setup-2-zed:/sys/bus/iio/devices/iio:device1 $ cat name ad2s1210 analog@setup-2-zed:/sys/bus/iio/devices/iio:device1 $ cat in_angl0_raw 34115
To generate samples using the triggered buffer, you will need a trigger. You can create an hrtimer trigger like this:
mkdir /sys/kernel/config/iio/triggers/hrtimer/test
You can grab some samples like this to connect the trigger and make sure things are working:
iio_readdev ad2s1210 -t test -s 1000 -T 10000 | hd
For other apps, we probably want a high sample rate. You can change the rate like this:
iio_attr -d test sampling_frequency 10000
See iio_event_monitor for an example of a program designed to read IIO events.
Fault to event mapping:
Fault | Channel | Type | Direction | |
---|---|---|---|---|
Sine/cosine inputs clipped [3] | D7 | altvoltage1 | mag | either |
Sine/cosine inputs below LOS | D6 | altvoltage0 | thresh | falling |
Sine/cosine inputs exceed DOS overrange | D5 | altvoltage0 | thresh | rising |
Sine/cosine inputs exceed DOS mismatch | D4 | altvoltage0 | mag | rising |
Tracking error exceeds LOT | D3 | angl1 | thresh | rising |
Velocity exceeds maximum tracking rate | D2 | anglvel0 | mag | rising |
Phase error exceeds phase lock range | D1 | phase0 | mag | rising |
Configuration parity error | D0 | *writes to kernel log* |
[3]: The chip does not differentiate between fault on sine vs. cosine so there will also be an event on the altvoltage2 channel.
AD2S1210 Pin | Eval Board Pin | RPi Header Pin | RPi Function |
---|---|---|---|
RES0 | LK6 [1] | 15 | GPIO22 |
RES1 | LK7 [1] | 16 | GPIO23 |
A0 | J4-12 | 18 | GPIO24 |
A1 | J4-11 | 22 | GPIO25 |
WR/FSYNC | J4-4 | 24 | SPI0 CE0 |
SAMPLE | J4-1 | 12 | GPIO18 |
VDRIVE | J704-1 | 1 | 3.3V |
DGND | J704-2 | 9 | GND |
SCLK | J4-10 | 23 | SPI0 SCLK |
SDI | J4-9 | 19 | SPI0 MOSI |
SDO | J4-8 | 21 | SPI0 MISO |
AD2S1210 Pin | Eval Board Pins (Jumpered) | Eval Board Signal |
---|---|---|
RD | J4-3, J4-7 | VDRIVE |
CS | J4-2, J4-6 | DGND |
Eval Board Signal | Eval Board Jumper | Position |
---|---|---|
SAMPLE | LK1 | B |
CS | LK2 | C |
RD | LK3 | C |
A0 | LK 4 | C |
A1 | LK5 | C |
RES0 | LK6 [1] | C |
RES1 | LK7 [1] | C |
SOE | LK9 | B |
VDRIVE | LK703 | B |
[1] There aren’t J4 pins for RES0/1 so have to use jumper pins. It is also possible to hard-wire resolution pins RES0/1, but device tree would need to be changed accordingly.
Add dtoverlay=ad2s1210
to /boot/config.txt
.
Overlay: ad2s1210-overlay.dts
See ad2s1210_sdz