Reading analog (ADC) values on BeagleBone black

Update July 17, 2013: In the latest kernel (3.8.13-00687 and onward) there is a new way of enabling and using the ADC driver. The bone-iio-helper driver is no longer used, instead the channels are exported to folder /sys/bus/iio/devices/iio:device0/. The bugs should be straightened as well, thanks toZubair: http://beagleboard-gsoc13.blogspot.no/2013/07/continuous-sampling-mode-for-adc-driver.html.

At you own risk: A pre-compiled kernel is available from http://distros.replicape.com. Follow the instructions here: http://wiki.replicape.com/index.php?title=Replicape_rev_A3_setup, but instead of writing just “make” write “make kernel”, and it will install the kernel 3.8.13-00687. This will overwrite your current kernel and kernel modules which may bork it: http://hipstercircuits.com/unbrick-beaglebone-black-without-erasing-emmc/

The Analog to Digital Converter (ADC) on the BeagleBone is both a Touch Screen Controller (TSC) and a general purpose ADC. Depending on how many of the lines are reserved for the TSC (4, 5, or 8), the remaining lines can be used for reading analog values. One of the lines is connected to the power Management Integrated Circuit (PMIC, TPS65217) of the white Bone,  in order to sense the power used by the board. This does not appear to be the case for the new BeagleBone Black.

The basics 
To read the analog inputs on your BeagleBone Black, first enable the driver:

echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots

The analog inputs should now be activated and exported to the filesystem. To read their values, just cat the files:

cat /sys/devices/ocp.2/helper.11/AIN1

This will read the analog value of AIN1 (The pin is P9_40). What you see is a voltage between 0 and 1.8V, but in millivolts (0 to 1799). If you tie the pin high by shorting the pin to the analog VDD (P9_32), you will see a 1799. If you tie the pin low to (P9_34, Analog ground), you will see a 0. There is a bug in the driver, so the value you read is actually the previous value you read. For now, just read the value twice. More on that later.

Bug in the ADC driver

Note: This was tested on kernel 3.8.6, the one that came with the early BeagleBone Black.

The driver for the ADC was riddled with errors early on. This manifested itself as getting weird values from the ADC when reading from one or several pins in rapid succession:

adc_failing

Clearly, a negative value is not right. The reason why this occurs is that there is no test to make sure the ADC is finished with sampling the pin. Furthermore, when one pin is read, the reading of this pin triggers the ADC to sample a new value (for all the pins) for the next reading. For further reading, consult the Linux mainline source: ti_am335x_adc.c. This will probably be fixed in later veriosn of the kernel, but if you need a solution now, have a look at these adc-patches and see if you can’t figure it out : )

Troubleshooting
If your analog inputs do not show up at the above spot, make sure the helper module is loaded:

lsmod

This shows a list of loaded kernel modules, make sure “bone_iio_helper” shows up in the list.
If the helper modules is loaded, but the fiels are not in the right place, try searching for them:

find /sys -name *AIN*

This should show you a list of the analog input files. If not, go to forum and rant. Make sure you include the kernel version you are using:

root@beaglebone:~# uname -a
Linux beaglebone 3.8.6 #1 SMP Sat Apr 13 09:10:52 CEST 2013 armv7l GNU/Linux

26 thoughts on “Reading analog (ADC) values on BeagleBone black

  1. Pingback: Reading Analog (ADC) Values on a BeagleBone Black « adafruit industries blog

    • Shea, I agree with you that the FS locations created by device tree seem random. The worst part is that the location of some of the devices change depending on the loading order. If you add a cape, this changes the order for when the device is added to the device tree and thus the unique number appended. I think the OCP (On Chip Peripherals to the uninvited) is pretty static [citation needed]. For the Replicape, this means that adding an LCD cape on top changes the locations of the PWM devices. I bet Koen Kooi and Jason Kridner knows about this, the latter has recently written a book on the topic, so there should be something in there about it.
      BTW, by using helper drivers, I have more or less abandoned the PyBBIO. Don’t get me wrong, it’s a great library, but with the broken compatibility I’ve found that it’s easier to just use (or make) helper drivers. I’m using SPI, I2C, PWM, analog and the PRU on Replicape, so if you need any these you can have look at the source code for that. Written in Python: Replicape software

    • Brock, are you having trouble with the PRU on BBB? It should work out of the box, unless you are experiencing a bug that (gulp) I introduced.. Have a look at this thread: BBB PRU bug.

      I have a couple of BBBs on my desk, but I am very busy making a new revision of Replicape that is more compatible with the BBB. In the final stage now. Once I have sent it in, I will start blogging about the quirks of BBB. FML (o_0)

  2. hi there, i have 2 BBW (different kernel version) using LM35DZ temperature sensor.
    I have problem with the value of the AIN.
    in the same condition BBW with kernel 23.2.34
    ~# cat /sys/devices/platform/omap/tsc/ain1
    494

    but if in BBW witk kernel 3.8.13 , using your configuration above,
    # cat /sys/devices/ocp.2/helper.9/AIN0
    804

    can you help me with this , thanks..

    • i got it, i have to use a Resistor to ground the pin first, then using voltage divider (using that R) to connect the Output of sensor into pin of BB

  3. The ADC offers afaik 4096 Bits, so a lot of resolution is lost when measuring in mV. Is there a solution known to use the full available scale?
    Michael

    • Not that I know of, sorry.. I suggest you look in the source code and change the way it’s done. The file is:
      dirvers/misc/cape/beaglebone/bone-iio-helper.c, in the function iio_helper_show_mvolts

    • Did you see the in_voltage*_raw devices in the /sys/devices/ocp.2/44e0d000.tscadc/tiadc/iio\:device0/ directory?
      (replace the number suffixes where appropriate ) For the BeBoPr, to be backwards compatible, I was scaling the voltage back to raw adc values by using a vsense_scale setting of 228, but now it looks like the in_voltage*_raw devices provide the same results.
      – Bas

      • try this :
        cat /sys/bus/iio/devices/iio\:device0/in_voltage*_raw
        i don’t know what is this, but it’s 4096 bit of analog reading value

  4. With kernel 3.8.13 there is no helper.11 in ocp.2. It’s now helper.14. And according to the readme, ADC is still “untested” https://github.com/beagleboard/kernel/tree/3.8

    root@beaglebone:~# uname -a
    Linux beaglebone 3.8.13 #1 SMP Wed Jun 5 11:21:00 CEST 2013 armv7l GNU/Linux

    root@beaglebone:~# ls -1 /sys/devices/ocp.2/
    44e07000.gpio
    44e09000.serial
    44e0b000.i2c
    44e0d000.tscadc
    44e35000.wdt
    44e3e000.rtc
    47400000.usb
    48038000.mcasp
    48042000.timer
    48044000.timer
    48046000.timer
    48048000.timer
    4804a000.timer
    4804c000.gpio
    4819c000.i2c
    481ac000.gpio
    481ae000.gpio
    48200000.interrupt-controller
    4830e000.fb
    49000000.edma
    4a100000.ethernet
    53100000.sham
    53500000.aes
    gpio-leds.8
    hdmi.12
    helper.14
    mmc.4
    mmc.5
    modalias
    nop-phy.6
    nop-phy.7
    nxptda@0.11
    power
    rstctl.3
    sound.13
    subsystem
    uevent

  5. Hallo Elias,

    First of all, your post on Reading Beaglebone Black analogues helped me a lot – thank you.
    I am very new to Linux and have a related question and perhaps you can answer it.
    I followed the steps to enable the analog driver “echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots”, it works fine and I can read reference input voltage fairly accurate. The problem however is that when I cycle the power to the B3 this analog driver enabling is lost and I must manually enable the driver again. Is there a process I can follow to automatically enable the analog drivers every time I power/reboot the B3?

    • Hi,

      Did you get solution to keep enabling analog driver persistent even if BBB is powered cycle?

      Kindly share your inputs if any.

      • Add this to your uEnv.txt file
        capemgr.enable_partno=cape-bone-iio (or whatever)

        If the boot partiton is not mounted automatically:
        mkdir -p /media/BEAGLEBONE/
        mount /dev/mmcblk0p1 /media/BEAGLEBONE/
        nano /media/BEAGLEBONE/uEnv.txt

        • Hi,

          Thanks for your qucick response. YEs, in this way, we can keep aalog driver persistent. But I can not read analog data using command “cat /sys/devices/ocp.*/helper.*/AIN1″. It is giving me an error indicating ” can’t open ‘/sys/devices/ocp.3/helper.11/AIN0′: No such file or directory”

          • Before adding “capemgr.enable_partno=cape-bone-iio” in uEnv.txt file, there was no directory named “helper*” in /sys/devices/ocp*. “helper*” directory was getting generated once I enable the driver manually using “echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots” command. But as per your suggestion, I have added “capemgr.enable_partno=cape-bone-iio” in uEnv.txt file and now “helper*” directory is visible but there is no directories named AIN* to read analog data. Also I have tried to grep “iio” word in dmesg but there is no such word in dmesg. Any thoughts?

            Thanks,
            Ashish

          • Hi,

            To access tty serial driver, I was facing the same issue. But I was able to solve it by compiling pin mux infomration in am335x-boneblack.dtb file. But I am not sure how to do it for analog driver?

  6. Hi,
    When I read analog value,I read same previous value.
    I must read twice for the new value. How can I solve this problem?
    Thanks for your reply

    • Yes, this is described above. I have submitted a patch for it, but it has not yet been pulled into the 3.8 kernel. For now, just read it twice and discard the first value, or you could try one of my custom kernels located at distros.replicape.com, but you really have to know what you are doing if you want to get a new kernel! Once downloaded and extracted on your bone, a “make kernel” will install a new kernel. Look at the make files for more info..

  7. Pingback: Beaglebone Black Analog to Digital Converter | oroboto

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>