UAV::Pilot v0.7 Released, Now Many Times Less Bad

Release 0.6 was terrible and sloppy, with a missing String::CRC32 dependency, and a bunch of tests that only passed if you had a previous version installed (due to the API change).

Release 0.7 is uploaded now and fixes the above. Some of the WumpusRover stuff got taken along for the ride because I didn’t feel like disentangling it in the master branch. Expect WumpusRover to get more fleshed out in the next release.

I also added Alien::ffmpeg as a dependency. This will hopefully make CPAN smoketesters have ffmpeg installed before running. I don’t really like it, though, because installing it seems to force compiling ffmpeg even if you already have it.

Arduino/RaspberryPi–UART (Serial) Communication

NOTE: This post was moved over from WumpusUAV.com. The Indiegogo campaign was not successful, so I’m copying some key posts from there to over here and shutting the site down.

UART/Serial is an old way of doing things, but also handy because you can do it without complicated wiring. Any USB port will do.

We do need to deal with a bunch of esoteric stuff like “parity bits” and “stop bits”. But it’s a simple matter of ensuring these things are set the same on each side.

Hardware Setup

If you don’t want to use USB, a voltage level converter is required, or else the Raspberry Pi’s 3.3V won’t meet the threshold for the Arduino’s 5V. Here’s an article with the details:

http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/

Otherwise, just plug the two in.

Arduino

In the sketch, we set the baud rate to 115,200. That’s bits-per-second. That might not sound very fast, but if you’re talking plaintext documents, it’s much, much faster than you can read. For UAV purposes, you wouldn’t transfer camera images over that line for processing, but for sending movement commands of a binary protocol, it’s more than enough.

The loop will then check if there’s anything waiting for us to read, and if so, sends it back.

#define SERIAL_BAUD 115200


void setup()
{
    Serial.begin( SERIAL_BAUD );

    while(! Serial) {
        // Wait for serial port to connect
    }
}

void loop()
{
    char next;

    if( Serial.available() > 0 ) {
        next = Serial.read();
        Serial.print( next );
    }
}

Raspberry Pi

We’ll use the Device::SerialPort module. This sets all the stopbits and such for us for clean communication with Arduino. The loop will wait for us to type something with a newline at the end, send it over the serial port, and then read back the response. There tends to be a slight delay before the string comes back, so we sleep a bit after sending.

Run it with serial_example.pl /dev/ttyUSB0. You probably don’t have anything else plugged in to a Raspberry Pi as a USB serial device, so the Arduino is almost certainly on /dev/ttyUSB0. In case it isn’t, check the output of dmesg.

#!/usr/bin/perl
use v5.14;
use warnings;
use Device::SerialPort;

use constant {
    BAUD     => 115_200,
    PARITY   => 'none',
    DATABITS => 8,
    STOPBITS => 1,
    BYTE_BUF => 255,
};


my $PORT = shift || die "Need serial port\n";


my $tty = Device::SerialPort->new( $PORT )
        or die "Can't open $PORT: $!\n";
$tty->baudrate( BAUD );
$tty->parity( PARITY );
$tty->databits( DATABITS );
$tty->stopbits( STOPBITS );

while( my $line = <> ) {
    $tty->write( $line );
    $tty->write_drain;

    sleep 1; # Wait for data to be processed

    my ($count_in, $string_in) = $tty->read( BYTE_BUF );
    if( $count_in ) {
        print '>' . $string_in;
    }
}

Arduino Standalone

NOTE: This post was moved over from WumpusUAV.com. The Indiegogo campaign was not successful, so I’m copying some key posts from there to over here and shutting the site down.

To keep size and weight down, the WumpusUAV will need a customized Arduino PCB with some of the sensors and connectors onboard. It’s therefore useful to know how to work the Arduino in a standalone circuit, rather than relying on the retail boards.

The Arduino circuit is a simple one, needing a +5V voltage regulator, a crystal, an ATMega328, and a few capacitors. A schematic can be found at:

http://arduino.cc/en/Main/StandaloneAssembly

The LED and reset switch are not strictly necessary. Connecting the RESET pin to +5V will work fine.

I hit some snafus with transferring the Arduino bootloader on Linux. I will document the solutions in a later post.

Arduino — Brushless Motor Control

NOTE: This post was moved over from WumpusUAV.com. The Indiegogo campaign was not successful, so I’m copying some key posts from there to over here and shutting the site down.

Brushless ESCs are more efficient than the regular DC motors of old. However, they need to be controlled more carefully, so they need a dedicated controller for each motor. I’m using the Turningy Plush 18A. Some of the details might change for other motor controllers, but should be broadly correct.

Hardware Setup

The common pinout on the ESC has three wires. The black is ground, red is +5V, and then some other color is signal.

The Arduino Servo library docs say that servos tend to take a lot of power, so you shouldn’t run more than one or two directly off of the Arduino board’s own +5V line. However, a typical servo doesn’t have any other power connector. Brushless ESCs do, in the form of an extra +5V and GND wire. The Arduino board may be able to power 4 ESCs just fine. I haven’t done any measurements to confirm that. The PCB designed for the WumpusUAV has a seperate 7805 voltage converter for the ESCs.

Software Setup

The motor controller takes a signal like the ones that were previously used to control RC servos. This is sometimes called PWM, but it isn’t at all like the PWM typically used to dim LEDs and such. Thus, it is controlled using the Arduino Servo libary.

The Servo library can controll any servo on any digital output pin. The usual servos (used for things like stearing on an RC car, or the ailerons on an RC plane) take a value between 0 and 179 degrees. For Brushless ESCs, this translates directly into throttle settings.

The ESC takes a few seconds to startup, during which we need to send a zero value. The Turningy has an audiable beep that gives diagnostic information during this time.

The code below will attach to an ESC on pin 8, send a zero throttle for 10 seconds (which is probalby more than necessary), and then start sending a throttle of 10 (179 being top throttle). Brushless motors can be surpirisingly powerful, so you don’t want to run them to hard during testing.

#include 

#define MIN_READING 0
#define MAX_READING 1023
#define MIN_DEGREES 0
#define MAX_DEGREES 179
#define PERCENT_THROTTLE 75
#define STARTUP_WAIT_MS 10000
#define MIN_PULSE_WIDTH 1000
#define MAX_PULSE_WIDTH 1000
#define PIN 8


Servo motor;
unsigned long start_time;


void setup()
{
    motor.attach( PIN, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH );
    start_time = millis();
}

void loop()
{
    unsigned long now_time = millis();
    unsigned long since_start = now_time - start_time;

    int throttle, want_throttle;

                                                                                
    if( STARTUP_WAIT_MS < since_start ) {                                                    
        want_throttle = 10;                                                     
    }                                                                           
    else {
        want_throttle = 0;
    }

    motor.write( want_throttle );
}

Arduino/Raspberry Pi — TWI

NOTE: This post was moved over from WumpusUAV.com. The Indiegogo campaign was not successful, so I’m copying some key posts from there to over here and shutting the site down.

NOTE 2: I later found that these instructions are flawed. You need to convert between the 3.3V signal on the Raspberry Pi to the 5V signals on the Arduino. Or get a 3.3V Arduino. I’ve ordered the Sparkfun Bi-Direction Logic Level Converter and will report back once I’ve received it.

Two Wire Interface (TWI) is a simple means of communication between two systems. “I2C” is another name for basically the same thing. On the Arduino side, it is implemented by the Wire library. On Raspberry Pi under Perl, we will use HiPi::BCM2835::I2C.

Hardware Setup

Take a look at the Raspberry Pi version 2 header pinout. With the header on the top-left, the I2C pins are the second and third pins on the bottom row. The Arduino pins depend on the board; see the link above to the Wire library for details.

The SDA pin (Serial Data Line) and SCL pin (Serial Clock Line) between the two boards must be connected. We also need to connect the Raspberry Pi’s GND and +5V wires to the Arduino’s GND and Vin pins, respectively.

(If the Arduino is powered externally, then only the GND wire needs to be connected to the Raspbery Pi.)

When using Raspbian on the Raspberry Pi, you need to load the kernel modules i2c_dev and i2c_bcm2708. The second one is blacklisted by default in /etc/modprobe.d/raspi-blacklist.conf, so remove it from there. It’s also handy to add these modules to /etc/modules so that they get loaded on startup.

Add your user to the i2c group if you want to be able to connect without being root.

Raspberry Pi Programming

On Raspberry Pi revision 2, the I2C pins on the main header are actually the second I2C device. The first sits on a secondary ribbon header, which is currently used for the Raspberry Pi camera accessory. Thus, we use the device /dev/i2c-1.

Each slave (which will be the Arduino board) needs an address starting at 4 and up to 127. The currently connected devices can be scanned with i2cdetect -y 1.

Example Perl program:

#!perl
use v5.14;
use HiPi::BCM2835::I2C qw( :all );
use constant ADDR       => 0x28;
use constant DEVICE     => '/dev/i2c-1';
use constant BUSMODE    => 'i2c';
use constant SLAVE_ADDR => 0x04;
use constant REGISTER   => 0x00;

my $DATA = 0x05;

#say "Baudrate: " . HiPi::Device::I2C->get_baudrate;


my $dev = HiPi::BCM2835::I2C->new(
        peripheral => BB_I2C_PERI_1,
        address    => SLAVE_ADDR,
);

say "Sending [$DATA]";
$dev->i2c_write( REGISTER, $DATA );
my @recv = $dev->bus_read( REGISTER, 1 );
say 'Got [' . join( ", ", @recv ) . ']';

Arduino

We intitilize the Wire library with the slave address. It then takes functions as arguments to onReceive and onRequest.

The loop() function will simply delay.

A complete example:

#include 

#define SLAVE_ADDR 0x04


uint8_t last_read_byte = 42;

void setup()
{
    Wire.begin( SLAVE_ADDR );
    Wire.onReceive( read_event );
    Wire.onRequest( write_event );
}

void loop()
{
    delay( 1000 );
}

void read_event( int len )
{
    last_read_byte = Wire.read();
}

void write_event()
{
    Wire.write( last_read_byte ):
}

References

http://neophob.com/2013/04/i2c-communication-between-a-rpi-and-a-arduino/

Underappreciated Perl Code: TAP’s YAMLish Syntax

If you write tests using Test::More, you may have seen the cmp_ok() sub output something like:

$ perl -MTest::More -E 'plan tests => 1; cmp_ok( 1, "==", 2, "fail" )'
1..1
not ok 1 - fail
#   Failed test 'fail'
#   at -e line 1.
#          got: 1
#     expected: 2
# Looks like you failed 1 test of 1.

This is a textual output of the file and line number of the tests, as well as what failed. If you wanted to write a TAP parser for a report, you could parse the comments and get that file location. But then you’d be parsing comments, and those aren’t supposed to be parsed by computers (SKIP and TODO being exceptions in TAP for hysterical raisins). Plus, Test::More makes no guarantees about the format of those comments, nor should it.

Fortunately, the TAP protocol has an official extension for parsable information about a test, called “YAMLish“. As the name implies, it’s a small subset of YAML, specifically the one supported by YAML::Tiny. This makes it easy to implement in other languages.

Test::More doesn’t seem to support outputting YAMLish, but we can get the functionality with TAP::Parser::YAMLish::Writer. We can write up a subroutine for a tests to handle YAMLish:

#!/usr/bin/perl
use v5.14;
use warnings;
use Test::More tests => 1;
use TAP::Parser::YAMLish::Writer;
use DateTime;


# Need to have write_yaml() on the same line so its line number output is correct
cmp_ok( 1, '==', 2, "Fail" ); write_yaml( 1, 2, { foo => 'bar' } );


my $yw = undef;
sub write_yaml
{
    my ($expected, $actual, $extensions) = @_;
    $yw = TAP::Parser::YAMLish::Writer->new
        unless defined $yw;
    my ($pack, $filename, $line) = caller;

    my $dt = DateTime->now;
    my $date = $dt->iso8601();

    my %fields = (
        datetime   => $date,
        file       => $filename,
        line       => $line,
        expected   => $expected,
        actual     => $actual,
        extensions => $extensions,
    );

    $yw->write( \%fields, \*STDOUT );
    return 1;
}

The keys datetime, file, line, expected, actual, and extensions are defined directly on the wiki page for YAMLish. The extensions key is a hashref that can hold custom information. The datetime key is in either ISO8601 or HTTP date format.

Output:

$ perl yamlish_example.pl 
1..1
not ok 1 - Fail
#   Failed test 'Fail'
#   at yamlish_example.pl line 9.
#          got: 1
#     expected: 2
---
actual: 2
datetime: 2013-10-06T16:55:14
expected: 1
extensions:
  foo: bar
file: yamlish_example.pl
line: 9
...
# Looks like you failed 1 test of 1.

But this is awkward and ought to be wrapped up by a CPAN module. The requirement for write_yaml() to be on the same line is particularly bad. Duplicating your actual/expected values in the call to write_yaml() is no good, either.

It’d be nice if Test::More did this for us, or barring that, a drop-in replacement. After a quick search, I can’t seem to find anything like that. Any takers? :)

What if Perl OO was a Core Feature?

Over on Reddit /r/perl, there’s a rather blatant troll complaining about the lack of OO as a core feature in Perl. The tone there is clearly not constructive and not worth responding further, but I feel compelled to answer a question: what would be improved if OO was a core feature, rather than built out of existing components of the language?

Personally, I think the fact that OO can be built this way is a demonstration of flexibility. It also allows you to build your own OO system that suits your needs. If the standard kind of blessed data structure doesn’t work for you, try Inside-Out Objects. This also had hidden benefits later on; when roles/traits/mixins became all the rage, Perl just added them via CPAN modules. There was no long, drawn out, design-by-committee bikeshedding discussion like there was for Java.

If you really wanted to, you could even build an object system without bless() or packages. The constructor would return a hash, which is filled with sub references:

sub new_object
{
    my %object = (
        foo => sub { 'foo' },
        bar => sub { 'bar' },
        baz => sub { 'baz' },
    );
    return %object;
}

my %obj = new_object;
say $obj{foo}->(); # Prints 'foo'

Inheritance is a matter of a different constructor calling the original constructor, then filling in different subrefs:

sub new_inherit_object
{
    my %object = new_object();
    $object{foo} = sub { 'override foo' };
    $object{qux} = sub { 'qux' };
    return %object;
}

my %obj = new_inherit_object;
say $obj{foo}->(); # Prints 'override foo'

(No, I don’t really suggest doing this. It’s just an interesting exercise in building an object system using limited language components. Although this isn’t too far from how JavaScript builds objects.)

Getting back to the usual bless() system, there is a drawback: the learning curve. Think of all the things you have to grasp before you can understand Perl OO. There’s subroutines, passing arguments to subroutines, and putting those subroutines into packages. Any bless‘d object is going to be a complex data structure, and before you can figure those out, you need to grasp references. Even for somebody experienced in another programming language, that’s a lot to ask before you can get them up to speed on object programming. It’s even harder for somebody with no programming background at all.

Moose somewhat alleviates this. It can hide a lot of the details of the complex data structure, though obviously you’re going to need to dig into that at some point. The constructors in Moose can also do sensible things for you. It’s a lot better than Java, where the constructors tend to have a lot of this.foo = foo; statements to set private member variables from the arguments.

What Moose can’t fix is subroutines. Sub signatures are a sore spot for Perl. I think it really is an embarrassment that we still have this problem in 2013. And we need signatures down pat before we can even start thinking about multi-method dispatch.

Perl SDL GUI Layout Engine

As it turns out, SDLx::App only supports having one window at a time. It’s effectively a singleton. This was a problem for UAV::Pilot, because I wanted to draw the navigation output and video in seperate windows.

The fix I have now is to implement a simple layout engine, where you can specify if you want the widget to be placed at the top or bottom of the window. I didn’t want to add complications like left or right. That’s good enough for now; the video always goes on top, the nav on bottom. If you were watching the AR.Drones 720p video stream on a 720p monitor, it might be an issue, but I’m not going to worry about it for now.

Where it could be an issue is when UAV::Pilot starts implementing other types of UAVs. I’m contemplating a rover, which makes the current nav output of roll/pitch/yaw rather pointless. But it’ll still need the battery output, and maybe add throttle and steering.

That all leads into breaking the current nav output into individual widgets with a complicated layout engine, like the sort you might see in Gtk+ or KDE.

As far as I can tell, Perl has nothing like this for SDL. There’s SDLx::GUI and SDLx::Widget. Both of these are limited, and look like the respective authors have left them by the wayside. Which I totally understand. I left Gopher::Server like that.

I’m tempted to write my own, but that seems like a full project in itself. Intergrating with Gtk2 might work, but I’m not sure how well that will go with SDL. Even making Perl bindings for a C layout library seems like a full project.

For now, I can ignore the issue. Implementing just a rover won’t introduce too much redundancy.

Any takers on this one? :)