LSM303D / A-Star 32U4 NMEA 0183 Compass

One of my favorite hobbies is fishing from a kayak.
A fishfinder/chartplotter is standard equipment these days, but it often happens that when I spot a fish and try to stay right on top of it in windy conditions the GPS is too slow to update the exact location and attitude of the kayak and the fish is lost. This is because the GPS sometimes requires the kayak to move quite a bit and even then it does not correctly show where the kayak bow is heading.

To supplement the chartplotter I decided to build a small electronic compass that will update the heading information to the plotter in the standard NMEA 0183 format.

Because I’m using a four cell lithium-polymer battery to power my Garmin plotter, the Pololu A-Star 32U4 Mini SV turned out to be a perfect choice for the controller. A fully charged battery is 16.8V, which the high efficiency step-down regulator on the SV can handle with ease.
As the sensor I’m using the Pololu module #2127 with the LSM303D Magnetometer/Accelerometer/Temperature sensor.
Most marine electronic devices would additionally require a proper serial adapter like the Pololu 23201a in order not to fry the serial port on the A-Star. My Garmin seems to be using single ended 5V levels though, so I’m getting by using just an inverter.

An additional benefit of the LSM303D module is the built in thermometer. The Li-Po batteries are known to heat up and catch fire in rare circumstances and as I plan to put the compass module in the battery box, I should get an early warning should it come time to abandon ship.

I will attach my code for everyone’s amusement. It has been aeons since I have been doing any programming so please don’t be too cruel. Fortran was the programming language at the time, so I’m not quite up to speed with the new languages.

To make it easy for anyone wanting to try the code I’m using the unmodified Pololu LSM303 Arduino library. The compass might benefit from calibrating the acceleration sensor as well, because at least on mine the offsets seem to be quite large.

The Garmin chartplotter seems to have quite heavy filtering on the compass input but I have also added a filter in the code. The filter design is not based on any exact science. It’s more or less a ‘common sense’ filter. The basic filter is an exponential moving average filter with some tuning of my own. The tuning that I have added is that the coefficient depends on the magnitude of the change. For very small changes the latest measured value affects the heading very little and for quicker turns the rate of change is accelerated. There is also a limit for abrupt changes. One could further add skipping measurements if the acceleration vector changes too abruptly but that should not be a problem on a boat. There is also some added juggling to handle the 360/0 degree crossing gracefully in the filter.
For testing I also set up a small Python script with a compass rose display.

I just noticed that after adding the numeric label to my Python compass display it became unstable and often freezes after a while. I know the reason is that the Qt code is not thread safe and I’m updating the compass and the label from the wrong thread. Without the label the program used to work pretty well. I know I should implement some kind of a signaling mechanism between the threads and do the updates in the main loop, but at this point I know way too little of PyQt/Qt4 to do it, sorry :blush:
Compass.ino (4.23 KB)
Compass.txt (4.38 KB)


That sounds like a cool application! (I hope you never need to jump ship!) Do you have pictures you could post of the electronics, or a writeup you could link to?