Cosm Gadget: Kissing the Pink Goodbye

One of the data logging services I use, Pachube, was rechristened as Cosm many months ago: a name that’s decidedly easier to pronounce, if only slightly easier to comprehend.  The new name and website design was making my Pachube Google Gadget look increasingly out of date, so I felt it’s well past time to redesign the gadget.

In addition to incorporating the new Cosm name and API, I’ve added a number of enhancements:

  1. Multiple datastreams per graph.
  2. Display datastreams with 2 different scales: left-axis and right-axis (e.g. temperature and humidity in the same graph)
  3. Mouse-over popups displaying the exact time and value of a datapoint
  4. Last, but not least, graph colors other than hot pink!

The new gadget can be installed from the Google Gadget Directory.  The old Pachube gadget will remain available, should you prefer it.

Settings Dialog

The gadget’s Settings dialog is shown below.

As a quickstart, you can just fill in the Feed ID field — everything else will work with default settings.

By default, the gadget will display 2 datastreams per chart, one plotted on the left axis and one on the right, for up to 3 charts. The default time frame is 1 day.

The default configuration is unlikely to be optimal for you — at a minimum, you’ll probably want to change to your local timezone and increase the gadget size to display all of the charts.

Here’s the full list of settings:

Feed ID – The numeric ID of a Cosm feed.  The feed needs to be public, even if it’s your own feed, since the API key used by the Gadget can only access public feeds.

Incidentally, Cosm’s current layout makes the feed ID a little hard to find.  It’s the last part of the feed’s URL, as shown in the screenshot below.

Chart 1 Datastreams – You can add as many datastreams as you like to each chart.  Datastreams entered in this particular field will be plotted using the left axis of the 1st chart.

Just type in the datastream ID, then click the Add button.  Each datastream you add will be listed under the field, as shown below.  You can click on the X button to remove the datastream from the chart.

Chart 1 Right Axis – Datastreams entered here will be plotted using the right axis of the 1st chart.  This field, and the other “right axis” fields are optional – if left blank, all datastreams in the chart will be plotted on the left axis only, freeing up a bit more space for the chart contents.

Adding a datastream to the right axis makes sense only if it is a completely different kind of measurement from the datastreams on the left axis (e.g. humidity on the right axis and temperature on the left axis), or if some datastreams have a significantly different range of values than others (e.g. Apple stock price vs. Microsoft stock price).

The screenshots below show the difference between plotting all of the data on the left axis, as opposed to making use of the right axis.

Personally, I prefer plotting different types of data in completely different charts.   If you need more than 3 charts, you can use multiple instances of the gadget.

Chart 2 and Chart 3 fields – The same as the above 2 fields, but for the second and third charts.  These are optional: you can have just 1 or 2 charts if you like.

Time Span and Time Span Units – The time range to be displayed in the charts.  Units are hours, days, weeks and months, and the Time Span can be any numeric value (e.g. 12 hours, or 10 days, or 3 months).

Note that Cosm currently “throttles” the API which retrieve datapoints to 100 values at a time: as a result, the datapoints will be evenly spaced over time so that only a maximum of 100 are used in the graph.  The longer the time interval, the more widely spaced the datapoints will be.

Gadget Height – The default height of 240 fits only a single chart: you have to scroll to see the others.  You can change this setting to make multiple charts visible.  Note that the height of each chart itself is fixed in the normal gadget view, but you can get a larger chart by maximizing the gadget.

Time zone – Cosm provides a large and somewhat eclectic list of time zones to select from: this affects the times that appear on the X axis of the chart.

Other features

Mouse-over Tooltip – Positioning the mouse over any part of a graph will display a tooltip displaying the time and value of the datapoint.  The time uses the time zone selected in the Settings dialog

Maximized View – Any gadget in iGoogle can be maximized using the dropdown menu.  This displays a much more conveniently sized version of the charts.

Browser Compatibility

The gadget works (for me) in Chrome, Firefox and Internet Explorer.  Being based on Google technology, it renders the graphs fastest in Chrome.  Firefox is almost as fast, and the appearance of the chart is pretty much identical to Chrome.

Troubleshooting

Error Codes: Cosm returns an error code when it is unable to return the data point values.  The most common error codes are:

  • 404 – The feed ID doesn’t exist, or isn’t public.  The gadget doesn’t support private feeds, even your own.
  • 405 – This is an intermittent error that occurs when Cosm isn’t able to retrieve your datapoints fast enough: basically a timeout.  I don’t think longer timespans will cause this error (i.e. a month of results takes about as long to retrieve as a day of results), but a large # of datastreams in a gadget will make this error more likely.  If you find it happens too often, try splitting the datastreams between multiple instances of the gadget: you can add as many copies of the gadget as you like to iGoogle.

Data Not Updating – The gadget will automatically refresh from time to time — using some inscrutable timetable controlled by Google — but you can manually refresh it using the browser refresh button.  However, Google automatically caches the data returned by the gadget, and the cache time for this gadget is set for 5 minutes.  This means that refreshing the browser more frequently than 5 minutes probably won’t display new results.

Wrapping Up

I wasn’t certain that Cosm would be fast enough to handle this new design of the gadget, where it needs to return 100s of individual datapoints rather than a prerendered graph, but I’m satisfied with the performance.  It’s proven to be similar in response time to the Nimbits gadget: slightly slower than the prerendered graph, but generally just a few seconds to display a chart.

Hopefully both Cosm and Nimbits will continue to thrive — I’ll certainly continue to use both.

The future of Google Gadgets is, on the other hand, rather murky.  Google hasn’t relented on its planned November 1 2013 shutdown of iGoogle, where the vast majority of users run their gadgets.  There doesn’t appear to be any plan to phase out the Gadget API, but there’s no clear option for hosting Google Gadgets after November 1.

I expect Google will step up with a solution, perhaps as part of their slick Google Now interface, but their indifference to users concerns thus far is evil disappointing.

If you have any suggestions or notice any bugs in my Cosm or Nimbits gadget, please leave a comment below or send me an e-mail.

Posted in Electronics, Software Tools | Tagged , , | 1 Comment

Beaglebone Coding 101: I2C

Updated 12/20/12 – Corrected instructions for installing python smbus on Angstrom.
Updated 1/6/13 – Another correction to the instructions for installing python smbus on Angstrom 

In previous articles in the Beaglebone 101 series, I covered digital GPIOanalog and serial pins, PWM and SPI.

One important coding interface remains: I2C.  I’ll cover it today, including I2C input and output, and level conversion, culminating in the Weatherbone, a basic LCD-based thermometer.

I2C Overview

I2C’s main advantage is simplicity.  It requires just 4 connections, 2 fewer than SPI: voltage, ground, clock and data.

The clock pin works pretty much the same way as with SPI: it is driven by the Beaglebone to control the timing of the data transfer, and works fine at 3.3V even when interfacing to a 5V device.  As with SPI, one option for controlling the state of the I2 clock pin is “bit banging”: using a plain old GPIO pin as the clock.  However, since the Beaglebone supports much higher and more reliable clock speeds through specialized hardware, we’ll make use of that.

Unlike SPI, I2C uses just 1 data pin, which transfers data in both directions.  This is great for simplicity and cost, not so great for speed.  As a result, I2C devices is most appropriate for devices that don’t send a lot of data, like sensors.

The fact that data travels in both directions on the same pin is an important consideration when interfacing with a 5V device: you must always use a level shifter on the data pin.  This is necessary even if using an output device like an LCD — there is no such thing as a “write only” connection when dealing with I2C.  I’ll give an example of level shifting in the I2C LCD circuit.

Like SPI, I2C supports multiple devices on the same I2C bus.  While SPI uses a latch pin to select the device, I2C handles the addressing with software.  This, again, makes wiring the circuit easier.

I2C and the Beaglebone

Most Beaglebone distros allow access to 2 I2C buses: /dev/i2c-1 and /dev/i2c-3.  For reasons that I don’t fully understand, /dev/i2c-1 doesn’t play nice with user applications, so we’ll stick with /dev/i2c-3.

The 2 pins used to interface with I2C bus 3 are pins 19 (clock) and 20 (data) on port 9.  Both pins default to I2C mode in Ubuntu and Angstrom, so no pinmuxing is required.

You may have seen references to the importance of pull-up resistors when using I2C.  You can ignore this when using the Beaglebone, since pull-up resistors are enabled by default on pins 19 and 20 in both Ubuntu and Angstrom.

When accessing SPI devices from Python, I used a C language extension (spimodule.c) as a go-between.  With I2C this isn’t necessary, since a Python-friendly interface exists: SMBus.   Technically, SMBus and I2C aren’t the same thing, but they both support the high-level read and write actions used by most applications.

Installing SMBus on Ubuntu is easy:

sudo apt-get install python-smbus

Updated 12/20/12 – I finally had a chance to try installing smbus on Angstrom.  It wasn’t as straightforward as the original text of this article suggested: here are the gory details..

Installing SMBus on Angstrom is somewhat more difficult.   There is no Angstrom package for python-smbus, so you’ll need to download it from source:

1/6/13: Added some corrections to the following instructions, as provided by the Hipstercircuit blog.  See Hipster’s instructions on getting an I2C PWM controller to work on Beaglebone Angstrom,  a good way of extending the Bone’s relatively limited PWM capabilities.

opkg install kernel-headers python-distutils
wget http://dl.lm-sensors.org/i2c-tools/releases/i2c-tools-3.1.0.tar.bz2
tar -xjf i2c-tools-3.1.0.tar.bz2
cd i2c-tools-3.1.0/py-smbus

Edit setup.py to add a new “include_dirs” line, as  highlighted in bold below:

...

 url="http://lm-sensors.org/",
 include_dirs=["../include", "/usr/include"],
 ext_modules=[Extension("smbus", ["smbusmodule.c"])])

Without that change, python setuptools won’t be able to find the “limits.h” file.

Run the standard python build command:

python setup.py install

You’ll get a new error “this linker was not configured to use sysroots”.  I don’t know how to properly fix this error, but a workaround is to run the same command without the sysroots parameter. The error message will include the full command, so just copy it to the clipboard and remove the part that begins with “–sysroot”.  On my PC, the resulting command was:

arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize
 -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8
 -D__SOFTFP__  -shared -Wl,-O1 -Wl,--hash-style=gnu 
-Wl,--as-needed 
-I../include build/temp.linux-armv7l-2.7/smbusmodule.o 
-L/usr/lib -lpython2.7 -o build/lib.linux-armv7l-2.7/smbus.so

Lastly, run the python build command again to finish the process:

python setup.py install

The MCP23008 Port Expander

The MCP23008 is the I2C equivalent of the 74HC595 chip that I covered in my SPI article.  As mentioned then, port expanders aren’t terribly useful with the GPIO-rich Beaglebone, but when combined with buttons and LEDs the MCP23008 provides a quick and easy way of testing I2C circuits and code.

Compared to the Beaglebone’s GPIO pins, the MCP23008 does offer a few advantages:

1. It can interface directly with 5V devices.  Note that this requires powering the MCP23008 with 5V, so you still need to use a level shifter to connect the MCP23008′s data pin to the Beaglebone’s data pin.  But converting one pin is, of course, a lot easier than converting each GPIO pin separately.

2. It can source and sink a higher amount of current than the Beaglebone: 20 ma, compared to just 6 ma source and 8 ma sink for the Beaglebone.

3. It has registers to support interrupts.  This means that code doesn’t have to rely on polling to detect input — sort of.  I’ll show an example of that below.

To demonstrate the input and output interface to the MCP23008, I’ll use the circuit shown below:

On the Beaglebone, pin 19 on Port 9 is I2C Clock, and pin 20 is data.  Since I’m powering the MCP23008 at 3.3V, these can be directly connected to the chip’s pins 1 and 2.

The 3 address pins of the MCP23008 are all connected to ground.  These pins determine the address that is specified in our code to select the MCP23008, and are important when using multiple MCP23008s: since there is no latch pin, the address determines which chip gets the data.  With all 3 address pins connected to ground, we’ll use the MCP23008′s base address of 0×20.

Pins 10 (GP0) and 16 (GP6) are used as input pins, connected to a pushbutton that is connected to ground.  The MCP23008 has an optional pullup resistor, which we’ll enable on this pins.  So, the pin is normally high, but when the button is pressed it will change to low.

Pins 11 (GP1) and 17 (GP7) are connected to LEDs through resistors (anything in the range of 330 to 680 is fine).

The idea is that the buttons will toggle the state of the LEDs.  Yes, that does sound suspiciously like the same thing that we were doing back in the first Beaglebone Coding 101 article, but 2 LEDs makes it twice as exciting!

Before running the code, it’s a good idea to run the i2cdetect command to make sure that your MCP23008 is correctly connected.  This is part of the i2c-tools package, which is preinstalled in Beaglebone Ubuntu.  (If it’s not in your copy, run “sudo apt-get install i2c-tools.)

The MCP23008 should be detected at address x20, as shown below:

ubuntu@omap:~ sudo i2cdetect -r -y 3
 0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

The Python code for this article can be downloaded from my Google Code page by running the following commands on your Beaglebone:

wget http://gigamega-micro.googlecode.com/files/WeatherBone.tgz
tar -xzvf WeatherBone.tgz
cd WeatherBone

The code for this circuit makes use of 2 Python classes:

  • Adafruit_I2C  - This is part of Adafruit’s Python library for the Raspberry Pi.  The code was almost 100% compatible with the Beaglebone: I only had to modify the bus number passed to SMBus (0 for the Pi, 3 for the Beaglebone)
  • gm_mcp23008.py – This is a wrapper I wrote for the MCP23008.

gm-mcp23008.py has a short bit of test code at the bottom, which is executed if you run it directly from python.

sudo python gm-mcp23008.py

You should find that the buttons faithfully toggle the LEDs’ state, with a slight pause.

The code begins with


mcp = mcp23008(3, 0x20, True)

The 3 parms being passed are the I2C bus number (3), the MCP23008 address (0×20), and a Debug flag that results in a message being written to the console each time I2C data is sent or received.

The code then initializes the 4 pins a la Arduino:


# button 1 connected to ground on pin 0 of MCP23008
mcp.pinMode(0, mcp.INPUT, True, mcp.INTERRUPT_PREVVAL, mcp.EDGE_LOW)
# LED 1 on pin 1
mcp.pinMode(1, mcp.OUTPUT)
# button 2 connected to ground on pin 6 of MCP23008
mcp.pinMode(6, mcp.INPUT, True, mcp.INTERRUPT_PREVVAL, mcp.EDGE_LOW)
# LED 2 on pin 7
mcp.pinMode(7, mcp.OUTPUT)

The INTERRUPT_PREVVAL and EDGE_LOW parameters require some explanation.

The MCP23008 supports interrupts, internally using some registers, and externally through pin 8 (which I’m not using).  The registers can be used to detect a case where the user pressed and released the button when the Python code wasn’t checking the pin.

The INTERRUPT_PREVVAL setting will trigger an interrupt when the pin state changes, and the EDGE_LOW parm will limit that to when it changes from high to low (remember, the pin goes from high to low when the button is pressed).

A good resource for learning more about the MCP23008′s registers is this article on embedded-lab.com.

The main part of the Python code loops indefinitely, checking the state of the buttons once per second — a leisurely rate that I’m using to test the interrupts:

# toggle LED when button is pressed
while 1 == 1:
   # NOTE!! - must get interrupts before reading pins, since reading pins clears the interrupts
   interrupt1 = mcp.wasInterrupt(0)
   interrupt2 = mcp.wasInterrupt(6)
   if interrupt1 or mcp.digitalRead(0) == mcp.LOW:
      led1State = not led1State
      mcp.digitalWrite(1, led1State)

   if interrupt2 or mcp.digitalRead(6) == mcp.LOW:
      led2State = not led2State
      mcp.digitalWrite(7, led2State)

   time.sleep(1)

As indicated by the comment, reading a pin’s state clears any interrupt for it. So, it’s necessary to call the wasInterrupt() method for both pins first.  This method returns True if the button was pressed since the last time the code checked (i.e. since the last call to digitalRead).

Writing to an LCD using the Adafruit I2C Backpack

As in my SPI article, I’ll leverage the GPIO extender code to write to a standard character LCD, using the Adafruit I2C/SPI LCD Backpack.

The backpack runs on 5V, and that voltage kills Beaglebones.  This wasn’t a concern when using SPI.  SPI uses a separate pin for input and output, so we were able to drive the output pin at 3.3V and leave the input pin disconnected.

With I2C, we need to use a level converter between the backpack and the Beaglebone’s I2C pins.  I used a $2 converter from Sparkfun.  I used the same Sparkfun board as a voltage divider in my article about analog input: the TX pins are level converters, while the RX pins are voltage dividers.  In this case, we want to use the TX pins.

I also made a small modification to the backpack to enable setting the backlight brightness via PWM.

The backpack normally feeds 5V into pin 15 of the LCD (the second from the end), resulting in maximum brightness.  As shown in the photo below, I’ve left pin 15 unsoldered in the backpack, connecting it instead to a NPN transistor.  One of the Beaglebone’s PWM pins is  connected to the base of the transistor.   A potentiometer attached to an analog pin is used to control the duty cycle setting of the PWM pin.

The PWM pin outputs 3.3V, which results in a noticeably dimmer LCD backlight, even though the transistor’s collector pin is connected to 5V.  So, I made use of the level converter to shift the PWM signal from 3.3V to 5V.

If all that seems way too complicated, you could actually avoid the need for level conversion by using the transistor with the LCD’s pin 16 instead of 15, connecting it to ground instead of 5V.  The only downside to that approach is you lose the API support for turning the backlight off and on, but the potentiometer can be used for this instead.

The circuit is shown below.  (The BMP085 part is explained in the next section.)

The Beaglebone pins are all on Port 9.  Along with ground, 3.3V and 5V, the pins are:

  • Pin 14 – PWM – white wire
  • Pin 19 – I2C Clock – brown wire (with no level conversion required)
  • Pin 20 – I2C Data – yellow wire (with level conversion)
  • Pin 32 – Analog 1.8V – orange wire
  • Pin 41 – Analog In – green wire

The Adafruit I2C backpack is (kind of) shown in the upper right of the diagram.  The wires leading to it are connected to:

  • Data – yellow wire1
  • Clock – brown wire
  • 5V – red wire
  • Ground – blue wire
  • Pin 15 of the LCD – Orange wire

I wrote a Python class, i2clcd to provide Arduino-like methods for writing to the LCD through the I2C port.  It’s included in the download file.

As a quick test, you can just run the Python class directly, which should turn on the backlight and write some text to the LCD:

sudo python i2clcd.py

The i2clcd class supports many of the same methods as the Arduino LiquidCrystal library.  So, to write text to all 4 lines of a 4×20 LCD:


# the LCD is connected to I2C bus 3

l = i2clcd(3)

l.begin(20, 4)
l.noBlink()
l.noCursor()
l.setBacklight(True)

l.clear()

for row in range(4):
   l.setCursor(0, row)
   l.Print("This is row " + str(row + 1))

Connecting Multiple I2C Devices

It’s quite easy to connect multiple devices to the same bus: just connect their clock pins and their data pins.  This is a lot simpler than controlling multiple SPI devices, which require a separate latch pin for each device.

I added a BMP085 to the circuit to demonstrate this.  It is powered by 3.3V, but coexists fine with the 5V LCD backpack provided that its data pin is connected to the 3.3V side of the level converter.

The code to read the BMP085 is taken from Adafruit’s Raspberry Pi Python library – it works on the Beaglebone without any changes at all.

To give all of the hardware something to do, I wrote a Python program, WeatherBone.py, to read the temperature and barometric pressure from the BMP085, and display that along with the sunrise and sunset time to the LCD.

Wrapping Up

The interfaces that I’ve covered in the Beaglebone Coding 101 series can be used to connect your Beaglebone to almost any type of device in the microcontroller world.

I have to admit that I’m not sure how big a gap the “almost” part leaves, since I tend to go down the path of least resistance.  If a particular sensor seems to be a little beyond the Beaglebone’s grasp (or beyond my grasp as a coder, anyway), I’ll switch to an equivalent sensor that uses a standard interface, or which others have already written code for.

The good news is that the paths of least resistance in embedded Linux coding are increasingly well marked, thanks to the Raspberry Pi.   It’s great to see so many new articles and sample code coming out of the Pi community.  The Pi’s code is generally easy to port to the Beaglebone, and the increased interest in embedded Linux is boosting both platforms.

Posted in Electronics, Programming | Tagged , , | 12 Comments

Beaglebone 101: Linux Tricks for Backing up and Resizing your microSD Card

I recently came across a couple of ideas on Raspberry Pi forums that made me think “wow, that’s so crazy it might just work!”

These are disk management commands that Linux allows, but probably shouldn’t.  Even Linux power users go pale (well, even paler) at the thought of trying them on their precious desktop PCs.  On SD-card systems like the Beaglebone, Beagleboard and Raspberry Pi, though, they’re considerably less scary, and they really do work.

Hot Backups

Let’s face it: backups are boring.  If I hadn’t put the word “hot” in the heading, you’d probably have skipped this section entirely.  Our aversion to backups stems from the PC world, where configuring backups is time-consuming and disk failures are increasingly infrequent.

You can’t be so complacent when working with a microSD card on a Beaglebone.  Systems can stop working for a number of reasons: package updates go awry, power outages and incorrect shutdowns can result in cryptic boot errors, and some microSD cards die young.

Fortunately, backups are relatively quick and painless on a Beaglebone.  Rather than decide which files to backup, you can easily and quickly do a “hot” backup of the entire microSD card while the system is still running.   A backup can be written to a new microSD card in about 15 minutes: a lot less time then it takes to configure a newly downloaded image.

The following work on both Angstrom and Ubuntu: actually, they’ll work on pretty much any Linux based system.

Hot Backups to a USB Drive

The fastest way to do this is by inserting a USB drive in your Beaglebone and copying the SD image onto it.

1. Determine the device ID of your USB drive.  If you’ve just inserted it, the last few lines of the output of the dmesg command will show it.  Otherwise, use fdisk:

root@beaglebone:~# fdisk -l
Disk /dev/mmcblk0: 8004 MB, 8004829184 bytes
4 heads, 16 sectors/track, 244288 cylinders, total 15634432 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Device Boot Start End Blocks Id System
/dev/mmcblk0p1 * 63 144584 72261 c W95 FAT32 (LBA)
/dev/mmcblk0p2 144585 15634431 7744923+ 83 Linux
Disk /dev/sda: 15.6 GB, 15606349824 bytes
116 heads, 52 sectors/track, 5053 cylinders, total 30481152 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xc3072e18
Device Boot Start End Blocks Id System
/dev/sda1 * 8064 30481151 15236544 c W95 FAT32 (LBA)

The last part of the output gives the size of the USB drive (15.6G), how it is formatted (FAT32), and the device ID (/dev/sda1).

2. Mount the USB drive.

mkdir /media/sda1
mount /dev/sda1 /media/sda1

3. Use the dd command to copy the full contents of the microSD card (partitions and all) to the USB drive, compressing it on the fly.  Double-check your typing before running any dd command — it’s nicknamed Disk Destroyer for a reason.  (The gzip parameter is a one, not an L.)

dd if=/dev/mmcblk0 | gzip -1 > /media/sda1/sd_backup.img.gz

A four gigabyte card will generally compress to under 1G.

The time required for this to complete will vary widely depending on the quality of your USB drive.

Among my motley crew of USB drives, the best performance I’ve seen is with a Patriot Xporter XT USB drive, 7.1Mb/s, resulting in a 19 minute backup for an 8G microSD card and 9 minutes for a 4G card.  The worst is with a grocery store brand (“President’s Choice”, but I’m pretty sure Obama had nothing to do with it):  I get just 1.6 MB/s, resulting in backup times of about 80 minutes and 42 minutes respectively.

If you’re in a hurry, you can speed things up by dropping the compression.

dd if=/dev/mmcblk0 of=/media/sda1/sd_backup.img

You’ll get a full byte-by-byte copy of the microSD card this way, so a 4G card will require (almost) 4G of free space on the USB drive.  This poses a problem if your microSD card is greater than 4G, since most USB drives are preformatted as FAT32, and FAT32 can’t handle files above 4G.

With my Patriot XT drive, an uncompressed backup runs at a 10M/s clip, completing the backup of a 4G card in under 7 minutes.

Monitoring Backup Progress

The dd command isn’t very chatty: it gives no indication of its progress whatsoever.  It does, however, respond to death threats.   Let me explain..

First, get the process ID of the dd command:

root@beaglebone:~# ps aux | grep "mmcblk0"
root 25437 4.6 0.2 3020 680 pts/2 S+ 18:17 0:01 dd if=/dev/mmcblk0
root 25446 0.0 0.2 2928 720 pts/0 S+ 18:17 0:00 grep --color=auto mmcblk0

The first line of the output shows the process ID of the dd command is 25437.

Next, enter the following command:

root@beaglebone:~# kill -USR1 25437

This won’t actually kill the dd process, but if you switch back to the session where the dd command is running, you’ll see some new lines of output, like this:

root@beaglebone:~# dd if=/dev/mmcblk0 | gzip -1 > /media/sda1/sd_backup.img.gz
175297+0 records in
175296+0 records out
89751552 bytes (90 MB) copied, 54.694 s, 1.9 MB/s

Updated 10/1: Thanks to kioan in the Comments for the following suggestion: use the Linux pv (pipe viewer) to get a progress bar for the backup.  The syntax is:

root@beaglebone:~# dd if=/dev/mmcblk0 | pv -s 4G -peta | gzip -1 > /media/sda1/sd_backup.img.gz

This displays a progress indicator like the following.

0:15:01 [1.57MB/s] [====================>               ] 51% ETA 0:14:06

A few notes on this:

  • The “-s 4G” parm specifies the amount of data being backed up (basically the size of the SD card).  If you have a bigger SD card, change that parm accordingly.
  • The “-peta” parm specifies that the average data transfer rate should be displayed, as well as being a fine tribute to the People For the Eating of Tasty Animals.  To display the (wildly fluctuating) current transfer rate, use “-petr” instead.
  • Ubuntu doesn’t include the pv command by default, but you can install it with apt-get install pv

Updated 10/2:  Thanks to mlitke and Chris Tyler for their comments with the following suggestions:

- Use killall instead of kill to save having to lookup the process ID:

killall -USR1 dd

- Use the watch command to have the output from dd update automatically.  For example, to update every 10 seconds:

watch -n10 killall -USR1 dd

Note that killall is included in Ubuntu’s psmisc package (i.e. apt-get install psmisc).  Also, since the “watch” command needs to be left running in the foreground, you’ll probably want to use a virtual terminal utility like screen for this (i.e. run screen, run the dd command in the first session, press Ctrl-A C to open a 2nd session, run the watch command, then Ctrl-A N to cycle back to the dd session.


Hot Backups Over the Network

If you don’t have a USB drive, or your Beaglebone is trapped in a burning house, it’s possible to run the backup over an SSH session.

From a Linux desktop PC, enter the following. This would be a good point at which to remind you of dd’s awesome ability to screw things up royally, so type carefully:

dan@ubuntu:~# ssh root@192.168.1.2 dd if=/dev/mmcblk0 | gzip -1 | dd of=sd_backup.img.gz

You should, of course, replace with IP address with your Beaglebone’s address.

The command will prompt you for your root password on the Beaglebone.  If you’re running Ubuntu on your Beaglebone this might stump you: there probably isn’t one.  You’ll have to set a password manually from the Beaglebone’s command line:

ubuntu@omap:~$ sudo -i
[sudo] password for ubuntu:
root@omap:~# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

As far as I know, Windows users are out of luck here, since you need to run dd at both ends of the SSH session.

Naturally, your network speed comes into play, as does the speed of your PC, but it’s generally going to be much slower than the USB drive approach.  On a my wired network, backups run at about 2.5MB/s, resulting in over 50 minutes to backup an 8G card.

Restoring a Backup

The .img or img.gz file that you created with the previous commands has the same format as one you download from the Beaglebone demo files or CircuitCo sites.  So, you can write it to a microSD card using the same commands.

On a Windows PC, you can use Win32DiskImager.

On a Linux PC, run the following command as root, when /dev/sdX should be changed to the device ID of the microSD card:

zcat sd_backup.img.gz > /dev/sdX

Resizing a 4G Image on an 8G Card

Beaglebone image files tend to be sized for 4G microSD cards.  This is true for both the image files on the Beaglebone Demo Files page and the image files on the CircuitCo site.

You can install these on a 8G or larger microSD card, but the resulting root partition will always be a little under 4G in size, leaving the rest of your card unused.

If this is news to you (I’m embarrassed to admit that I only caught onto this recently), you can check how much of your microSD card is being used with the following command:

root@beaglebone:~# fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 8004 MB, 8004829184 bytes
 255 heads, 63 sectors/track, 973 cylinders, total 15634432 sectors
 Units = sectors of 1 * 512 = 512 bytes
 Sector size (logical/physical): 512 bytes / 512 bytes
 I/O size (minimum/optimal): 512 bytes / 512 bytes
 Disk identifier: 0x00000000
Device Boot Start End Blocks Id System
 /dev/mmcblk0p1 * 63 144584 72261 c W95 FAT32 (LBA)
 /dev/mmcblk0p2 144585 7132859 3494137+ 83 Linux

The first line of the output shows the total MB on the card: 8004 MB, or 8G .  The last line shows us where the root partition ends, in 512 byte blocks.  So, this card is using 7132859 blocks, or about 3.5G of the card.

The safest way to extend the partition on the card is to take it over to a Linux PC and run parted or GParted.

However, you can actually extend the root partition while the Beaglebone is running off the card.  I wouldn’t have thought it possible, but it’s all the rage among Raspberry Pi users, where image files tend to be just 2G in size.  I’ve (belatedly) resized the partition on my 8G cards, and the process worked fine for me too.

Here are the steps:

1. Run fdisk

root@beaglebone:~# fdisk /dev/mmcblk0

Note that fdisk doesn’t touch the card until step 4, so if you make any mistakes before that point, it’s best to enter the q command to quit fdisk, then start over again.

2. At the fdisk command prompt, enter d to delete a partition, then select partition 2.

Command (m for help): d
 Partition number (1-4): 2
 Partition 2 is deleted

3. Still at the fdisk command prompt, enter n to create a new partition. You’ll then be prompted for various settings.  Enter

  • Partition Type: p
  • Partition Number: 2
  • First sector: Press Enter for the default
  • Last sector: Again, press Enter for the default.

Here’s the full text from one of my fdisk sessions:

Command (m for help): n
 Partition type:
 p primary (1 primary, 0 extended, 3 free)
 e extended
 Select (default p): p
 Partition number (1-4, default 2):
 Using default value 2
 First sector (144585-15634431, default 144585):
 Using default value 144585
 Last sector, +sectors or +size{K,M,G} (144585-15634431, default 15634431):
 Using default value 15634431
 Partition 2 of type Linux and of size 7.4 GiB is set

4. If everything went as expected, enter w to save your changes.  Again, if you’re unsure, it’s best to enter q at this point to abort the process then start over.

Command (m for help): w
 The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
 The kernel still uses the old table. The new table will be used at
 the next reboot or after you run partprobe(8) or kpartx(8)
 Syncing disks.

5. It’s important that you reboot before doing anything else:

 root@beaglebone:~# shutdown -r now

6. At this point, you have an 8G partition with a 4G file system.  Fortunately, Linux has a command to fix that:

root@beaglebone:~# resize2fs /dev/mmcblk0p2

This command will take quite awhile to run – at least 30 minutes on my system.  The output should look like this:

 resize2fs 1.42.1 (17-Feb-2012)
 Filesystem at /dev/mmcblk0p2 is mounted on /; on-line resizing required
 old_desc_blocks = 1, new_desc_blocks = 1
 Performing an on-line resize of /dev/mmcblk0p2 to 1936230 (4k) blocks.
 The filesystem on /dev/mmcblk0p2 is now 1936230 blocks long.

7. Another reboot is required at this point.

root@beaglebone:~# shutdown -r now

8. After this second reboot, you should have a nice big root partition.  You can confirm this with the df (disk free) command — the following shows a 7.6G root partition:

root@beaglebone:~# df
Filesystem 1K-blocks Used Available Use% Mounted on
rootfs 7622928 1202920 6035060 17% /
Posted in Gadgets | Tagged , , | 15 Comments

Arduino for Visual Studio: Come Over to the Dark Side

As a guy who earns his living writing software in the corporate world, I’ve always felt a little out of place in the Arduino world.

The Arduino platform hardware and software is, to quote the Arduino home page, “intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments“.

Good artists borrow code, great artists steal code, but no artist should have to write code.

And yet most do, or at least try to.  Coding is hard for beginners, and coding in C is not a great place to start.  Case sensitive names, mismatched parentheses, strongly typed variables: these are the things that trip up every newcomer, and there is no getting around them.   The minimalist Arduino IDE hides these issues, but it doesn’t solve them.

In fact, I feel that the Arduino IDE undermines the software side of Arduino projects by pretty much guaranteeing that beginners will quickly learn to hate programming.  Writing and debugging code in the Arduino IDE is time-consuming and frustrating: a drudgery of trial and error.

It doesn’t have to be this way!  Artists, designers, hobbyists: throw down your primitive tools and join the technological revolution!  Behold…  Arduino for Microsoft Visual Studio!!

No, seriously!

The Reason Not to Switch

OK, let’s get this over with.  Your reaction to this is probably one of 3 things:

1. Oh great, Microsoft.  How much is that going to cost me?

2. Oh great, Microsoft.  How long is that going to take me to learn?

3. #@*&! Microsoft!!!! You expect me to use a closed-source, over-engineered hairball sold by a shameless monopolist to cubicle-dwelling corporate drones??

The answers are:

1. Probably nothing

2. Less than you think

3. Bah, occupy this, hippy.

Clearly, I don’t have a good answer to the 3rd issue.   Yes, Microsoft makes tons of money, Visual Studio is never going to be open source, and it only runs on Windows.  If that’s a dealbreaker for you, then you can stop reading.  You may not want to know what you’re missing.

Cost and the Learning Curve

Visual Micro’s Arduino add-on requires Visual Studio Professional, not Visual Studio Express.  Back in the day, Microsoft targeted Visual Studio at large corporations, and it was priced accordingly.

Fortunately, that’s no longer true.  Visual Micro’s web page has details on how you can legally get a copy of Visual Studio for free.  Another option for young whippersnappers is Microsoft’s Dreamspark program for  students.

Don’t worry — it’s not a trick.  Over the last 10+ years, Microsoft has increasingly lowered the barrier to developers acquiring their development tools.  Microsoft is not being purely altruistic here.  Their motivation is to attract new developers to the cult platform — come over to the dark side, we have candy — but the end result is that Visual Studio is a lot easier to get than it used to be.

As for the learning curve, Visual Micro has done a good job at reducing to 3 steps the process of loading/creating a sketch and uploading it to your Arduino.   (I should mention that Visual Micro’s documentation is extensive — you don’t have to rely on blogs and forums to figure out how to use their product.)

Yes, Visual Studio is bristling with menus, toolbars and windows, but you can safely ignore 95% of them, just like you already do in Microsoft Word. The remaining 5%  of these features will, on the other hand, save you a ton of time.

Not convinced?  Let’s get into what I feel are the 6 coolest features in Arduino for Visual Studio.  Most of these will be familiar to anyone who’s used Visual Studio with other languages: the cool thing is that Visual Micro has brought them to the Arduino world.

1. Code Completion

Do you ever have trouble remembering what the exact syntax of an Arduino statement is?  Is it Serial.Print, or Serial.print, or Serial.Write?  What are the parameters.

Yeah, us professionals have the same problem.   A dirty little secret of our profession is that we tend not to memorize things unless we have to, and thanks to Code Completion in Visual Studio (and to Google), we rarely have to.

As you begin to type in a statement in Visual Studio, a pop-up list of options for completing the statement will appear.  Rather than typing the whole thing, just use the arrow keys to select the one you want, then click the Tab key to fill in the rest.

When you aren’t sure which one you want, just pause at one of the options and a tooltip will appear listing the parameters that the methods takes.

2. Error Highlighting

The process of correcting typos in the Arduino IDE is a tedious grind: build, decipher the error message, figure out what line of code its referring to, take a stab at fixing the error, build, repeat….

That’s the way we professionals coded software too, 20 years ago.  Then we smartened up, and put some effort into building better tools.

One result of this is on-the-fly error highlighting.  Each new version of Visual Studio has got better at this, and it’s now at a point that you can fix 90% of your errors before you get to the build stage.

And, of course, it’s a lot easier to figure out which line of code is wrong when it’s underlined for you.

3. Intelligent Search

The one-result-at-a-time search feature is another area where the Arduino IDE is about 15 years behind the state of the art.  Given that we’ve all learned to leverage search engines when looking for all sorts of answers, it’s puzzling that this hasn’t been improved.

There are lots of different ways to search for information in Visual Studio:

  • Need to quickly review the code that uses a variable?  This happens all the time: you aren’t sure whether its a string or number, or you aren’t sure what value you initialized it to, or you aren’t sure where its being read or updated in your program.  In Visual Studio, just right-click and select Find All References.  A window will open listing all the code that uses that variable.
  • Forgotten what a variable is called?  If you know part of the name, Visual Studio’s Find feature will list all the lines of code that contain a particular search string. Wildcards are supported.  Double-clicking on one of the search results will bring you directly to that line of code
  • You know that cool “search as you type” feature when searching for text on a web page, where the cursor automatically jumps to the first match as you type in your search term?  Visual Studio has that too: just type Ctrl-I to search.

4. Libraries: My God, it’s full of code!

Libraries are the Arduino’s greatest strength.  Brilliant coders have created packaged libraries to handle all the complicated stuff: reading and writing to devices, handling Strings, connecting to web sites, and so on.  You don’t know how they work, and you don’t care. They just work.

Except when they don’t.  When you call a library function, and it hangs, returns a generic error message, or does nothing, you’re left high and dry.  What’d I do wrong?  Wrong parameter? Wrong settings?  Google?!!

In Visual Studio, there are a few different ways to pull back the curtain and have a good look at the library you’re using.

If you right-click on a class or function and select Find Declaration, Visual Studio will automatically load it  into the editor.  Often, the comments added by the coder will give you the information you’re missing.  If not, have a look at the code.  Don’t be intimidated: if you can write it, you can read it.  Open source isn’t just a buzzword, you know?

In the Visual Studio Find In Files dialog, it you change the “Look In” field to “Current Project”, it  will list all occurrences of a variables, including ones that appear in libraries.  This is useful when you’re searching for a particular constant: you have an idea what you want, but you’re not sure what the exact spelling is.

Lastly, when you want to pull back and have a look at the bigger picture, the Object Browser lists everything about a library in one convenient place.   The left hand pane lists all classes in the libraries that are included in your project.  Selecting a class lists the functions in that class in the upper right pane.  Double-clicking on a function opens the library source code and takes you to the function definition

If you really want to blow your mind, turn on the “Show All Arduino Files” option, then check the Solution Explorer.  Yikes, where did all those files come from?  Those have all been in your project all along, covered by Arduino’s invisibility cloak.    You’ll probably want to leave the “Show All Arduino Files” setting off most of the time (I do), but it’s handy to be able to easily look through that code on the few occasions when you need to.

5. Serial Console: Not Just an Afterthought

The Arduino Serial Console has also seemed to me like something reluctantly tacked on to the software.  Arduino code is supposed to “just work”.  Who needs a debugger?  Why bother to put work into something that nobody’s going to use?

Visual Micro did put some work into their’s, and it has several nice features that Arduino’s lacks.

First and foremost, they’ve done away with that silly limitation of having to close the Console every time you upload code to the Arduino.   Debugging using print statements is hard enough: taking away that information every time you run your code is just nasty.  In Visual Studio, you don’t have to close the Console, ever.  When you transfer your code to the Arduino, the Serial Console quietly and automatically frees up the serial port, then reconnects when the transfer is done.

When you select some text in the Serial Console and right-click, a context menu lists all of your options: Select All, Copy, Cut, etc.. It’s a small thing, but a timesaver that any text window should have.

Another timesaver is the ability to quickly re-enter text by selecting it from a pull-down menu.  Trial-and-error debugging is always a pain, but being able to enter input in one click makes the trials less painful.

6. No Java

Java is beginning to rival Internet Explorer as software that is more trouble than it’s worth.  The passive aggressive auto-updater is bad enough, but malware authors are increasingly targeting Java as a means of sneaking their software onto PCs.  The only Java software I run is Arduino, so replacing the Arduino IDE has a major side benefit.

A lot of newcomers to Arduino get the impression that Java is central to Arduinos; some think that the Arduino programming language is Java.  In actual fact, Java and the Arduino are an odd couple.  Arduinos are coded in C++, the same language Visual Studio is written in, and a language that the Visual Studio IDE has supported for 15 years .  Visual Studio gets C++ in a way that a Java-based IDE cannot.   Visual Micro has done an amazing job at leveraging Visual Studio’s rich support for C++ development.

Wrapping Up

Arduino for Visual Studio has actually been around for awhile now, and I’d intended to write about it back in the spring.  It drifted off my radar when I stopped using the Arduino in my projects.

My main problem with the Arduino is the lack of debugger.   Trial-and-error debugging is a major time-waster.

Arduino for Visual Studio popped back up on my radar recently when Visual Micro released an Arduino Debugger for beta testing.  If you thought “Visual Studio for Arduino” was an odd-looking phrase, how about “Arduino Debugger”?  This is a software debugger, with no need for JTAG or other hardware add-ons, something I had previously thought impossible.  It’s not such a crazy notion, though.  Like I said earlier, Visual Studio is closely integrated with C++, and its debugger has been connected to various C++ runtimes.    Visual Micro has figured out how to connect the Arduino to it.

An Arduino debugger, integrated into Visual Studio,  is a potential game-changer, something that will make it possible to do a lot more ambitious coding projects in a lot less time.  I’m eager to give it a try.  If you are too, head over to Visual Micro’s web site and read all about it.

Posted in Electronics, Programming | Tagged , | Leave a comment

Beaglebone Coding 101: SPI Output

It’s been too long since my last “Beaglebone Coding 101″ article.  Perhaps many of you have graduated to Beaglebone Coding 201 by now, but I’m going to continue with the 101 level for us less gifted students.

I’ve been experimenting with SPI and I2C on my Beaglebone lately.  When I first tried using them at the beginning of the year, I found they required a level of Linux Kung Fu that was beyond me.  However, both of these protocols are now supported from “userland” applications  in both Angstrom and Ubuntu.  A Google search turns up plenty of working examples for SPI and I2C on the Beaglebone, along with some more advanced projects.  I think the water’s safe safe for the rest of us.

I’m going to begin with SPI.  Ultimately I’ll be using a graphical LCD, specifically an Adafruit ST7565-based LCD, but in this article I’m going to use a simpler character LCD backpack, also from Adafruit, that uses the popular and well-documented 74HC595 SPI chip.

Beaglebone Connected to SPI LCD
Beaglebone Connected to SPI LCD

My coding language of choice is Python.  I really wanted to do this in Bonescript instead, since I like Jason Kridner’s idea of using it as a way for Arduino coders to ease into the embedded Linux world. Unfortunately, I haven’t found the time to get the hang of coding in node.js.  Bonescript has added SPI support through a shiftOut method.  If you’re interested in learning how to use SPI with Bonescript, I’d recommend Ken Keller’s blog and Github code library.

Updating the Kernel

SPI has been supported in the Angstrom kernel for awhile now, and was added to Ubuntu’s kernel relatively recently.  A quick way to check if you have SPI support is to look in the /dev directory:

ubuntu@omap:~$ ls /dev/spi*
 /dev/spidev2.0

Note that bus 2, device 0 is the only option available to “userland” code in the current Angstrom and Ubuntu kernels.  Multiple SPI buses and devices are possible, but require that you build a custom kernel.

If you don’t see an SPI device in the /dev directory, you’ll need to upgrade your kernel.  If you are running Angstrom, either download a new image (I use the top entry on the Beaglebone demo files page), or follow the instructions in the “Enabling PWM Support in the Kernel” section of my Buttons and PWM article.

[Update Sept 11: I just noticed that Angstrom kernel 3.2.28 was automatically enabled on my Beaglebone when installed via opkg. I didn't have to manually copy the uImage file onto the boot partition, just reboot.   Whoa!  

I'm using the 2012.08.14 image from the Beaglebone demo files page.  I'm not sure yet whether this feature is only to be found in newer Beaglebone images. If you find that the latest kernel isn't automatically installed for you, then you'll have to manually update it as described in the Buttons and PWM article.]

If you’re running Ubuntu, see my recent article on updating the kernel.

(If you’re running Android or another OS, sorry, dunno :-( .)

Adding an SPI Extension Module to Python

If you Google Python SPI, you’ll find various references to a C extension for Python, py-spi.  It was written back in 2009 by Volker Thoms, but as far as I can tell its still the best method for giving Python full access to SPI on Linux.

The module consists of  C code with Python bindings, spimodule.c.  It limits the amount of data being sent to 32 bytes, and the speed to 8 Mhz — both unnecessarily low limits on the Beaglebone — but for now we’ll use it as-is.  We’ll need to lift those limitations later when we use it with an SPI graphical LCD.

(If you’d rather avoid building the extension on your Beaglebone, I’ve built binaries for Angstrom and Ubuntu.  See the Python Extension Binaries section below).

Before we can install it, we need the python-dev package.

On Angstrom

opkg update
opkg install python-dev

On Ubuntu

sudo apt-get update
sudo apt-get install python-dev

To install the py-spi module, you’ll need to download a few files into any directory on your Beaglebone:

wget http://elk.informatik.fh-augsburg.de/da/da-49/trees/pyap7k/lang/py-spi/src/setup.py
wget http://elk.informatik.fh-augsburg.de/da/da-49/trees/pyap7k/lang/py-spi/src/spimodule.c

Note: if you have problems downloading these files (I downloaded them without problems a few weeks ago, but got 0-length files when I tried today), you can download my slightly customized versions instead:

wget http://gigamega-micro.googlecode.com/files/setup.py
wget http://gigamega-micro.googlecode.com/files/spimodule.c

If you download the original setup.py, you’ll need to make a couple of changes to the setup.py file.  (You can skip this if you download my customized version). The original looks like this

#!/usr/bin/env python
from distutils.core import setup, Extension
setup( name="spi",
 version="1.1",
 description="Python bindings for Linux SPI access through spi-dev",
 author="Volker Thoms",
 author_email="unconnected@gmx.de",
 maintainer="Volker Thoms",
 maintainer_email="unconnected@gmx.de",
 license="GPLv2",
 url="http://www.hs-augsburg.de/~vthoms",
 include_dirs=["/usr/src/linux/include"],
 scripts=['scripts/93LC46_LAtest.py','scripts/93LC46_test2.py',
'scripts/93LC46_test.py','scripts/ds1305_test.py',
'scripts/mcp3304.py','scripts/mcp3304_test.py',
'scripts/mcp4922.py','scripts/spitest3.py'],
 ext_modules=[Extension("spi", ["spimodule.c"])])

We’ll need to change the include_dirs line to match the correct location of the Linux include files, /usr/include.  Otherwise, when you compile on Angstrom you’ll get an error “no include path in which to search for limits.h“.  Incidentally, this appears to be one of those error messages for which Google returns 1000 explanations, none of them being this one.  I hate it when Google makes me think for myself!

We’ll also remove the scripts line, since we aren’t using those files.  The setup.py should look like this:

#!/usr/bin/env python
from distutils.core import setup, Extension
setup( name="spi",
 version="1.1",
 description="Python bindings for Linux SPI access through spi-dev",
 author="Volker Thoms",
 author_email="unconnected@gmx.de",
 maintainer="Volker Thoms",
 maintainer_email="unconnected@gmx.de",
 license="GPLv2",
 url="http://www.hs-augsburg.de/~vthoms",
 include_dirs=["/usr/include"],
 ext_modules=[Extension("spi", ["spimodule.c"])])

To compile and install the Python extension, enter the following as root:

python setup.py install

On Ubuntu, you should get the following.  (The warnings won’t be there if you use my customized version – 10 points for Gryffindor!):

 
 running install
 running build
 running build_ext
 building 'spi' extension
 creating build
 creating build/temp.linux-armv7l-2.7
 gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall 
  -Wstrict-prototypes -fPIC -I/usr/include -I/usr/include/python2.7
 -c spimodule.c -o build/temp.linux-armv7l-2.7/spimodule.o
 spimodule.c: In function ‘SPI_readbytes’:
 spimodule.c:156:7: warning: unused variable ‘addr’ [-Wunused-variable]
 spimodule.c: In function ‘SPI_xfer’:
 spimodule.c:204:10: warning: unused variable ‘ret’ [-Wunused-variable]
 creating build/lib.linux-armv7l-2.7
 gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,
  -Bsymbolic-functions -Wl,-z,relro 
  build/temp.linux-armv7l-2.7/spimodule.o 
  -o build/lib.linux-armv7l-2.7/spi.so
 running install_lib
 copying build/lib.linux-armv7l-2.7/spi.so -> 
  /usr/local/lib/python2.7/dist-packages
 running install_egg_info
 Removing /usr/local/lib/python2.7/dist-packages/spi-1.1.egg-info
 Writing /usr/local/lib/python2.7/dist-packages/spi-1.1.egg-info

An Extra Step on Angstrom

On Angstrom, you’ll run into a problem:

 python setup.py install
 running install
 running build
 running build_ext
 building 'spi' extension
 arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize
   -mthumb-interwork -mfloat-abi=softfp -mfpu=neon 
  -mtune=cortex-a8 -D__SOFTFP__ 
  --sysroot=/OE/angstrom-v2012-05/build/tmp-angstrom_v2012_05-eglibc/sysroots/beaglebone 
  -fno-strict-aliasing -O2 -pipe -g 
  -feliminate-unused-debug-types -DNDEBUG -g -O3 -Wall 
  -Wstrict-prototypes -fPIC -I/usr/include 
  -I/usr/include/python2.7 -c spimodule.c 
  -o build/temp.linux-armv7l-2.7/spimodule.o
 arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize
   -mthumb-interwork -mfloat-abi=softfp -mfpu=neon 
  -mtune=cortex-a8 -D__SOFTFP__ 
  --sysroot=/OE/angstrom-v2012-05/build/tmp-angstrom_v2012_05-eglibc/sysroots/beaglebone 
  -shared -Wl,-O1 -Wl,--hash-style=gnu -Wl,
  --as-needed build/temp.linux-armv7l-2.7/spimodule.o 
  -L/usr/lib -lpython2.7 -o build/lib.linux-armv7l-2.7/spi.so
 /usr/lib/gcc/arm-angstrom-linux-gnueabi/4.5.4/../../../../arm-angstrom-linux-gnueabi/bin/ld: 
  this linker was not configured to use sysroots
 collect2: ld returned 1 exit status
 error: command 'arm-angstrom-linux-gnueabi-gcc' failed with exit status 1

OK,  whose idea was it to use sysroots??  Anyone?

Actually, I have no idea who or what is telling setup.py to include that “sysroot=..” parm (another seemingly unGoogleable solution), so I just created stripped the sysroot part out of the compile and link commands:

arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8 -D__SOFTFP__ -fno-strict-aliasing -O2 -pipe -g -feliminate-unused-debug-types -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/include -I/usr/include/python2.7 -c spimodule.c -o build/temp.linux-armv7l-2.7/spimodule.o
arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8 -D__SOFTFP__ -shared -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed build/temp.linux-armv7l-2.7/spimodule.o -L/usr/lib -lpython2.7 -o build/lib.linux-armv7l-2.7/spi.so

Having generated the object file, you can rerun python setup.py install to complete the process.

 python setup.py install

 running install
 running build
 running build_ext
 running install_lib
 copying build/lib.linux-armv7l-2.7/spi.so -> /usr/lib/python2.7/site-packages
 running install_egg_info
 Writing /usr/lib/python2.7/site-packages/spi-1.1-py2.7.egg-info

Python Extension Binaries

If above process left you totally confused, or simply didn’t work, you can try downloading a binary of my customized version of the Python extension.

If you’re running Ubuntu on your Beaglebone:

wget http://gigamega-micro.googlecode.com/files/spi.so.gz
gunzip spi.so.gz

If you’re running Angstrom:

wget http://gigamega-micro.googlecode.com/files/spi-angstrom.so.gz
gunzip spi-angstrom.so.gz
mv spi-angstrom.so spi.so

Writing to an SPI Device  from the Python Shell

Before running some Python code to write to an SPI-attached LCD, we can test the setup using an 74HC595 chip.  (If you don’t have a 74HC595 chip, you can skip ahead to the example Python commands: they would be basically the same for any SPI-controlled device).

The 74HC595 is commonly used as a GPIO-extender: by using the 3 SPI pins on the Beaglebone, we get 8 extra GPIO pins.  This isn’t a particularly attractive tradeoff on the GPIO-rich Beaglebone, but the 74HC595 makes a good testbed for playing with SPI before moving on to more sophisticated (and finicky) devices.

The HC74595 pinout looks like this, as taken from the datasheet.  You can find a thorough and easy-to-understand explanation of this chip on the Arduino web site.  Note that the latch pin, aka the Chip Select pin, is aaka the “storage register clock input” pin here.  Don’t ask me!

An easy way to test SPI output is by hooking by LEDs (through resistors) to each of the 8 GPIO pins on the 74HC595.

The following diagram shows this kind of setup. I used an LED bar instead of individual LEDs.  If you’re lazy and/or don’t have an LED bar or 8 LEDs, you can hook up a couple of LEDs — I’d suggest Q0 and Q 1 — and still verify that everything is working OK.

The Beaglebone pins involved in SPI Bus 1 are as follows:

  • Port 9 Pin 28 – Chip Select – connected to pin 12 of the HC74595 with yellow wire
  • Port 9 Pin 29 – Data 0 (aka MISO – Master In Slave Out) – unused in this project, but could be connected to pin 9 of the HC74595
  • Port 9 Pin 30 – Data 1 (aka MOSI – Master Out Slave In) – connected to pin 14 of HC74595 with green wire
  • Port 9 Pin 31 – Clock – connected to pin 11 of the HC74595 with white wire

The “master”, in this case, is the Beaglebone.  Since at this point we are only writing, not reading, we’ll leave Pin 29 unconnected.  This gives us the liberty of connecting the 74HC595′s voltage pin, Pin 16 (to the right of the chip’s semicircular imprint), to 5V if we want to make those LEDs sweat.  More usefully, it also allows us to safely connect the Beaglebone to SPI write-only devices that run at 5V, as we will with the LCD.  Do not connect Pin 29 to an SPI device running at 5V!

Note that the spidev2.0 device is identified as SPI1 in the System Reference Manual.  Note also that the pinmuxing for the SPI1 pins all default to SPI mode (mode 3).

Now that we have things hooked up, let’s fire up Python and send a command to the 74HC595.   Note that this needs to be done as root, so run sudo python if you are on Ubuntu:

root@beaglebone:# python
 Python 2.7.2 (default, Apr 27 2012, 09:45:45)
 [GCC 4.5.4 20120305 (prerelease)] on linux2
 Type "help", "copyright", "credits" or "license" for more information.


 >>> from spi import SPI
 >>> leds = SPI(2, 0)
 >>> leds.writebytes([0x00])

Even if you don’t know Python, you probably figured out that this should turn all of the LEDs off (by setting all of the 74HC595 pin’s low).  To turn the LEDs on:

>>> leds.writebytes([0xFF])

If that’s not working for you, check the wiring: aside from the GPIO pins, there are a bunch of pins on the 74HC595 that need to be connected to ground or to voltage, as shown in the figure above.

Let’s see which pins correspond to which bits:

>>> leds.writebytes([0x80])

This will set high the lowest GPIO pin on the 74HC595, Q0, which is connected to the leftmost LED in the circuit diagram and photograph.  Similarly, if we had written 0xC0, it would set Q0 and Q1 to high.  So, the data is sent LSB first — the opposite of what you might expect (but the same as the Arduino, by the way).  We’ll have to keep this in mind when coding.

Beaglebone connected to 74HC595. Yellow is SPI CS, green is Data, white is Clock.
Beaglebone connected to 74HC595. Yellow is SPI CS, green is Data, white is Clock.

Although we won’t need it when dealing with the 74HC595, sending multiple bytes of data is pretty simple from Python:

>>> leds.writebytes([0x01, 0x02, 0x03, 0x04])

Technically, that command turns on each of pins Q0 to Q3 in  turn, though of course it occurs too quickly to see any but the last one.

There are a bunch of other commands that are supported by the spi Python extension:

>> dir(SPI)
 ['__class__', '__delattr__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__sizeof__', '__str__', '__subclasshook__', 'bpw', 'close', 
'cshigh', 'loop', 'lsbfirst', 'mode', 'msh', 'open', 
'readbytes', 'threewire', 'writebytes', 'xfer', 'xfer2']

I haven’t experimented with most of these, but 2 that are worth pointing out are:

  • writeBytes – writes a list of byte data, as shown in the example above.  The original spimodule.c had a hard-coded limit of 32 bytes, which I increased to 1024.  I don’t know what the practical limit is: 1024 is enough for my current uses.
  • msh – Sets the clock frequency.  For example, the following displays the clock rate being used in our connection to the 74HC595, then changes it to 1 Mhz.
>>> leds.msh
 8000000
 >>> leds.msh = 1000000

The default of 8 Mhz is actually the maximum clock rate allowed by the original spimodule.c code, though I removed that in the version I customized.

Having said all that, changing the clock rate is completely unnecessary for this project, either with the LEDs or the LCD. The 74HC595 is very flexible about the frequency (it supports up to 100 Mhz, and anything from 1 Mhz up worked fine when I tried it), and neither the LEDs nor  a character LCD require much bandwidth.  The speed setting will be more useful when dealing with graphical LCDs.

Writing to an I2C/SPI LCD Backpack from Python

Adafruit’s I2C/SPI LCD Backpack is a handy accessory for testing SPI and I2C.   It uses 2 common GPIO extenders ( the 74HC595 and, for I2C, the MCP20008) to connect to a standard character LCD, allowing you to test SPI and I2C without much wiring.  It’s also the cheapest LCD connector that I’ve seen: $10. I’ll be using it again in a future article about using I2C with the Beaglebone.

Assembly instructions for the backpack are at http://learn.adafruit.com/i2c-spi-lcd-backpack.  Note that, by default, it uses I2C, so you’ll need to put a blob of solder on the SPI bridge for use with the code below.

The 5 screw terminals on the backpack should be connected to the Beaglebone as follows:

  • LAT – Port 9 Pin 28 (i.e. Chip Select)
  • DAT – Port 9 Pin 30
  • CLK – Port 9 Pin 31
  • 5V – Port 9 Pin 5 or 6
  • GND – Port 9 Pin 1 or 2

Beaglebone connected to Adafruit I2C/SPI Backpack.  White is SPI CS (Latch), yellow is data, green is Clock.
Beaglebone connected to Adafruit I2C/SPI Backpack. White is SPI CS (Latch), yellow is data, green is Clock.

I’ve written some Python class modules to make it easy to write to a backpack-connected LCD:

wget http://gigamega-micro.googlecode.com/files/spilcd.py
wget http://gigamega-micro.googlecode.com/files/gmspi.py
wget http://gigamega-micro.googlecode.com/files/hd44780lcd.py
wget http://gigamega-micro.googlecode.com/files/bone.py

You will also need the spi.so Python extension, either installed as a Python library or as a file in the same directory as the other files. If you don’t have it, go back to the section Adding an SPI Extension Module to Python section above for instructions.

Once you have all the files, run the following as root to write some text to the LCD

root@beaglebone:# python
Python 2.7.3 (default, Aug 1 2012, 08:09:58)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.


>>> from spilcd import spilcd
>>> lcd = spilcd(2, 0)
>>> lcd.begin(16, 2)
>>> lcd.setBacklight(True)
>>> lcd.home()
>>> lcd.Print("Hello world")
>>> lcd.setCursor(0, 1)
>>> lcd.Print("Hello line 2")

(You should, of course, use begin(20, 4) for a 4-row, 20-character LCD.)

As you can see, the syntax is based on the Arduino LiquidCrystal library.  I’ve implemented many (but not all) of the same methods: enter help(spilcd) from Python to get the list.

I’ve also written a plant light controller application which makes use of the spilcd class, along with the Arduino-like bone class for accessing the GPIO .  It uses the LCD to display the current date and time, the sunrise and sunset times, and the plant light settings.  While it doesn’t break any new ground in terms of Beaglebone functionality, you might want to refer to it for sample code on how to use my Python classes for SPI and GPIO access.

You can download the plant light controller code from here.

Wrapping Up

This article covers one of the simpler uses of SPI, but this protocol opens the door to a lot of inexpensive LCDs.  I’m currently working on a Beaglebone project that uses an Adafruit ST7565-based 128×64 LCD, and Adafruit has an assortment of other SPI-based LCDs for sale.  SPI-based input devices are less common: I2C is the standard protocol used by sensors.  I’ll look at I2C in upcoming “Beaglebone Coding 101″ article.

Posted in Electronics, Programming | Tagged , , , | 16 Comments

Adding a Linux CUPS Printer to Windows 8

On my home network, I have an elderly HP Deskjet 932C printer connected to a middle aged Beagleboard running Ubuntu.  This combination has served me well as a print server for many years.  As such, they’ve borne silent witness to a sad little ritual that’s been repeated many times: I add or upgrade a Windows PC, then stomp, wail and curse as I try to remember the settings for convincing that PC to write to the printer.

The latest iteration of that ritual featured more cursing than usual, only partially because it involved Windows 8.  This convinced me to finally write down the steps involved.  That will save me some grief the next time I setup a PC, and will hopefully be of use to others too.

1. The trick is that you need to use a URL as the printer address.  I don’t know if it’s listed elsewhere, but one place you’ll find it is in the CUPS Printer list.  I was inexplicably surprised to find it displayed as a link, rather than displayed in plain text.

2. Open the Windows “Add Printer” dialog.  Every new version of Windows seems to make this a little harder to find than the previous version.  In Windows 8, here’s what I think is the most direct method:

  • Press Windows Key + Q to bring up the Search textbox
  • Type “printer”, then click the Settings bar below
  • Rather than selecting the enticingly named “Add printer” option, select “Advanced printer setup”.

(“Add printer” launches a Metro app, which attempts to find the printer, predictably fails, then offers you no option for finding it on your own.  Incidentally, I actually like Windows 8 overall: it’s Windows 7  + a lot of nice enhancements + a lot of Metro stuff that isn’t that useful on a PC  minus the Start menu.  It all adds up to a significant improvement over Windows 7, even on a desktop PC.)

The “Advanced printer setup” brings you back to the Desktop and familiar ground.  The process from this point on is pretty much identical to Windows 7.

3. The  Add Printer dialog (nee “Advanced printer setup”) attempts to find the printer, predictably fails, but gives you an option: “The printer I want isn’t listed”.  Select that option.

4. Here’s where that printer URL from step 1 comes into play (and where I usually go down the wrong path).  Paste that URL in the “Select a shared printer by name” textbox, then click Next.

5. The next dialog allows you to specify the printer model so that it can install the right drivers.  If you have a well known printer model of recent vintage, it might be listed in this dialog.  Mine isn’t, and hasn’t been since XP days.  At some point HP stopped offering the driver as a download, and instead made the surprisingly useful suggestion of using the “Windows Update” button to automatically locate the driver.  Holy smokes, it actually works!  So, give that a shot, even if your printer isn’t an HP 932C.   Otherwise, you’re left with the old school “Have Disk” option.

6. Ta da!  You’re done.  You might want to change the name, but up to now it’s been my only clue that a URL was involved, so I’m keeping it.

7. As a bonus step, check out the banner of the new Windows 8 “Print Test Page” output.  Those guys got  into the Metro spirit, too.

 I kind of like the fact that the test page no longer puts a dent in my ink supply.  It’s not so great if you’re checking to see that your printer can print more than 1 colour, but that’s Windows 8: one step forward, one aesthetically pleasing step back.

 

Posted in Uncategorized | Tagged | 3 Comments

Ubuntu on the Beaglebone: Enabling Analog In, PWM, I2C and SPI

When writing about the Beaglebone in the past, I mentioned that you needed to be running Angstrom in order to have access to certain devices, since they weren’t yet supported by the kernel in Ubuntu.

Well, I’m rather late in giving Ubuntu its props, but that’s no longer true. Ubuntu has caught up to Angstrom in protocol support: analog input, PWM, SPI and I2C are all working.

In order to get these features, you need to have a recent kernel.  I’m not sure exactly which kernel version they were added in — 3.2.twentyish — but current kernel version for Ubuntu  is 3.2.28.  If you’re running an earlier kernel, I’d recommend that you upgrade.

To determine your current kernel version, run the following command

ubuntu@omap:~ uname -r
 3.2.21-psp16

You have a couple of options for getting the latest and greatest Ubuntu kernel.

Creating a new Ubuntu Image

If you aren’t already running Ubuntu on your Beaglebone, you can download a new image.

You’ll need to use Robert C Nelson’s customized Ubuntu build.  The instructions for creating the image are on the eLinux Beagleboard page, under “Demo Image”.   (Don’t be put off by the word “demo” — it’s a fully functioning Ubuntu distribution, with a vast array of available packages).

The procedure is quite reliable and mercifully free of obscure Linux commands, but you will need to be running Linux to write the image to the microSD card.

Before starting, you’ll need to decide which Ubuntu version to run on your Beaglebone.  The latest released version is usually a good bet, currently Precise 12.04.  That’s the one I’m using.

However, if you plan to use a GUI desktop, then you may want to drop back to the previous version, Oneiric 11.10.  That’s because the 12.04 release is compiled with hardware floating point support (aka “armhf”), and while that makes some things faster (the apt-get package manager is noticeably zippier), it reportedly makes some GUI packages too slow to use.  The kernel version in Oneiric is the same as in Precise, so as far as I know you can still get analog in, PWM, I2C and SPI with that release.

You should refer to the eLinux page for the latest instructions, but here are the steps you would currently following to create a microSD card with Precise 12.04 on a Linux desktop:

1. Begin by downloading the image file.  It’s not huge, a little over a hundred megs:

wget http://rcn-ee.net/deb/rootfs/precise/ubuntu-12.04-r5-minimal-armhf-2012-07-29.tar.xz

2.  While you’re waiting for it to download,  insert your microSD card. It needs to be 4G or higher.  Personally, I’m sticking with 4 or 8G cards, since some people have reported problems with higher capacities: it depends on the manufacturer.  Also, I’d suggest you use a USB card reader that has a microSD card slot.  I’ve personally had problems with those SD card-sized adapters that allow you to fit a microSD card into an full SD card slot.

3. Determine what your microSD card device ID is, and make sure it wasn’t automatically mounted by Linux.  The easiest way to determine the device ID is to run the dmesg command after inserting the card: the messages at the end of the output will include the device ID.

The format will be /dev/sdX, where X varies.  For example, on my PC it’s /dev/sde.  Note that you want the device ID, not the partition ID: that is, /dev/sde, not /dev/sde1.

To check if the card was mounted, run the “mount” command. Look at the lines at the bottom of the output to see if they contain your card’s device ID, such as:

/dev/sde1 on /media/sde1 type vfat (rw)

If so, you’ll need to unmount them before writing the image to the card.  Personally, I’ve had problems when unmounting from Ubuntu’s file manager (the device ID is no longer recognized by the OS after doing so), so I’d suggest you do it from the command line:

sudo umount /dev/sde1

4. Once the download from step 1 has completed, you’re ready to run the commands to write the image to the microSD card.

tar xJf ubuntu-12.04-r5-minimal-armhf-2012-07-29.tar.xz
cd ubuntu-12.04-r5-minimal-armhf-2012-07-29

Note: In the following command, replace “/dev/sdX” with the actual device ID from step 2 (e.g. /dev/sde).  Unlike the previous commands, this one needs to be run as root:

sudo ./setup_sdcard.sh --mmc /dev/sdX --uboot bone

This script handles all the nitty gritty work for you: it repartitions the card, builds the boot and root partitions and downloads the latest kernel for you.   The whole thing should be done in 20-30 minutes. If you find it still grinding away after an hour, there’s likely a problem with the card or the way its connected to your PC:  if you ignored my advice from step 2, you might want to reconsider it now.

5. When the script completes, you’re all done.  Unmount the card from your Linux PC, if necessary, then pop it into the Beaglebone.  The initial bootup will be slower than subsequent boots, generally a few minutes.  You’ll need to login as user-ID ubuntu, password temppwd.  The ethernet port is configured for DHCP (using /etc/network/interfaces, not connman, yay!), and SSH is enabled by default.

Upgrading the Ubuntu Kernel

Unlike Angstrom, Ubuntu doesn’t automatically deliver new kernel releases via its package manager, apt-get.  So, if you installed Ubuntu on your Beaglebone awhile ago, you’ll find that kernel version has become quite outdated.  Fortunately, Robert C Nelson has made the upgrade process quite easy to do manually.

The procedure depends on which Ubuntu release you’re running on your Beaglebone.  In my case, running the 12.04 armhf image, instructions are at http://rcn-ee.net/deb/precise-armhf/LATEST-omap-psp:

ABI:1 EXPERIMENTAL http://rcn-ee.net/deb/precise-armhf/v3.2.0-rc2-d0/install-me.sh
ABI:1 TESTING http://rcn-ee.net/deb/precise-armhf/v3.2.0-psp0/install-me.sh
ABI:1 STABLE http://rcn-ee.net/deb/precise-armhf/v3.2.28-psp21/install-me.sh

The “stable” version is, of course, the best choice.   So, to upgrade hte kernel to 3.2.28, I’d run the following commands on my Beaglebone:

wget http://rcn-ee.net/deb/precise-armhf/v3.2.28-psp21/install-me.sh
sudo bash install-me.sh

The script will download and install the kernel and related files (kernel modules, etc.).  The process should take about 5 minutes, depending on the speed of your microSD card.  If all goes well, the script should end with a reboot message:

. . .
`/boot/vmlinuz-3.2.28-psp21' -> `/tmp/boot/zImage'
 `/boot/initrd.img-3.2.28-psp21' -> `/tmp/boot/initrd.img'
 Please Reboot

Instructions for upgrading the kernel in other Ubuntu versions, and for other hardware architectures, can be found in other subdirectories of  http://rcn-ee.net/deb.  For example, if you’re running 11.10 Oneiric on your Beaglebone, upgrade instructions are in http://rcn-ee.net/deb/oneiric-armel/LATEST-omap-psp.  (In Ubunuese, “omap-psp” means Beaglebone, apparently.)

Enabling Analog Input

After booting your new image, you should find PWM, SPI and I2C in their expected file system locations:

ubuntu@omap:~$  ls /dev/i2c*
 /dev/i2c-1 /dev/i2c-3
ubuntu@omap:~$  ls /dev/spi*
 /dev/spidev2.0
ubuntu@omap:~$ ls -Fd /sys/devices/platform/omap/e*
 /sys/devices/platform/omap/ecap.0/ /sys/devices/platform/omap/ehrpwm.0/
 /sys/devices/platform/omap/ecap.1/ /sys/devices/platform/omap/ehrpwm.1/
 /sys/devices/platform/omap/ecap.2/ /sys/devices/platform/omap/ehrpwm.2/
 /sys/devices/platform/omap/edma.0/

Analog support has a twist: the file system interface is implemented in a kernel module, which isn’t loaded by default. To load it, enter the following command:

 sudo modprobe ti_tscadc

The file system interface should then be visible:

ubuntu@omap:~$ ls /sys/devices/platform/omap/tsc/a*
 /sys/devices/platform/omap/tsc/ain1 /sys/devices/platform/omap/tsc/ain5
 /sys/devices/platform/omap/tsc/ain2 /sys/devices/platform/omap/tsc/ain6
 /sys/devices/platform/omap/tsc/ain3 /sys/devices/platform/omap/tsc/ain7
 /sys/devices/platform/omap/tsc/ain4 /sys/devices/platform/omap/tsc/ain8

To have the kernel module loaded automatically when the Beaglebone is rebooted, enter the following commands:

ubuntu@omap:~ sudo -i
root@omap:~# echo ti_tscadc >> /etc/modules
root@omap:~# cat /etc/modules
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.

ti_tscadc
root@omap:~# sudo depmod -a

Wrapping Up

You should find that analog input, PWM, I2C and SPI all work the same way in Ubuntu as in Angstrom.  Code that you find for using these features on Angstrom will work on Ubuntu without any changes.  Here are a couple of articles I wrote on using analog input and PWM:

I’ve recently been using both SPI and I2C on the Beaglebone to write to LCDs from Python, and I plan to write articles on these in the future.

Posted in Electronics | Tagged , | 8 Comments

A New Nimbits Gadget: It’s About Time

I’ve just released an updated Google Gadget for monitoring your Nimbits data.

If you have no idea what that means, here’s a quick overview:

Nimbits has been updated several times since the first Gadget was released, most recently to version 3.2.  If you haven’t checked it out in awhile, you should head on over to their site to have a look around.  Among other things, you’ll find that each Data Point has a handy pop-up Report page that displays a chart and status information, and new integration options for WolframAlpha and SVG-based process diagrams.

While the Nimbits console is great for analyzing your data, for day-to-day monitoring I really like the iGoogle interface.  Using a gadget, you can plot all your data points in a few charts, leaving plenty of space for your e-mail, calendar, Twitter feed, hamster with OCD, and anything else you want to keep an eye on.

What’s New

I’ve added a number of enhancement to the gadget:

  1. It’s about time! The horizontal axis is now labelled with the date and time, making the chart much more meaningful.  You can now tell at a glance whether any of your data points have stopped updating, or had an outage in the past.
  2. The chart is rendered using Google’s newer Visualization API, similar to the one on the Nimbits Report pop-up.  It’s an interactive chart: you can position your mouse over any point in the chart to get a pop-up with its timestamp and exact value.
  3. Multiple data points can be plotted in the same chart (a feature that was in the original gadget, but was dropped a few months ago after a Nimbits upgrade).  If the data points use different scales, you can choose to plot some of them on a second axis on the right side of the chart.
  4. The Y axis is now automatically scaled to fit the data. That is, if all your data is between 500 and 600, the chart will automatically zoom in on the 500 to 600 range.

Getting Started

Before you can use the Gadget, you’ll need to create at least one data point on Nimbits.  To learn how to use the Nimbits’ user interface, click on the Learn link at the top of the Nimbits home page, or check out my (somewhat outdated) instructions in the Tweet-A-Watt: Beyond the Twitter, Part Deux article.  To learn how to write some code to post data to Nimbits, see the links on the right-hand side of the Nimbits home page.  For Python code that I’ve used in various projects, search my blog for “Nimbits”.

You can add the new Gadget to your iGoogle page using its entry in the Google Gadget Directory.

The Gadget will initially display a Settings dialog.   You’ll need to fill in at least 3 of the fields: a Data Point ID, your Gmail address, and the time span.

Settings

Server – If you are using the public Nimbits server, leave this field at its default setting of app.nimbits.com.  Otherwise, fill in site address of your personal Nimbits server (e.g. yournimbits.appspot.com)

Chart 1 Data Point – This field is used to add data points to the 1st chart in the gadget.

In the simplest case, where you want to plot just 1 data point, type its name into the Chart 1 Data Points textbox then click the Add button.  The data point name should then be listed below the textbox.

To add a second data point to the same chart, type in its name and click the Add button again.  The screenshot below shows a Settings dialog with 2 data points added  to the first Chart.

I’ve placed a (completely arbitrary) limit of 12 total data points in the gadget code.  So, for example, you could put 12 data points in the first chart (messy, messy), or 4 data points in each of 3 charts.   If you want to track more than 12 data points, you can add multiple copies of the gadget to your iGoogle page.

Chart 1 Right Axis – This text box is also used for adding data points to the first chart, but these ones will be plotted on a separate axis, on the right side of the chart.  This is useful if your data points are using 2 different numeric scales, such as temperature and humidity.  You can plot temperature on the left axis, and humidity on the right axis.  The following screenshot shows the settings for doing so, and the resulting chart.

Hey, I never said it would be pretty!  Personally, I prefer using separate charts for different measurement types.

Chart 2 Data Points, etc.  As you’ve no doubt figured out, these are for adding optional 2nd and 3rd charts to your gadget.  If you have multiple charts, you may want to adjust the size of the gadget in order to see them all — see Gadget Height, below.

Your Email.  Enter your Gmail address here.  Yes, I agree that its an egregious invasion of privacy, but otherwise the gadget won’t be able to figure out whose Data Points you want to see!  (You need a Gmail address, as opposed to other email providers, because Nimbits requires one.)  Those concerned about the security of their personal data can feel free to leave the e-mail field blank, in which case you’ll get a super-private empty chart.

Time Span and Time Span Units.  These fields determine how long a time frame is covered by the charts.  You can either specify either the # of hours or the # of readings — in both cases ending with the current time.  For example, if you specify 100 Readings, and select 2 Data Points, the chart will show the most recent 100 values logged for each of the Data Points.  There is no limit on the length of the time span, but too much data will affect performance.

Gadget Height.  The default of 240 pixels should allow 1 chart to fit in the gadget on any browser.  If you have multiple charts, and want them all to be visible, you should increase the height.  If not all of the charts will fit, a vertical scrollbar will appear to allow you to see the rest of the charts.

Other Features

Like all Google Gadgets, you can maximize the size of the gadget by clicking on the arrow icon at the right end of its titlebar.  This gives you a much more readable view of the data, especially if you have multiple data points in the chart:

Need more than 3 charts?  You can add multiple copies of the gadget to your iGoogle page. The settings for each are independent, so you can plot completely different data points in each one.

The gadget will automatically update the graphs from time to time — the interval is up to iGoogle and can’t be configured by mortals like us.  You can, of course, manually reload the iGoogle page to get more frequent updates.

Browser Compatibility

The gadget works (for me) in Chrome, Firefox and Internet Explorer.  Being based on Google technology, it renders the graphs fastest in Chrome.  Firefox is almost as fast, and the appearance of the chart is pretty much identical to Chrome.  Internet Explorer is noticeably slower and replaces Google’s chart fonts with its own – why can’t you two boys get along? — but is still quite usable.

Wrapping Up

I’ve been using the updated gadget for a couple of weeks now without any problems, so I hope it works well for you, too.  If you run into any problems, feel free to leave a comment or send me an e-mail.

I’m also open to suggestions for enhancements.  On my own To Do list are adding Settings to control how the date and time are labelled on the horizontal axis, and identifying the data points through properties other than its ID. (An, um, friend of mine made the mistake of labelling some of his Data Points Plant1Moisture, Plant2Moisture, etc.)

There are a lot of possible enhancements, because the Google Visualization Line Chart has a gazillion options. I found Google’s API to be quite fun to monkey around with, and it plugged into the Nimbits Data Series API without much coding effort.  I’ll write about the code and the basics of using the Google Chart Tools API in a future blog post.

Posted in Electronics, Software Tools | Tagged , | 1 Comment

Beaglebone Coding 101: Buttons and PWM

Update Dec 16 2012 – As pointed out in the comments, the PWM clock is activated by default in the current Angstrom version, Revision A6A.  If you are running this image, there is no need to use mmap to activate thte clock.  

My earlier articles [1, 2] on Beaglebone coding ignored one of the basics: digital input.  The main reason I skipped it is that the I only knew how to handle input by polling, and polling is lame.  I decided to wait until I had some Python code to handle input using interrupts, and write about that instead.

Well, here we are, a couple of months later, and … um … it turns out that polling is cool.  Interrupts are lame.  You know who uses interrupts?  Microsoft!  Need I say more?

I’ll also cover a relatively new addition to the Beaglebone’s kernel, PWM.

Digital Input

The Beaglebone has a number of pins that default to GPIO mode, and all of them are initially configured for input, not output: the receive feature is enabled, and the GPIO direction flag is set to “in”.

If you take a look at the pin mux settings for these pins, you’ll notice they are similar, but not the same.

For example, here is Port 8 Pin 3:

root:/sys/kernel/debug/omap_mux# cat 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

And here is Port 8 Pin 11:

root:/sys/kernel/debug/omap_mux# cat gpmc_ad13
 name: gpmc_ad13.gpio1_13 (0x44e10834/0x834 = 0x0027), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: gpmc_ad13 | lcd_data21 | mmc1_dat5 | mmc2_dat1 |
 NA | NA | NA | gpio1_13

Both pins are configured for Mode 7 (GPIO mode), but Pin 3′s mux setting is x37, and Pin 11′s is x27.

From the mux register description in the AM335x Technical Reference, we know that this means both pins are configured for input (Received enabled), but Pin 3 is set to use pullup resistors, and Pin 11 is set to use pulldown resistors.

By default, then, Pin 3 reads HIGH when nothing is connected to it, and Pin 11 reads LOW.

Sure enough, if we export the pin, then look at its value, we see that it is a 1 for Pin 3:

root:/sys/class/gpio# echo 38 > export
root:/sys/class/gpio# cd gpio38/
root:/sys/class/gpio/gpio38# cat value
 1

…and a zero for Pin 11:

root:/sys/class/gpio# echo 45 > export
 root:/sys/class/gpio# cd gpio45
 root:/sys/class/gpio/gpio45# cat value
 0

I have no idea why these default settings were chosen: possibly to give creators of capes more plug-and-play flexibility, possibly to give me yet another opportunity to write about mux settings, or maybe they just couldn’t decide.  However, when you hook up a circuit you really do have to make a choice.

With Pin 3′s setting, a button (or any other digital input device), needs to connect to Ground when the button is pressed.  If you connect it to a voltage pin, nothing good will come of it, but quite possibly a lot of bad.

The GPIO pins on the Beaglebone are quite fragile, compared to the Arduino‘s or Netduino‘s.   The Arduino is happy with 5V of input, but can also work with 3.3V.  The Netduino prefers 3.3V, but is 5V “tolerant”, meaning you can get away with it.  The Beaglebone, on the other hand, is decidedly intolerant of 5V.  Hook it up to 5V, even for a split second, and it will die.  I wish I could say that I learned this by reading about it, but you can trust me on this one.

The GPIO pins are also more delicate than the Arduino when it comes to current.

According to this post  by Beaglebone hardware designer Gerald Coley, the recommended max output current through a pin is 4-6 mA, and the max input current is 8 mA.  On the Arduino, it is 40 mA.  (Based on my own experience, the Beaglebone seems to be tolerant of higher currents: I’ve measured 60 mA coming out of a GPIO pin.  That was a different Beaglebone than the one that died, by the way. What can I say: I’m the Michael Vick of electronics!)

For this reason, I think it’s safest to configure a digital input pin with a pull-up resistor, and connect the button to ground.  If you go the other way and use a pull-down resistor, be very certain you don’t accidentally hook it up to the 5V pins, and be sure to use an external resistor too – the internal pull-down resistor won’t knock down the current for you.

The photo below shows 2 pushbuttons connected to 2 GPIO pins: Port 9 Pins 12 (purple wire) and 15 (green wire).

Pin 12 is configured with a pull-up resistor by default.  (Note that there is a typo in the System Reference Manual: the pin name is gpmc_ben1, not gpmc_be1n. )

root:/sys/kernel/debug/omap_mux# cat gpmc_ben1
 name: gpmc_ben1.gpio1_28 (0x44e10878/0x878 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: gpmc_ben1 | mii2_col | NA | mmc2_dat3 | NA | NA | mcasp0_aclkr | gpio1_28

So, the circuit for connecting a button is quite simple:

  • Pin 12 to Button (purple wire)
  • Button to Ground

When the button is pressed, the value will change from 1 to 0, making the button behave like a normally closed button (unless you actually have a normally closed button – hey, so that’s what those crazy NC buttons are for!). Be sure to account for this in your code.

root:/sys/class/gpio# echo 60 > export
root:/sys/class/gpio# cd gpio60
root:/sys/class/gpio/gpio60# cat value
0

Pin 15 is, by default, configured to use pull-down resistors.

root:/sys/kernel/debug/omap_mux# cat gpmc_a0
name: gpmc_a0.gpio1_16 (0x44e10840/0x840 = 0x0027), b NA, t NA
mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
signals: gpmc_a0 | mii2_txen | rgmii2_tctl | rmii2_txen | NA | NA | NA | gpio1_16

You can, of course, change that mux setting if you want to use the same simple button circuit as with Pin 12, but for the sake of variety I’ve hooked it up as-is:

  • Pin 15 to button
  • Button to 1K resistor
  • Resistor to 3.3V

The resistor value is actually quite unimportant, as long as it’s 550R or higher.  While the Beaglebone’s GPIO pins don’t like high current, they have no problem with very low current, so 1K, 10K or 100K resistors should all work.

With the button connected to Pin 15 held down, we get a value of 1:

root:/sys/class/gpio# echo 48 > export
root:/sys/class/gpio# cd gpio48
root:/sys/class/gpio/gpio48# cat value
1

As promised, I’ll be showing some code that reads the buttons using some cutting edge polling technology, but first let’s take a look at PWM.

Enabling PWM Support in the Kernel

PWM support was added to version 3.2 of the Angstrom kernel.  (I believe it was initially in 3.2.0, but I didn’t start working with it until 3.2.6.)  These kernel updates were delivered via opkg updates in February.

Unfortunately, while opkg delivers the new kernels, it doesn’t activate them.  That requires some manual intervention.  Let me walk you through it…

First, check what kernel version you are currently running

root:~# uname -r
3.2.6+

If you have 3.2.6+ (or later), then great, you’re ready to go.  Skip ahead to the Activating the PWM Clock section below.

Otherwise, you’ll need to update the kernel.

[Update Sept 11: I just switched to the latest Angstrom image (stamped 2012.08.14) from the demo files page, and found -- to my shock and awe -- that the process of upgrading the kernel is a lot simpler.  Just, update the packages and reboot:

okg update

opkg upgrade

shutdown -r now

This brought me from kernel version 3.2.25 to 3.2.28.  Groovy!  

This is news to me, so I don't know whether you're likely to have the same experience in other Angstrom images. If you don't get the kernel automagically installed through this method, then read on...]

Check to see what kernels have been installed by opkg:

root:~/tmp# ls -l /boot
total 12180
-rwxr-xr-x 1 root root      33 Feb 14 18:31 uEnv.txt
lrwxrwxrwx 1 root root      13 Mar  7 20:26 uImage -> uImage-3.2.9+
-rw-r--r-- 1 root root 3042328 Jan 26 12:49 uImage-3.1.0+
-rw-r--r-- 1 root root 3135840 Feb 10 03:57 uImage-3.2.0+
-rw-r--r-- 1 root root 3137472 Feb 22 05:37 uImage-3.2.6+
-rw-r--r-- 1 root root 3140088 Mar  6 13:47 uImage-3.2.9+

Right now (mid March), the latest and greatest is 3.2.9+.

If you don’t have the 3.2.x kernels listed in /lib/modules, then be sure to update your packages:

opkg update
opkg upgrade

If the opkg fairy still didn’t leave a new kernel under your pillow, then you might need to upgrade to a new image on the SD card.

Currently, the latest image is the February 14th “2012.02” version, which shipped with Revision 5 of the Beaglebone.  You can download it from the Beaglebone Demo page  or from CircuitCo .  Circuitco’s page has instructions for installing the image to an SD card using Windows.  This image comes with the 3.2.5+ kernel, which supports PWM, but after giving it a spin you’ll probably want to go ahead and upgrade to the latest kernel anyway.

When opkg delivers the kernels, it doesn’t install them.   To start using a new kernel, you need to manually install it onto the boot partition of the SD card – you can easily do this right from the Beaglebone command prompt.

Begin by mounting the boot partition.  You need to use a directory as a mount point: I’m using one called tmp:

root:~# mkdir tmp
root:~# mount /dev/mmcblk0p1 tmp

If you look at the mount point, you should see the following files:

root:~# ls tmp
Docs     LICENSE.txt  README.htm    u-boot.img  uImage
Drivers  MLO          autorun.inf  info.txt    uEnv.txt

Overwrite the uImage with the latest kernel file from /boot:

root:~# cp /boot/uImage-3.2.9+ tmp/uImage

Unmount to make sure everything is nicely tucked away on the SD card, then reboot:

root:~# umount tmp
root:~# shutdown -r now

After rebooting, your system should report the new kernel:

root:~# uname -r
3.2.9+

Activating the PWM Clock

Update Dec 16 2012 – As pointed out in the comments, the PWM clock is activated by default in the current Angstrom version, Revision A6A.  If you are running an up-to-date Angstrom image, you can skip this section.

By default, the 3.2 kernel supports PWM, but doesn’t enable it.  If you try to use it through the file system, you’ll get “segmentation errors” and a lot of other moaning and groaning from the kernel.

As explained in this post on the Beagleboard group, the PWM clock needs to be enabled before you start using PWM.

The clock control register is documented in the AM335x Technical Reference Manual as follows:

The clock register isn’t exposed through the file system, so the only way to change this setting is by directly updating the register in memory.  Fortunately another post in the Beagleboard group provided the necessary code:

I’ve put a copy of the code here.  To run it on the Beaglebone:

root:~# opkg install python-mmap
root:~# wget http://www.gigamegablog.com/docs/setPWMReg.py
root:~# python setPWMReg.py

You should see:

Register CM_PER_EPWMSS1_CLKCTRL was 0x30000
Register CM_PER_EPWMSS1_CLKCTRL changed to 0x2

So, the IDLEST field is initially set to Disable – the code clears that field, and set the MODULEMODE field to ENABLE.

Having got the clock up and running, we’re ready to control the PWM settings through the file system.

Controlling PWM Using the File System

There are 2 pins on Port 9 that, by default, are configured for PWM, Pins 14 and 16.  The Beaglebone System Reference manual identifies these as EHRPWM1A and EHRPWM1B; to the file system, they are ehrpwm.1:0 and ehrpwm.1:1, respectively.

The “EHR” part means Enhanced High Resolution.  There is also a second type of PWM pin on the Beaglebone, called ECAP, or Enhanced Capture.  The 2 types of PWM pins have similar settings exposed through the file system, as explained in the AM335x PWM Driver’s Guide on the TI web site.

To me, the most important difference between the 2 type of PWM is that I can’t get ECAP to work.  So, let’s give the EHR PWM a whirl.

A good way to experiment with the PWM settings is to connect the positive pin of an LED to one of these pins, and negative pin of LED to ground.  You can safely do so without using a resistor, assuming the LED can be powered by the 3.3V that comes out of these pins.

A garden variety red or white LED should be fine – in the photo below, I have a red LED connected to pin 14.

[Updated Apr 25: Added the mux mode settings] 

For starters, set the mux mode settings for the 2 pins to Mode 6 for EHRPWM:

root:~# echo 6 > /sys/kernel/debug/omap_mux/gpmc_a2
root:~# echo 6 > /sys/kernel/debug/omap_mux/gpmc_a3

There are a variety of PWM settings exposed through the file system, as described in the PWM Driver’s Guide, but the two key ones are period_freq, which is the frequency in Hz, and duty_percent, the duty cycle setting.

The following will blink the LED slowly, once per second: [Updated Mar 25: Before changing the period_freq  setting, duty_percent should be set to 0.  Otherwise, the value of duty_percent might be (silently and mysteriously) reset to another value]

root:~# cd /sys/class/pwm/ehrpwm.1:0
root:/sys/class/pwm/ehrpwm.1:0# echo 0 > duty_percent
root:/sys/class/pwm/ehrpwm.1:0# echo 1 > period_freq
root:/sys/class/pwm/ehrpwm.1:0# echo 50 > duty_percent
root:/sys/class/pwm/ehrpwm.1:0# echo 1 > run

The following settings will cause the LED to glow dimly [Corrected Mar 20]

root:/sys/class/pwm/ehrpwm.1:0# echo 0 > run
root:/sys/class/pwm/ehrpwm.1:0# echo 0 > duty_percent
root:/sys/class/pwm/ehrpwm.1:0# echo 200 > period_freq
root:/sys/class/pwm/ehrpwm.1:0# echo 20 > duty_percent
root:/sys/class/pwm/ehrpwm.1:0# echo 1 > run

To make the LED glow more brightly:

root:/sys/class/pwm/ehrpwm.1:0# echo 80 > duty_percent

It’s safe to change the duty_percent setting on the fly, without changing the other settings first.

The TI guide advises checking the availability of the PWM pin first:

root~:/sys/class/pwm/ehrpwm.1:0# cat request
 ehrpwm.1:0 is free

I haven’t seen it return anything except “free” yet, so I’m not sure under which circumstances it returns “busy”.  But, feel “free” to check.

With the second PWM port, right next door,  I decided to try a high-power LED with this one, the CREE XLAMP. This is actually a good use of PWM, since without it the CREE’s brightness makes it a pain to work with.  (I blinded me with science!)

Here, the GPIO pin’s current restriction is a problem: the CREE won’t even flicker with the max recommended output current of 6mA.  The 300 mA that flows out of the 3.3V port will do the trick, though.

To control the flow using PWM, you can use a transistor.  I used a common NPN “switching” transistor, the 2N2222.

The base of the transistor can be connected to the PWM pin, through a resistor. The resistor keeps the current within the recommended 4-6 mA for a GPIO pin.  I used a 1K resistor, but as with the digital input sensors the exact value doesn’t matter as long as you’re above 550R:  you don’t need much current to control the transistor base.

  • Pin 16 to 1K resistor.
  • Resistor to Base
  •  3.3V to positive pad of XLAMP
  • Negative pad of XLAMP to Collector of 2N2222
  • Emitter of 2N2222 to ground

With this circuit, and a duty cycle of just 1%, the XLAMP is no longer blinding (though still surprisingly bright).

A couple of things to note about the frequency setting:

  • Corrected Mar 21: As pointed out by muhoo in the Comments section, you can take the PWM frequency well past 250 Hz.  The key is to set the duty_cycle to zero before changing the frequency.  I’m not sure what the actual maximum frequency is, but the file system allows it to be set to 10 Mhz:
# echo 0 > run
# echo 0 > duty_percent
# echo 10000000 > period_freq
# echo 50 > duty_percent
# echo 1 > run
# cat period_freq
10000000
# cat period_ns
100

  • The maximum is 250 Hz.  I actually couldn’t find this documented anywhere, but currently setting it to anything above that value returns an error message.  (There is an alternative setting of period_ns, but the minimum for that is 4 million – same difference.)
root:/sys/class/pwm/ehrpwm.1:0# echo 251 > period_freq sh: echo: write error: Invalid argument
  • The frequency setting is shared between ehrpwm.1:0 and ehrpwm.1:1 — if you change it for one, the other will be automatically set to the same frequency.  So, unlike the duty_percent, you’ll probably want to set the “run” flag to 0 for both PWM devices before changing it.

Programmer’s Show And Tell

There aren’t many interesting ways to combine digital input and PWM output, and I’ve set out to prove this with some sample Python code  I’ve used one of the buttons and the 2 PWM-driver LEDs from earlier in the article.  Press the button and the lights come on.  Press and hold the button, and light state toggles between on and off.  Whee!

You can download the program from my Google Code site.

There are, however, a few things worth pointing out in the code.

Firstly, I’ve (ahem) borrowed the pin mode table from bonescript in order to implement Python versions of pinMode, digitalRead and digitalWrite .

Python’s Dictionary is an easy-going data type: you can store anything in it, including another dictionary.  This  is similar to node.js, so the syntax of the bone_pins definition is almost identical to its bonescript counterpart:

bone_pins = { "P8_1": { "name": "DGND" },
 "P8_2": { "name": "DGND" },
 "P8_3": { "name": "GPIO1_6", "gpio": gpio1+6, "mux": "gpmc_ad6", "eeprom": 26 },
 "8_4" : . . .

Adding more information to a pin definition is just a matter of adding another entry to the dictionary.  So, to extend the table to include PWM pins, I just added a “pwm” key …

"P9_14": { "name": "EHRPWM1A", "gpio": gpio1+18, "mux": "gpmc_a2", "eeprom": 34, "pwm" : "ehrpwm.1:0" },
 "P9_16": { "name": "EHRPWM1B", "gpio": gpio1+19, "mux": "gpmc_a3", "eeprom": 35, "pwm" : "ehrpwm.1:1" },

To check if a pin supports pwm:

if not "pwm" in bone_pins[pin]:
   print "ERROR: pin %s does not support PWM" %  pin

Like node.js, Python provides a command line for experimenting with code without running the full application. So, you can take advantage of these functions by loading the module, then calling the functions manually.

This is somewhat quicker and a lot easier than controlling the settings from the Linux command prompt.  For example, to set Port 8 Pin 5 for input, then check the current input value (you’ll need to run python from the directory that contains ButtonsAndLights.py):

root:~# python
>>> import ButtonsAndLights as bb
>>> bb.pinMode("P8_5", "in")
 setting /sys/kernel/debug/omap_mux/gpmc_ad2 to 0x37
 getting direction /sys/class/gpio/gpio34/direction
 exporting GPIO 34
 Exported /sys/class/gpio/gpio34/direction is in

 >>> bb.digitalRead("P8_5")
 /sys/class/gpio/gpio34/value is 1
 1

The extra “verbiage” are some print statements in the Python code for debugging purposes – I haven’t fully cleaned up the code yet to make it more usable as a plug-in module. For a more polished and better performing Python implementation of digital I/O functions, take a look at PyBBIO.  This code interacts with the GPIO pins using direct register access, rather than the file system, so PyBBIO should prove much faster, perhaps fast enough to handle the microsecond-level timing needed to implement device drivers.

I’ve also implemented pwmMode, pwmStart and pwmStop functions.  (This time I didn’t go with the Arduino naming convention – I can’t bring myself to refer to PWM as “analogWrite” like those bohemian Arduinoists.).

def pwmWrite(pin, frequency, duty_cycle, start = True):
 """ Changes settings of specified PWM pin (e.g. "P9_14") and optionally enables it.
 Note that frequency and duty_cycle can be omitted to leave them unchanged """

def pwmStart(pin):
 """ Turn on PWM on the specified pin. PWM settings must previously have been passed to pwmWrite() """

def pwmStop(pin):
 """ Turn off PWM on the specified pin """

These, too, can be used from the Python command line.  To set Port 9 Pin 14 to run at 200 Hz 80%:

>>> bb.pinMode("P9_14", "pwm")
 setting /sys/kernel/debug/omap_mux/gpmc_a2 to 0x6
>>> bb.pwmWrite("P9_14", 200, 80)
>>> bb.pwmStart("P9_14")

Last, and least, there is the polling for digital input:

lastButtonState = digitalRead(BUTTON_NC_PIN)
while 1 == 1:
    buttonState = digitalRead(BUTTON_NC_PIN)

    # NOTE: will return another value if unable to read
    if buttonState == HIGH or buttonState == LOW: 
         if buttonState != lastButtonState:
         # do stuff
    time.sleep(BUTTON_POLL_INTERVAL / 1000.0)

While polling is, um, rather quaint, the AM335x is fast enough that it doesn’t significantly slow things down – the polling done in the sample code, once every 250 ms, spends about 99% of its time sleeping.

However, polling becomes somewhat less quaint when you’ve got a lot of digital inputs or sensors to keep track of, so I’m still looking for an interrupt driven solution for GPIO pins.  If anyone has that working from Python on a Beaglebone, please let me know.

Wrapping Up

These are still early days for the Beaglebone, and some of the basic building blocks for hobbyists are yet to fall in place.  No big surprise, of course: when the Arduino first appeared (back in the day, naught-5 I believe it was) it lacked libraries for things like LCDs and I2C sensors, but over the next few years those were written and became standardized.

But I’ve noticed quite a few interesting projects over the last month pushing out the boundaries of what can be done with userspace applications, like the aforementioned PyBBIO project,  and this bonescript project that writes to a Nokia 5110 display.

The kernel continues to leap ahead with new releases every few weeks: kernel maven Koen Kooi recently posted a proposed roadmap for what lies ahead.

The Beaglebone has also popping up on some popular hobbyist sites, like Make Magazine and Hack-A-Day.

It’s quite fun to watch a platform grow from the ground up!

Posted in Electronics, Programming | Tagged , , | 68 Comments

Beaglebone Linux 101: Assigning a Static IP Address with Connman

My article on configuring Angstrom Linux included instructions for setting a static IP address. Sometime after posting that article, I realized that the instructions work great unless you happen to reboot. Then, the settings reverted to the default of using a DHCP server.

Ooops!

It turns out that this sleight-of-hand is the work, aptly enough, of a package named Connman.

This newfangled connection manager is, in some ways, a good fit for the Beaglebone, since it was designed to run on memory-constrained embedded Linux systems. It was originally developed for use on 2 Linux platforms that have struggled, Meego and Moblin, but we won’t hold that against it.

However, Connman presents one big problem for Beaglebone users: it’s rather difficult to configure from the command line.

It doesn’t come with a command line configuration tool, but it does provide some well documented APIs that command line applications can use. As such, the best command line interface right now can be found in a package intended to test that the APIs are working correctly: connman-tests.

To install the package:

opkg install connman-tests

This will install a set of Python scripts in /usr/lib/connman/test.

To check your current configuration:

cd /usr/lib/connman/test/
./get-services

The output should look like the following:

[ /net/connman/service/ethernet_405fc276b749_cable ]
 IPv6.Configuration = { Method=auto Privacy=disabled }
 AutoConnect = false
 Proxy.Configuration = { }
 Name = Wired
 Nameservers = [ 206.47.244.104 206.47.199.155 ]
 Provider = { }
 Favorite = true
 Domains.Configuration = [ ]
 State = online
 Proxy = { Method=direct }
 Nameservers.Configuration = [ ]
 LoginRequired = 0
 IPv6 = { }
 Domains = [ lan ]
 Ethernet = { Interface=eth0 MTU=1500 Method=auto 
Address=xx:xx:xx:xx:xx:xx }
 Security = [ ]
 IPv4.Configuration = { Method=dhcp }
 Type = ethernet
 Immutable = false
 IPv4 = { Netmask=255.255.255.0 Gateway=192.168.1.1 
Method=dhcp Address=192.168.1.161 }

The important thing to note here is the service ID at the top of the output, in my case  ethernet_405fc276b749_cable.  (Dumb name for an ethernet cable, if you ask me.)

You can also get the DNS nameserver and gateway IP addresses from this output, if you don’t already know them.

To change the configuration, you use 2 other scripts, set-ipv4-method and set-nameservers.

The syntax for set-ipv4-method is:

./set-ipv4-method <service> [off|dhcp|manual <address> [netmask] [gateway]]

The service parm is that long string that appears at the top of the output from the get-services script.

So, to set the Beaglebone to use a static IP address of 192.168.1.2, with a gateway of 192.168.1.1, I entered:

./set-ipv4-method ethernet_405fc276b749_cable manual 
192.168.1.2 255.255.255.0 192.168.1.1

To set the DNS nameservers, use set-nameservers.  The syntax is:

./set-nameservers <service> [nameserver*]

In my case, I entered

./set-nameservers ethernet_405fc276b749_cable 206.47.244.104 
206.47.199.155

That’s it: after entering those 2 commands, you’ll be running with the new network settings, no reboot required. (Though, if you plan to blog about it, a reboot is definitely recommended!)

Posted in Gadgets | Tagged , | 19 Comments