Sunday, 30 December 2012

Controlling servos from a computer

The Pololu Maestro is a tiny USB device that, amongst other things, lets you control servos from a computer via an USB connection. To be more precise, it can control anything that is driven by a regular RC PWM signal, like an ESC controlling a brushless motor for example.

A Pololu Micro-Maestro (6 channels) controlling a servo

The device comes with a program that lets you try it out and play with the connected servos. It's called the Maestro Control Center. Even more interestingly, the device can be easily controlled by code. There are two approaches for that:
  • the native USB interface 
  • and the serial interface

The first one is available in C# and provides access to all the functionalities of the Maestro. The second one is available for any langage that can talk to a COM port, but it offers only a subset of the functionalities.

I gave the Serial Interface a go based on the Pololu examples, and once I saw I could do what I wanted I wrapped everything up in a nice cross-platform C++ library for everyone to use. I called it Polstro (a fusion of "Pololu" and "Maestro"). 

I tested it on a Windows desktop PC and a Raspberry PI. And it seems to work pretty well!

A Raspberry PI controlling a servo

Besides manufacturing sweet little devices, Jan at Pololu also keeps a blog where he shares his RC-electronics wisdom. I found his posts on servos very useful and interesting:

Sunday, 4 November 2012

Steady data transmission over WIFI - Part 2 - Unexpected oversleeping

The first puzzling thing to show up on the transmission graphs was the amount of time one of the machine  appeared to be sleeping. Sleeping occurs in the test application as part of the main-loop: when it's not yet time to send (every 20ms in the example) or check for incoming packets (every 2ms), the application simply goes to sleep. Instead of sleeping for a "long" time (for example 19ms if it took 1ms to send the packet), it sleeps multiple times by a small amount (2ms).

All this appears OK on the bottom line of the graph (the Raspberry PI playing the "client" role) but on the top  (the Windows 7 netbook), the blue blocks representing the Sleep calls are far too big! They should be the same size as the bottom ones.

As a result, in this particular test, the receive packet operation on the server side is running at longer intervals (16ms) than specified (2ms).

Weirdly enough, the problem didn't show when doing the same test using a Windows 7 desktop PC instead of the netbook.

It turns out that on some Windows machines, the granularity of the Sleep() function can be quite substantial, basically not less than 16ms (not sure if it has anything to do with 32-bit vs 64-bit Windows).

Anyway, this granularity can reduced using the Multimedia function timeBeginPeriod (this requires the app to link against Winmm.lib though):

This is more like it!

Saturday, 3 November 2012

Steady data transmission over WIFI - Part 1 - The set-up

As part of a “bricolage” project, I’m investigating replacing the 2.4Ghz RC transmitter of my tricopter with a WIFI-based system. I believe using WIFI could open the door to a lot of other interesting things... More on that later, if the whole thing ever works!

So I’ve started some experiments at home between my old netbook and a Raspberry PI equipped with a USB 
WIFI adapter.

My goal is to transmit packets of data very regularly. I totally accept packet loss every now and then and I expect it to increase as I approach the limit of the transmission range. However, I really need the transmission to be as steady as possible: no transitory lag, no bursts of data and if possible a reasonable (few milliseconds) and fairly constant latency.

In terms of software, I’ve decided to go for the UDP protocol with non blocking sockets checked at a constant rate (basically a main-loop running at a fixed frequency). To study this approach, I’ve developed a command line test application, running on the two distant computers. The app sends packets, or receives them, or do both and log everything into a file.

Each of these data-exchange session is what I call a “test”. The app can go through a series of these tests (each with its own settings), one after the other at specified times. This is the “test schedule”. It is described in a text file that gets read by the application at startup (both end must have the same file). Here’s an example:
# Test #1 (name;starttime;duration;sleepDuration)
    # Server (role, packetSize, sendInterval)
    # Client (role, receiveInterval)

# Test #2
    # Server 
    # Client 
# Test #3
A machine is arbitrarily defined as the “server” (initially I wanted it to send the test-schedule to the other one at startup, but didn’t go that far) and the other one is the “client”. Depending on the role, the application will look at the appropriate sections in the file.

For each test, a log is created. For the test named “Test1” in the example above, I get two files “Test1.server.csv” and “Test1.client.csv”. Here are first few lines of one these files:
And now, the fun part! Once I collect all these files, I can visualize the result graphically with another application (using QT of course!):
Example of a rather nice full-duplex session. Packet 128 got lost!
Being able to analyze graphically what happens in a test is tremendously useful. I toyed with network programming in the past, and making sense of text logs was pretty hard. By contrast, a glimpse at a graph like the one above and you instantly see if something’s wrong.

Needless to say, something did appear wrong right from the first tests...

Saturday, 22 September 2012

Accessing XBox 360 controllers by code on Windows - Xiol library

The XInput API is branded by Microsoft as the "new standard" for accessing game controllers on Windows. By "game controllers" here I should rather say "XBox-360-style-only" controllers.

XBox 360 controller
This means that old-school joysticks seem to be considered "legacy devices" now... Too bad! Look at this beauty:
A well ugly old-school joystick

Anyway, I wanted to give XInput a go as I got my hands on a couple of XBox 360 controllers. The API is not bad and is indeed simpler than DirectInput (though more limited). I managed to rapidly get a small test application working.

As per usual in the Windows world, XInput is a C API. This means global functions, and other structs. As I rather work with classes and objects, I decided to write a C++ object-oriented wrapper library. I called it Xiol (short for XInput Object Layer) and it's available here.