The "PFEC" sentence is a proprietary sentence used so that my Furuno RD30 display can read roll and pitch. I use the free NKE Marine Electronics app on my phone to display everything, so I include a few XDR sentences so that it recognizes them (same with GPVTG).

Out of curiousity, I'm going to compare the costs here between a DIY setup and a professional one (minus all the blood and sweat of course).DIY Setup

Compass/Accelerometer

$12

Atmospheric Sensor

$15

USB GPS

$30

DST800

$250

Raspberry Pi

$40

Assorted Cables

$100

Total

$447

Professional Setup

Airmar 220WX*

$1154

DST800

$250

Regatta Processor**

$8,324

NMEA WiFi

$461

Total

$10,189

* the Airmar 220WX has a compass, accelerometer, GPS, and weather station all in one unit. However, I personally don't think having a GPS at the top of a rocking mast will produce very good GPS data

Step 1: Setup the Raspberry Pi

Once you purchase your Raspberry Pi, set it up by following their NOOBS guide here. I'm running this with a brand new fresh install of Raspbian Jessie on April 18th, 2016. Once you have booted up the Pi, connected your monitor/mouse/keyboard, and connected an ethernet (or connected to wifi), ensure you're software is all up to date by running these two commands from the Terminal (the "Terminal" is the program on the top bar with a logo like a black box. The Terminal will be your primary workhorse for this guide). Type the first row in and hit enter and let it run through. It may prompt you to type "Y" if you want to download the new programs. If you're really new, you should know that when you type in "sudo" before a command like this, it runs it in the "God Mode" on the Raspberry Pi and you can make important changes to the system.

sudo apt-get update
sudo apt-get upgrade

Once this is done, open up Menu->Preferences->Raspberry Pi Configuration, and change your hostname or password if you wish. But the one thing we're looking for is under the Interfaces tab; click I2C Enabled. I also recommend configuring your Localisation tab to your location. Once you're done, click OK and reboot.

Next, we're going to begin the long process of installing all the necessary software (these are all for the MPU-9250 Digital Compass--if you're not using that, then you probably don't need these except you might need python-dev).

and you should see a 68 somewhere in the grid. If not, well... you might have to go to RichardsTech's website to troubleshoot. Let's assume it is working. Great.

These next few steps are going to come fast, so keep up. We make a working directoy called 'kts' to store everything and to stay organized (keep in mind if you use my scripts, your directoy must also be called kts (or you can just change the scripts to reflect your name)). After making the directory, we download the RTIMULib from github and install its calibration program.

This installs the calibration program, which is 100% necessary for the compass to work. Again, if you get lost, just mosey on over to his github page, or my earlier and expanded writeup on the MPU-92450 with the Raspberry Pi. However, I cannot reiterate this enough: when you calibrate the compass, you MUST be working in the RTIMUEllipsoidFit folder--otherwise it WILL NOT WORK. Not only that, but there must be a copy of the RTIMUEllipsoidFit folder in the directory above the script that is using the MPU-9250. If you follow my directions, this won't be a problem.
So let's do that.

When you're on your boat, and your compass is installed where it will be used (I unfortunately cannot help you with this part), then run the calibration program RTIMULibCal. It doesn't make sense to calibrate it anywhere other than its intended final location. This creates a RTIMULib.ini file in the RTEllipsoidFit folder, which you then copy over to the scripts folder. Wait, the scripts folder? Yes, let's make that and download all the scripts used for this project from my github page:

cd ..

git clone https://github.com/OldCC/scripts.git

cd scripts

cd ../RTEllipsoidFit/

cp RTIMULib.ini ../scripts/

Now we have all the programs installed, we have all the folders made, and we have all the scripts.

Bonus Step: Setup a Wifi AP on the Raspberry Pi 3 Model B

This step took forever, mainly because there's a hundred tutorials out there on how to set up a wifi router with the Pi. That's not what I want to do. I just want a wireless access point to connect a bunch of things to, with no internet. I don't need the internet (yet). Fortunately, this is super super super easy to do, thanks to this awesome script that you just run once, edit one file, reboot, and you're good. Finally.

But that script actually didn't work for me, so I modified it slightly by making it a little less user friendly (sorry). I included this script in the scripts folder, if you downloaded it from github above. Set up the apsetup.sh by

sudo chmod +x apsetup.sh

sudo nano apsetup.sh

and change PASSWORD and NAME to whatever you want for your network. Then Control + C to save and exit. Next, run that script as the root user by

sudo ./apsetup.sh

This will take a minute or two to run through everything. When it's finished, we need to make it run at startup all on its own. To do this, open this file:

sudo nano /etc/default/hostapd

and then turn this line here

#DAEMON_CONF=""

into this line (make note that I remove the the #)

DAEMON_CONF="/etc/hostapd/hostapd.conf"

Go ahead and reboot, and when it's back online, try to connect to your wifi network with your laptop or phone. If it connects, then you're good! But there won't be any internet. That's okay, because there will be NMEA-0183 data in just a little bit.

Bonus Interim Step: Assign Persistent Names for your USB Devices

If you will have more than one USB device plugged in, follow this section. If you only have one USB device plugged in, you'll have to change your

ser = serial.Serial('/dev/gps', 4800, timeout=5)

to something like

ser = serial.Serial('/dev/ttyUSB0', 4800, timeout=5)

but if you will have more than one USB device plugged in, proceed with this step.

I followed this guide here, which I will summarize below. First, figure out which USB ports are assigned to which ttyUSB* names. Typically, it'll be ttyUSB0, ttyUSB1, ttyUSB2 and then ttyUSB3. You can easily find this by typing in

ls /dev/tty*

then unplug a device, retype that command, and whichever /dev/ttyUSB* is missing, then that port is assigned that number. However, everytime you startup the Pi, it will randomly change. This makes it nearly impossible to keep consistent coding when you're trying to get serial information over a port that changes names. So we'll assign the port name based on it's physical position. How do we do this?

One port at a time. For USB0, run this command:

udevadm info --name=/dev/ttyUSB0 --attribute-walk

and you'll get a bunch of info about that particular USB port. Look for the fourth section, or wherever it says this:

KERNELS=="1-1.3"

That means that the physical port my USB0 is plugged into (remember, we figured out what the USB0 is in the previous step--for me, it's my GPS), it's physical port 3 (from 1.3). If you get confused, follow the original guide for more detailed instructions. Write this down, and repeat for however many USB devices you have. For my RPi3, the ports go (left to right top row, then left to right bottom row) 2, 4, 3, 5.

To create a "rules" file to permanently assign those physical ports with a persistent (permanent) name we can use in our code, run this command:

sudo nano /etc/udev/rules.d/99-usb-serial.rules

and enter the information that follows, but with your appropriate numbers/titles:

For my setup, I have a GPS plugged into one port, my DST-800 connected to an RS-422 to USB converter for my inputs (my python scripts use those two--instead of assigning a serial port to /dev/ttyUSB0, it's /dev/gps). "rd" outputs to my RD2030 display, and the "ap" outputs to the autopilot (these are used by kplex in the kplex.conf file).

This script is quite useful, aside from starting the whole system. It first changes the working directory to the kts script folder, which is necessary for the imu script to access the right calibration data. Without this step, the MPU-9250 won't work correctly.

Throughout the monitor script, it writes down what it's doing to a log file to see what's happening with the script.

After that, it executes the python scripts which then start running in the background (thanks to the "&" symbol), starts kplex, and then sets up the UDP ports to listen to each script's health monitor.

Every half second, each instrument script sends a timestamp which is read by this monitor script. If more than 10 seconds have gone by without receiving an update from the script (which means the script has failed for whatever reason), it will kill the process and restart it. It logs each action in the log file, which is helpful if I want to see if something is failing a lot.

First, it starts a log file to log the raw input for funsies. After that, it starts looping, and it sends the health monitor signal out every .5 seconds to the monitor.py script. It also logs the raw input from the GPS for the last 60 seconds (any and all input, regardless if it's a valid NMEA sentence). Next, it runs a quick routine to verify it really is a valid NMEA sentence, and only if it's the RMC one.

If it is, then it extracts the heading information from IMU (see next section), and if the groundspeed is less than .1 knots and heading is recent (from the last 3 seconds), then it replaces course with heading. Why? I've found that sitting at dock, even with a groundspeed of 0, the course still moves all over the place. This isn't really necessary, but it's slightly annoying since I'm a perfectionist and if I'm not moving, then the course should, by default, be the same as the boat's heading.

Then it assembles the whole sentence, writes it to the GPS bus file for the DST script, and prints it out to kplex via a UDP port.

It also creates the ZTG sentence (groundspeed and track) and ZDA (time in UTC). If there are any other valid NMEA sentences coming through, it prints them too.

It should be noted that the "try" section is there because if this script tries to read the file when the imu.py script is writing the file, it'll freeze. It's very rare that that would actually happen, but just in case, it "tries" to read it, and if it returns an error, it waits .03 seconds for the imu.py script to write and close the file, then tries again.

Step 4: The MPU-9250 Tilt-Compensated Compass Python Script

You can read all about it in my previous post, but the big take away is that you must calibrate it. Otherwise it will be useless. Remember, run the calibration command in the RTIMUEllipsoidFit folder. This will produce a RTIMULib.ini file. Copy that file over to the kts scripts folder, so it's in the same directory as the imu.py script.

Long story short--if it doesn't initialize, it will let you know via the XDR NMEA sentence, then shut down. The monitor will keep restarting it every 10 seconds. Also, if it stops receiving input for more than 5 seconds, it'll let you know that too.

Don't forget to update the magnetic deviation for your location. This is in the file simply called "mag" and if it's east, it's negative. For the SF Bay in 2016, it's approximately 14 degrees East, so I have -14 in there.

It dampens out heading over three seconds, and roll over one second, and prints all available AHRS information (attitude, heading, and rates of change) via a sentence. Most of this is just for gee-whiz, but the heading is necessary, and the roll/pitch is useful for other functions in the next section.

Also, there are built in "offsets." I ran this system in my slip and logged all the NMEA data for five minutes, and took the average roll, pitch, and heading. Then I made an offset such that it would subtract to get zero (if the average roll was +5.2 degrees, then the "rolloff" is 5.2). I have a compass on my boat, so I used that to compare the heading and made the appropriate offset.

This is very similar to the GPS script, in that it checks for validity, and has a routine for each sentence. For the SDDPT sentence, it corrects for installation offset. My sensor is at a 23 degree angle from straight up and down, so the depth is skewed. Since we know the vessel pitch and roll from the previous section, we can correct the depth reading for the boat's attitude. Nice.

It writes the water temperature to a bus (for later), and it also calculates the correct VWVLW voyage log sentence. The DST only stores the total nautical mileage, and doesn't have a reset function. No problem, I built one in the script.

For the VWVHW vessel water speed sentence, it corrects the water speed reading from boat velocity and roll (see this post here for more on that). Not only that, but every time it receives a VWVHW sentence, and heading/course/groundspeed info is from the last 3 seconds, it calculates the VDR Set and Drift Sentence (see this post here). It dampens that out over the last 5 readings to give smooth data.

Atmospheric Step: Setting up the BME280 Atmospheric Sensor with the Raspberry Pi

This one was just for fun. The sensor was really cheap, and I used some strange Chinese tutorial to set it up but I actually forget where I found it.

The sensor detects temperature, pressure, and humidity. I had to dust off my old atmospheric science textbooks from college, but I found a few equations to use this data to derive all sorts of humidity. It produces the MDA Meteorological Composite Sentence (go to this page and search MDA for more info), which includes barometric pressure (inches of mercury and bars), air temperature, water temperature, relative humidity, absolute humidity, and dewpoint. Whew.

It also sends out standard NMEA sentences for that data, which spoofs NKE Marine Electronics instruments.

Step 6: Setup a Wireless Kplex Multiplexer

Kplex is a fantastic tool, but to be totally honest, the documentation kind of sucks. It isn't written for computer morons like me, so I had to do a lot of testing and searching to figure it out. First, install it by doing this (in the kts directory of course):

Here is my kplex.conf file that accepts UDP inputs from the previous python scripts, and prints it all to a TCP port that my laptop/phone can connect to (as well as to the display I got on eBay and an additional port that can print to my Autopilot, or receive from another instrument). This kplex.conf file is also included in the github download from my page.

Simply save this as kplex.conf in the kts/scripts folder (where a copy already is if you downloaded my github) and copy it into the /etc/ directory with the following command in the terminal:

sudo cp kplex.conf /etc/

But we're not done. What address should you connect to on your phone or laptop? Find out with the following command:

ifconfig

and write down the number next to inet address of wla0 (mine is 10.0.0.1). When you add a connection in OpenCPN or the NKE Marine Electronics iOS app, use that number for the address, and use the port number that is in your kplex.conf file (if you used mine, the port number is 10110). Now, when you connect, you'll have a steady stream of NMEA data!

But let's make sure everything is working before we proceed. We're going the run the imu.py script, which will output NMEA data to the kplex port, and then run kplex as well with the raw text output:

python imu.py &

sudo kplex file:direction=out

That will output a text string of whatever kplex is receiving. Great. So now our instruments are outputting data, kplex is receiving, if you connect to the WiFi network and type in the inet address on your device (OpenCPN/NKE, with the port number specified in kplex.conf) you can receive over WiFi. So now, we just need to run the monitor script on its own so all this will happen automatically.

Step 7: Execute a Python Script at Startup on a Raspberry Pi

Save yourself some trouble, and just read this blog post here about it. I followed it, and have my results right here. Basically, it runs the init.sh script at startup, which executes the monitor.py script, which then starts everything.

You already have the monitor.py script from above, so now all that's left to do is make these two scripts "executable," and copy this init.sh to the right directory.

That's easy, all you have to run is the following commands, assuming you're in the kts/scripts folder:

sudo chmod a+x init.sh

sudo chmod a+x monitor.py

sudo cp init.sh /etc/init.d/

sudo update-rc.d init.sh defaults

Now it will execute init.sh at startup, which will execute monitor.py, which then executes all the instrument scripts and kplex.

Make note of two things: the very first line of monitor.py is "#!/usr/bin/env python" because it needs to know its a python script. Also, the first step in monitor.py is to change the working directory to the scripts folder for IMU calibration.

Final Thoughts

Now when you turn on your Raspberry Pi, all these scripts should start up and you'll receive good NMEA data through the wifi connection. If you want to check out the log files, you can ssh in with the same inet address we've been using. With your laptop connected to the RPi's Wifi, use Terminal and type the following in:

ssh -Y pi@10.0.0.1

# Enter your password (the default is "raspberry")

cd kts/scripts

sudo nano log

or just nano whatever file you want to see. This way, you can debug/see what's up without a screen or a keyboard on your Pi when you're down on your boat with your laptop. Pretty useful, huh?

All in all, this is what we're looking at:

Raspberry Pi

$40

USB GPS

$30

MPU-9250

$12

DST800

$250

BME280

~$15

Cables/Misc

~$100

Total:

~$450

Not too bad for a wireless multiplexer, especially considering what it can do. Tilt-compensated compass. Data dampening. Wireless multiplexing. VDR Set and Drift. Correct paddle wheel readings. I am always interested in hearing what other applications people can find with the little device.

In another comment section, someone mentioned using it to automatically modulate a windlass based on depth--something that could be useful if you always want to drop out seven times the depth worth of chain for your anchor, or in his case, I believe it was fishing nets. Use the comments below to tell me your ideas.