Marine Autopilot

I am trying to develop a marine autopilot using an Arduino Duemilanove accepting the autopilot output from my PC of GPS RMC and RMB. The autopilot prog is OpenCPN which works fine with my Maplins GPS dongle.

I have tried several approaches with limited success but all my research points me toward using TinyGPS. Unfortunately this only parses GPS RMC an GGA. I have attempted to modify TinyGPS substituting RMB for GGA in the header file and modifying TinyGPS "suitably" but all my attempts have failed. Having been retired a long time now I do little programming but I am fairly competent in Visual Basic and C but C++ has always been a bit of a mystery.

Can anyone help or point me to someone who can, please?

I have attempted to modify TinyGPS substituting RMB for GGA in the header file and modifying TinyGPS "suitably"

And those modified files look like?

Can anyone help or point me to someone who can, please?

If you can read data from the GPS, reliably, then you can parse the data. But, we need some links to the device you are talking about, and we need to see some code.

We also need to know what problems you are having.

@PaulS I thought my problem was clearly stated. [u]I[/u]cannot parse the NMEA sentences reliably but it is done within the chart plotter program OpenCPN. This is an Open Source program. OpenCPN then outputs GPS RMC and RMB on a USB port. I can receive that via the USB port on the Arduino and I can parse out the RMB part successfully. However I now need to also receive and parse out RMC hence I thought to use, after modification, TinyGPS. Is this the best course of action or is it too difficult to do? Should I be trying to develop all the code from basic principles or use someone else's (Mikal's)valuable work as a starting point? A life in electronics and communications has taught me not to want to reinvent the wheel! I say again should I be trying to modify TinyGPS or not?

Might be best to show us what the data you are sending to the Arduino looks like. And what do you want to do with that data once it gets to the Arduino. Because this is your project, you need to give us some specifics, not just generalities, as we are not involved with the hardware and software you are using. If your want some advice on paring some strings, you need to give us exam[les of those strings, and what you what you are wanting from them.

With Arduino you are looking at a fairly generic C, and the C++ stuff you really don't have to deal with a whole lot.

And still nobody is prepared to advise me whether to modify TinyGPS or not.

The data going to the Arduino is the NMEA GPS RMB andRMC sentences. These are completely defined elsewhere by NMEA but the RMB sentence is comprised of a text string like
RMC Recommended Minimum sentence C
123519 Fix taken at 12:35:19 UTC
A Status A=active or V=Void.
4807.038,N Latitude 48 deg 07.038’ N
01131.000,E Longitude 11 deg 31.000’ E
022.4 Speed over the ground in knots
084.4 Track angle in degrees True
230394 Date - 23rd of March 1994
003.1,W Magnetic Variation
*6A The checksum data, always begins with *
The RMB sentence is similar but importantly contains the bearing to the next waypoint as shown on the intended course on the chart plotter (OpenCPN)

I need to have both the course being travelled (from RMC) and the required Course (bearing to the waypoint from RMB). These come from the PC via USB and since I need to parse both sentences I thought modifying TinyGPS might be the way to go.

Has anyone got any further advice, please?

If I were doing this from scratch, I'd change tinyGPS - it's already got some useful parsing routines for the data you're going to be reading. However, you say that you've already parsed RMB, so perhaps you do too. That makes it a little hard to advise you which would work better for you.

Thanks, Wildbill. My parsing is not very tidy code and because TinyGPS is well established and tested AND parses two NMEA sentences, I thought that might be a better way to go. I shall persist with it.

Thanks, Wildbill. My parsing is not very tidy code and because TinyGPS is well established and tested AND parses two NMEA sentences, I thought that might be a better way to go. I shall persist with it.

One suggestion: Don’t simply replace the code that parses the GGA sentence type - instead simply add support for a 3rd sentence type. You will have to know a bit of C++, but 90+% of the work is simply adding to the case statement in term_complete().

Plus you never know - you may need the altitude and it’s not in the RMC sentence.

If you’d like, I’ve got a version of TinyGPS 12 that has preliminary support for GPRMB sentences. I’m still testing the changes, and I haven’t added functions to actually retrieve the additional 9 data elements extracted (cross-track error, cross-track direction (L/R), origin waypoint Id, destination waypoint Id, dest waypoint lat, dest waypoint long, range to destination, true bearing to dest, velocity to dest, and a boolean arrival alarm (1=arrived).

I’m not sure if TinyGPS is still tiny anymore, but it might be useful.


EDIT: Ok, so I’ve attached a first pass at modifying TinyGPS to support the GPRMB sentence. It compiles and heck, it might even work. Let me know what you think. (8.64 KB)

Nice work, Brad Burleson.

I rewrote TinyGPS 12 with the intention of making it more easily expandable, and your sample code is exactly the kind of thing I envisioned.



PROJECT: WILE E COYOTE AUTOPILOT (WECA) (Wile E Coyote is my boats name)

OBJECTIVE: Build an Arduino based autopilot that will steer my 40 foot sailboat. Steering a compass course, a GPS course or a wind angle course.

STATUS: I recently completed a 40 mile course using the GPS mode with the course laid out in commercial navigation software (Nobeltec) on my PC. It also steers a compass course.


WECA uses a 9 degree of freedom gyro compass (MinIMU9 from Pololu) for the heading sensor. It reads GPS data from a couple of sources. The rudder is operated with a small DC motor driving a hydraulic pump and piston (already existed).

WECA uses two Arduinos. The main processing is on a MEGA 2560 and the GPS is done on an UNO. Two boards are used because MinIMU9 runs at 50 Hz and the GPS at 1 Hz. The GPS was significantly degrading the IMU9 processing. The GPS data is transmitted from the UNO to the MEGA once a second but the transfer is handled in a few milliseconds and within the 50 Hz structure of the IMU9. The transfer is done using Bill Porter’s Easy Transfer library.

WECA has an LCD (4 lines of 20 characters) and a telephone keypad for input and output.

The code uses the following simple PID.

PID_Output = Gain1 *( Gain2 * Heading_Error – Gain 3*Bearing_Rate) where: Heading_Error = Heading_to_Steer – Heading (from the IMU9) (proportional term). Bearing_Rate is the horizontal plane component of the three axis bearing rate from IMU9 (differential term). No integral term is used.

In Mode 1 the WECA steers a compass course. Line the boat up in the desired direction and press the “1” button to steer that heading. This captures the current heading as the Heading_to_Steer. Note that attempts to get an absolute calibration of the IMU9 compass have not been very successful. So WECA is going where it is pointed. The Keypad can be used to increment the course 1 or 10 degrees left or right.

Mode “2” is GPS. The concept used is to use to get a Course to Steer (CTS) to the next waypoint and the actual Course Over Ground (COG) to generate a Heading_to_Steer (HTS) and then use the PID to steer that heading. Note that Heading to Steer is not equal to Course to Steer because of compass error and cross currents. The idea is to adjust the Heading to Steer so the Course Over Ground is equal to the GPS generated Course to Steer. The following form is used.

Define tracking error as the difference between the heading the boat is pointing and the actual course the boat is traveling. tracking_error = HDG – COG.

The tracking error is a fairly constant term, it changes as currents change or compass error varies on different headings. One problem with this is that when the boat changes course to a new waypoint the heading changes quickly whereas the course over ground changes slowly so the constant nature of the tracking error is not preserved. To correct this a low pass filter is used to get heading that responds about the same rate as the course over ground.

Low Pass Filtered Heading,

HDG_LPF = .999 * HDG_LPF + .001 * HDG

tracking_error = HDG_LPF – COG, note the whole tracking error could be low pass filtered also.

Finally, the GPS heading to steer is:

HTS = CTS + tracking_error

Note, WECA does not yet have a cross track error correction. I erroneously assumed that the Nobeltec PC navigation software output a course to steer (CTS) that included a course correction to get back on the original track. So this is the next area for development. There is no easy solution because the cross track error transmitted by Nobeltec ($GPAPB sentence) is only reported to 0.1 nautical miles (600 feet). The alternative approach is to capture the next waypoint position and then do all of the navigation calculations in the Arduino. The difficulty with this approach is that in NEMA 0183 protocol the waypoint information is only sent once when the waypoint is activated and it will be hard to be certain the data is captured.

Mode “3” is sailboat TACK mode and the keypad will initiate a 90 degree (adjustable) turn left or right.

Mode “4” will be wind angle but has not been implemented yet. It will use an approach similar to the GPS approach where the wind angle will provide a reference for a heading to steer but a heading error term will be needed. The main challenge will be to read the Raymarine Seatalk data to get the wind angle.


  1. Hydraulic Drive: The boat already has a hydraulic steering autopilot. This is a DC 12V motor driving a small hydraulic pump connected to a piston. To change directions the motor is reversed. There is a solenoid (12V) valve between the two hydraulic lines. It is open when the autopilot is off. This allows the hydraulic cylinder to move when steering manually. When the autopilot is placed in the steering mode the solenoid is closed. The autopilot is a Wagner, built in Vancouver in 1983. It steers a compass course but not a GPS route. The pump motor has a built in controller. WECA taps into the control wires and has switches to select either autopilot as the control source.

  2. GPS input: The GPS uses RS232 serial output at 4800 baud. RS 232 is a +/- 5 V signal. The Arduino uses TTL which is 0 V, +3.3V. Therefore the GPS input needs to be converted which is done using a Sipex SP232E chip. This was an easy straight forward activity. Get the IC chip add 5 capacitors, plug the RS 232 and GPS into one side and the Arduino into the other.

  3. MinIMU9 heading sensor: The Pololu MinIMU9 has nine degrees of freedom, three axis fluxgate compass sensors, three axis accelerometers, and three axis gyro angular rate sensors. All of the coding is provided in the Pololu library. I added coding to extract the horizontal bearing rate, (regardless of sensor orientation).

PS If there is interest I can post the code but I don’t know the best way to do this.

coyotewaits: PS If there is interest I can post the code but I don’t know the best way to do this.

Click Reply Click [u]Additional Options[/u] Click [u]Browse[/u] Select the source file Click [u]Post[/u]

Reference Comment #9 Marine Autopilot by coytewaits. My original post did not include the code. Here is a link to a Dropbox that has the my current autopilot files. Let me know if these are helpful to you. I would like to see an Arduino Project Page for Marine Autopilots but know how to get that going.

Jack Edwards

coyotewaits: I would like to see an Arduino Project Page for Marine Autopilots but know how to get that going.

The Playground is a publicly editable wiki...

You are certainly welcome to carve out a space for Marine Autopilots.

Hallo, I´m very interested in your Marine autopilot "child". I downloaded all files from your dropbox. As I´m fairly new to arduino and software development I need some more informations: How must I put the single files together to get a working system?? What is the main file, and how to integrate the routines of the different hardware components?

Hi all,

Just started my Autopilot project.
The idea starts after I attached a linear actuator to my outboard with a remote control (April/2015).
So, if you want give a look, please see the PDF or



RabadakPilot .compressed.pdf (1 MB)


I have an autopilot project involving a Raymarine St 1000+, and Arduino, and a Raspberry Pi.

Open CPN (or equilavent) will be used to send navigation commands through the Pi, to the Arduino, and onto the Autopilot.

I have purchased a Seatalk converter, that I hope to install on the i/o pins of the Pi. Otherwise, I will use NMEA strings from the Pi to control the autopilot. There is one major hurdle in the way of this project: the waypoint advance feature that requires the operator to press two buttons on the autopilot in order to advance from one waypoint to the next. The reason this feature is a problem for me is that I won't be on the boat, it's a drone. I know there are safety concerns--but all are being considered and taken very seriously.

Does anyone out there have code, or suggestions for interfacing this setup? Ideally, I would like to provide all of the navigation strings required for the drone to complete routes: waypoint to waypoint, without the interruption of the Raymarine st1000+ waypoint advance feature. Perhaps if I only provide the unit with the minimum message required it will not be so temperamental.

Any and all recommendations are greatly appreciated.