Sources
http://en.wikipedia.org/wiki/Analog-to-digital_converterhttp://www.linux.com/learn/tutorials/787511-how-to-get-analog-input-on-the-beaglebone-black
http://hipstercircuits.com/reading-analog-adc-values-on-beaglebone-black/
Introduction
An Analog-to-Digital Converter (ADC, A/D, or A to D) is a device or chip that converts a continuous physical quantity (analog signal) to a digital number that represents the quantity's amplitude. Typically an ADC converts an analog voltage to a digital voltage. This tutorial will go over the ADC pin properties and how to enable them on the BeagleBone Black (BBB).
Analog to Digital Converter Layout
The BBB ADC pins are labelled as AIN pins and are located on the P9 header under the DC barrel jack.
Figure 1: BeagleBone Black GPIO pinout.
Table 1: ADC pin names and numbers.
Name | Header | Number |
---|---|---|
AIN0 | P9 | 39 |
AIN1 | P9 | 40 |
AIN2 | P9 | 37 |
AIN3 | P9 | 38 |
AIN4 | P9 | 35 |
AIN5 | P9 | 36 |
AIN6 | P9 | 33 |
GNDA_ADC | P9 | 34 |
Analog to Digital Properties
The BBB ADC can sink an maximum of 1.8V. You will break the pin and likely the board if you provide an ADC more than 1.8V! Since you will likely be measuring voltages greater than 1.8V, you can use a voltage divider to cut the voltage down.
Figure 2: Voltage divider circuit and equation.
A voltage divider is just a ratio of resistor 2 (Z2) to the total resistance (Z1 + Z2). You can think of it in percentages. If we want to cut down from a 5V source to 1.8V, then with a couple resistors we get:
Vin = 5V
Z1 = 1000 Ω = 64%
Z2 = 1777 Ω = 36%
Z1 + Z2 = 2777 Ω = 100%
Using the equation in Figure 2 we find Vout = 1.8V, which is 36% of Vin!
Enabling ADC Pins
To enable the ADC driver to read the pins type the either of the following into the terminal.
echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots
or
You should be able to enable the drivers on boot by appending the uEnv.txt file with
However, I have had no luck with this so I just echo every time the BBB gets power-cycled.
You should see a value between 0-1799 representing milliVolts. If you ground the pin, the value won't likely go all the way to 0 but that is O.K.
If you are reading the pins faster than about 250ns you could run into bogus values. The ADC can only operate so fast because it must convert from a continuous signal to a digital one with discrete time steps.
Then run the program with:
echo BB-ADC > /sys/devices/bone_capemgr.*/slots
You should be able to enable the drivers on boot by appending the uEnv.txt file with
optargs=quiet drm.debug=7 capemgr.enable_partno=BB-ADC
or optargs=quiet drm.debug=7 capemgr.enable_partno=cape-bone-iio
However, I have had no luck with this so I just echo every time the BBB gets power-cycled.
Reading ADC Pins Via Terminal
To read the ADC pins from the terminal use the cat command. The following command will read ADC 1 (AIN1).
cat /sys/devices/ocp.2/helper.11/AIN1
You should see a value between 0-1799 representing milliVolts. If you ground the pin, the value won't likely go all the way to 0 but that is O.K.
If you are reading the pins faster than about 250ns you could run into bogus values. The ADC can only operate so fast because it must convert from a continuous signal to a digital one with discrete time steps.
Reading ADC Pins Via C Code
The following code enables the ADC pins inside the code (so you don't have to remember to do it!), reads the 7 ADC pins and prints the values to the terminal.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> //close()
#include <fcntl.h> //define O_WONLY and O_RDONLY
#define MAX_BUF 64 //This is plenty large
//Function declarations
int readADC(unsigned int pin);
//main program
int main()
{
//Enable ADC pins within code
system("echo BB-ADC > /sys/devices/bone_capemgr.*/slots");
//Read ADCs
int adc0 = readADC(0);
int adc1 = readADC(1);
int adc2 = readADC(2);
int adc3 = readADC(3);
int adc4 = readADC(4);
int adc5 = readADC(5);
int adc6 = readADC(6);
//Print ADC readings
printf("ADC 0: %d\n",adc0);
printf("ADC 1: %d\n",adc1);
printf("ADC 2: %d\n",adc2);
printf("ADC 3: %d\n",adc3);
printf("ADC 4: %d\n",adc4);
printf("ADC 5: %d\n",adc5);
printf("ADC 6: %d\n",adc6);
return 0;
}//end main
//Function definitions
int readADC(unsigned int pin)
{
int fd; //file pointer
char buf[MAX_BUF]; //file buffer
char val[4]; //holds up to 4 digits for ADC value
//Create the file path by concatenating the ADC pin number to the end of the string
//Stores the file path name string into "buf"
snprintf(buf, sizeof(buf), "/sys/devices/ocp.2/helper.14/AIN%d", pin); //Concatenate ADC file name
fd = open(buf, O_RDONLY); //open ADC as read only
//Will trigger if the ADC is not enabled
if (fd < 0) {
perror("ADC - problem opening ADC");
}//end if
read(fd, &val, 4); //read ADC ing val (up to 4 digits 0-1799)
close(fd); //close file and stop reading
return atoi(val); //returns an integer value (rather than ascii)
}//end read ADC()
To compile, copy the text to a file and save the file as ADC_Example.c. Then in the Terminal type:
gcc -Wall ADC_Example.c -o ADC_Example.o
Then run the program with:
./ADC_Example.o