An Analog to Digital Converter (ADC) is a device that translates an analog voltage to a digital value that a microprocessor can understand.

The ConnectCore platforms have several ADC interfaces. You can find more information in Hardware reference manuals and Analog-to-Digital Converter (ADC).

Digi adds an API to Linux for managing these ADC interfaces. To use this API, include the following header file in your application:

#include <libdigiapix/adc.h>

Request an ADC

You can request an ADC with one of the following functions:

Function Description

adc_t *ldx_adc_request(unsigned int adc_chip, unsigned int adc_channel)

Requests an ADC by its chip number and channel number.

It returns a pointer to adc_t on success, NULL on error.

adc_t *ldx_adc_request_by_alias(char const * const adc_alias)

Requests an ADC by its alias name. The ADC alias mapping must be defined in the /etc/libdigiapix.conf file under the [ADC] section. See Establish ADC aliases.

It returns a pointer to adc_t on success, NULL on error.

Requested ADCs must be freed once they are no longer used. See Free an ADC.

Both functions may fail and return NULL for the following reasons:

  • The provided chip and channel numbers cannot be exported.

  • The associated chip and channel numbers to the given aliases cannot be exported.

  • The API encountered problems allocating memory to initialize the ADC. Your system may have run out of resources.

Requesting an ADC
[...]
 
/* Request an ADC using its alias */
adc_t adc1 = ldx_adc_request_by_alias("DEFAULT_ADC");
 
/* Request an ADC located in the chip = 0 channel = 1 */
adc_t adc2 = ldx_adc_request(0, 1);
 
printf("The ADC 1 is on chip %d, channel %d\n", adc1->adc_chip, adc1->adc_channel);
printf("The ADC 2 is on chip %d, channel %d\n", adc2->adc_chip, adc2->adc_channel);
 
[...]

Establish ADC aliases

To help you identify the ADCs in your design, you can assign aliases to your ADC Linux IDs. Map the assigned chip number, channel, and name in the /etc/libdigiapix.conf file:

  1. Add a section called [ADC], if one doesn’t already exist.

  2. Below the section name, add the list of mapped ADCs following the format:

    <alias> = <adc_chip>,<adc_channel>

    Where:

    • <alias> is the human-readable name for the ADC.

    • <adc_chip> is the ADC chip.

    • <adc_channel> is the ADC channel used by that ADC chip.

Example of ADC section
[ADC]
 
# ADC1_IN2 on GPIO board connector (pin 13)
DEFAULT_ADC = 0,2

For example, using the configuration above, you can request an ADC with the API using DEFAULT_ADC alias. See Request an ADC.

You can use these functions to get the chip and the channel associated with an alias:

int ldx_adc_get_chip(const char * const adc_alias)
int ldx_adc_get_channel(const char * const adc_alias)
For more information about how to include libdigiapix.conf in your Digi Embedded Yocto images, see Define interface aliases.

Free an ADC

You must free a requested ADC when it is no longer required. To do so, use the ldx_adc_free() function.

int ldx_adc_free(adc_t *adc)
Freeing a requested ADC
[...]
 
adc_t *adc = ...;
 
[...]
 
/* Free ADC once it is not required anymore */
ldx_adc_free(adc);
 
[...]

Read ADC samples

Synchronous read

You can read an ADC sample using this function:

Function Description

int ldx_adc_get_sample(adc_t *adc)

Retrieves the value of the ADC channel. It returns a value between 0-4096 (depending of the input voltage). If there is an error, -1 is returned.

For more information, see Analog-to-Digital Converter (ADC).

Read ADC value
[...]
 
adc_t *adc = ...;
int sample = 0;
 
[...]
 
/* Read the adc value */
sample = ldx_adc_get_sample(adc);
 
printf("Input ADC sample acquired: %d", sample);
 
[...]

Asynchronous read

You can configure an ADC channel to perform asynchronous sample reads using a defined time interval. To do so, use the non-blocking ldx_adc_start_sampling() function.

int ldx_adc_start_sampling(adc_t *adc, const ldx_adc_read_cb_t read_cb, unsigned int interval, void *arg)

This function registers the specified callback handler to be executed when the sample interval is finished and a sample is read.  After that, it continues sampling each time the interval expires.

arg is passed as an argument of ldx_adc_read_cb_t callback.

ldx_adc_start_sampling() returns:

  • EXIT_SUCCESS on success.

  • EXIT_FAILURE when failing:

    • If the ADC doesn’t exist.

    • If there is a problem allocating memory.

The provided callback must follow this prototype:

typedef int (*ldx_adc_read_cb_t)(int sample, void *arg)

To stop the asynchronous samples read, use ldx_adc_stop_sampling().

int ldx_adc_stop_sampling(adc_t *adc)
Use continuous sampling
/* Sample read callback */
static int adc_sampling_cb(int sample, void *arg)
{
int* tmp_count = (int*) arg;
*tmp_count = *tmp_count + 1;
printf("Input ADC sample acquired: %d in loop: %d\n", sample, tmp_count);
 
return EXIT_SUCCESS;
}

[...]

int samples_count = 0;
int sampling_interval_sec = 10;
adc_t *adc = ldx_adc_request_by_alias("MY_ADC");
 
[...]

/* Start ADC sampling */
ldx_adc_start_sampling(adc, &adc_sampling_cb, sampling_interval_sec , &samples_count);
 
do {
    printf("Number of samples obtained: %d\n", samples_count");
    sleep(1):
} while (samples_count < 10);

[...]

/* Stop sampling */
ldx_adc_stop_sampling(adc);

[...]

Convert ADC value into millivolts

By default, the ADC samples are read in raw mode. You can convert the raw read into millivolts using the ldx_adc_convert_sample_to_mv() function:

Function Description

int ldx_adc_convert_sample_to_mv(adc_t *adc, int sample)

Scale the sample to convert the value to mV. Returns -1 if there is an error.

For more information, see Analog-to-Digital Converter (ADC).

The driver automatically reads the scale applied to the raw sample in order to convert the value into millivolts. You can use the ldx_set_scale() function to change the scaling factor:

int ldx_set_scale(adc_t *adc, float scale)
Configure ADC scale
[...]
 
adc_t *adc = ...;
float scale_raw_to_mv = 0.805; // 3300 mV --> 4095 raw
int sample;

[...]
 
/* Configure ADC scale value */
ldx_adc_set_scale(adc, scale_raw_to_mv);
sample = ldx_adc_get_sample(adc);
sample = ldx_adc_convert_sample_to_mv(adc, sample);
 
printf("The voltage in the ADC chip %d, channel %d is %dmV\n", adc->chip, adc->channel, sample);

[...]

ADC example

In this example, you can select an ADC to get periodic samples of the channel.

You can import the example in Eclipse using the Digi Embeddded Yocto plugin. For more information, see Create a new DEY sample project. This example is included in Digi Embedded Yocto. Go to GitHub to see the application source code.