Driving an 80s robot with a 90s OS at VCF West 2026

10 min read Original article ↗

Table of Contents

  1. Hero BASIC programs
  2. Plan 9 shell scripts
  3. Webcam
  4. Driving the robot
  5. Crowd reactions
  6. Conclusions

A few months ago I acquired three Heathkit HERO 20001 robots (and two HERO 1 robots) when, to my astonishment, someone actually answered my “Heathkit robots wanted” Craiglist ad. They were all in various stages of disarray but after some fiddling and some new batteries I have one of each up and running more or less as designed.

img

With VCF West coming up, I thought it might be fun to take the Hero 2000 and drive it around the show. As a kid I always thought these 80s “home robots” were so cool, but never got to see them in person… so let’s get out there and let some other people see them in person!

I was short on time and extremely short on documentation (seriously, if you have Hero 2000 documentation, email me) so I needed a simple way to remote-control the robot. Without more documentation I had no hopes of programming it for autonomy, and I don’t want to gut the original hardware to put something else in. I settled on the following architecture:

  • Onboard 8088 computer running in BASIC mode
  • Thinkpad running Plan 9 hanging off the back of the robot, connected via RS-232 serial
  • Thinkpad running FreeBSD which connects to the Plan 9 system, from which I issue commands

I went with Plan 9 for a few reasons. First, I’d been meaning to spend more time with 9front for a while now, and this was a good opportunity. Second, I find using serial ports easier on Plan 9 than on any other system: I can configure the serial port and send data using nothing more than echo.

Hero BASIC programs

After staring at the only source of Hero 2000 programming documentation I can find for a while, I came up with a few simple BASIC programs that I could wire together into a demo. I’ll reproduce them here:

10 for i = 0 to 10
20 if sonar(23) < 30 then end
21 if sonar(0) < 30 then end
22 if sonar(1) < 30 then end
23 if sonarb < 20 then end
40 base 7,1,$
50 next i

10 for i = 0 to 5
15 let b = 0
20 if sonar(23) < 50 then b = 1
21 if sonar(0) < 50 then b = 1
22 if sonar(1) < 50 then b = 1
23 if sonarb < 40 then b = 1
40 if b = 0 then print "FOUND", b: END
50 rht 10,$
60 next i

Turning left and right is as simple as sending a command like rht 10 (drive the right motor 10 units), so I didn’t really need to write programs for those.

Plan 9 shell scripts

To actually execute these programs, I wrapped them in small rc shell scripts. Because I was in a hurry, I hard-coded the particular USB-serial adapter I was using, and also had each shell script set the ready-to-send flag on the serial port (which turns out to be necessary for actually transmitting the bytes over the wire to the robot, I don’t know if this is a fluke of the 9front drivers or the way the robot implements its serial port or what).

hero-fwd:

#!/bin/rc
echo r1 > /dev/eiaUa3a94ctl
echo new > /dev/eiaUa3a94
cat > /dev/eiaUa3a94 <<'EOF'
10 for i = 0 to 10
20 if sonar(23) < 30 then end
21 if sonar(0) < 30 then end
22 if sonar(1) < 30 then end
23 if sonarb < 20 then end
40 base 7,1,$
50 next i
EOF
echo run > /dev/eiaUa3a94

hero-findpath:

#!/bin/rc
echo r1 > /dev/eiaUa3a94ctl
echo new > /dev/eiaUa3a94
cat > /dev/eiaUa3a94 <<'EOF'
10 for i = 0 to 5
15 let b = 0
20 if sonar(23) < 50 then b = 1
21 if sonar(0) < 50 then b = 1
22 if sonar(1) < 50 then b = 1
23 if sonarb < 40 then b = 1
40 if b = 0 then print "FOUND", b: END
50 rht 10,$
60 next i
EOF
echo run > /dev/eiaUa3a94

hero-left:

#!/bin/rc
echo r1 > /dev/eiaUa3a94ctl
echo rht 5 > /dev/eiaUa3a94

hero-right:

#!/bin/rc
echo r1 > /dev/eiaUa3a94ctl
echo lft 5 > /dev/eiaUa3a94

hero-stop:

#!/bin/rc
echo r1 > /dev/eiaUa3a94ctl 
echo  > /dev/eiaUa3a94

hero-say:

#!/bin/rc
echo r1 > /dev/eiaUa3a94ctl
echo new > /dev/eiaUa3a94
cat > /dev/eiaUa3a94 <<EOF
10 say "$*"
EOF
echo run > /dev/eiaUa3a94

With those in hand, I made a little script that watches for keypresses and dispatches the appropriate script:

#!/bin/rc
fwd=w
rev=s
left=a
right=d
findpath=f
stop=' '
quit=q
if (~ $1 t) {
    echo TWIDDLER MODE
    fwd=e
    rev=t
    left=n
    right=r
    findpath=o
    stop=' '
    quit=a
}
{
    echo rawon
    while () {
    ifs=() cmd=`{read -c 1}
    switch ($cmd) {
    case $fwd
        echo forward > /dev/cons
        hero-fwd &
    case $left
        echo left > /dev/cons
        hero-left &
    case $right
        echo right > /dev/cons
        hero-right &
    case $findpath
        echo find path > /dev/cons
        hero-findpath &
    case $stop
        echo STOP > /dev/cons
        hero-stop &
    case $quit
        exit
    case q
        # just so it's easy to remember how to quit even in twiddler mode
        exit
    }
    }
}</dev/cons >/dev/consctl

Webcam

I used double-sided tape to stick a Logitech webcam on top of the sonar turret. This was plugged into the Plan 9 laptop, with the intention of viewing it remotely, but I found that video over drawterm wasn’t going to work, between wifi and the known “performance” of 9p2.

Since it was only 2 days to VCF, I vIBeCoDeD a little Go tool that converts the Plan 9 image format of the video file to MJPEG and serves it over HTTP. This worked well enough to go on.

Driving the robot

Getting things ready to run turned out to be a bit of a dance. First, I booted the Plan 9 laptop, connected to wifi3, and ran a script which enabled incoming cpu connections to the terminal. Then I closed the laptop and slid it into a little Ikea trash basket I had zip-tied to the back of the robot (there’s not enough room inside the torso for the laptop, sadly).

On my FreeBSD laptop, I used drawterm to connect to Plan 9, then ran a small script which set up a few windows in a large font: one running hero-loop (above) for commands, one that would send anything I typed to hero-say, and a plain shell, in which I manually started the webcam video server. I put the drawterm window on the left, then opened Firefox on the right and pointed it at the URL of the webcam server.

After verifying that everything was working (video was streaming, hitting the ‘w’ key made the robot inch forward, etc.) I plugged in my Twiddler chording keyboard, switched hero-loop over to “Twiddler mode”, and stuck the laptop in a messenger bag slung over my shoulder.

At that point I was mobile: I could follow the robot around the floor, sending commands from my left hand, with my right hand free to help push it over cables, shake hands, etc. I had keys set to go forward, turn left, turn right, and “find a clear path”4, as well as one button to stop immediately (send Ctrl-C). This worked pretty well, aside from occasional odd behavior: every so often, the robot would start driving fast, turning erratically. I couldn’t figure out exactly what led to that state, so I’d just jump over and hit the RESET button on the robot to make it stop. This happened perhaps half a dozen times over the course of 2 hours.

After driving around for a bit, I plugged in my Vufine+ wearable display and put it on so I could watch the webcam’s view while driving. I’d initially planned to drive it like that from a greater distance, but the crowded room, the mediocre camera FOV, and the occasional inexplicable “runaway” behavior all kept me close. Still, it was fun to have a robot’s-eye-view at the same time, and if you’re going to dress up like a gargoyle VCF is probably your best choice after DEFCON.

Crowd reactions

The robot drew a crowd as it wandered around. People were very excited to see something in that yellowed-beige-vintage-computing plastic actually wandering around the place. Within 15 minutes of bringing it in, an ex-Heathkit engineer came over to check it out.

Kids loved it. It’s a big tall thing, as tall as a young child, and to a 7 year old it’s irresistable. Even better: you can actually drive it around by pushing buttons on the keypad on top, and that’s an incredibly exciting prospect for a kid.

The revolving sonar turret on top also caught a lot of interest, more than any other aspect of the robot. Many people guessed radar, sone asked if it was LIDAR, I think only one person correctly identified it as sonar.

Although I had it set up to “speak” on command, the hall was far too noisy to hear anything it said.

Conclusions

This was fun! I met a lot of interesting people who were very enthusiastic about seeing an old robot rolling around.

VCF West is getting almost too big anymore. The crowds were intense, and I sometimes had a hard time walking, let alone driving this slow-moving robot.

The remote-control-via-scripts thing is basically a dead end outside of demos like this. I’ve always considered remote controlled robots (as opposed to autonomous) rather boring. Now, two of my scripts (“go forward avoiding obstacles” and “find a clear path”) are almost the barest outlines of a subsumption architecture, in which the lowest levels of the robot are capable of very basic behaviors (moving without bumping into things) which can be triggered or overridden, in this case by the human in the loop. If I can ever get access to the programming documentation, I think it would be interesting to write a more advanced version of the on-robot code that takes instructions like “go forward” but can also stop by itself if something is obstructing it, and can feed up the current sensor state. Then, more advanced software running on a modern computer could integrate that sensor data with perhaps LIDAR to perform SLAM and decide where to go.

Footnotes

1 Released 1986, differential drive, 8088 processor with Z80 peripheral processors, optional arm unit which I have but isn’t ready to use.

2 Did I do a master’s thesis on 9p’s performance in 2010? Yes. Has it improved? No. Still my favorite protocol.

3 Turns out the public wifi at the Computer History Museum doesn’t allow connections between client devices, so I had to use my phone in hotspot mode.

4 In the end I hardly used the “find clear path” function, opting to steer manually instead.