06-Jun-2014
7 channels of the ADC are available on the expansion port of the Beaglebone Black. Accessing them can seem like a daunting task at first but it is quite simple once you get the hang of it.
The kernel that ships with the BBB as of 27 July doesn't support the stuff below. So compile one from the latest sources available at
https://github.com/beagleboard/kernel/tree/3.8.
If you don't know how to compile the latest kernel sources, check the following links for help on how to compile the kernel.
http://beagleboard.org/linux
http://wiki.beyondlogic.org/index.php/BeagleBoneBlack_Building_Kernel#Compiling_the_BeagleBone_Black_Kernel_2
http://eewiki.net/display/linuxonarm/BeagleBone+Black
After booting the BBB, you have to configure the ADC pins and enable the Touchscreen/ADC (TSADC) module in the processor. This is done via the device tree(DT) files.
DT is a standard format since kernel 3.8 that tells the kernel what it needs to do to enable the TSADC module and configure the ADC pins.
Thanks to the great people at BB.org, you only need to do this
echo BB-ADC >
/sys/devices/bone_capemgr.*/slots
Check that it loaded correctly using
dmesg
You can also list the current configured peripherals using
cat
/sys/devices/bone_capemgr.*/slots
Now checking the analogue value at one instant is simple
All you need to do is type the following
cat /sys/bus/iio/iio:deviceX/in_voltageY
_raw
where X is your adc device number and usually 0.
And Y is your analogue channel number.
Some people might be happy with one sample every once in a while in their applications.
However, the ADC is capable of much more. If you need to sample a signal continuously via a C/C++ application from the userspace, you are in luck.
The am335x driver is a standard IIO driver. And the IIO subsystem provides a sample test application to test the driver. Or in our case, to read from the driver.
The test application can be found in your kernel sources in the drivers/staging/iio/Documentation directory titled generic_buffer.c
Or if you want to take the easy route, check the following link for sources.
https://github.com/ZubairLK/adc-iio-continuous-sampling-userspace
There are two parts to continuous sampling.
Configuring the ADC and the buffer.
Triggering the driver to tell it when to start filling in the buffer.
The IIO subsystem supports a trigger mechanism which is separate from the main ADC driver. The ADC driver supports any standard IIO trigger. And IIO provides trigger files which enable triggering via GPIOs or sysfs files.
Here I'll explain the sysfs way of doing things.
To add a sysfs trigger file type the following
echo 1 > /sys/bus/iio/iio_sysfs_trigger/add_trigger
this creates a trigger directory in
/sys/bus/iio/trigger0
Note: If you dont see this directory. You don't have a supported kernel. Compile the one using the latest sources.
Running the following pulses the trigger.
echo 1 >
/sys/bus/iio/trigger0/trigger_now
The trigger alone is useless. We need to connect this trigger to the adc driver.
Compile generic_buffer.c from the above github repo.
Then run the file using the following parameters
./generic_buffer -n TI-am335x-adc -t sysfstrig1 -l 128
The application searches for an IIO driver named 'TI-am335x-adc'.
Connects the trigger named "sysfstrig1" to the driver.
And configures the buffer size for 128 samples.
You might have noticed that you haven't exactly specified which channel you wish to sample. That is enabled separately via sysfs.
All this might seem confusing at first. But the IIO subsystem is designed to be highly configurable and adaptable to accommodate a variety of peripherals such as accelerometers, gyros, adcs etc.
Enabling which channel to sample using the triggered buffer mechanism is as simple as
echo 1 > /sys/bus/iio/iio:deviceX/scan_elements/in_voltageX_en
Where X is the channel number.If you wish to enable another channel. Go ahead. The generic_buffer application will list both channels. Just note that the buffer is common for both channels.
e.g. 128 will result in 64 samples of 2 channels.
generic_buffer.c is just a starting point for your userspace application.
To sum up, you need to run the following to read continuously from the ADC.
echo 1 > /sys/bus/iio/devices/iio_sysfs_trigger/add_trigger
echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage7_en
echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage5_en
/home/root/main -n TI-am335x-adc -t sysfstrig1 -l 128
And then run this in another terminal to trigger the driver to start sampling
echo 1 >
/sys/bus/iio/trigger0/trigger_now
The generic_buffer application will display the length of samples.
Enjoy hacking with the BBB.
Leave a comment if you have a question or notice a bug somewhere.
Nice. I got it all working with the 2013.07.31 angstrom demo files (which still uses the driver name tiadc rather than TI-am335x-adc).
ReplyDeleteTrying to cross compiling the kernel on a mac is a bad idea...
Any suggestions on how to set the sampling rate for continuous acquisition?
An aspect I am not looking into at the moment.
DeleteThere is no interface at the moment. Max sampling I think.
You'll have to check TRM and manually fix registers to your required rate..
When I run generic_buffer, it reports that it can't find tiadc or TI-am335x-adc (I've tried both). I'm using the prebuilt systemd image, so I may be missing a required package. Any idea what it could be?
DeleteThings have changed since this post. I have yet to update the blog..
DeleteSorry for the confusion.
Also. You need the latest kernel uImage file for these.
Hi, Fred. Do you bother to shed some light into cross compiling kernel on Mac? What was your setup and what would it be right now?
DeleteWorks with BBB-eMMC-flasher-2013.08.21.img.xz.
ReplyDelete"modprobe iio-trig-sysfs" is needed though.
Several typos in the post, e.g.
/sys/bus/iio/trigger0/trigger_now
/sys/bus/iio/iio_sysfs_trigger/add_trigger
should be
/sys/bus/iio/device/trigger0/trigger_now
/sys/bus/iio/device/iio_sysfs_trigger
/add_trigger
Thank-you for pointing it out.
DeleteBut the interface has changed significantly since this post.
The linux kernel folk didn't like the trigger handling this way as it wasn't how iio usually handled triggers.
Feel free to use this code if it works for you. But I'll be updating the blog soon with the new stuff.
Is it possible to start ADC with the iio-trig-gpio (HW continuous mode) on BBB?
ReplyDeleteWhy "modprobe iio-trig-gpio" doesn't work on BBB?
Thanks in advanve
I haven't worked on gpio. I asked the iio mailing list and Lars Peter replied
Delete"You need to register a platform device for your IIO trigger, like this:
static struct resource iio_gpio_trigger_resources[] = {
[0] = {
.start = IRQ_NR_FOR_YOUR_GPIO,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
static struct platform_device iio_gpio_trigger = {
.name = "iio_interrupt_trigger",
.num_resources = ARRAY_SIZE(iio_gpio_trigger_resources),
.resource = iio_gpio_trigger_resources,
};
platform_device_register(&iio_gpio_trigger);
Once you've done that the trigger will appear in the list of available
triggers and you can assign it to your device."
It's seems like you did that before: "....It took a while to restructure the driver".
DeleteI'm wondering where to insert this struct ressource for register the iio-trig-gpio platform device: I have no information about that?
Please I need some references for me to follow it step by step?
Thank you in advance.
I haven't done it before.
Deleteif i remember correctly, you are looking for board-generic.c in arch/arm/mach-omap2/
I can insert this modole (insmod iio-trig-gpio.ko) from the "/lib/modules/3.8.13/drivers/staging/iio/trigger/" directory and find it in the "/sys/module/iio_trig_gpio" like installed module; but it can't be activated like device in "/sys/bus/iio/devices/ directory". This is not the same with the iio-trig-sysfs module.
DeleteDid you notice that before? Any help will be very welcome.
Thank you again.
Sorry I can't help out more. I have no experience. You could try emailing the IIO list.
DeleteI'm using the tiadc driver with command " -n tiadc -t sysfstrig1 -l 128" and it is able to run the application with return some adc reading value, but the application only return 60++ value to me instead 128 sample adc value.Anything go wrong or i'm doing it wrongly?
ReplyDeleteLim Kean, You must have enabled two channels of the ADC.
ReplyDelete128 samples divided on 2 channels makes 64 samples each..
Using this driver and your procedure I managed to get about 4000 samples per second. For sound capturing we need at least 16ksamples/s. Is there a way to do that ?
ReplyDeleteThe sampling frequency select side isn't set up in the driver. I am not sure what it has been set at in the code. Check the TRM. If I remember correctly, this is max sampling.
ReplyDeletealso. Why do you wish to use the ADC for sound capturing?
There is an Audio cape available. Needs a bit of a workaround to run with beaglebone black.
And there are 10$ usb audio dongles that work..
Check https://groups.google.com/forum/#!topic/beagleboard/8Zc9DPd7rxc
Hello-- Your code has a buffer overflow in iio_utils.h build_channel_array() which is always triggered. The problem occurs at the line
ReplyDeletefscanf(sysfsfp, "%u", ¤t->enabled);
Even after the ci_array has been filled, the loop continues to check the remaining files, and while this happens "current" points *beyond* the end of the array. This fscanf() causes random memory to be stomped on and unpredictable behavior. I changed "current->enabled" to a local variable "current_enabled" and it worked fine then. Another way to solve the problem is end the loop after ci_array has been filled.
Could you please post a patch on the IIO list and cc me as well?
DeleteThanks
I'm not a member of iio mailing list, nor do I know where iio_utils.h came from other than your sample code. I posted a commit here which resolves the problem:
ReplyDeletehttps://github.com/CBGoodBuddy/adc-iio-continuous-sampling-userspace/commit/280d5243a31d35a7282dd0575a615107289976f0
Can you please forward as appropriate?
Hi Craig,
DeleteI forwarded your patch to the IIO mailing list and it has been accepted.
The subsystem maintainer (Jonathan Cameron) was asking about your email address..
Details here :
http://beagleboard-gsoc13.blogspot.co.uk/2013/09/success-at-last.html?showComment=1388592362802#c8166626499201609384
Thanks
Zubair
sorry if this has already been covered... but ive spent a few literally sleepless nights so the brain is a little claged.. but shouldnt "echo BB-ADC > /sys/devices/bone_capemgr.*/slots" actually have a "9" rather than a "*" ? for me "*" did work till i tried adding it to my /etc/rc.local and it failed and after some more searching i found using the "9" got it working automatically (along with my w1 which is also in there)
ReplyDeleteapologies if none of that is clear.... ill try my best to explain better in the morning
Hi Zubair,
ReplyDeleteI need to read all 7 analog inputs of the BBB every 5 milliseconds for a real-time
audio app. However, reading using the usual file io interface to the analog pins consumes too much cpu. (See https://groups.google.com/forum/#!category-topic/beagleboard/beaglebone-black/9NYdGWOT_Mg).
Are the techniques discussed here still available in a current BBB build? I'm using Debian and here's the output of uname -a:
Linux beaglebone 3.8.13-bone43 #1 SMP Wed Mar 26 14:21:39 UTC 2014 armv7l GNU/Linux
Any pointers will be greatly appreciated since I'm in a bit of a dead end.
Rafael.
Clarification: I wont use the ADCs to sample audio, but control signals
DeleteReplied on the post
Deletehttps://groups.google.com/forum/#!category-topic/beagleboard/beaglebone-black/9NYdGWOT_Mg
This comment has been removed by the author.
ReplyDeleteHi Zubair,
ReplyDeleteIn response to
./generic_buffer -n tiadc -t sysfstrig1 -l 128
this is what I get:
iio device number being used is 0
iio trigger number being used is 0
sysfstrig1
Could not open /trigger/current_trigger
Failed to write current_trigger file
I verified that /trigger/current_trigger exists in the /iio/devices directory.
I also tried:
root@arm:/home/ubuntu# echo sysfstrig1 > /sys/bus/iio/devices/iio:device0/trigger/current_trigger
root@arm:/home/ubuntu# cat /sys/bus/iio/devices/iio:device0/trigger/current_trigger
sysfstrig1
Do you have any thoughts?
Thanks in advance
This is an old post. And trigger is not implemented by the driver anymore.
Deleteto use the latest driver, you have to modify generic_buffer.c and remove the trigger checks
When I run the generic buffer application, it says cannot find TI-am335x-adc.
ReplyDeleteIs there any other other way I can read from the raw voltage files continuously at certain intervals of time?
try
Delete./generic_buffer -n tiadc -t sysfstrig1 -l 128
instead of
.generic_buffer -n TI-am335x-adc -t sysfstrig1 -l 128
it depends on kernel versions. Naming conventions changed between 3.8 and 3.12..
DeleteThe name should be in sysfs somewhere
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteGood Morning.
ReplyDeleteI followed all the instructions and when I run ./generic_buffer -n tiadc -t sysfstrig1 -l 128 it says:
iio device number being used is 0
iio trigger number being used is 0
Problem reading element scan information
diag / sys / bus / iio / devices / iio: Device0
Is there anyone who can help me.
Thanks Franco
Nice tutorial. How to sample ADC channels continuously with constant sampling rate.
ReplyDeleteHOw you get the trigger name as sysfstrig1? I am using 2.6.37 kernel.
ReplyDeleteBest,
Jebaraj
Any pointers will be greatly appreciated since I'm in a bit of a dead end.
ReplyDeleteplaystar slots
gold slots