Skip to main content
Version: 5.0

ADC (Linux)

ADC accessibility in User Space​

Apart from Colibri T20, all Toradex Computer-on-Modules use an ADC driver based on the Industrial Input/Output (iio) framework, which can be accessed through sysfs.

Depending on the module type the analog inputs are connected via different ADCs (see ADC).

In contrast to hwmon, which is directed at low sample rate sensors used to monitor and control the system itself, like fan speed control or temperature measurement, the iio framework provides support for devices that in some sense perform either analog-to-digital conversion (ADC) or digital-to-analog conversion (DAC), or both.

Access through sysfs is easy to implement since it only involves reading a regular file corresponding to a given ADC and the desired channel.

There are two ways for userspace interaction with iio drivers:

  • /sys/bus/iio/iio:deviceX/, this represents a hardware sensor and groups together the data channels of the same chip.
  • /dev/iio:deviceX, character device node interface used for buffered data transfer and for events information retrieval.

If the conversion is needed to be performed at slow rates, also called one-shot conversion, sysfs interface is used.

If Continuous conversions of a single channel at a time are required and supported by the device, the dev interface is used with sysfs.

Keep in mind that opening and closing a file for every ADC read-out is relatively slow and rather resource-intensive.

However, the internal ADCs are anyway not meant to be used for high-speed applications.

TorizonCore​

Since TorizonCore, our Industrial Linux Platform, is based in our Board Support Packages (BSPs), the information provided in this article also applies to it.

Nevertheless, we recommend that your start with our article How to Use ADC on TorizonCore, which presents a step-by-step guide showing how to access the Analog-to-Digital converter interfaces within a container.

Reference Images for Yocto Project​

For access to the Analog-to-Digital (ADC) interfaces in our Reference Images for Yocto Project, you can find detailed instructions in the sections below for each of our Computer-on-Modules.

General information​

The ADC Linux drivers usually support two modes of performing conversations:

  • One-shot conversions performed by reading the ADC files for your specific board. For example: /dev/colibri-ain*
  • Continuous conversions of a single channel at a time using the /dev/iio:device0 character device file.

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).

One-shot Mode​

To read a single ADC output from a particular channel, Toradex provides useful symlinks for each SoM family. This also helps you to write software that is compatible across SoMs within a family.

Apalis Family​

Toradex NameDevice
AN1_ADC0/dev/apalis-adc0
AN1_ADC1/dev/apalis-adc1
AN1_ADC2/dev/apalis-adc2
AN1_ADC3/dev/apalis-adc3

You can list the devices as follows:

# ls -l /dev/apalis-adc*

It will display the available Apalis pin-compatible ADCs and display the corresponding names used by the BSP. Those corresponding names are important because the Linux kernel logs will print the real device names (e.g. /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage3_raw), not the Apalis symlinks (e.g. /dev/apalis-adc0).

To get a one-shot conversion, just read the file contents:

# cat /dev/apalis-adc1

Colibri Family​

Toradex NameDevice
ANALOG_IN0/dev/colibri-ain0
ANALOG_IN1/dev/colibri-ain1
ANALOG_IN2/dev/colibri-ain2
ANALOG_IN3/dev/colibri-ain3

You can list the devices as follows:

# ls -l /dev/colibri-ain*

It will display the available Colibri pin-compatible ADCs and display the corresponding names used by the BSP. Those corresponding names are important because the Linux kernel logs will print the real device names (e.g. /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage3_raw), not the Colibri symlinks (e.g. /dev/colibri-ain0).

To get a one-shot conversion, just read the file contents:

# cat /dev/colibri-ain0

Verdin Family​

Toradex NameDevice
ADC_1/dev/verdin-adc1
ADC_2/dev/verdin-adc2
ADC_3/dev/verdin-adc3
ADC_4/dev/verdin-adc4

You can list the devices as follows:

# ls -l /dev/verdin-adc*

It will display the available Verdin pin-compatible ADCs and display the corresponding names used by the BSP. Those corresponding names are important because the Linux kernel logs will print the real device names (e.g. /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage3_raw), not the Verdin symlinks (e.g. /dev/verdin-adc1).

To get a one-shot conversion, just read the file contents:

# cat /dev/verdin-adc1

Continuous Mode​

The single-channel continuous conversion mode converts a single channel continuously and indefinitely in regular channel conversion.

The continuous mode feature allows the ADC to work in the background.

The ADC converts the channels continuously without any intervention from the CPU. Additionally, the DMA can be used in circular mode, thus reducing the CPU load.

Important folders in the iio:deviceX directory are:

  • buffer directory:
  • data_available: a read-only value indicating the bytes of data available in the buffer.
  • enable: get and set the state of the value buffer
  • length: get and set the length of the value buffer.
  • watermark: a single positive integer specifying the maximum number of scan elements to wait for.
  • scan_elements directory contains interfaces for elements that will be captured for a single sample set in the buffer:
ls -la /sys/bus/iio/devices/iio\:device0/scan_elements/
total 0
drwxr-xr-x 2 root root 0 Dec 3 01:56 .
drwxr-xr-x 6 root root 0 Dec 3 00:57 ..
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_timestamp_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_timestamp_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_timestamp_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage0-voltage1_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage0-voltage1_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage0-voltage1_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage0_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage0_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage0_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage1-voltage0_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage1-voltage0_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage1-voltage0_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage1_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage1_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage1_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage2-voltage3_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage2-voltage3_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage2-voltage3_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage2_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage2_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage2_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage3-voltage2_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage3-voltage2_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage3-voltage2_type
-rw-r--r-- 1 root root 4096 Dec 3 17:08 in_voltage3_en
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage3_index
-r--r--r-- 1 root root 4096 Dec 3 17:08 in_voltage3_type

scan_elements exposes 3 files per channel:

  • in_voltageX_en: is this channel enabled for capturing?
  • 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 le:u12/16>>0

Set up the channels in use (you can enable any combination of the channels you want):

# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage0_en

Set up the buffer length:

# echo 100 > /sys/bus/iio/devices/iio\:device0/buffer/length

Enable the capture:

# echo 1 > /sys/bus/iio/devices/iio\:device0/buffer/enable

Notice: For some ADCs the continuous conversion mode of the ADC driver can only enable one channel at one time or is not even supported at all. For example, for the i.MX 6ULL is a known limitation (this is explicitly mentioned in 53.3 ADC Driver Overview of i.MX Linux Reference Manual and in NXP community question).

You can also use userspace libs like iioutils/libiio. These libraries abstract the low-level details of the hardware and provide a simple yet a complete programming interface that can be used for advanced projects.

Notes​

  • Colibri/Apalis iMX6: Since the ADC is shared with the touchscreen it's not recommended to change the ADC characteristics such as sample time.

  • Colibri iMX7: The ADC channels are only 1.8V capable! This is a limitation of the i.MX7 SoC.

Send Feedback!