Delving the depths of computing,
hoping not to get eaten by a wumpus

By Timm Murray

Cheap Quadcopter Hacking: Noted

2013-11-19


Via Hacker News, I found about a reverse engineer of the protocol for a cheap HobbyKing quadcopter. This would be a great thing to have in UAV::Pilot. I’m still trying to finish a rover, but this might be my next project after that. Giving people a $35 option rather than a $300 option lowers the barriers to entry quite a bit.


Don't Get Bent Out of Shape About Being Cross Platform

2013-11-16


We had an interesting exercise at the recent Madison Perl Mongers meeting, where we took an ugly Windows shell script and turned it into a Perl script. The resulting Perl was noticeably longer than the original script, but also had functionality broken up between subroutines, and was far easier to understand.

One of the sub-problems was to get the current free space on the disk. After some searching with Google and Perl Monks, I found Win32::DriveInfo. Problem is, it isn’t cross-platform.

I didn’t want to bring up a counterargument right then and have to explain it out, because we could have been debating it the rest of the night. But here’s my position: I don’t care if it’s cross-platform or not. But I don’t care in a carefully considered way.

This particular script was for an automated daily sysadmin task on a couple of Windows servers. There is no guarantee that it will ever need to run on anything else. So what I would do in the real-world is make a short search for a cross-platform alternative. If nothing came up within a few minutes, I would shrug my shoulders and wrap all Win32::DriveInfo access into its own subroutine and move on.

As it happened, some people already knew about a cross platform solution (I believe it was Filesys::DfPortable), which is fine. But if I hadn’t found that (and it’s really not a good, easily searchable name for a diskspace module), I wouldn’t worry about it.

It might be that I never have to port it to another system. In that case, my search would be a big waste of time. What I need to do is write it in such a way that it’s easy to pull out the old behavior and substitute it. This way, if I ever do need to port it, the job will be easy.

Furthermore, you’ll almost certainly make hidden assumptions that aren’t cross platform, anyway. The history of Java ought to be a lesson here.

One of the goals for this committee hacking session was to make the script cross platform, which was fine. I just don’t see a reason to get overly concerned about it, provided you otherwise write code in a modular way.


Running VLC Automatically on a Headless Raspberry Pi

2013-11-07


I’ve been setting up a living room stereo with playback with Raspberry Pi. The server runs headless and uses the HTTP interface. Here’s what I did:

  1. Install vlc with apt-get install vlc

  2. Pick a port and allow it with iptables:

iptables -A INPUT -p tcp --dport 43822 -j ACCEPT

  1. Go into your network’s router and give your Raspberry Pi’s MAC address a static DHCP assignment

  2. Edit /etc/vlc/lua/http/.hosts to allow connections from the local network (this will depend on your network’s address settings)

  3. Generate an M3U playlist and save it to /etc/vlc/playlist.m3u

  4. Test vlc by running:

cvlc -I http --http-port 43822 /etc/vlc/playlist.m3u

Using cvlc here will run it purely on the command line. You should now be able to open up a web browser on another machine, go to http://<raspbery pi IP>:43822, and be able to control it from there.

  1. VLC refuses to run as root, so create a vlc user with no homedir, password, or shell:

sudo adduser --no-create-home --shell /bin/false --disabled-password vlc

  1. Create a script at /etc/vlc/start.sh:

#!/bin/sh VLC_PORT=43822 VLC_USER=vlc sudo -u vlc cvlc --http-port ${VLC_PORT} /etc/vlc/streaming.m3u > /dev/null

Make sure to set it chmod +x

(I choose to redirect its output to /dev/null because the SD card that the Raspberry Pi runs off of isn’t going to last long with a lot of log writes.)

  1. Run the script command into /etc/rc.local:

/etc/vlc/start.sh &

  1. Restart the Raspberry Pi. When it’s finished, you should be able to browse to the same location above and get the controls again.

You can then install an app on your phone like “Remote for VLC” to control it from there, or just use the raw HTML interface in a browser.


Why Gopher is Awful

2013-10-27


With Overbite recently making the rounds on Reddit /r/programming and Hacker News, I thought it was time to chime in with some thoughts on Gopher, and why it lost to HTTP for good reason. Despite claims to the contrary, the only reason it’s being floated in some circles really is nostalgia.

If you go looking through my CPAN directory, you will notice Gopher::Server and Apache::GopherHandler. The first was a server implementation of the Gopher protocol, and the second glued that into Apache2.

I don’t consider this to be a complete waste of time. I learned how to use Apache2’s protocol handlers (yes, Apache2 is decoupled enough that it can implement other protocols inside mod_perl). Many years ago, I used it as sample code for a job interview and I was praised for its quality.

(Sidenote: as a minor point of criticism, I was also told by the interviewer to never put “fix later” in a comment. You can put “fix after this other project is done” or “fix by 10/23/20xx”. If you put “later”, it’ll never get done. I didn’t take that job, but I’ve tried to follow that since.)

Gopher has some interesting ideas. Its structure forces a menu hierarchy between servers, and allows clients to present that hierarchy in any way they see fit. This could be a simple text-based menu, but it could be some kind of node diagram where the user navigates entirely by touching entities.

Both HTTP and Gopher have design flaws. If we roll back to HTTP/0.9, we see:

Of these, only the last one is still an issue in HTTP/1.1, and it’s a relatively minor point–you’d maybe want to have the server version and the Server header in there (again, like what SMTP servers do), but it’s not that important. Response codes were added for both success and failure. “Length” and “Content-Type” headers were added. “Keep-Alive” was added to keep the connection open for making multiple requests (further improved by Google’s SPDY).

EDIT 2013/12/14: After thinking about it for a while, the lack of an initial server header is more important than I thought. It’s not so much optimizing for TCP use, but rather for authentication. By sending a bit of randomly-selected data in that initial connect, the client can use that data in an encrypted password scheme to protect against certain cryptographic attacks, such as replay attacks.

Now lets look at Gopher’s problems:

Gopher+ adds the possibility for MIME types (like HTTP’s Content-Type header) and a few error codes (still nowhere near HTTP/1.1’s rich number of codes, but at least it’s something). Using the “$” command in selectors gives a view with ballpark estimates of document length, but it isn’t meant to be an exact measure for transfer, just a nice thing to display to users [EDIT 2013/12/14: There is a length field specified in section 2.3 of the Gopher+ protocol for data transfer.] There’s still no checksums, is still inefficient over TCP, and has no provisions to help caching.

Giving Gopher the benefit of Gopher+ extensions is being generous. The extensions were specified in July 1993. Mosaic 1.0 was released in November of that year, and quickly became all the rage. Mosaic could function as a Gopher client, but it also was the first HTTP/HTML browser that worked. Just as people were starting to implement Gopher+, everyone decided to move to HTTP. Gopher+ has been on the back burner ever since.

Whereas the fixes to HTTP that happened in versions 1.0 and 1.1 are now widespread, the Gopher+ fixes never went anywhere. Not even (as far as I can tell) within the Gopher Revival team. Even if they were, Gopher+ is still badly flawed for the reasons above.

The Gopher Revival people make a big deal about how Gopher is “resource lite”. This is only true because it’s intentionally hobbled. HTTP gives you the choice to have a complex web site. A valid, minimal HTTP/1.1 header is only a few dozen bytes more than a Gopher selector. We have huge server farms for HTTP because we choose to have complex web applications. If we wanted to serve mostly-static content over HTTP, we could run it on extremely minimal hardware, too. (I can’t find the link at the moment, but an HTTP server running on an old Amiga once survived the Slashdot Effect just fine.) For that matter, the lack of caching provisions and inefficient TCP usage actually increase its bandwidth usage compared to running modern HTTP for equivalent content.

The combination of HTTP and HTML won for a reason. Gopher is awful and way behind what HTTP now gives us. I see no reason to bother fixing it.


Space Engineers -- Minecraft Innnnnnn Sppppaaaaacccceeee

2013-10-26


Downloaded Space Engineers off Steam yesterday for their early access alpha. This game has some real potential to be the Minecraft in Space that 0x10c was supposed to be.

It’s very limited in it current state. Infinite resources, no tools, just you and some blocks. The devs are apparently turning features on as they debug them on their end. We’ll have to see where this goes, but I like what’s there so far.


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

2013-10-24


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

2013-10-17


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;
    }
}

UAV::Pilot v0.6 Released

2013-10-16


UAV::Pilot version 0.6 is now on CPAN. Lots of little changes this time. The big thing is an API change, where Control::ARDrone and Driver::ARDrone were instead named ARDrone::Control and ARDrone::Driver, respectively. This keeps everything related to a single type of UAV under one namespace directory, which I think will be nicer going forward as I implement other UAV systems.

I had hoped to get multiconfig working, which would have made the 720p stream work. I ran into problems getting it to work, though, and my message on the ARDrone dev forums has so far gone unanswered. No idea what I’m doing wrong, but I didn’t want to hold up this release any longer. Might have to see how (or if) Nodecopter handles this.

For version 0.7, I’m building a rover. This is my backup plan since the WumpusUAV Indiegogo campaign didn’t work out (because I suck at marketing). I have an old RC car that I’ve upgraded with a brushless motor and LiPo battery, and retrofitting with a Raspberry Pi and Arduino. The Raspberry Pi will handle the WiFi and video stream (the Rapsberry Pi camera module is supposed to be really nice), while the Arduino handles motor control.

The protocol will be the Ardupilot protocol, or at least something close to it. I won’t be testing it against an actual Ardupilot, at least not at first. It should get the system close enough that we can implement an actual Ardupilot later.


Arduino Standalone

2013-10-16


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

2013-10-15


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 );
}


Copyright © 2024 Timm Murray
CC BY-NC

Opinions expressed are solely my own and do not express the views or opinions of my employer.