Use ADCs in high-level applications

This topic describes how to use analog-to-digital converters (ADCs) in a high-level application. See Use peripherals in a real-time capable application for information about ADC use in RTApps.

Azure Sphere supports analog to digital conversion. An ADC converts an analog input to a corresponding digital value. The number of input channels and the resolution (as number of ADC output bits) are device dependent.

The ADC_HighLevelApp sample demonstrates how to access ADCs on an MT3620 device.

The ADC Peripheral snippets demonstrate two ways to interact with ADCs using either simplified or advanced functions.

The MT3620 contains a 12-bit ADC with 8 input channels. The ADC compares an input voltage to a reference voltage and produces a value between 0 and 4095 as its output. The ADC input channels and the GPIO pins GPIO41 through GPIO48 map to the same pins on the MT3260. However, if your application uses the ADC then all 8 pins are allocated for use as ADC inputs. None of them can be used for GPIO.

ADC requirements

Applications that communicate with ADCs must include the adc.h header file and add ADC settings to the application manifest.

All applications must set their target hardware and include the corresponding hardware definition header file.

Header Files

 #include <applibs/adc.h>
 #include "path-to-your-target-hardware.h"

Replace "path-to-your-target-hardware.h" with the path to the header file for your hardware.

Application manifest settings

The ADC setting in the application manifest lists the ADC controllers that are accessed by the application. To configure these settings, add the Adc capability to the application manifest, and then add each ADC controller to the capability. The Azure Sphere application manifest topic has more details.

In your code, use the constants that are defined for your hardware to identify the ADC controllers. The compiler will translate these values to raw values when you build the app.

For example, here's an excerpt from an application manifest for an application that targets an MT3620 reference development board (RDB).

   "Adc": [ "$MT3620_RDB_ADC_CONTROLLER0" ]

The following excerpt shows how to specify the same ADC controller in an application that targets the Avnet MT3620 Starter Kit:

   "Adc": [ "$AVNET_MT3620_SK_ADC_CONTROLLER0" ]

Implementation overview

To implement your application for accessing ADC, use one of two approaches:

This topic describes both methods. You can find the complete sample code for each method here:

ADC access with simplified functions

Azure Sphere high-level applications can access ADCs by calling Applibs ADC APIs.

Open an ADC controller

To open an ADC controller for access, call ADC_Open and pass the ID of the controller as a parameter. A file descriptor will be returned if the call is successful. Otherwise, an error value will be returned.

int ADC_Open(ADC_ControllerId id);

Read from an ADC

To read from the ADC, call ADC_Poll. You pass the following parameters to ADC_Poll: the file descriptor returned by ADC_Open, the ADC channel, and a pointer to where the ADC value will be stored.

To get the number of valid bits (resolution) returned by the ADC_Poll function, call ADC_GetSampleBitCount.

Set the ADC reference voltage

Call ADC_SetReferenceVoltage to set the ADC reference voltage.

The MT3620 has an on-chip, 2.5 volt reference. Alternatively, it can be connected to an external voltage reference that is less than or equal to 2.5 volts.

ADC access with advanced functions

As an alternative to the high-level simplified functions to interact with the peripheral, you can take advantage of the the ioctl library to open up functionality. This section explains how to do that and how using ioctls differs from using the generic Linux functions.

ADC Advanced Functions Snippet shows how to read ADC using the Azure Sphere advanced functions.

As an example, you can see a side-by-side comparison of reading ADC with the simplified, advanced, and linux sysfs implementations:

Open the ADC channel

To open an ADC controller for access, use the Linux open call passing in the path to the directory which will start with /dev/adc<number> where ‘number’ is the controller ID. A file descriptor is returned if the call was successful. Otherwise, an error value is returned.

See Example Implementation for parameters, permissions, and error checking.

Get the channel specification

While using the advanced functions, get the channel specification by using ioctl calls before polling, setting reference voltage or getting the sample bit count. This step can be skipped by hard-coding some of the values obtained, but it is not recommended. Note that this step is handled by code supplied in the simple functions.


// Used to get the size of the buffer to allocate for the channel specification

IIO_GET_CHANNEL_SPEC_BUFFER_TOTAL_SIZE_IOCTL
// Used to get the channel specification and set the ‘iio_ioctl_chan_spec_buffer’ struct properly

IIO_GET_CHANNEL_SPEC_BUFFER_IOCTL

Set the reference voltage

To set the reference voltage of a channel using the advanced API:

  1. Set the ADC information populated in the iio_ioctl_chan_spec_buffer structure that was retrieved in Get Channel specification.

  2. Get the property index of the property to set for the channel.

  3. Write the reference voltage using the property index and channel specification information.

To get the index of the reference voltage property:

  1. From the iio_ioctl_chan_spec_buffer structure retrieved in Get Channel specification, use the value from the channel field and, from the channel field, use the value from the ext_info field. The ext_info field is an iio_ioctl_chan_spec_ext_info struct that is the head of a linked list of property descriptors for the channel.

  2. Starting from 0, traverse the list counting the nodes until the name field matches the reference_voltage string.

    • Each node in the list has a "next" field that points to the next node in the list. The last node points to NULL.
    • The resulting counter is the index of the property.
  3. To set the reference voltage, use the IIO_WRITE_CHANNEL_EXT_INFO_IOCTL ioctl that takes in a struct of type iio_ioctl_write_chan_ext_info, which contains the relevant data (in this case the voltage), the channel to set, and the specific property (reference voltage) that is set for that channel.

Get the sample bit count

To set the reference voltage using the advanced APIs:

  1. Ensure you are getting the information of the proper ADC channel. This information is populated in the iio_ioctl_chan_spec_buffer structure that was retrieved in the Get Channel Specification section.

  2. Get the property index of the property you want to read for the channel, which in this case is the sample bit count.

  3. Use Linux ioctls to get the sample bit count using the property index and channel specification.

To get the property index of the sample bit count, use a process identical to Set reference voltage. However, while iterating over the linked list called ext_info of type iio_ioctl_chan_spec_ext_info, match the string current_bits.

Call the ioctl IIO_READ_CHANNEL_EXT_INFO_IOCTL to populate a struct of type iio_ioctl_read_chan_ext_info with the necessary data in the bufferfield.

Read the ADC channel

To read the ADC channel, poll using the ioctl call IIO_READ_RAW_CHANNEL_INFO_IOCTL, passing in the struct iio_ioctl_raw_channel_info which will be populated with the data from the ADC channel.

Example implementation

To read ADC using the Azure Sphere advanced implementation, see the snippet in ADC Advanced app sample.

To compare the differences in semantics between interacting with the peripheral when coding for Azure Sphere and coding for a generic Linux system, see LinuxSysfsNodes.

MT3620 support

The supported ADC features for the MT3620 are listed in MT3620 Support Status. The MT3620 development board user guide describes the pin layout and pin functions.

The HardwareDefinitions folder in the Microsoft Azure Sphere SDK installation directory contains definitions for common Azure Sphere development boards, modules, and chips. It contains header and JSON files that define the master interfaces for the MT3620, MT3620 RDB, along with other MT3620 hardware. The default location for the HardwareDefinitions folder is C:\Program Files (x86)\Microsoft Azure Sphere SDK\Hardware Definitions on Windows and /opt/azurespheresdk/HardwareDefinitions on Linux.