Friday, October 24, 2014

BeagleBone Black: Analog Input Pins

Sources

http://en.wikipedia.org/wiki/Analog-to-digital_converter
http://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
 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  


5 comments:

  1. Hi,
    after getting the values on terminal, I want to save these values so as plot them in MATLAB
    Can u help me with that?

    ReplyDelete
  2. Yes, you can redirect the output to some other file while executing the executable. e.g. ./ADC_Example.o > Output.txt

    Then, use matlab to read the file and plot the graph. Also you can take help from windows MFC for achieving the same.

    ReplyDelete
  3. how to read analog pins of Beaglebone Black on ADC.

    ReplyDelete
  4. Your Z1 and Z2 values don't appear to be correct.
    Z1 should be 1777 ohms
    Z2 should be 1000 ohms

    Then the current flowing through both resistors would be the same:
    I = V/R
    I1 = V1/R1 = (3.2 volts)/(1777 ohms) = 0.001800 amps
    I2 = V2/R2 = (1.8 volts)/1000 ohms) = 0.001800 amps

    ReplyDelete
  5. Top Casino Stays in Arizona | MapYRO
    Find 김천 출장마사지 the 안산 출장샵 best casinos in Arizona in 2021. Earn free hotel stay bonuses, online 고양 출장안마 gaming, and win real money! 통영 출장안마 River Rock Casino Resort Hotel & Spa. 부천 출장안마

    ReplyDelete