adc_example: Add an example about how to use the adc.
This example takes periodic samples using a thread and calculate the rms value and the mean value of the samples taken. https://jira.digi.com/browse/DEL-4889 Signed-off-by: Francisco Gil <francisco.gilmartinez@digi.com>
This commit is contained in:
parent
4e013d621a
commit
68f3f0f815
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Copyright 2017, Digi International Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
BINARY := apix-adc-example
|
||||
|
||||
CFLAGS += -Wall -O2
|
||||
|
||||
CFLAGS += $(shell pkg-config --cflags libdigiapix)
|
||||
LDLIBS += $(shell pkg-config --libs libdigiapix)
|
||||
|
||||
$(BINARY): main.o
|
||||
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ -lm
|
||||
|
||||
.PHONY: install
|
||||
install: $(BINARY)
|
||||
install -d $(DESTDIR)/usr/bin
|
||||
install -m 0755 $^ $(DESTDIR)/usr/bin/
|
||||
|
||||
.PHONY: all
|
||||
all: $(BINARY)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -f *.o $(BINARY)
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
Digi APIX ADC Sample Application
|
||||
===================================
|
||||
|
||||
Sample application to access and manage ADC channels using the Digi APIX library.
|
||||
|
||||
The application enables one ADC channel on the board. After that, the application
|
||||
takes periodic samples and calculates the rms and mean value of the samples batch.
|
||||
|
||||
The ADC lines used in the sample are mapped as follows in the Digi Boards:
|
||||
- **CCIMX6 SBC**: PMIC_ADCIN1 (GPIO Connector Pin 1).
|
||||
- **CCIMX6UL SBC Express**: ADC1_IN4 (Expansion Connector Pin 7).
|
||||
- **CCIMX6UL SBC Pro**: ADC1_IN2 (GPIO Connector Pin 13).
|
||||
|
||||
The following device tree modifications are required for the sample to work:
|
||||
- **CCIMX6 SBC**: _No device tree modifications are required._
|
||||
- **CCIMX6UL SBC Express**:
|
||||
```
|
||||
&adc1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_adc1>;
|
||||
adc-ch-list = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&iomuxc {
|
||||
imx6ul-ccimx6ul {
|
||||
pinctrl_adc1: adc1grp {
|
||||
fsl,pins = <
|
||||
MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
- **CCIMX6UL SBC Pro**:
|
||||
```
|
||||
&adc1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_adc1>;
|
||||
adc-ch-list = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&iomuxc {
|
||||
imx6ul-ccimx6ul {
|
||||
pinctrl_adc1: adc1grp {
|
||||
fsl,pins = <
|
||||
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Running the application
|
||||
-----------------------
|
||||
Once the binary is in the target, launch the application:
|
||||
```
|
||||
#> apix-adc-example [adc_chip adc_channel interval number_of_samples]
|
||||
```
|
||||
Where:
|
||||
- 'adc_chip' the ADC chip number.
|
||||
- 'adc_channel' the ADC channel number.
|
||||
- 'interval' is the time interval between samples.
|
||||
- 'number_of_samples' is the number of samples to take.
|
||||
|
||||
Compiling the application
|
||||
-------------------------
|
||||
This demo can be compiled using a Digi Embedded Yocto based toolchain. Make
|
||||
sure to source the corresponding toolchain of the platform you are using, e.g:
|
||||
|
||||
```
|
||||
$> . <DEY-toolchain-path>/environment-setup-cortexa7hf-vfp-neon-dey-linux-gnueabi
|
||||
$> make
|
||||
```
|
||||
|
||||
More information about [Digi Embedded Yocto](https://github.com/digi-embedded/meta-digi).
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright 2017, Digi International Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright 2017, Digi International Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libdigiapix/adc.h"
|
||||
|
||||
#define ARG_ADC_CHIP 0
|
||||
#define ARG_ADC_CHANNEL 1
|
||||
|
||||
static adc_t *adc;
|
||||
|
||||
struct adc_sampling_cb_data {
|
||||
adc_t *adc;
|
||||
int total_value;
|
||||
int total_value_rms;
|
||||
int number_of_samples;
|
||||
};
|
||||
|
||||
/*
|
||||
* usage_and_exit() - Show usage information and exit with 'exitval' return
|
||||
* value
|
||||
*
|
||||
* @name: Application name.
|
||||
* @exitval: The exit code.
|
||||
*/
|
||||
static void usage_and_exit(char *name, int exitval)
|
||||
{
|
||||
fprintf(stdout,
|
||||
"Example application using libdigiapix ADC support\n"
|
||||
"\n"
|
||||
"Usage: %s <adc_chip> <adc_channel> <interval> <number_of_samples> \n\n"
|
||||
"<adc_chip> ADC chip number\n"
|
||||
"<adc_channel> ADC channel number\n"
|
||||
"<interval> Time interval for sampling\n"
|
||||
"<number_of_samples> Number of samples to get\n"
|
||||
"\n\n"
|
||||
"\n", name);
|
||||
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup() - Frees all the allocated memory before exiting
|
||||
*/
|
||||
static void cleanup(void)
|
||||
{
|
||||
/* Free adc */
|
||||
ldx_adc_stop_sampling(adc);
|
||||
ldx_adc_free(adc);
|
||||
}
|
||||
|
||||
/*
|
||||
* sigaction_handler() - Handler to execute after receiving a signal
|
||||
*
|
||||
* @signum: Received signal.
|
||||
*/
|
||||
static void sigaction_handler(int signum)
|
||||
{
|
||||
/* 'atexit' executes the cleanup function */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* register_signals() - Registers program signals
|
||||
*/
|
||||
static void register_signals(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
|
||||
action.sa_handler = sigaction_handler;
|
||||
action.sa_flags = 0;
|
||||
sigemptyset(&action.sa_mask);
|
||||
|
||||
sigaction(SIGHUP, &action, NULL);
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_argument() - Parses the given string argument and returns the
|
||||
* corresponding integer value
|
||||
*
|
||||
* @argv: Argument to parse in string format.
|
||||
* @arg_type: Type of the argument to parse.
|
||||
*
|
||||
* Return: The parsed integer argument, -1 on error.
|
||||
*/
|
||||
static int parse_argument(char *argv, int arg_type)
|
||||
{
|
||||
char *endptr;
|
||||
long value;
|
||||
|
||||
errno = 0;
|
||||
value = strtol(argv, &endptr, 10);
|
||||
|
||||
if ((errno == ERANGE && (value == LONG_MAX || value == LONG_MIN))
|
||||
|| (errno != 0 && value == 0))
|
||||
return -1;
|
||||
|
||||
if (endptr == argv) {
|
||||
switch (arg_type) {
|
||||
case ARG_ADC_CHIP:
|
||||
return ldx_adc_get_chip(endptr);
|
||||
case ARG_ADC_CHANNEL:
|
||||
return ldx_adc_get_channel(endptr);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* adc_sampling_cb() - ADC callback for sampling
|
||||
*
|
||||
* @arg: ADC sampling data (struct adc_sampling_cb_data).
|
||||
* @sample: The ADC read sample.
|
||||
*/
|
||||
static int adc_sampling_cb(int sample, void *arg)
|
||||
{
|
||||
struct adc_sampling_cb_data *data = arg;
|
||||
float sample_mv = 0;
|
||||
|
||||
data->total_value += sample;
|
||||
data->total_value_rms += powf(sample, 2);
|
||||
data->number_of_samples--;
|
||||
sample_mv = ldx_adc_convert_sample_to_mv(data->adc, sample);
|
||||
|
||||
printf("ADC sample acquired: %d (raw) - %2.f (mV)\n", sample, sample_mv);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int channel, chip, interval;
|
||||
int number_of_samples;
|
||||
char *name = basename(argv[0]);
|
||||
struct adc_sampling_cb_data cb_data;
|
||||
|
||||
/* Check input parameters */
|
||||
if (argc != 5) {
|
||||
usage_and_exit(name, EXIT_FAILURE);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Parse command line arguments */
|
||||
chip = parse_argument(argv[1], ARG_ADC_CHIP);
|
||||
channel = parse_argument(argv[2], ARG_ADC_CHANNEL);
|
||||
interval = atoi(argv[3]);
|
||||
number_of_samples = atoi(argv[4]);
|
||||
|
||||
if (chip < 0) {
|
||||
printf("Invalid chip number\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (channel < 0) {
|
||||
printf("Invalid channel number\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (interval <= 0) {
|
||||
printf("Time interval must be greater than 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (number_of_samples <= 0) {
|
||||
printf("Number of samples must be greater than 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
cb_data.number_of_samples = number_of_samples;
|
||||
cb_data.total_value = 0;
|
||||
cb_data.total_value_rms = 0;
|
||||
|
||||
/* Register signals and exit cleanup function */
|
||||
atexit(cleanup);
|
||||
register_signals();
|
||||
|
||||
adc = ldx_adc_request(chip,channel);
|
||||
|
||||
if (!adc) {
|
||||
printf("Failed to initialize ADC\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
cb_data.adc = adc;
|
||||
|
||||
if (ldx_adc_start_sampling(adc, &adc_sampling_cb, interval, &cb_data)) {
|
||||
printf("Failed to initialize the sampling data\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while (cb_data.number_of_samples > 0) {
|
||||
printf("Waiting for samples, %d samples remaining\n",
|
||||
cb_data.number_of_samples);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
printf("The mean value of the samples is: %d mV\n",
|
||||
cb_data.total_value/number_of_samples);
|
||||
printf("The RMS value of the samples is: %.2f mV\n",
|
||||
sqrt(cb_data.total_value_rms/number_of_samples));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
SUBDIRS := apix-gpio-example apix-i2c-example apix-pwm-example apix-spi-example
|
||||
SUBDIRS := apix-gpio-example apix-i2c-example apix-pwm-example apix-spi-example apix-adc-example
|
||||
|
||||
all: $(SUBDIRS)
|
||||
|
||||
|
|
|
|||
|
|
@ -64,4 +64,18 @@ the number of address bytes.
|
|||
<platform>ccimx6ulsbc</platform>
|
||||
</platforms>
|
||||
</sample>
|
||||
<sample id="apix-adc-sample">
|
||||
<name>Digi APIX ADC Sample</name>
|
||||
<description>
|
||||
Sample application to access and manage ADC channels using the Digi APIX library.
|
||||
The application enables one ADC channel on the board. After that, the application takes periodic samples and calculates the rms and mean value of the samples batch.
|
||||
</description>
|
||||
<path>apix-adc-example</path>
|
||||
<platforms>
|
||||
<platform>ccimx6sbc</platform>
|
||||
<platform>ccimx6qpsbc</platform>
|
||||
<platform>ccimx6ulstarter</platform>
|
||||
<platform>ccimx6ulsbc</platform>
|
||||
</platforms>
|
||||
</sample>
|
||||
</samples>
|
||||
|
|
|
|||
Loading…
Reference in New Issue