[Updated Jan 22 - various improvements to the Python sample code at the end of the article]
In November, Texas Instruments, Digi-Key and the other members of Beagleboard.org, the Beaglebone. This is a simpler, more hobbyist-friendly little brother to the Beagleboard (which I’ve written about in past articles).
Compared to the Beagleboards, the Beaglebone is considerably less expensive ($90), provides access to all of its pins, is pin-compatible with 3.3V sensors and devices (aside from analog in, which is still 1.8V), and provides a more friendly “out of the box” experience. As with the Arduino, the only thing you need to get started is a USB cable.
As a developer, my most pleasant surprise with the Beaglebone was the inclusion of an entry-level IDE and scripting language: the Cloud9 IDE configured to run node.js and bonescript.
With the Beagleboards, there was no “out of the box” IDE. There were plenty of options for developing with the Beagleboard – Texas Instrument’s Code Composer Studio, Eclipse, or the command-line GCC tools being the most prominent – but all had a fairly steep learning curve just to do something basic, like blink an LED.
One of the most slippery patches on that learning curve is figuring out how to convince the Linux kernel to let your code access the pins. It’s nowhere near as simple as Arduino’s “digitalwrite(13, HIGH)” – or, at least, it wasn’t until bonescript came along. Although bonescript is still in its very early stages, there is enough meat on it to give the embedded Linux newbie a friendly introduction to coding.
The Circuit
The circuit is your garden-variety LED configuration:
- an LED
- a resistor (680R or thereabouts) connected to the negative pin of the LED
- a jumper from the positive pin of the LED to the digital pin
- a jumper from the resistor to ground
The Beaglebone actually has 65 GPIO pins to choose from, but we’ll go with the one used by the blinkled.js program that is included with bonescript. This is Pin 3 on Header 8, referred to by the Beaglebone System Reference Manual as GPIO1_6 on Expansion B, but known to Linux as gpmc_ad6.
Say what?
Well, the “Pin 3 on Header 8″ part is simple enough. If you look at the Beaglebone, Port 8 is one of the 2 double-rows of female headers, labeled P8 on the circuit board. (In the figure below, taken from the System Reference Manual, Port 8 is labeled “Expansion B).
At either end of the headers you’ll find the rows marked 1 and 2, and 45 and 46. So, Pin 3 is the 2nd row from the top, left column, as indicated in the figure.
The other names for the pin, along with the locations of the ground pins, can be found in the System Reference Manual. If you look at Table 8 – “Expansion Header P8 Pinout” (a portion of which is shown below), you’ll find the pins labeled with their default usages in the Angstrom Linux demo image (the one that comes packaged with the beaglebone on a microSD card).
Clearly, Ground is the top row of Port 8, so that’s the last bit of information we need to know to hook up the circuit. But we’ll need to understand that part about pins having “default usages” – more on that later.
Cloud9 IDE and bonescript
When you boot up the Beaglebone with the microSD card from the box, the Cloud9 IDE is automatically started. Once you have an IP address assigned to the Beaglebone (either through its Ethernet port connection or through USB networking), you can load the Cloud9 IDE on your PC browser at http:<beaglebone address>:3000
(I haven’t tried to use USB networking myself, but the procedure for doing so is explained in Getting started with your new BeagleBone.)
The Cloud9 IDE interface is pretty intuitive. You select a source code file in the left pane, edit it in a tab in the right pane, and select Debug or Run from the toolbar to execute the code.
If you are coming at this from the Arduino, you will notice 3 significant differences from the Arduino IDE:
- You don’t upload your code to the board. The Beaglebone is more like a PC than an Arduino – the code is stored on its file system, and you just run it.
- You can debug your code. Not Arduino’s form of debugging – print statements to the console (though you can do that too) — but real debugging, as in breakpoints, watch variables, step-by-step execution.
- The coding language is Javascript, not C. Specifically, it’s node.js, which is Javascript optimized for running on a server, rather than in a browser, by way of some extra libraries. The “server” in this case is the little old Beaglebone. As you might imagine, node.js is not the fastest environment for running code on the Beaglebone, but for LED blinking and many other types of prototyping, it’s fast enough.
Despite the differences, Arduino coders should find the transition to Cloud9 and bonescript to be quite easy. The blinkled.js code looks very much like Arduino code. That’s no coincidence: the README for the bonescript project, which you can find on its github page here, says that the goal is “to have something that provides most of the Arduino functions and is generally usable by Summer 2012″.
var ledPin = bone.P8_3;
var ledPin2 = bone.USR3;
setup = function() {
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
};
loop = function() {
digitalWrite(ledPin, HIGH);
digitalWrite(ledPin2, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
digitalWrite(ledPin2, LOW);
delay(1000);
};
This code from blinkled.js does the following:
- defines 2 pins, P8_3 (Port 8, pin 3) and USR3 (which is one of the built-in LEDS on the board, next to the Ethernet port)
- sets these pins for Output
- loops, turning these 2 LEDs on and off, once per second, ad infinitum
If you’ve attached an LED to pin 3, and you run blinkled.js in Cloud9, you should find it blinking happily away. (There is a dropdown button next to the Run and Debug toolbar icons in Cloud9 to let you choose the file).
It’s that simple.
I lie.
There is actually considerable complexity behind the code which creates those 2 pin objects, bone.P8_3 and bone.USR3. The complicated code is in one of the 2 “library” files in the bonescript folder, index.js.
Pins and Muxing
Before we dive into the index.js code, let’s return to the Beaglebone System Reference Manual. As you’ll recall, I earlier referred to the “default usage” on Port 8 Pin 3. It has other usages, and the process of telling the board how you want to use that pin is called muxing (short for multiplexing).
The available usages of the pin, and all of the others on the Port 8, are listed in Tables 9 (the first part of which is shown below) and 10 of the System Reference Manual. Each pin can have up to 8 uses, “mux mode” 0 through 7. The default setting in the Angstrom Image is generally, but not always, mode 7. Table 8 is the definitive guide to Angstrom’s default mux setting for each pin.
(Incidentally, other Linux distributions for the Beaglebone, such as Ubuntu, will have their own default mux settings. The board doesn’t control the mux settings, the software does. The developers of the Angstrom Linux image on the SD card selected their defaults to be the most commonly used ones by hobbyists, providing a good out-of-the-box experience.)
If you Google “Beagleboard mux”, you’ll find lots of pages explaining the various ways in which you can change the mux setting. Many of them refer to U-Boot configuration and kernel modules, which are complicated and, fortunately, no longer necessary. There has been a lot of work done recently at making the mux settings accessible to “userland” code by way of the Linux file system. If you (or your code) wants to read or change the mux setting, it just needs to read or write to a file.
Great. So which file?
This information used to be hard to come by, scattering amongst various forum and blog posts, or hidden inside code in U-Boot or the linux kernel. However, if you’re learning to code with the Beaglebone, I think the best way to learn the mux file system is to look at how bonescript handles it.
Muxing the bonescript way
So, back to the Cloud9 IDE. This time, open up the index.js file in the bonescript directory. (Note that this part of bonescript is in active development and is likely to change by the time you read this, but the underlying file system will still be the same)
A little ways into the code (line 39 in the current release, bonescript 1.0-r10), you’ll find the following:
var gpio0 = 0;
var gpio1 = gpio0+32;
var gpio2 = gpio1+32;
var gpio3 = gpio2+32;
bone = exports.bone =
{
P8_1: { name: "DGND" },
P8_2: { name: "DGND" },
P8_3: { name: "GPIO1_6", gpio: gpio1+6, mux: "gpmc_ad6" },
P8_4: { name: "GPIO1_7", gpio: gpio1+7, mux: "gpmc_ad7" },
P8_5: { name: "GPIO1_2", gpio: gpio1+2, mux: "gpmc_ad2" },
P8_6: { name: "GPIO1_3", gpio: gpio1+3, mux: "gpmc_ad3" },
P8_7: { name: "TIMER4", gpio: gpio2+2, mux: "gpmc_advn_ale" },
P8_8: { name: "TIMER7", gpio: gpio2+3, mux: "gpmc_oen_ren" },
. . .
USR0: { name: "USR0", gpio: gpio1+21, led: "usr0", mux: "gpmc_a5" },
USR1: { name: "USR1", gpio: gpio1+22, led: "usr1", mux: "gpmc_a6" },
USR2: { name: "USR2", gpio: gpio1+23, led: "usr2", mux: "gpmc_a7" },
USR3: { name: "USR3", gpio: gpio1+24, led: "usr3", mux: "gpmc_a8" }
This table contains 3 important pieces of information:
- the label that bonescript uses to identify the pins (P8_1, P8_2, etc)
- the GPIO pin number (P8_3 is gpio1+6, or 38)
- the mux label (P8_3 is gpmc_ad6)
The GPIO pin number tells you the directory name you will use to read from or write to the pin. The mux label tells you the filename you will use to read or write the mux setting.
Let’s start with the mux setting. This is handled by some code just below the exports.bone table:
if(pin.mux) {
try {
var muxfile = fs.openSync(
"/sys/kernel/debug/omap_mux/" + pin.mux, "w"
);
fs.writeSync(muxfile, "7", null);
} catch(ex3) {
console.log("" + ex3);
console.log("Unable to configure pinmux for: " + pin.name +
" (" + pin.mux + ")");
. . .
There is more to the error handling, but the important part is the reference to “/sys/kernel/debug/omap_mux/” + pin.mux. This is the file used to read and write the mux setting. In the case of Port 8 Pin 3, the full path is /sys/kernel/debug/omap_mux/gpmc_ad6.
This is the part that is newcomers to pin muxing often trip over: if you want to set a pin to be a GPIO pin, your code needs to reference a filename that appears to be intended for a different usage of the pin (gpmc_ad6). The mux filename isn’t taken from its intended usage, it’s taken from its mode 0 usage. The mode 0 usage for Port 8 Pin 3 is gpmc_ad6 – we know this from the table in the bonescript code, but the definitive reference for the Beaglebone pin mux modes are Tables 9 and 11 of the Beaglebone System Reference Manual.
Having opened the file (fs.openSync), the bonescript code writes a 7 to it (fs.writeSync). This, as you probably guessed, sets the mux mode to 7, the GPIO mode for that pin. The process of setting mux modes isn’t quite as simple as “write the mode to a file”: the mux mode setting also affects other aspects of the pin, such as whether it can be used for input. The bonescript code shown above is actually correct only for setting pins to be GPIO Output pins. The bonescript project will soon support other mux mode settings.
Blinking LEDs the bonescript way
Having set the pin to be in digital output mode, the next task is to set it high or low. You’ll recall that this was handled in blinkled.js by calling a function called digitalWrite, same as the Arduino does.
The source code for digitalWrite can be found further down in index.js:
digitalWrite = exports.digitalWrite = function(pin, value)
{
fs.writeFileSync(gpio[pin.gpio].path, "" + value);
};
OK, so it’s writing a value to a file, either HIGH (defined as 1) or LOW (0). But which file?
The code to set that “path” property also in index.js, just below where the pin mux setting was done:
try {
try {
fs.writeFileSync("/sys/class/gpio/export", "" + n);
} catch(ex2) {
// TODO: If the file is already exported, can we know who did
// did it so that we aren't opening it twice? In general, this
// shouldn't be an error until we have some better resource
// management.
//console.log(ex2);
//console.log("Unable to export gpio: " + n);
}
fs.writeFileSync("/sys/class/gpio/gpio" + n + "/direction",
mode);
gpio[n].path = "/sys/class/gpio/gpio" + n + "/value";
return(true);
} catch(ex) {
// Perhaps we couldn't open it because it was allocated as an LED
if(pin.led) {
fs.writeFileSync(
"/sys/class/leds/beaglebone::" + pin.led + "/trigger",
"gpio");
if(mode == OUTPUT) {
gpio[n].path =
"/sys/class/leds/beaglebone::" + pin.led +
"/brightness";
} else {
gpio[n].path =
"/sys/class/leds/beaglebone::" + pin.led +
"/gpio";
}
return(true);
}
}
The first thing it does is try to write to a file named “export”, specifically , “/sys/class/gpio/export”. The value written is the GPIO pin number, which you’ll recall was specified in the table earlier in index.js. For Port 8 Pin 3, it was defined as gpio1+6, or 38.
The export file is a funky weird-ass file: when you write a pin number to it, it (well, the kernel process which monitors that file) creates a directory and a bunch of files that provide interfaces for accessing the pin. The directory is created at /sys/class/gpio/export/gpioNN. In the case of Port 8 Pin 3, that’s /sys/class/gpio/export/gpio38.
For the purpose of using a GPIO pin, the two most important files in the gpioNN directory are named direction and value.
The direction file determines whether the pin is going to be used for reading or writing. As mentioned earlier, you can’t use a pin for reading without setting flipping a bit in the mux mode setting, so our only choice at this point is output. The bonescript code writes the value “out” to the direction file (i.e. to /sys/class/gpio/export/gpio38/direction).
The code then saves the path to the value file (i.e. /sys/class/gpio/export/gpio38/) in the pin’s path property. This, then, explains what the code in the digitalWrite function is doing:
fs.writeFileSync(gpio[pin.gpio].path, "" + value);
It writes a 1 to the value file (i.e. /sys/class/gpio/export/gpio38/value) to set the pin high (and the turn the LED on) and a 0 to set it low (and the LED off).
But wait, there’s more!
The bonescript code shown above also has an error handler.
Writing to the export file also tells the kernel that you intend to use that pin. If the pin is already being used by something more important than your dinky userland application (i.e. the kernel or one of its pals), it will helpfully toss an error at you.
Generally, when your attempt to export a pin fails, you have no option but to go away and sulk. Something is using that pin, and it might be a hardware driver that won’t be giving it up any time soon (such as the SD card socket, or an LCD). There are ways of tracking down what’s using it, but I won’t cover them in this post.
One possibility is that the GPIO pin is being used by one of the built-in “user LEDs”, USR0 – USR3. As you can see from the final entries in the bonescript mux table, those LEDs are connected to GPIOs 53-56. So, the bonescript code checks to see if you’re trying to write to those GPIOs – if so, it assumes you want to access the user LEDs, and redirects you to their address.
These user LEDs are accessed through a different part of the file system than the GPIOs – technically, they are part of the Beaglebone board, not part of the CPU. So, they are accessed through the /sys/class/leds/beaglebone directory, not /sys/class/gpio.
The Beagleboard (the ‘bone’s big brother) also has user LEDs, and they are accessed in basically the same way there, so you can find a good explanation of how to write to them in some of the articles written for the Beagleboard. The command line interface is explained in this article on eLinux. For C language code that interfaces to the user LEDs, see this sample from Jan Axelson’s USB Embedded Hosts: The Developer’s Guide. (This, by the way, is one of the few books currently available that specifically covers Beagleboard programming).
Blinking LEDs the Python Way
The directories and paths used by the bonescript code can also be used from other programming languages: pretty much anything that runs on Linux can read and write from the file system.
Here is my own humble contribution, a snippet of Python code which blinks the USR2, USR3 and Port 8 Pin 3 ten times. It has the advantage of distilling the bonescript code down to the bare bones needed to access that particular pin.
[Updated Jan 22 - added support for User LEDs 2 and 3, handle case where pin already exported, and simplified the file I/O syntax:]
import time
# put Port 8 Pin 3 into mode 7 (GPIO)
open('/sys/kernel/debug/omap_mux/gpmc_ad6', 'wb').write("%X" % 7)
try:
# check to see if the pin is already exported
open('/sys/class/gpio/gpio38/direction').read()
except:
# it isn't, so export it
print("exporting GPIO 38")
open('/sys/class/gpio/export', 'w').write('38')
# set Port 8 Pin 3 for output
open('/sys/class/gpio/gpio38/direction', 'w').write('out')
# we will assume that USR1 and USR 2 are already configured as LEDs
for i in range(10):
# turn on USR1 and external LED
open('/sys/class/gpio/gpio38/value', 'w').write("1")
open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr1/brightness", 'w').write("1")
# turn off USR2
open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr2/brightness", 'w').write("0")
time.sleep(1)
# turn off USR1 and external LED
open('/sys/class/gpio/gpio38/value', 'w').write("0")
open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr1/brightness", 'w').write("0")
# turn on USR2
open("/sys/devices/platform/leds-gpio/leds/beaglebone::usr2/brightness", 'w').write("1")
time.sleep(1)
# cleanup - remove GPIO38 folder from file system
open('/sys/class/gpio/unexport', 'w').write('38')
The Python code also demonstrates something that the bonescript code doesn’t handle. To be a nice little userland app and clean up after yourself, you can write the GPIO pin number to /sys/class/gpio/unexport. This doesn’t “release” the GPIO to other apps – you never had it locked for your exclusive use in the first place – so unexport’ing is just a convention to make the gpio file system is a little more manageable.
Since python is already installed on the Angstrom image, you can download the file and run it as follows:
wget http://gigamega-micro.googlecode.com/files/gpiotester.py python gpiotester.py
Wrapping Up
If you think that’s a lot of work in order to blink an LED, you should have tried it a few years ago, when the Beagleboard was first released.
Back in the day, to do anything with a GPIO pin you pretty much had to be an embedded Linux guru, or beg for crumbs of knowledge from the guru’s table. (Oh, and good luck getting your LED to light up on 1.8V. You kids have it easy these days!)
The Beaglebone arrives at a time when the embedded Linux device market is growing by leaps and bounds, both in terms or hardware and development tools. As a hobbyist (or a budding professional), this is a good time to hop on board the platform.
Incidentally, while the Beaglebone platform is geared for hobbyists and prototypers, the chip it uses is very much targeted at professionals. The Texas Instruments Sitara AM3359 is a descendent of (and largely code compatible with) the storied OMAP chip family, which powers a lot of consumer gadgets: many of Nokia’s high-end smartphones like the E90, Motorola’s Droid line of Android smartphones, the Nook Color and the Kindle Fire.
If you can get to a root command line on one of those devices, you can probably set a GPIO high and low using the same code as above (and if you’re lucky, cause an inglorious crash). How cool is that?




Hi Dan,
great article, thanks a lot!
I still wonder, how much current the pins support. I have not found any (understandable) information in the data sheets or other documentation. You described how to use a LED, but did you use low-current LEDs?
Best regards, Georg.
Hi Georg,
Yes, I was using a low current LED. I can’t find where the max current is documented either – I think it’s somewhere in the 4500 page Technical Reference for the AM335x processor, but most of that stuff is over my head. On the Beagleboard XM’s DM3730, the max current is different for different pins, and depends on how many pins are driving or sinking current at the same time, but the absolute maximum was quite low, 8 mA.
Dan.
Thanks for the intro. I received a BB but only played with it slightly. There doesn’t seem to be much info out there compared to the Arduino so hope to see more such as PWM, etc…
At last! I’ve been searching for this kind of practical information for 2 weeks! Now to get busy.
Any recommended forums for BeagleBone related info? I’ve found the Google Groups Beagle Board forum–that’s how I got here.
Hi,
The Beagleboard Google Groups forum is my main source of BB info too.
To keep an eye on new BB-related articles on the web I use the RSS feed at http://feeds.feedburner.com/BeagleBoard — it was dormant for awhile, but seems to have recently sprung back to life.
Dan.
Dan,
It was dead because Google disabled the RSS feed from Google Reader. Different solutions have come out to publish as RSS feeds output from G+, which is why it is going again.
-Jason.
Pingback: Beaglebone Coding 101: Using the Serial and Analog Pins | GigaMegaBlog
You wouldnt happen to know how to read a poteneiemeter or a transistors tempurature sensor… Im still straching my head on this one thanks alot!
Thank you so much for the great article!
Question, I am able to get P8_3 working as you describe in the tutorial, but I cannot seem to get the GPIO to work on any other pins. For gpmc_ad6 it shows gpio1_6 which matches the BeagleBone manual. For P8_4, however, gpmc_ad7 should have gpio1_7, but instead shows “NA” as shown below.
cat /sys/kernel/debug/omap_mux/gpmc_ad6
name: gpmc_ad6.gpio1_6 (0x44e10818/0x818 = 0x0037), b NA, t NA
mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
signals: gpmc_ad6 | mmc1_dat6 | NA | NA | NA | NA | NA | gpio1_6
/sys/kernel/debug/omap_mux/gpmc_ad7
name: gpmc_ad7.(null) (0x44e1081c/0x81c = 0x0037), b NA, t NA
mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
signals: gpmc_ad7 | mmc1_dat7 | NA | NA | NA | NA | NA | NA
Is there something special I need to do to make this pin accessible as GPIO, or can it not be configured that way? Any help would be greatly appreciated. Thanks.
Hi,
I get the same results if I set gpmc_ad7 to mode 7: the signals line seems to indicate it isn’t supported.
However, most of the GPIO pins indicate “NA” for Mode 7, but most work correctly in this mode. This post in the Beagleboard Google Groups forum indicates that it’s a known problem which (I think) only affects the output of the signals line, not the behaviour of the pin:
http://groups.google.com/group/beagleboard/browse_thread/thread/6c665c087c07c2b2/8126e0d4afe2a2b3?lnk=gst&q=beaglebone+user+leds#8126e0d4afe2a2b3
However, gpmc_ad7 (Pin 4 on Port 8 ) has another problem: if you try to interact with it through the file system, you’ll likely get an error…
root@gigamegabone:/sys/class/gpio# echo 39 > export
sh: write error: Device or resource busy
I haven’t found an explanation for this. I can only assume that the pin really is in use by some other software.
I’ve found that the next 2 pins on Port 8 (5 and 6) work as expected as GPIO pins, when put in mode 7 (they are in mode 0 by default). These are gpmc_ad2 (GPIO 34) and gpmc_ad3 (GPIO 35).
HTH,
Dan.
Pingback: Beaglebone Linux 101: Configuring Angstrom Linux | GigaMegaBlog
Great series on Beaglebone coding. How applicable is this to the original BeagleBoard? You’ve added some links for LED control with a CLI or in C for the BeagleBoard, but is it possible to use the Cloud9 IDE and bonescript? (the name would suggest otherwise)
Hi,
I haven’t tried it yet, but apparently the Cloud9 and bonescript packages are available for the Beagleboard if you install a 2012 Angstrom image. See this post in Beagleboard Google Groups: http://groups.google.com/group/beagleboard/browse_thread/thread/742c5f7a55039d3c/25c9c3816b810a33?lnk=gst&q=beagleboard+cloud9#25c9c3816b810a33
If the kernel in that image includes support for accessing the GPIO pins through the filesystem (i.e. omapmux etc) then much of bonescript would be usable.
My Beagleboard Rev C is running an old version of Ubuntu – I’ll have to try out a new Angstrom build to see what is possible.
Dan.
Thank you for putting the work in and posting this! This is awesome awesome awesome.
Pingback: beaglebone ubuntu user led gpio « Lost Ferry
Hi,
You mentioned that Jan Axelson book is one the few books that covers Beagleboard. May I know which other books that also discussing beagleboard.
I know “Practical Beagleboard” is supposed to be one of them, but seems like the publication was cancelled.
Thank you
Well, I was admittedly being optimistic when I said “few”. Hopefully others will appear, but the only other one that I know about is “Embedded Linux Primer: A Practical, Real-World Approach” by Christopher Hallinan. I’ve started to read this, and it’s relatively easy to understand for non-engineers, but not a project-oriented book like Practical Beaglebone would have been.
Dan.
Hi,
It’s an excellent tutorial. But as a beginner to embedded linux, I dont’ really get the “big picture” . For example, if we want to stick with bonescript, do we write the whole application with bonescritpt or can we combine it with c for example ? and how to make the board to automatically load our written application upon botting-up? And how can we make use of watchdog timer as on microcontroller world ?
I’m trying to compare the development process on beagleboard/beaglebone with PIC microcontrolelr for example…
Thank you
I’m new to this type of development too, so I’m afraid that I don’t know the answers to your questions. You might want to post the questions to the Beagleboard Google Group, where the expert developers hang out.
In general, there are 2 types of development you can do with the Beaglebone: Linux or “native”.
Native development is similar to what you do with a PIC or AVR microcontroller — there is no Linux involved. You’d be dealing directly with the AM335X processor. I haven’t looked into this, but Texas Instruments has a lot of info and sample code for this, such as their StarterWare page: http://processors.wiki.ti.com/index.php/AM335X_StarterWare_Booting_And_Flashing
If you go with embedded Linux development, then you have 2 options: develop kernel modules (drivers) which have relatively low-level access to hardware, or “userland” code which can only do what Linux allows it to do. Bonescript and Python code are userland code. This type of code is easiest to learn, and there is relatively good documentation and example code on the web for this. For example, the answer to your question about invoking C code from bonescript can probably be found by reading or Googling info about “node.js”.
Personally, I plan to stick with userland code, mostly in Python, and wait for more advanced developers to write the low-level code in the form of drivers and kernel modules. There are a lot of new hardware features built into the new 3.2+ kernel, such as PWM support, and lots more new stuff is in development.
Dan.
And for example, if I want to communicate with external peripheral like USB keyboard, how can I do that ?
Thank you
From a coding standpoint, you can read from a USB keyboard using the /dev/input/event file system. When you plug in a USB keyboard, you should find that a new directories named /dev/input/event0 and event1 appears. Each time you press a key on the keyboard, an event is raised. You can see the contents of these events by running the evtest utility (i.e. evtest /dev/input/event0 ), and you can write your own code to read them — Google for examples.
This event system can actually be implemented for any GPIO pin, but requires configuration in the kernel. I looked into this, but it’s over my head right now. You can read more about this by Googling “gpio-keys”.
Dan.
Ok, Now it makes more sense to me … everything is file in linux ….
By the way, how about the watchdog or such in embedded linux ? Do I need external supervisory IC (watchdog timer IC) ?
And I imagine Linux as an RTOS with all the drivers on microcontroller systems. Is that basically what Linux is doing ?
Do I need to write a Linux script to automate the loading of my application when it’s powered up?
Thank you.
Sorry, I don’t know about watchdog timers, or how (if) they are supported in Angstrom. This post might be useful to you: http://embeddedfreak.wordpress.com/2010/08/23/howto-use-linux-watchdog/
I don’t know much about RTOS either. If you are looking for an RTOS to run on the Beaglebone, Angstrom Linux probably isn’t the best choice. Maybe QNX?
Linux offers a few different ways to automatically run a program at boot time. Typically, you add a shell script to the /etc/init.d file system for this — you can find tons of examples by Googling.
If you are using Angstrom Linux, then the best choice is probably systemctl, which simplifies the process considerably. Take a look at the scripts in /lib/systemd/system for examples of how to do this.
For example, to run a Python script at startup I created the following file:
bigdog:/lib/systemd/system$ cat gm_sensorrelay.service
[Unit]
Description=GigaMega Sensor Relay
ConditionPathExists=|/media/sda1/python
[Service]
WorkingDirectory=/media/sda1/python
ExecStart=/usr/bin/python /media/sda1/python/SensorRelay.py
[Install]
WantedBy=multi-user.target
Dan.
Dan,
I’d love to see more detail on how you got your systemctl script to work. I’m having no luck with mine.
Do you have to do anything special with your *.py file? I have mine in the /home/root folder.
Thanks,
Matt
Matt,
Mine is in a user subdirectory. I actually didn’t have to troubleshoot systemctl much, since it (surprisingly) worked with the first configuration.
My .service file is as follows:
root@gigamegabone:/lib/systemd/system# ls -l gm*
-rw-r–r– 1 root root 239 Mar 24 18:43 gm_lightcontroller.service
root@gigamegabone:/lib/systemd/system# cat gm_lightcontroller.service
[Unit]
Description=GigaMega Light Controller
ConditionPathExists=|/home/dwatts/python
[Service]
WorkingDirectory=/home/dwatts/python
ExecStart=/usr/bin/python /home/dwatts/python/LightControllerVS.py
[Install]
WantedBy=multi-user.target
The python file’s settings are:
root@gigamegabone:/home/dwatts/python# ls -l LightC*
-rwxr–r– 1 dwatts dwatts 18633 Apr 17 21:26 LightControllerVS.py
All I did to configure the service is:
1. Created the Python file, and made sure it ran OK from the command line.
2. (As root), created the .service file in /lib/systemd/system
3. Tested it with:
root@gigamegabone:~# systemctl start gm_lightcontroller.service
root@gigamegabone:~# systemctl status gm_lightcontroller.service
gm_lightcontroller.service – GigaMega Light Controller
Loaded: loaded (/lib/systemd/system/gm_lightcontroller.service; enabled)
Active: active (running) since Tue, 17 Apr 2012 21:28:15 -0400; 5 days ago
Main PID: 1710 (python)
CGroup: name=systemd:/system/gm_lightcontroller.service
â 1710 /usr/bin/python /home/dwatts/python/LightControlle…
4. Set it to start automatically at bootup with:
root@gigamegabone:~# systemctl enable gm_lightcontroller.service
If none of that sheds any light on your problem, then a couple of general troubleshooting suggestions:
1. Update the kernel if you are running an old one (I’m on 3.2.13), and update the packages (i.e. “opkg update”, “opkg upgrade”). There were some patches to systemctl awhile back, December-ish.
2. Use “systemctl status” and “systemctl list-units” to see if an error message is reported for your service.
HTH,
Dan.
Pingback: » BeagleBone tutorial: Blinking LEDs using bash Wunderkammer
Pingback: Beaglebone Coding 101: Buttons and PWM | GigaMegaBlog
Hi
I’m new with the beaglebone, thank’s to your explanations about GPIO it really helped me. But i still have problems to resolv:
- Pin muxing is ok, i have to treat 6 interrupts (issued from 6 opto encoders mounted on stepper motors) so i have to make some treatments under interruption. are you able to tell me how to manage interrupts with Angstrom Linux.
- How can i configure the kernel to take into account my needs. I think specially at the real time clock. I want to use the DS1307 RTC chip instead of the default time managing. Any idea about thats ?
Thank’s for your answers
Italo
Hi,
Sorry, I haven’t tried to do those things, so I can’t give you very good advice. Here is some not-so-good advice:
For interrupts, you can look at this page in the Beagleboard Embedded Linux Course: http://elinux.org/EBC_Exercise_03_gpio_Polling_and_Interrupts. The sample C code for handling interrupts should also work on the Beaglebone.
For interfacing with the DS1307, there is the hwclock command that allows you to directly read or write to it. I haven’t played around with it myself. You can find more information on this page in the Gumstix wiki (Gumstix uses a similar hardware platform to the Beagleboard/Beaglebone):
# hwclock –help
BusyBox v1.19.3 (2012-03-03 09:26:58 CET) multi-call binary.
Usage: hwclock [-r|--show] [-s|--hctosys] [-w|--systohc] [-t|--systz] [-l|--localtime] [-u|--utc] [-f|--rtc FILE]
I hope that helps,
Dan.
Pingback: Puppy’s First Month « bwgz57
Great article. Thank you
Is it possible to control a pin remotely using a webserver running on BB ?
I have done this with arduino. A webserver runs on the board that depending on what page user requests pulls a pin high or low. Can this be done using BeagleBone? or is it too much to ask at this point.
Hi,
Yes, it’s definitely possible to do that (but I haven’t done it myself yet). Assuming you are OK with running your webserver on an embedded Linux platform (as opposed to writing native code for the Beaglebone’s AM335x processor), you have a lot of coding options.
One popular option is node.js. Here is a project that uses a node.js to serve a web page that controls the serial port. It would be pretty easy to modify the code to control a GPIO pin instead. http://www.jpeterson.com/projects/project-weblightswitch/
Another widely used platform for the Beaglebone is Python. Here is a project that runs a custom webserver in Python http://www.nathandumont.com/node/255. Again, it would be pretty easy to modify the code to control a GPIO pin.
The Beaglebone is also capable of running web servers with CGI support, like Lighttpd or Apache. That would allow you to invoke C code, or just a shell script, that interfaces with the GPIO pins.
Dan.
Hello
.
Very nice article, thank you very much
I have one doubt in index.js.
#
if(mode == OUTPUT) fs.writeSync(muxfile, “7″, null);
else fs.writeSync(muxfile, “27″, null);
#
in above condition why 27 for input ??
Hi,
The pin mux settings are shown in this table, and I explained them a little better in this article
The 27 is a hex value (i.e. x27). The “2″ turns on bit 5 in that table, which is the “input enabled” bit. Note that the other bits that affect GPIO input are set to 0, so a pulldown resistor has been enabled. The 7 is, of course, the mux mode for GPIO.
Dan.
Ok.. Now understood (with the help of that table)
.. Thank you.
Pingback: Beaglebone and ExtJs Web App « Isola Software
Very good article – thanks for the C code. I’ve just got my BB up on Ubuntu today. Kind of exciting actually. My question – how do you access the GPMC? Is the Ubuntu kernel already set up for this out of the box? You seem to imply that this would be Mode 0/i.e. the default.
I’ve seen some discussions of the GPMC using /dev/mem to access it – is that the way to go? I’m interested in talking to an external FPGA – and even a 4K window within a page would be okay.
Sorry, GPMC is way over my head. If you haven’t already, you should search the Beagleboard Google Groups posts on “GPMC” or post a new question there.
Dan.