Vladislav Pomogaev

Engineering Physics Graduate

Boat Autopilot

One of my projects this summer was an autopilot system for my dad’s home-made catamaran. The cat is very fun and easy to steer, but extended length journeys become tiresome. That’s why I decided to build an autopilot system that could automate the task of steering the boat, as well as function as a remote-steering system so that you could steer away from the helm.


The actuator is connected through a quick-release safety-bolt 😉 to the chain around the steering wheel. This allows you do enable and disable the autopilot quickly.

The system works by having a 12V 12″ linear actuator connected to the steering system of the boat in the back of the helm. The actuator has a potentiometer feedback, and is connected to a main control unit just above. The main control unit controls the actuator when needed to place the boat on the correct heading.

The actuator is mounted on a hinge which allows for some mechanical play. As you can see, the setup is far from ideal, but it has been very dependable in the several tests that have been done on the system.

The main control unit is a prototyped circuit which has an ESP8266 development board, a motor driver, OLED Display, buttons, a GPS, and even Bluetooth (unused so far).

Here you can see the main control unit, as well as the back of the breaker panel.

The ESP8266 emits a local WiFi network to which devices can connect to and interface with the autopilot. The main method of controlling the autopilot is through an Android app I developed for this project. The app sends the autopilot commands through a RESTful API, and can also query information from the autopilot such as position, speed, etc.

Everything here was designed for reliability. The electronics were well sealed in a watertight case, which included adding watertight connectors and watertight harness.

Closeup of the inputs and outputs of the autopilot. I placed all of the electronics and used more-or-less sealed outputs to prevent moisture from leaking in. Either way the autopilot is removed for storage over the winter so this wasn’t a huge deal.
At first I wanted to utilize a stepper motor and reduction gear ratio around the chain drive to control the direction of the steering wheel. However, after installing a proof of concept mechanical system the stepper motor proved to be too slow to drive the motor. It did have the added bonus of being able to be overpowered by the user though.
Closeup of the perfboard construction of the electronics. No PCB for this project as I was doing a majority of the project remotely and did not have the time to get a PCB manufactured.


The firmware for this project is available on my GitHub. The firmware’s basic job is as follows:

  1. The ESP chip sets up a local WiFi network with authentication
  2. The ESP chip sets up a RESTful API server which interfaces with an Autopilot object
  3. The Autopilot is a state machine which has four modes:
    1. “Offline” mode does absolutely nothing. This is the starting state.
    2. “Manual control” mode will move the rudder to a defined position. The defined position can be set via the API
    3. “Autopilot control” will run a custom-programmed PID loop to keep the boat headed in a particular direction. The initial course is the one the boat is on. The course can be adjusted through the android app. The PID loop prevents cross-track error, and the algorthm will take in error parameters from the heading, cross-track error, as well as various derivative and integral terms.
    4. “Error” mode. This mode is entered through a loss of hardware functionality; such as losing connection to the GPS. Hardware-wise there is a buzzer to let you know that this has happened, but that functionality is not there.

The hardest part of the project was probably tuning the PID control loop. At first, the gain terms were only adjustable by flashing the firmware, but I quickly implemented API methods to change them as well. I took a random guess at which terms would get the job done and adjusted them over the course of an 8 hour voyage.

Here we see the track of the boat on autopilot with about a 45 degree step input. You can see oscillations before and after the step caused by backlash. Since the autopilot relies on GPS for heading, it is not sensitive to drift due to wind. The software plots an invisible line from the moment you adjust the heading and uses a cross-track error to keep the boat from drifting.

A good indication for me was how good the autopilot is at handling an unexpected impulse (a change in desired heading). Here you can see the autopilot navigating east, then north-east. As you can see there is a bit of overshoot in the control loop, but this was actually not caused by the loop itself but by excess mechanical backlash.

One potential solution to this backlash is to account for it in firmware, which will be coming really soon.

Several smaller angular step inputs help the boat navigate through a river.

Here is another good example of navigation in straight lines. The autopilot is not perfect; I continue to blame the backlash. However, it can keep the boat within ~5m of cross-track error on a calm day, which is fine for navigating a strait, but probably not a river like shown above. Again, compensating for mechanical backlash is the most-likely solution, which will probably require decreasing the PID gains.

I encountered the same problem on my model boat autopilot, but that was a result of a non-tilt-calibrated compass.


Lastly, this wouldn’t be a real project if it wasn’t controlled by an app. The code for the app I made is also on my GitHub.

Here is the screen for the “Autopilot” mode of the autopilot. Here you can see the current heading, course, adjust the course, as well as the PID gains. All of this needs to be revamped, but it tends to work well for now.

The app is built using basic Android elements in Android Studio, with the back-end written in Java. The app is very simple; it simply sends HTTP requests to the RESTful API to either change states, variables, or receive information from the autopilot. The bottom of the app can be used to change the state of the autopilot state machine, and the main display is used to send/receive information.

I programmed the bulk of the code overnight, but looking back on it I would change a lot to make the code more scalable and more easily editable. Right now, if I were to add a function I would have to write a number of functions for it, whereas I see ways to only add one function instead.

Going forward

The first step when I get back to working on this project is definitely fixing the mechanical backlash issue. I’m absolutely convinced that the overall system could be improved.

In addition to this, I’m also looking to integrate the remote control I built in a previous post.

Other than that, it looks good!