Beaglebone Coding 101: Using the Serial and Analog Pins

[Updated Jan 25: Correction! There is a 1.8V voltage source on the Beaglebone: Port 9 Pin 32.  Thanks to Koen Kooi for the info.  I've updated the text with this information]

[Update May 5: In kernel version 3.2.14, the file system path for the analog pin readings was changed from /sys/devices/platform/tsc to /sys/devices/platform/omap/tsc]

This article is my second explaining the fundamentals of coding with the Beaglebone. In the first article I explained some of the mysteries of pin muxing, and gave an example of a very simple usage of a digital pin. This time, I’ll use an analog sensor and serial I/O (just O, actually), to create a time and temperature LCD display.

I have to admit that I’m far from an expert – I’m basically writing about this stuff as I figure it out.

The Beaglebone will hopefully prove to be a ground-breaking product, introducing a lot of electronics hobbyists to embedded Linux programming. Unfortunately, at this point there isn’t much in the way of embedded Linux development tools or tutorials that is geared to newcomers. This should change by the summer of 2012, as bonescript expands and more Beaglebone-based projects pop up on blogs and sites like Instructables. Until then, it will be one baby step at a time…

Analog Input

The first rule of analog input with the Beaglebone is:
NOTE: Maximum voltage is 1.8V. Do not exceed this voltage. Voltage dividers
should be used for voltages higher than 1.8V.

So sayeth the Beaglebone System Reference Manual (Emphasis theirs. )

I haven’t experimented with what happens if you go above 1.8V, but since they’ve made the warning red and underlined, I’m pretty sure it would not go well.
This limitation is a problem, since:

  • There is no pin on the Beaglebone that provides a 1.8V source
    [Correction Jan 25 - as pointed out in the comments, there is a pin that provides 1.8V, Port 9 pin 32 (labelled VDD_ADC in the Beaglebone System Reference Manual).    So you can ignore the stuff about voltage dividers and level converters below if you are using an analog sensor that can operate on 1.8V, like a potentiometer.]
  • Many analog sensors require a minimum voltage greater than 1.8V

So, until someone has a better idea, voltage dividers will be an important part of any Beaglebone analog circuit.

The second most important thing to know about the Beaglebone’s analog input is that the software support seems to be a work-in-progress. The approach I’m taken is based on a brief blog post by one of the maintainers of the Beaglebone Angstrom demo images. His remarks would suggest that they have a better plan that is under development. As far as I know, the approach taken here is an Angstrom kernel modification that won’t work at all on a Ubuntu image with the vanilla Ubuntu kernel.

Back to the issue of 1.8 max voltage. You have a couple of options in your design:

  • Added Jan 25: Use Port 9 Pin 32 as your voltage source, if your analog sensor can work on 1.8V
  • Use a couple of high precision resistors that can knock 3.3V or 5V down to exactly 1.8V
  • Use a couple of garden variety resistors to knock the voltage below 1.8V, then modify your software to adjust for the difference

Being lazy, I’m going with the latter approach. Being very lazy, I’m not even bothering to hook up the resistors – as shown in the screenshot below, I’m using a tiny breakout board to do the work.

Specifically, this is a Sparkfun Logic Level Converter – BOB-08745. You’ll see this part recommended quite often in Beagleboard/Beaglebone circles, since it is an inexpensive solution that can handle a range of voltages, and supports 2-way conversion (necessary for I2C).

For the purpose of analog input I’m not using the board as intended – I’m taking advantage of a semi-documented hack. The RX pins on this board just use a voltage divider: the voltage going into the “HV” pins comes out as half the amount from the LV pins. The circuit for this, taken from the BOB-08745 schematic, is shown below.

If you don’t have a BOB-08745, you can just use a couple of 10K resistors.

Before actually using this type of circuit, measure what voltage you get from the LV end of the voltage divider if the HV end is connected directly to 3.3V. If it isn’t below 1.8V, figure out what’s wrong before you hook it up to the Beaglebone. (Red and underlined, remember?) Don’t worry if the reading isn’t exactly 50% – we will calibrate the software to handle the variance.

The 2 analog sensors I’m using are a 10K potentiometer and an analog thermistor (temperature sensor), the Microchip MCP9700A.

As you can see from the photos, the connections are:

- Potentiometer and MCP9700A:

  • Input pin to 3.3V (which connects to pins 3 or 4 of Port 9 on the Beaglebone),
  • Ground pin to ground (connects to pins 1 or 2 of Port 9 of the Beaglebone),
  • Output pin to one of the RXI pins on the Sparkfun level converter (or to the HV pin on the voltage divider circuit)
  • Added Jan 25: An alternative for the potentiometer is to connect the input pin to Port 9 Pin 32 (VDD_ADC)., and the output pin directly to the Beaglebone AIN0 pin (pin 39 on Port 9)

- Sparkfun level converter:

  • HV to 3.3V
  • HV GND and LV GND to Ground
  • LV RXO for the potentiometer to the Beaglebone AIN0 pin (pin 39 on Port 9, or the outside pin of the 4th row from the “bottom” – the end opposite the Ethernet port)
  • LV RXO for the MCP9700A to the Beaglebone AIN1 pin (pin 40 on Port 9, or the inside pin of the 4th row)

Note that the LV pin on the level converter isn’t used, since we are just interested in the voltage divider.

The definitive guide to the Beaglebone pin connections is the System Reference Manual. For this project we are just using Port 9, so you can refer to the table below:

Testing Analog Input

Remember all that stuff about pin muxing from the first article? You can forget about it for analog in.

As you can see by looking at Table 12 of the Beaglebone System Reference Manual (part of which is shown below), the mux table for all of the analog in pins (AIN1 to AIN6) is empty: the pins can only be used for analog in.

There actually are entries for these pins in the file system, /sys/kernel/debug/omap_mux, but they have the correct setting by default, and as far as I can tell the Mode setting has no effect on the pins. (The Python code I wrote sets them anyway, but that’s admittedly more out of ignorance than caution.)

So, we can proceed directly to using the pins.

Let’s start with the potentiometer on analog 0 (pin 39 of Port 9). To get the current reading from the pot, enter the following (yes, it’s ain1 for analog 0 – go figure):

[Update May 5: In kernel version 3.2.14, the path to the analog pins was changed slightly, from /sys/devices/platform/tsc to /sys/devices/platform/omap/tsc.  The following examples use the original path]

root@beaglebone:~# cat /sys/devices/platform/tsc/ain1

A number should be displayed. Turn the pot all the way up and repeat. You’ll see the maximum value.

For me, it’s 3779. Or 3775. Or 3776. It drifts around a little. Go figure.

The analog input pins on the Beaglebone are 12-bit, so the maximum possible value is 4096. This represents a value of 1.8V. At 3779, it’s reading 3779/4096 * 1.8V, or 1.66V, which is about what you would expect with a 10K/10K voltage divider with 3.3V input.

Now, check the MCP7200A thermometer on analog 1 (again, the analog index is off by 1, so it’s ain2):

root@beaglebone:~# cat /sys/devices/platform/tsc/ain2

You should get a relatively low value: if it’s above 1000, either you are in hell or your thermistor isn’t hooked up correctly.

The formula for converting this reading to a temperature is:

(milliVolts – 500) / 10

The 826 reading I got is 826/4096 * 1.8V, or 362 mV.

Is it cold in here, or is it just me?

It’s just me. The voltage divider knocked the reading from the MCP7200A down by about half, or the actual reading is 362 * 2, or 724 mV. The temperature reading is therefore (724 – 500) / 10, or 22.4. (No, that isn’t cold, it’s just metric).

Actually, neither the MCP9700A nor this approach is very accurate. The MCP7200A’s datasheet says it’ typical accuracy is to within 1 degree C . There isn’t anything we can do to improve that, but we can make our calculation more accurate by allowing for slight variances of the resistors in our voltage divider.

To see what effect the voltage divider is having, temporarily hook the input to 3.3V instead of the MCP9700A’s output pin. Then check the value of /sys/devices/platform/tsc/ain2 again.

And again. And again.

I get 3765. And 3762. And 3759.

Given that each 10mV is a degree, that jumping about is a real problem. We’ll plug the average (call it 3762) into the code, then average a bunch of readings to get the temperature, approximately.

Serial I/O

The Beaglebone has 6 serial UARTs. One of those, UART0, is connected to the USB port, but that leaves us with 5 to play with. This is quite a step up from the Arduino’s single UART, or the Netduino’s 2 UARTs.

All of these are 3.3V UARTs. This is a problem if you’re communicating with a 5V device, but only when receiving data. Some 3.3 microcontrollers, like the Netduino’s, have “5V tolerant” pins, so they can communicate directly with 5V serial devices. But, for the Beaglebone:

NOTE: Do not connect 5V logic level signals to these pins or the board will be

So sayeth the Beaglebone System Reference Manual.

I assume this means that connecting an UART RX pin directly to the TX pin of a 5V serial device is a bad idea. I did it for awhile, and my Beaglebone lived to tell the tale, but maybe I got lucky.

Were we receiving data from the Serial LCD, then a level converter would be required, like the Sparkfun BOB-08745 described earlier. (Actually a second level converter would be needed, since we would be going between 3.3Vand 5, not 3.3 and 1.8ish.)

However, it will be serial TX only for this project, and all 5V serial devices that I’ve come across handle 3.3V on the RX pin without problems.

In the demo Angstrom image, the pins are not enabled for UART by default. Yup, time for the black art of pin muxing again.

Working with UART1’s mux mode is relatively straightforward. UART1 is the Mode 0 usage for the pin, and as you may recall from my first article, the pin name used in the file system are taken from the Mode 0 usage. To check the current settings:

root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_rxd
 name: uart1_rxd.(null) (0x44e10980/0x980 = 0x0037), b NA, t NA
 signals: uart1_rxd | mmc1_sdwp | d_can1_tx | NA | NA | NA | NA | NA

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_txd
 name: uart1_txd.(null) (0x44e10984/0x984 = 0x0037), b NA, t NA
 signals: uart1_txd | mmc2_sdwp | d_can1_rx | NA | NA | NA | NA | NA

As you can see, both are set to 0×37 by default in the Angstrom demo image. This setting means they are in Mode 7 (as the 2nd line of the output confirms) and that the Receive feature is enabled for both pins.

Let’s briefly take a closer look at the meaning of these mux pins. In my last article I explained the Mode settings, but not the other bits. The full list of the bit settings can be found in Table 9-58 of the AM335x Technical Reference Manual – you can find a link to it here. I’ll save you the trouble of searching for the table in that 4500-page behemoth:

The 2 UART pins currently have a mux setting of 0×37, or 0011 0111. So:

  • The slow fast [Corrected - July 5] slew rate is selected – this might concern me if I knew what it meant.
  • The Receiver is enabled – we want that for the RX pin, not so much for the TX pin
  • The pullup/pulldown is set to pullup – not a concern for serial communication
  • The pullup/pulldown is enabled
  • The 3 mode bits are all on, to indicate mode 7

We want to set both pins to Mode 0, and we also want the receiver disabled on the TX pin:

root@beaglebone:~# echo 20 > /sys/kernel/debug/omap_mux/uart1_rxd

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_rxd
 name: uart1_rxd.uart1_rxd (0x44e10980/0x980 = 0x0020), b NA, t NA
 signals: uart1_rxd | mmc1_sdwp | d_can1_tx | NA | NA | NA | NA | NA

 root@beaglebone:~# echo 0 > /sys/kernel/debug/omap_mux/uart1_txd

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_txd
 name: uart1_txd.uart1_txd (0x44e10984/0x984 = 0x0000), b NA, t NA
 signals: uart1_txd | mmc2_sdwp | d_can1_rx | NA | NA | NA | NA | NA

Having said all that, I’m actually going to use UART2 for this project.

UART2 is a little trickier, since its pins have other names in the file system. Looking at Table 11 of the Beaglebone System Reference Manual, we see that UART2_TXD is pin 21, and UART2_RXD is pin 22. Table 12 (below) tells us that pin 21’s Mode 0 usage (and therefore the name used in the file system) is spi0_d0, and that UART2_RXD is the Mode 1 usage. For Pin 22, it’s spi0_sclk, and we also want to change it to Mode 1.

Here are the commands for checking the current settings, and changing the settings to use UART2:

root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_d0
 name: spi0_d0.(null) (0x44e10954/0x954 = 0x0037), b NA, t NA
 signals: spi0_d0 | NA | NA | NA | NA | NA | NA | NA

 root@beaglebone:~# echo 1 > /sys/kernel/debug/omap_mux/spi0_d0

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_d0
 name: spi0_d0.(null) (0x44e10954/0x954 = 0x0001), b NA, t NA
 signals: spi0_d0 | NA | NA | NA | NA | NA | NA | NA

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_sclk
 name: spi0_sclk.(null) (0x44e10950/0x950 = 0x0037), b NA, t NA
 signals: spi0_sclk | NA | NA | NA | NA | NA | NA | NA

 root@beaglebone:~# echo 21 > /sys/kernel/debug/omap_mux/spi0_sclk

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_sclk
 name: spi0_sclk.(null) (0x44e10950/0x950 = 0x0021), b NA, t NA
 signals: spi0_sclk | NA | NA | NA | NA | NA | NA | NA

A Python Time and Temperature Display for the Beaglebone

I’ve written some Python code to try out the analog and serial pins of the Beaglebone. It gets the temperature from the MCP9700A, and uses the potentiometer to set the backlight of the LCD.

You can download the Python program from my Google Code project page: it’s just a single file,

From the Beaglebone command line, you can download the Python program as follows:

root@beaglebone:~# wget

I’ve tested the code with the Sparkfun Serial Enabled LCD Kit, the Sparkfun Serial Enabled Backpack. I’ve also coded support for Matrix Orbital serial LCDs, but haven’t tested that yet.

The code uses one Python library that isn’t included in the Angstrom demo image, python-pyserial. To install it:

root@beaglebone:~# opkg install python-pyserial

There is no configuration file or command line parameters yet, so any changes to the default settings (the Sparkfun Serial LCD Backpack and a 4-row 20-column LCD) should be made to the code near the top of the program:

# -------------- configurable settings ---------
# settings for UART1
 #DISPLAYPORT = '/dev/ttyO1'
 #RX_MUX = 'uart1_rxd'
 #TX_MUX = 'uart1_txd'
 #MUX_MODE = 0
# settings for UART2
 DISPLAYPORT = '/dev/ttyO2'
 RX_MUX = 'spi0_sclk'
 TX_MUX = 'spi0_d0'
# settings for Serial LCD
# settings for analog voltage conversion
 MAX_ANALOG = 3762 # approx 4096 * (1.65/1.8), since voltage divider gives me max of 1.65
 # -- actual values of 3762 based on measurements
# settings for display updates
 TIME_UPDATE_INTERVAL = 1 # every second
# determines whether debug info is written to the console
 Debug = True
# ---------------------------------------------------------

Then, just run the program as root:

root@beaglebone:~# python

To stop the program, press Ctrl-Z to put it in the background, then kill the background job:

root@beaglebone:~# kill %1

If you want to keep the program running all the time, I’d recommend using the GNU Screen utility:

root@beaglebone:~# screen
<Press enter when prompted>
root@beaglebone:~# python

To return to the main command command prompt (leaving the Python program running in the background) press Ctrl-A D.  To go back to the Screen session at any time in the future:

root@beaglebone:~# screen –r –d

For troubleshooting, any error messages are written to serdisplay.log in the same directory as

Programmer’s Show And Tell

Since the focus of this article is the Beaglebone, not Python, I’ll just point out some Beaglebone-specific parts of the code.

The code which initializes the UART for the serial display is:

DISPLAYPORT = '/dev/ttyO2'
 RX_MUX = 'spi0_sclk'
 TX_MUX = 'spi0_d0'
 BAUDRATE = 9600
 TIMEOUT = 3 # serial port timeout is 3 seconds - only used when reading from display
# MUX settings
. . .
open('/sys/kernel/debug/omap_mux/' + RX_MUX, 'wb').write("%X" % (RECEIVE_ENABLE + MUX_MODE))
 # set the TX pin for Mode 0
 open('/sys/kernel/debug/omap_mux/' + TX_MUX, 'wb').write("%X" % MUX_MODE)
 serDisplay = serial.Serial(DISPLAYPORT, BAUDRATE, timeout=TIMEOUT)

There are Linux character devices assigned to the BeagleBone UARTs: UART1 is /dev/ttyO1, UART2 is /dev/ttyO2, and so on.

From the point of view of the Python program, the Beaglebone’s UART behaves like any other serial port. The code I wrote would work unchanged (aside from the /dev name) when communicating with an XBee, or through a USB-based virtual COM port.

Analog input is a little more finicky. The code which reads the analog value is:

def readAnalog(pinIndex):
    # add 1 to pin index to get analog pin sys filename
    reading = open("/sys/devices/platform/tsc/ain" + str(pinIndex + 1), "r").read()

    # sometimes string has trailing nulls - delete them
    val = int(re.sub(r'[^\d]+', '', reading))
    return val
    log.exception('Error in readAnalog')

As indicated by the comments, I found that the value read through the file system was sometimes corrupted: it contained nulls, usually after the value, but occasionally imbedded within the value. I’m not sure if this is a Python-specific thing, or other code would also encounter the problem. In Python, you can strip out the null (and any other non-numeric) values using a regular expression:

val = int(re.sub(r'[^\d]+', '', reading))

From time to time, the attempt to read the analog value will throw an exception.  So, it’s best to use a try/except handler like the one above.

One other problem is that the analog value tends to jump around by about 5 points from one reading to the next, even when it should be constant (e.g. from the potentiometer). I adjusted for this by using an average reading for the temperature, and by ignoring potentiometer readings (i.e. LCD brightness settings) that are within 20 of the last setting.

Don’t forget that the analog value is from 0-4096 – 16 times more sensitive than on the Arduino —  so allow for a greater range of readings.

Wrapping Up

Based on my testing of the code in this project, I’ve found that the Beaglebone’s UARTs are quite reliable and pretty easy to use.  Serial communications should be a relatively easy and trouble-free addition to any Beaglebone project.

Analog in, on the other hand,  has room for improvement.

The approach I used for reading analog input in is good enough for things that don’t require precise accuracy, like the potentiometer or a light meter.  The readings returned by the MCP9700A thermistor are not as stable as they should be.

Fortunately, analog is not the only game in town when it comes to temperature readings, so I plan to experiment with some I2C sensors in the future.

This entry was posted in Electronics, Gadgets, Programming and tagged , , , , . Bookmark the permalink.

79 Responses to Beaglebone Coding 101: Using the Serial and Analog Pins

  1. Koen Kooi says:

    P9_32 (VDD_ADC) is 1.8V

    • dwatts says:

      Ah, good to know! That will save a lot of trouble when it comes time to do I2C level conversion. Thanks for the correction!

  2. Ricer1 says:

    Nice writeup. I want to use one of the UART ports for a 4800-baud serial interface… (using a voltage-level translator of course) but my coding abilities are near-zero. Using the UART for that would require writing a driver of some sort… true?

    • dwatts says:


      As far as I know, but you should be able to use the UART at 4800-baud without any problems, either from a command line terminal (I use minicom on the BB) or from a program. You shouldn’t require a custom driver – the built-in Linux driver should do the job.


  3. Duncan says:

    Thank you for writing these blog posts :) I hope to receive my initial equipment from Tigal next month, and since this is my first foray into the embedded/GPIO/muxing world, your posts are going straight into my bookmarks so I have something to refer to and build from (I’m a Linux sysadmin, so that part is easy).

  4. Yo says:

    Amazing description.!!!! Keep this tutorial series going….

  5. Xenland says:

    Thanks alot for this information been trying to brute force the Frak outta the beaglebone to give me an analog signal from python or C# — I’m in the middle of trying out your tutorial I’ll let you know how it goes thanks again!

  6. Congratulations, I’m new to the world “ARM LINUX”, after weeks of research, this article “taught me” (clarified) using the “MODE – PINMUX” in BeagleBone (and in line AM335x). The change PINMUX, on the fly, is a very useful feature, as we know. I just can not help you as you helped us. Again, congratulations on the excellent article. “Knowledge belongs to humanity,” you is a proof of this. Jose Garcia – Sao Paulo Brazil.

  7. Xenland says:

    Your tutorial worked flawlessly I actually wrote a tutorial that is in video demonstrating how to read an analog signal(Just to keep it simple i didn’t include serial,spi or i2c):

  8. Pingback: Beaglebone Linux 101: Configuring Angstrom Linux | GigaMegaBlog

  9. Del3D says:

    Great work! Well done… Just a small point, you state that:”The analog input pins on the Beaglebone are 10-bit, so the maximum possible value is 4096″. It’s not stated in the Beaglebone manual, but they must be 12-bit ADC as 2^12 is 4096. D.

  10. Kai says:

    running opkg install python-serial throws an error saying
    Unknown package ‘python-serial’.
    Do you know where the problem is?

    • dwatts says:

      Oops, the problem is that I typed in the package name incorrectly. It should be python-pyserial.

      I’ve corrected the article – thanks for letting me know.


      • I am still getting the same error with the command “opkg install python-pyserial” any thoughts on why?

        • dwatts says:

          Does the error message say “Unknown package ‘python-pyserial’? If so, then perhaps you need to run “opkg upgrade” first, if you haven’t already tried that.


          opkg upgrade
          opkg install python-pyserial

          If you still get “unknown package”, then perhaps your list of repositories is different from the ones on my Beaglebone? I’m using the latest Angstrom demo image (Angstrom-Cloud9-IDE-eglibc-ipk-v2012.01-core-beaglebone-2012.01.27.img.xz from I don’t remember if I installed python-pyserial on the original Angstrom image that came in the box. However, I’m pretty sure the images use the same repositories.


          • So I tried to opkg update and it didn’t work on the version that shipped with the A4 board. However, after updating to the latest image and running the update it worked.

            Thanks again Dan. Great write-up!



  11. Thanks for the article. This is clearer and more informative then some of the BeagleBone developer documentation. Little things like this are what build a great community. Keep it up, looking forward to more reading.



    • Xenland says:

      I agree any Beagle Bone documentation is almost cryptic… Granted they did say that the Beagle Bone would become a usable system by summer 2012 but I think they really meant was that hackers will get so anxious that they’ll do the work for them.

  12. Xenland says:

    Trying to figure out how to send UART commands to this LCD display I have but I can’t seem to find in your code on the actual sending part located in the python descriptions. What command in terminal or python needs to be executed to send one command through UART?

    • dwatts says:


      The code that sends the commands through the UART is writeToDisplay, which just calls pyserial’s write method:

      def writeToDisplay(s):
      time.sleep(0.1) # Sparkfun LCD backpack needs pause between commands

      The actual commands that are sent to the LCD are built in other functions, such as clearScreen:

      def clearScreen():
      cmd = array.array(‘B’, (COMMAND_PREFIX, 99))
      cmd = array.array(‘B’, (COMMAND_PREFIX, 1))

      I ended up using the byte-array-tostring approach after some trial-and-error. Usually, a simple UTF8 string (which is the default string format in Python 2.x) can be passed to the pyserial write method, but it choked on the 0xFE command prefix for reasons that I couldn’t figure out.



  13. Kelvin says:

    Great Post!
    Even though I don’t have the beaglebone I still find this post useful since it can be applied to the pandaboard. The problem that I have now is figure out how to control the mux to enable pullup during input mode. What I don’t understand is that my pullup is enable for output mode but not for input mode. Does it require a separate control?

    • dwatts says:

      Sorry, all I know about the Pandaboard’s multiplexing register is that the bit layout is quite different from the Beaglebone’s but similar to the Beagleboard’s.

      Your best bet is to check the OMAP4430 Technical Reference Manual – the pin mux register layout should be documented in there (probably labelled “multiplexing register”).

      If the OMAP4 has the same register layout as the OMAP3, then the information at the start of this page should help:

  14. Bora says:

    Thanks for Beaglebone writings,
    You mentioned above about program running all the time, I have a question about this.
    I want to run a program automatically after powering. There is no need an Ethernet or USB cable in my work, at least at the beginning.
    Do you know how it can be done ?

    • dwatts says:

      The Angstrom image uses systemctl to configure programs which should run at bootup.

      The configuration files for systemctl are in /lib/system/systemd. If your program doesn’t have many dependencies, then you can probably figure out what you need to do by looking at these files.

      For example, the bone101 service, which runs a node.js program, is configured in bone101.service. By changing the paths, you can probably use the same settings for your program:

      Description=Beaglebone 101 presentation

      ExecStart=/usr/bin/node bone101.js


      After you’ve created a configuration file for your service, e.g. /lib/systemd/system/myprogram.service, you can configure it to start at bootup with the following command:

      systemctl enable myprogram.service

  15. Pingback: MAKE | How-To: Get Started with the BeagleBone

  16. Pingback: How-To: Get Started with the BeagleBone | HEY LAURENT VOANH IS HERE

  17. Pingback: How-To: Get Started with the BeagleBone | TransAlchemy

  18. Pingback: How-To: Get Started with the BeagleBone | Knitting 4 Cash

  19. Pingback: How-To: Get Started with the BeagleBone | House of Mods

  20. Pingback: High Technology » Blog Archive » How-To: Get Started with the BeagleBone

  21. Pingback: BeagleBone | Mambohead

  22. Pingback: How-To: Get Started with the BeagleBone

  23. Pingback: XBee BeagleBone Communication |

  24. SWR_DMaster says:

    I have been looking into getting a BeagleBone and making a couple of capes and have given thought to the analog ranges. Since a 1.8V source is supplied I was thinking of using a voltage follower (via an op amp) to bring the 5 volt supply down to 1.8v. This gives us quite a bit of current capacity and keeps us from popping the 1.8V source. After we have a high current 1.8V source I would have an op amp setup as a scaling circuit. Was thinking of having two I2C pots in the op amp scaling circuit so as to let software adjust the zero and span but have the 1.8V as the supply for the op amp. This will make it near impossible to supply any voltage over 1.8V and give us control over what parts of the signal we are most interested in. A dual op amp IC with a dual i2c pot IC would be the extent of parts needed for a single channel. Or, if you wanted to do all 6 channels, you could use 2 quad op amps, and 6 dual i2c pots.


  25. Pingback: Beaglebone Coding 101: Buttons and PWM | GigaMegaBlog

  26. Thibaut says:

    Thank’s a lot for this tutorial, it helped me a lot understanding the Pin mux. However, I’m stuck with some unlogical things.. As I planned to use UART5, I realised that it was writen in the Beaglebone’s documentation that RXD and TXD were situated on mode4 from P8′s 36th and 37th Pins. The associated file in Angstrom is /sys/kernel/debug/omap_mux/lcd_data8 as it is mode0′s configuration.

    # cat ./lcd_data8
    name: lcd_data8.gpio2_14 (0x44e108c0/0x8c0 = 0x002f), b NA, t NA
    signals: lcd_data8 | gpmc_a12 | NA | mcasp0_aclkx | NA | NA | uart2_ctsn | gpio2_14

    The problem is that when I look into thin file, it is not written UART5_TXD or RXD but NA instead.

    Do you think the file is not up to date and the beaglebone still has UART5 linked, or do you think that the documentation isn’t up to date ?

    • dwatts says:


      It’s the “signals” line that is incorrect: Mode 4 for that pin shouldn’t say “NA”. The “NA” appears incorrectly for a lot of different pins, so I tend to ignore the “signals” lie. The Beaglebone System Reference Manual is the most reliable guide to the mux mode settings.

      So, UART5 Tx in Pin 37 and Rx is Pin 38.

      I haven’t tried using UART5 myself, but it should be accessible through /dev/ttyO5. I noticed that the System Reference Manual says that RTS and CTS aren’t available for UART5, so I guess that there is something unusual about that port.


      • Thibaut says:

        I just got my Uart0 working the way I wanted, and I tried to figure out what was wrong with Uart5.. And in fact it does not work.. just like Uart4 which I tried to use, it also isn’t noticed in the file signals (just like UART5 ) and it also doesn’t work… I get an error on “fs.bindings” while using node.js to connect my serial.

        I’ll have some more investigation on that tomorrow as I’m away from the beaglebone right now…

        • Thibaut says:

          Here you go, I used the same js file as with Uart0 that I got working, the only thing I changed was the pin setting of course, and /dev/ttyOX in my file..
          Here is the configuration:

          P9_11 RX
          P9_13 TX

          echo 26 > /sys/kernel/debug/omap_mux/gpmc_wait0
          echo 6 > /sys/kernel/debug/omap_mux/gpmc_wpn

          Here is the error I got :

          node ./Uart4.js

          binding.write(fd, buffer, offset, length, position, wrapper);
          TypeError: Bad argument
          at Object.write (fs.js:298:11)
          at /var/lib/cloud9/Uart4.js:38:7

  27. MikeP says:

    Hi Dan,
    Thanks for the great tutorials, just got my BeagleBone A5 with the latest Angstrom image from 02/14/2012.
    I am getting “Unknown Package” when trying to install python-pyserial.

    Command: opkg install python-pyserial

    The installed Python version seems to be 2.7.2.
    I searched here and pyserial seems to exist (as version 2.4):

    Any suggestions how to get pyserial installed?


    • dwatts says:


      Others have had this problem too, but I haven’t seen it myself. I just checked to make sure the package python-pyserial hasn’t become unavailable, but no, it’s still there.

      The only cause of this problem that I know about is when something goes wrong with the “opkg update” command. It’s not unusual for this to fail to get a copy of a repository, causing subsequent “opkg install” commands to fail.

      So, if you haven’t already, try running “opkg update” again, and check the output to ensure there are no error messages in there. If there are, just retry “opkg update”: running it a second time almost always works. If it continues to fail, there is probably a problem with the repository, so try again the next day.

      Another possibility is that something is wrong with the opkg configuration on your Beaglebone, though this should be very unusual. opkg looks in the following file for its python packages: /var/lib/opkg/lists/python. So, if you grep this file for “pyserial”, and the package is listed in the output, then the problem is likely something in the opkg configuration. If that’s the case, I’d suggest you post the problem on the Beagleboard Google Groups to see if anyone has a suggestion.

      Here’s what the output of grep should be:

      root@beaglebone:~# cat /var/lib/opkg/lists/python | grep “pyserial”
      Package: python-pyserial-dbg
      Recommends: python-stringold-dbg, python-pyserial-dbg, python-io-dbg, python-pyserial (= 2.4-ml3), python-fcntl-dbg
      Filename: python-pyserial-dbg_2.4-ml3_armv7a.ipk
      Description: python-pyserial version 2.4-ml3 – Debugging files
      OE: python-pyserial
      Package: python-pyserial-dev
      Depends: python-pyserial (= 2.4-ml3)
      Recommends: python-stringold-dev, python-fcntl-dev, python-pyserial-dev, python-io-dev, python-dev
      Filename: python-pyserial-dev_2.4-ml3_armv7a.ipk
      Description: python-pyserial version 2.4-ml3 – Development files
      OE: python-pyserial
      Package: python-pyserial
      Filename: python-pyserial_2.4-ml3_armv7a.ipk
      Description: python-pyserial version 2.4-ml3
      OE: python-pyserial


  28. Bent Hansen says:

    Any1 tryed using the ttyO5 ? How is that setup as a com-port ?
    I got like 5 sensors – 1 on every port. But can’t get any data on ttyO5..
    Do I need to re-compile my kernel ? or is there a setting somewhere ?
    Im Running Ubuntu Omap 11.10 from

  29. Jeshwanth Kumar N K says:

    Hi, nice article :) thank you so much :) ..

  30. Jeshwanth Kumar N K says:

    When I connect my pot to the pin ain1 the board powered OFF,

    POT + p9_32
    Wiper ain1
    POT – GND

    What was the problem ?

    Thank you

    • Jeshwanth Kumar N K says:

      And I am using 5k POT.

      • Jeshwanth Kumar N K says:

        Actually I have connected to Normal GND pin not GNDA_ADC is that the problem ?

        • dwatts says:

          I actually didn’t even notice that there was a GNDA_ADC until now.

          I’m not sure, but my guess is that it’s the same as the other GND pins. If you have a multimeter, I’d suggest you measure the current between VDD_ADC (port 9 Pin 32) and GNDA_ADC, then measure the current between VDD_ADC and a regular GND pin (e.g. Pin 1) to see if it makes any difference.

    • dwatts says:


      The problem might be that the current becomes too high for AIN1 when the pot resistance is turned down low.

      Try adding a 1K resistor between port 9 pin 32 and the potentiometer.


  31. Pingback: Descriptive Camera: An Instant Camera that Prints Text Instead of PhotosBusiness & Financial News, Breaking US & International News | News24h.infoNews, Travel, Weather, Entertainment, Sports, Technology, Business & Financial News, Breaking US

  32. Mike Kelly says:

    Please note that “/sys/kernel/debug/” filesystem is not mounted by default on some ARM distributions including ARCH ARM. In order to see any content under /sys/kernel/debug/ run “mount -t debugfs none /sys/kernel/debug” or better still, add the following line to /etc/fstab “debugfs /sys/kernel/debug debugfs 0 0″


  33. ak says:

    There are only 5 effective UARTs, UART3 is not broken out to the headers and doesn’t appear to be accesible in any method. Maybe point to point solder on the bone itself?

  34. Cris says:

    Any chance I could use my lcd 4 x 20 device (no serial interface) in a similar manner to display analog output with the BB? Thanks for the great work!!


  35. Mandar says:

    Awesome info…Keep it up..
    I already enabled UART1 and UART2 and they are working fine but i need more serial ports and i also want hardware flow control enabled, that means with reference to previous comments i can use UART4 or UART5… but again problems in UART5 RTS & CTS uses so only option left is UART4… Can anyone tell me how to enable UART4 pins?

    • Mandar says:

      To be more specific i just want hardware flow control enabled for my sensor…
      is there anyone who had done the pin mux setting for RTS,CTS of UART4? or can we use other uart for this?

  36. Mike Kelly says:

    I notice that the specs for the MCP9700A say the output is 1.75v at max temp. Is the voltage divider really necessary?


  37. Pingback: Beaglebone Startup Items |

  38. Thanks for your blog post.
    This helped a lot getting a Java program to use RXTX properly.

    I’ve posted a blog post related to Serial I/O too, giving all settings for all UARTs in a more readable way (no need to lookup the various tables anymore):

    Thanks again.

  39. Mike says:

    i think u made a mistake, that in your artikel this a ‘The 2 UART pins currently have a mux setting of 0×37, or 0011 0111.’

    The 6 bit is 0, why did u wirte “The slow slew rate is selected”, is was fast slew. Am i right????

    • dwatts says:

      Yes, you’re right – it is set to fast slew. I’ve corrected the article. Thanks for pointing it out.


      • Mike says:

        Hallo Dan,
        i just do not understanad the different betw. the fast and low rate. now i am controlling a digital Temp sensor DS18B20 with C code, and connect to Port8_15 , but i dont now which mode of GPIO i need to use, now the value regiser of this PIN is 0×0027, means it works in fast rate and Pull down selected. Have you tryed use this Sensor to mess the Temperature?


        • dwatts says:


          I haven’t tried it, but here is a blog post showing how it’s done:

          It uses a w1 (i.e. One Wire) driver, which is included in the Angstrom image. You shouldn’t have to do any pinmux settings – the driver will detect the DS18B20 when it is connected. (In the blog post, he’s connected the middle pin to P8_3 – I don’t know if it would also work using P8_15).


  40. Matt Rich says:


    Great Article, just got a beaglebone and want to use it for a few projects. This article was super helpful getting the UARTs working. I’m looking forward to reading your other BeagleBone articles. Thanks for posting!

  41. Student says:

    I am considerig the option of interfacing the beaglebone with Xbee. Can you provide some links or any other helpful material in that regard?

    • dwatts says:


      The Beaglebone and XBee get along quite well, since they both use 3.3V. You can connect the XBee directly to the Beaglebone, though the XBee’s pins are so thin and closely spaced that you might want to use a breakout board.

      Here is a good article giving all the details on how to connect the XBee:

      In terms of software, the simplest approach is to just use the XBee as a serial port. I used that approach with some Python code in this article:

      The code I’m running currently on a Beaglebone uses the Python XBee library ( This has the advantage of allowing the code to identify which device sent a packet, and also allows the code to direct a packet to a specific device. I haven’t written about that code yet, but the basics are:

      Connecting to the XBee:

      serXBee = serial.Serial(XBEEPORT, BAUDRATE, timeout=TIMEOUT)
      xbee = XBee(serXBee, callback=readXBeeData)

      Sending a packet:

      xbee.send(“tx”, dest_addr = ‘\x00\x01′, data=dataString)

      Reading a packet:

      def readXBeeData(frame):
      frame_id = frame['id']
      # source address is 2-bytes binary (e.g. x00x01)
      source_addr = ord(frame['source_addr'][0]) * 256 + ord(frame['source_addr'][1])
      # rssi (signal strength) is 1-byte binary
      rssi = ord(frame['rssi'])
      data = frame['rf_data']


  42. Cyril says:

    Hello Dan,

    Another awesome how-to. I just ordered my beaglebone, itching to try these out.
    Using a Serial LCD is part of my project that I will be working on. And a 4×4 keypad (serial/I2C). this will def. help me.



  43. Pingback: Sonar sensor on the BeagleBone part 1, direct approach | Flesh and machines

  44. Sundy says:

    I come into the direction ,but in the “tsc” direction ,thereis no ain0 or ain1……
    Could you give me some advice?
    Thank you.
    My e-mail address is

    • dwatts says:


      In some Linux versions the analog driver isn’t automatically loaded. To load it manually, try the following command:

      modprobe ti_tscadc

      You should then see ain0 and ain1 in /sys/devices/platform/omap/tsc

      If that doesn’t work, can you tell me which kernel version and Linux distro (e.g. Angstrom, Ubuntu) you are using?


  45. Pingback: BeagleBone and RFID | Mark's Blog

  46. Sameer says:

    Thanks for the great article. I have followed the instructions here, connected up all my pins, and I ran screen /dev/ttyO1 57600 connected to a 57600 baud device. However I got nothing. I connected an oscilloscope to the pins to verify that Rx was receiving data. I also tried to send some data out and I didn’t see anything on Tx. I am not getting junk characters or anything, just nothingness.
    I also tried UART2, but the same result.

    Do you have any suggestions on how to debug this?


    • dwatts says:


      I’ve seen others mention having problems with serial I/O using screen. I’d suggest using minicom to see if that gives better results — minicom has always worked fine on the Beagleboard for me under both Angstrom and Ubuntu.



  47. dwatts says:


    The port wouldn’t be ‘/sys/kernel/debug/omap_mux/uart1_rxd’, it would be ‘/dev/ttyO1′:

    ser = serial.Serial(

    The /sys/kernel/debug/omap_mux/uart1_rxd file is used only to set the mux settings. You can do it in code:

    open(‘/sys/kernel/debug/omap_mux/uart1_rxd’, ‘wb’).write(“%X” % 32))

    … or just from the command line before running your code:

    echo 20 > /sys/kernel/debug/omap_mux/uart1_rxd

    If it still isn’t reading the data, you might want to try running a serial terminal on the Beaglebone to rule out any Python issues. I use minicom for this (installed using “opkg install minicom”). Be sure to set the COM settings to the values you want — if you launch it with “minicom -s”, it will display a menu for this.


Leave a Reply

Your email address will not be published.

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>