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 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).
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.
The firmware for this project is available on my GitHub. The firmware’s basic job is as follows:
- The ESP chip sets up a local WiFi network with authentication
- The ESP chip sets up a RESTful API server which interfaces with an Autopilot object
- The Autopilot is a state machine which has four modes:
- “Offline” mode does absolutely nothing. This is the starting state.
- “Manual control” mode will move the rudder to a defined position. The defined position can be set via the API
- “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.
- “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.
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.
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.
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.
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!