Gumstix Overo, RC Servos, and PWM Signal Generation

What I want to do: Control RC Servos from a Gumstix Overo

I have a project where I need to drive standard RC servos from a Gumstix Overo.  It doesn’t appear that the Overo ships with any built in PWM drivers.  I did quite a bit of googling, and still couldn’t find a single drop-in driver that worked well for driving RC servos.  I did find some great help though, rolled up my sleeves, and stitched pieces together to make the mother of all RC servo drivers.
Scott Ellis @ jumpnowtek.com has a nice introduction to programming the Overo hardware PWM signal generators: http://www.jumpnowtek.com/index.php?option=com_content&view=article&id=56&Itemid=63
The Overo has 4 available PWM signal generators on 4 specific GPIO lines.  Scott provides a simple driver that demonstrates how to configure PWM10 to generate a signal at any frequency and duty cycle.

What is PWM?  Frequency?  Duty Cycle?

PWM stands for “pulse width modulation”.  It is a common approach for computer servo control.  Essentially the computer sends a short signal pulse (raises the signal line high.)  The exact length of this pulse tells the servo where to position itself.  The computer sends the pulse at a regular rate and varies the “width” (or the time span) of the pulse to control the position of the servo.  This is how all standard RC servos work.  The number of pulses we send per second is called the “frequency”.  Typical RC systems use a frequency of 50hz.  The ratio of the on versus off time of the signal is called the “duty cycle”.  A duty cycle of 0% means no pulse at all.  A duty cycle of 100% means the pulse is always on.

For a standard RC system running at 50hz, there will be a pulse generated every 20,000 us.  (1 sec = 1,000,000 us; and 1,000,000us / 50hz = 20,000us).  The pulse length to center a servo is 1500 us and the useful pulse range to run the servo through it’s full range of motion is about 1000 us – 2000 us.  If you send a 1500us pulse every 20,000us, then the duty cycle is 1500 / 20,000 or 7.5%.  The duty cycle range for controlling a servo at 50hz is then between 5% and 10%.

Scott Ellis’s “Basic” PWM Kernel Driver

Scott Ellis on the page linked above makes a basic pwm.c driver available.  This driver only sets up one PWM (PWM10 aka GPIO145).  This is routed to pin 28 on the “standard” 40 pin breakout header included on many overo expansion boards.  This was a great start, but has some limitations.

  • It only supports one PWM line (PWM10)
  • Duty cycle is entered as an integer percentage.  RC servos operate across the range of about 5-10% so that only gives me 6 unique positions, not nearly the granularity I want

Signal (Logic) Level Translation

A quick note on something that can turn into a really tricky headache for newcomers to the Overo.  The Overo uses 1.8v logic for all it’s output.  This means that even though you are generating a perfect PWM signal to drive your servo, nothing will probably happen because the servo is expecting 3.3v (or maybe even 5v) signal logic.  It may not see or respond correctly to 1.8v logic.  This is also a more general issue for any external communication with the gumstix overo and is something embedded hardware engineers encounter every day.  There are many ways to address this issue, but one quick and easy solution is to buy a logic level converter from sparkfun.com: http://www.sparkfun.com/products/8745

This sparkfun board supports level shifting for 4 lines at the same time.  I soldered 0.1″ male header pins onto both sides and then used sparkfun 6″ single wire jumpers to connect things together.  It is slick and relatively easy and with the color coded wires it even looks cool, especially on a glass desk with the office lights off and all the LED’s blinking.  🙂  All you have to do is tie your grounds together.  Then connect 1.8v (pin #16 on the 40 pin header) to the LV side.  Connect 3.3v (pin #2 on the 40 pin header) to the HV side, and then pipe the signal line through to the servo.  Despite the RX/TX labelling, I believe the signal conversion is bi-directional on the latest version of this sparkfun level shifter board.

Jack Elston’s Driver Extension to Support all Four PWM Lines

Scott emailed me an update to his pwm.c which expands support to all 4 hardware PWM signal generators.  This is a great next step.  However this version of the driver also had some limitations:

  • PWM10 and PWM11 used the 32Khz clock (which is the default).  Leaving the details aside, the 32Khz clock can only achieve about 32 unique positions across the typical RC servo range of motion.
  • I believe there is some integer overflow for PWM8 and PWM9 when computing the duty cycle which leads to odd results.
  • Part way into the project I decided I wanted to generate PWM pulses with sub us resolution.

13Mhz Versus 32Ghz Clock

Scott Ellis to the rescue again.  Scott emailed me an older testing driver he had built called “pulse.c” (note: Scott makes all his drivers available github.com under the GPL license.)  The pulse.c driver includes code to set the PWM10 and PWM11 timers to use the 13Mhz clock.
The 13Mhz clock allows us to have 259,998 duty cycle steps.  In other words 0 corresponds to 0% duty cycle and 259,998 corresponds to a 100% duty cycle.  Since an RC servo is expecting a 5-10% duty cycle at 50hz, this gives us a numeric range of about 13,000 values to work with.  We are interested in a pulse with range of 1000-2000us (a range of 1000us) so 1000us / 13,000 step sizes gives us better than 0.1us resolution.
0.1 us resolution gives us 10,000 unique positions across the range of motion of a typical RC servo.  For reference, if we were driving a pan servo on a camera system that was setup for 180 degree coverage, we would have approximately 0.02 degree resolution.
Now, whether or not an RC servo can resolve input signals down to this level of accuracy is a different discussion, but servo technology does continue to improve steadily.

Integer Overflow!

Integer overflow is never any fun.  The math proceeds without reporting any errors and you get the wrong answer.  Grrr.  Note that INT_MAX for an unsigned 32bit integer is 4294967295.  tmar is the integer duty cycle percentage ranging from 0 to 259,998.  num_freq is the max number of duty cycle steps (in our case 259,998 for the 13Mhz clock.)  The formula to compute the tmar value is then: pulse_us * frequency * num_freq / 1000000.
Here’s the problem, when computing this formula with a pulse of 1500us, you get an intermediate value of 19499850000 before dividing by 1,000,000.  This is way larger than INT_MAX so the math wraps around and the result after the divide is totally wrong.
As a work around I observe that frequency (50) divides evenly into 1,000,000 so I can rearrange terms and do that division first.  This keeps all the intermediate values less than INT_MAX.

Getting to 0.1 us Resolution

So far so good if I’m specifying integer us pulse widths to the kernel.  However I want to have 0.1 us resolution because the 13Mhz clock offers that level of resolution.
Doing floating point math inside a kernel driver is considered bad form, and you have to do a lot of horsing around just to get proper machine code generated and linked with the right libraries.  We don’t want to go there, so no floating point.
Instead I will specify timing values in 10ths of a us.  So to request a 1500us pulse I would write a value of 1500us*10 or 15,000.  Writing a value of 15,001 to the driver will give me a 1500.1 us pulse.
Back to integer overflow again.  Specifying a larger input value in the range of 10,000 to 20,000 suddenly pushes me back into integer overflow territory with my intermediate values.  259,998 / INT_MAX = 16519.2 so any pulse longer that 1651.9 us will push me back into int overflow.  The solution is that I observe that 259,998 is divisible by 2, so I can pre-divide this number by 2 and earlier divide 1,000,000 by 2 to get an equivalent answer.  This allows me to specify signal widths of up to 3303.8 us which is well beyond that standard RC range again.  I realize this is a pretty specific solution for this particular hardware and this particular clock frequency, but when dealing with embedded systems, you often have to get specific.

What’s so special about 259,998?

When dealing with low level hardware and clocks, you end up running into very odd ball numbers that some CPU hardware designer somewhere must have thought was cool.  259,998 is an annoying number.  Prime factorization is 2 • 3 • 17 • 2,549.  This means it’s hard to divide evenly with anything and it can be a challenge to try to simplify integer math expressions to eliminate intermediate integer overflow!
Observe that 259,998 * 50hz = 12,999,900.  In computers, kilo often refers to 1000 and mega refers to 1,000,000.  So 12,999,900 / 1,000,000 = 12.9999 Mhz.  Let’s round that up to 13 and I think you see this is the number of clock ticks per second a 13Mhz clock generates.  259,998 is the number of ticks per 1/50 of a second.  (You see, it all makes perfect sense!)

Getting the Updated Driver Code (Driver to Command and Control 4 High Resolution PWM Signals on a Gumstix Overo)

Scott was kind enough to commit my version of the pwm driver to a branch of his omap3-pwm project on github.  You can access the branch here (called “four-channel”):  https://github.com/scottellis/omap3-pwm/tree/four-channel

Future Enhancements

Scott suggested that a nice extension would be to allow the user to select which of the 4 PWM channels are activated and configured when the module is loaded (or via a platform device whatever that is.)

Fedora 15 and Gnome 3

This weekend I took the plunge into Fedora 15 with Gnome 3.  This is a major change from previous versions of Fedora.

Overview

Fedora 15 is very different from previous Fedora releases.  The main reason is the upgrade to Gnome 3 which is entirely different from Gnome 2.  In Gnome 3 your entire desktop experience is completely (and I say completely) changed.  This is no small thing.  As with any change, there is good and bad; some things I like, some things I miss.

Cool thing: gnome-shell

The gnome-shell is something new in Gnome-3.  This isn’t a “shell” in the classic unix sense.  Instead it is really your desktop or your graphical user interface experience.  If you are coming from windows or previous versions of Linux, you might be in for some initial system shock!  Life suddenly got way different.  If you’ve ever used a Mac, you might think Gnome 3 is more Mac like than anything else.

Cool thing: Windows map + dual head display

Hey this is cool: when I press the “windows” modifier key on my keyboard, it pops up a map of my windows and workspacers.  In my primary display (on the left) I see all the windows from my current workspace.  In the secondary display (on the right) I see a selection of my my most commonly used windows from my other workspaces.  Neat feature!  On the right hand side of the primary display I get a map of all my workspaces and windows.  This makes it very quick to find an app or window, move things to different workspaces, etc.

Cool thing: Application launching

If you’ve ever used a modern mac, you’ll have gotten used to a different way of finding apps and launching them.  Gnome-3 follows this general style.  The “start menu” is completely gone with no hint of it left.  Instead you have an applications folder with all your apps.  You can select different categories to limit the options, or start typing part of the name in the search box.  If you have a collection of apps you use quite often, you can pin them on your activities bar so they are always handy to find when you need them.

Cool thing: Desktop recording

Alt+Ctrl+Shift+R – this toggles desktop recording on/off.  You’ll see a little red “record” icon in the far lower right corner of your display to indicate if recording is active.  I sometimes like to record movies of my FlightGear flights so I’ll have to see what kind of performance I can get with this feature.

Cool thing: Dynamic workspace allocation

Coming from the gnome-2 world, I spent quite a bit of time googling & trying to figure out how to configure more than 2 workspaces on my desktop.  (Normally I like to have 6 workspaces for grouping all the windows/apps related to different kinds of tasks.)  Well it turns out that the gnome-3 shell dynamically allocates workspaces on the fly … so you always have one more empty work space.  You can use Alt-1, Alt-2, … Alt-n to hot key between workspaces. When you launch an app from the app folder or the dock, you can middle click on it to launch on the last (empty) workspace. I don’t call any of these things “intuitive”, but once you get the hang of this new way to do things and “understand” the way gnome-3 thinks, it’s slick, and quick, and it’s growing on me quickly.

Cool thing: Desktop search

When you press the “windows” special key on your keyboard or mouse up to the activities corner of your workspace, a search box pops up.  You can start typing anything in this box.  Immediately (and as you type) you are presented with items that match: Applications, Settings, Places and Devices, and event Recent Items (files) from your hard drive.  I’m sure I will still have trouble finding that critical misplaced file when I need it (because I forgot the name, or forgot to copy it from my laptop, etc.), but this should be another great tool for quickly finding what you need when you need it.  I haven’t figured out what qualifies as a recently used file or how the indexer works or what it indexes.  I would like to understand that better.  I’ve seen hints that in the next release of gnome, the search indexer might be expanded to include file contents and not just file names.

Issue: Some things I miss

The new graphical interface gives up some things I have become used to and depend on:

  • The “start menu” is gone.  It’s replaced by an applications folder with application icons that is much more Mac-like (or maybe like a tablet or smart phone application selector.)
  • All my desktop icons and files are gone.  Gnome-3 doesn’t let you litter your desktop with 100’s of files and shortcuts stacked on top of each other any more.  This is distressing.  I like my messes, I like them a lot, I know where to find things!  [Edit] See comment from “AceRoom” below: apparently it is possible to get your desktop icons back if you wish.
  • The trash can on my desktop is gone (now moved to the file manager window.)
  • The “status bar” at the bottom of the screen is gone.  No longer can I see what apps are running on what workspace at just a glance.
  • The “status bar” at the top of the screen is changed.  Now it shows the current app, the time, and a few little icons way to the right.  That’s it.
  • Gnome widgets are gone.  I can’t have a weather applet in my top status bar any more.  Why?  There’s tons of room for stuff like this?  Maybe they will add it later?  Maybe they won’t?  Guess I’ll have to keep my phone handy so I can check the weather when I need to.
  • There’s no date displayed on the status bar of the desktop.  You have to click on the time to see the calendar and remind yourself of the date.
  • So far I haven’t seen if/where the little notification icon comes up to let me know there are new software fixes available to install.  I have been running “yum update” manually to keep my system current.
  • [Edit] Fedora has switched from Open Office to Libre Office.  After a couple spot checks, I haven’t noticed any problems working with office documents.  http://en.wikipedia.org/wiki/LibreOffice#History

Issue: Misleading screenshots on fedoraproject.org?

Minor nits, but when I go to the fedoraproject.org web site and look at the screenshots of fedora 15 … many of them are obviously fedora 14 and bear no resemblance to what fedora 15 looks like.  The web site also advertises a non-linear video editing tool.  That doesn’t show up in the install or anywhere I can find it.  Maybe last minute issues?  I can write these off as oversights, but I usually expect a little better from fedora … they are usually a pretty classy outfit with their act together pretty well.

Issue: Dual head display and workspaces

Problem: I run two displays on my desktop PC.  This was detected by default, however, any window that was at least 50% on the secondary display became “sticky”.  In other words, when I switch workspaces (a key aspect of my daily work flow), all the windows on the second display would follow to every workspace. If I was doing a presentation on a laptop and the second display was a projector, then this would make perfect sense.  But for my daily work, it’s absolutely the wrong way and very annoying.

Solution: Fortunately (as is often the case) a little bit of googling turned up a solution.  The recommendation is to “yum install gconf-editor”, then run it from a terminal.  Navigate to: Desktop->Gnome->Shell->Windows and you should see an option called “workspaces_only_on_primary”.  Uncheck this option.  It will not immediately take effect though, you will need to log out and back in.  Now both displays will participate in workspace switching.

Issue: No audio on Asus M4A88TD-V EVO/USB3 motherboard (Realtek 892) and Kernel 2.6.38

Problem: After the upgrade to Fedora 15, all I hear are random clicks and pops.

Solution: I tried a bunch of things with no progress.  Then I did a complete power cycle and my sound came back.  Weird.  First time I’ve had trouble with the onboard audio with this machine, but I’m back up and going so <whew>.

Tell me where I’m wrong!

If I haven’t discovered a cool gnome-3 or fedora-15 feature yet, please tell me about it.  If something I have an issue with is handled in a different or better way let me know!  I’m learning as I go and I’d love to hear your feedback.  Thanks!