<< Raspberry Coffee page

Enriching the on-board NMEA Stream with a Raspberry PI and Java



Most - if not all - the software and hardware components mentioned in this document are reachable from the Resources section, at the end of this document.

The context

Top
Several electronic instruments are available on boats (sailing boats, motor boats).
Those instruments read, compute, and eventually provide various data used for navigation. The idea here is to have an easy access to those data, display them on several kinds of devices (and not only on the expensive displays sold by the nautical electronic providers), and possibly add more data to the ones already managed and manipulated by your existing electronic instruments.

NMEA

The electronic instruments available on boats are used to measure data like the boat speed and heading, the wind speed and direction, read the boat position (GPS), all this kind of things used for navigation.
Some data are read from transducers (boat speed through water, wind speed, compass heading, etc), and some are computed (true wind speed and direction, true heading, etc).
Those data are usually available in the NMEA format. NMEA stands for National Marine Electronics Association. The definition of the NMEA strings is one of the oldest electronic standards.
The NMEA sentences (or strings) are human readable (i.e. it is a text format, it can be some times a bit cryptic). They can be easily parsed by a computer program, several such parsers can be found for free.
Here is what an NMEA stream can look like:
$IIMWV,112,R,00.8,N,A*19
$IIMWV,109,T,00.7,N,A*1A
$IIMTA,31.5,C*02
$IIRMB,A,0.23,R,,HMB-3   ,,,,,001.20,184,,V,A*1F
$IIXDR,P,1.0156,B,0*71
$WIMDA,29.991,I,1.016,B,31.5,C,,,,,,,,,,,,,,*3B
$IIRMC,225158,A,3730.075,N,12228.854,W,,,021014,15,E,A*3C
$IIVHW,,,355,M,00.0,N,,*67
$IIVLW,08200,N,000.0,N*59
$IIVWR,112,R,00.8,N,,,,*6B
$IIGLL,3730.075,N,12228.854,W,225158,A,A*4C
$IIHDG,356,,,15,E*16
$IIMTW,+16.0,C*3F
$IIMWV,111,R,00.9,N,A*1B
$IIMWV,112,T,00.8,N,A*1F
$IIRMC,225158,A,3730.076,N,12228.855,W,,,021014,15,E,A*3E
$IIVHW,,,356,M,00.0,N,,*64
$IIVLW,08200,N,000.0,N*59
$IIVWR,111,R,00.9,N,,,,*69
$IIGLL,3730.076,N,12228.855,W,225158,A,A*4E
$IIHDG,356,,,15,E*16
$IIMTW,+16.0,C*3F
...
          
 Hint: What is a parser?

Several challenges

Introducing the Raspberry PI

Top
The Raspberry PI is a credit-card-size computer that can be used to address all the challenges mentioned above.
It is a fully featured Linux computer, that you can get for less than US$40 (2015).
Linux has no incompatibility with Java, hence Java runs just fine on the Raspberry PI.
The choice of a language is a delicate topic; it has some close-to-religious dimension... You cannot convince someone who does not believe you that your language is better than his language. At least, I can't.
I will spend no time trying to convince anyone to use Java rather than any other language.
But I use Java at least because This being said, all the softwares I wrote to run on the Raspberry PI (in this document) are written in Java. They are all in Open Source.

Navigation Console

The Navigation Console is a program I've been using on board for several years (I wrote it, partly at sea). It provides - among other features - a graphical user interface to the navigation data.

Graphical, yes. Because even the smartest guy is tired after several days upwind against a snow storm...
And even if you are not the smartest guy, if you are not upwind, not tired, and it is not snowing, there are better ways to use your energy than scanning raw NMEA sentences.


The Navigation Console, Swing GUI


I have recently enhanced it to run in headless mode (i.e. without graphical user interface), to run on the Raspberry PI. And it works just fine. In those headless conditions, the role of the console is to read and compute the data, possibly log, and re-broadcast them on one or more channels. For such a re-broadcasting to happen, the Raspberry PI creates its own ad-hoc wireless network. Other devices will join this network, and will then have access to the re-broadcasted data.


The Raspberry PI at work on board, in the chart table.

Notice on the picture above: the slice of Pi on top of the Raspberry PI, hosting the battery monitoring device, and the small breadboard, with a BMP180 PCB plugged in it, and connected to the Slice of Pi. We'll talk more about those two later in this document.
 Hint: What is a slice of PI?

We need to plug-in three USB sockets here: The device featured here is a Raspberry PI Model B, that comes with two USB ports. The more recent one B+ has 4 USB ports; this would cancel the need for the USB hub you can see on the picture, as we would have by default have more than the three USB sockets we need in this context.

Re-broadcasting

Many navigation programs provide the possibility to read the NMEA streams from other channels than the Serial connection. Those other protocols are usually TCP (Transfer Control Protocol) or UDP (User Defined Protocol). Also available for the same purpose: HTTP (Hyper Text Transfer Protocol), RMI (Remote Method Invocation), WebSocket...
The idea here is to use a Serial port of the Raspberry PI (USB) to read the NMEA data from the station, and then to re-broadcast the data as they were read on another channel. All the channels mentioned above can be consumed simultaneously from several clients. This way, the data read by the Raspberry PI are simultaneously available to all the devices interested in reading them.
The Navigation Console provides TCP, UDP, HTTP, and RMI servers. Those servers are very tiny, and do not overload the Raspberry PI.
The HTML5 WebSocket protocol is also available, through node.js and a user-exit.

Multiplexing

Multiplexing is this technique that takes data from several several origins and merges them into a single channel.
Here we read NMEA data from the NMEA station (already NMEA formatted, obviously), and the program puts them in a cache (technically, it is a HashMap, living in a singleton). Whatever component - like other components of the soft that would need the GPS position, all the different servers (TCP, UDP, etc) would read that cache as the single point of truth. Computed data are also read from the cache. As a matter of fact, all computed data (like True Wind Direction and Speed, Current Speed and Direction, Performance, etc) are re-calculated every time a new value is inserted into the cache by the NMEA reader.
Two things to notice: We will use those aspects to inject extra data in the cache.
For example, you can read the battery voltage from some specific device you can build (Open Source as well), turn this value into an NMEA Sentence, and inject it in the cache. Whatever component has subscribed to the manageEvent event in its listener will be notified of the injection of the NMEA sentence.
The same is true for any other data. I used a BMP180 PCB (from ) to get the air temperature and the atmospheric pressure (NB: unlike the battery voltage, those data do have an NMEA equivalent, but not available on the NMEA station I have on board). They are read from the sensors, turned into an NMEA string, and injected in the cache. See in the picture below the data prefixed with BAT (custom NMEA chain, BATtery), MTA (Air Temperature), MMB (Barometric Pressure). The Character Console featured below is reading the data from the cache they're injected in.

Character Console


The Character Console, on a 7" RCA screen, on board.

This one provides for (almost) nothing an access to the data computed by the Raspberry PI. It can be customized by the user. The goal here is to have an access to those data, without having to turn on a laptop or any such demanding device. The only one to switch on is the screen itself, which can be turned back off when done reading.

Other devices

TCP and friends


On the laptop, using TCP to get the data from the Raspberry PI, simultaneously using the Graphical Console, and OpenCPN.

TCP and UDP are light protocols, designed for computer-to-computer communication. They are both based on a socket mechanism. Once a socket is established between two computers (a client, and a server), then the logic of the dialog will be implemented by the programs running on both client(s) and server, which they have to agree on (to understand each other). In our case, this is extremely simple, once a client is connected, the server is sending it all the valid NMEA strings it reads.
HTTP
HTTP has always been HTML's best friend. HTML is a markup language (widely used to design web pages), HTTP is a transport protocol that can convey HTML streams.
HTTP is based on TCP, but is has been designed to be a request-response protocol. For the server to do something, a client has to ask first.
As long as you have a browser on the device you want to use, then HTTP would be an obvious choice. To refresh the data, we would use AJAX, in order to avoid a refresh to be performed by the client.
HTML5 provides elaborated graphic capabilities that will give us the possibility to come up with a nice graphical user interface.


The HTML5 console, as seen in a browser (laptop, tablet, smart-phone, ...)

The HTML console is refreshed every seconds. The AJAX request performed every second returns an XML document, parsed on the client side.
This page can be reached by default at http://192.168.1.1:9999/html5/console.html.
WebSocket
The WebSocket protocol has been introduced with the release of HTML5.
It is also based on TCP.
One of the drawbacks of HTTP is that it is a request-response (a.k.a. push-pull) protocol. You have to make a request to get a response. For example, if you want to get a flight status from some airline website, the first time you reach the page, it gives you the expected arrival time of the flight. Every time you want to see it this estimated time has changed, you must refresh your page. In other words, request it again.
The WebSocket protocol precisely addresses (among others) this kind of issue. Once the client (i.e. your browser) is connected on the server, data will be pushed (by the server, to the client) as needed, without requiring the client to refresh its page. This clearly divides the traffic by two.
The browser you use must be WebSocket aware though. As of now (2015), some browsers (like Internet Explorer 9) still do not support it.

In the Navigation Console, the WebSocket interface is implemented as a user-exit.
It requires a WebSocket server to be available. We can (fortunately) run it on the Raspberry PI. Node.js is the one we use, with its WebSocket module. Google it to see how to install all this, it is fast and easy.
In short, here is how it is going:
  1. An HTTP/WebSocket server is started on the Raspberry PI
  2. A user-exit (listening to the cache) is pinging the WebSocket server everytime some data is inserted
  3. A web page (WebSocket client) will reach the WebSocket server to display real-time data, pushed by the server, from as many clients as needed. The data to display are returned as a json object, embedded in the payload of the WebSocket message send by the server to the client.
The WebSocket console looks exactly like the HTML5 one featured above. But it takes about half the resources. And the data are refreshed by the server.

Summary of the architecture


The full set. The Raspberry PI is the heart of the system.
HTTP and WebSocket play the same role on the picture.

The Raspberry PI is the only device connected to the NMEA Interface (the boat's instruments). It is the first to be turned on, and the last to be switched off. I've been running it continuously for weeks, without any glitch.

The Raspberry PI fulfils two distinct functions:

The Raspberry PI rebroadcasts the data using TCP, HTTP, and WebSocket (in this case). Data can also be logged on the Raspberry PI's SD card.
The laptop uses TCP to consume the data, and can run simultaneously several programs using the NMEA data.
The character console also runs on the Raspberry PI, but in another process than the one reading the data. This way, the character console can be stopped, without interrupting the logging and re-broadcasting performed by the NMEA Reader process.
Tablets and smart-phones can join the wireless network, using HTTP or WebSocket to display the HTML5 Console.

See on the picture above the central place taken by the Raspberry PI. It is acting as the main hub of all the system. It is the only one reading the NMEA data out of the NMEA station. In addition, it manages its own sensors to read extra data (in this case: battery voltage, atmospheric pressure and air temperature). All the data gathered by the Raspberry PI are re-broadcasted onto several channels, depending on the devices connected on the Raspberry PI's own ad-hoc wireless network. Those devices can join or leave the network at their leisure, the only piece remaining alive will be the Raspberry PI, maintaining all the infrastructure. And all this for between 0.13 and 0.19 Amps. The character console running on the 7" RCA screen preserves a rapid access to the data currently available on the Raspberry PI.

Pebble (July 2016)

As of July 2016, we can now add a Pebble watch to the boat's network. It is easy to connect it to the network, a first implementation is currently using WebSockets. XMLHttpRequest may follow. And the basic Pebble works just fine, the battery lasts way long enough away from the power supply, and its price is under $100.
Application list Press SELECT to start Choose your data Select... Display!
The code is on GitHub.
Currently, a smartphone - paired with the watch with BLE - is still required. I'm looking forward to playing with the PebbleCore...

Extra data

Top
What we've seen so far does not involve the extra data we can feed in the NMEA stream from the Raspberry and its connected sensors.
We've seen above that the Raspberry PI has 2 extra sensors to The data read from those sensors are converted into an NMEA string, and injected into the NMEA stream (see the multiplexing section for details).
As they're part of the NMEA stream, any client reading those data cannot tell their origin.
For the same reason, those data can be logged along with all the others.
About logging...
The disk of the Raspberry PI is actually an SD card. I use a 16GB SD Card. It allows me several weeks of continuous logging.

Let us take the battery voltage data as an example.
Here is a graphical rendering of a several day logging of the battery voltage.


Battery Voltage logging

Using another Java project I own, I can calculate the sunrise and sunset, at the location of the boat, for the date of the logging. This is what's rendered in the background of the graph, gray for the night, white for the day.

A quick analysis

The small notches on the red line correspond to the periods when the fridge goes on.
During the day (white background), you can notice that the voltage goes up, and back down before dark. This is because of the solar panel, that feeds the batteries.
Orienting the solar panel so it permanently faces the sun makes a very big difference! Specially on this graph, during the first part of the day.
During the night (gray background), there is nothing to charge the batteries.
The notches corresponding to the fridge are there, but beside that, it is clear that the average voltage does not drop during the night.
This means that there is no leak in the circuit. And that is good news!

More data

We can also log the atmospheric pressure, read from the BMP180 sensor. That one can prove very useful to anticipate atmospheric phenomenons. Logging those values and sending a warning when the pressure drops below a given threshold becomes very easy, and can happen to be a precious asset.

There are many cheap sensors that can be used with the Raspberry PI. Many of the data they emit can certainly contribute to a safer and more accurate navigation.
The only boundary is your imagination!

It is also possible to compute NMEA data that would not be returned by your NMEA Station. Data about True Wind for example, like its speed, angle and direction. Those data are to be calculated, and turned into valid NMEA strings such as VWT, MWD and MWV.
Any program, aware of those sentences, can render them accordingly.


True Wind, available in OpenCPN.


OpenCPN 3.3.2316 MDA support for barometric pressure

Following the exact same pattern, you can insert the current speed and direction (String VDR). See the olivsoftdesktopuserexits.sample.TrueWindSentenceInsertion and olivsoftdesktopuserexits.LongTimeCurrentCalculator user exits to see how.

 Hint: What is True Wind and Current calculation?

 Hint: What to calculate True Wind with?

More about TCP...

There is this Android soft, SeaWi, that can consume the TCP feed without any question.
Above is a replay of a trip between Nuku-Hiva and Rangiroa...

Other Boards?

We've been talking about the Raspberry PI here. Why not other boards?
There are indeed many such boards already available, and new ones show up almost every day.
The criteria to choose the right board for your project could be - among others: As of now (2015), a Raspberry PI B (and B+) costs less than $40. A Raspberry PI A (and A+) comes for less than $30.
An Arduino Uno is less than $20 (and this is a great board, probably the one that started all this), but to get the network, you need an extra shield that you will get for another $20. And the Arduino Uno has 32Kb of memory (yes, Kb, this is not a typo).
The BeagleBone is more powerfull than the Raspberry PI, but also more expensive.
The Raspberry PI comes with Linux and Java (both free and OpenSource). It has the GPIO Header we need for extensibility.
It does indeed seem to be the right choice for this project, mostly because of its memory, CPU, and connectivity capabilities. Even the Raspberry PI A+ (which I just tested) works just great. It comes with 256Mb of RAM, it has no Ethernet port, and just one USB port. The energy consumption is even lower than on the Raspberry PI B. And it is even smaller.
About the CPU and memory
It is interesting to remind the youngests of us that 25 years back, I was working with a desktop that had 25 Mb of RAM (yes, about 10 times less than the Raspberry PI Model A). And this was a huge machine. At that time, programming skills included saving (and reusing) memory. That is a skill to keep alive in this area.

The B+ and A+ models use a micro-SD Card, very small in size (the actual challenge is not to lose it), not in capacity.
Here is a screenshot showing top running on the Raspberry PI A+, with all the features above running, including the WebSocket server (nodejs).

Click to enlarge
Top at work

My favorite configuration today (Jan-2015) would definitely include This being said, any Raspberry PI currently available would fit, as well as Banana PI, BeagleBone, Olimex, etc. I believe that the Raspberry PI A+ is the one drawing the smallest amount of energy, among all the boards running Linux & Java (correct me if I'm wrong). Any board running Java (on Linux or not), and able to connect to a network will do the job.
One of my goals here was to save as much energy as possible.
Monitor the JVM
The Java Virtual Machine (JVM) comes with several tools, including jconsole, that allows you to see what is going on regarding the resources, so you can tune the JVM's parameters.
The jconsole utility lets you monitor a remote JVM. Run it from another box, like the one you develop on.
You need to add the following parameters when starting the JVM to monitor (i.e. on the RPi):

 JAVA_OPTIONS="$JAVA_OPTIONS -Dcom.sun.management.jmxremote.port=1234 \
                             -Dcom.sun.management.jmxremote.ssl=false \
                             -Dcom.sun.management.jmxremote.authenticate=false \
                             -Djava.rmi.server.hostname=raspberrypi-boat"
        
The port and the hostname need to match your environment, of course.
The other parameters should make sense, to whom it may concern...

Click to enlarge
Connect...

Click to enlarge
Monitor

New setting (Apr-2015)

I reworked the setting of the Raspberry PI on board. I got rid of the cigarette-lighter socket for the 12v-5v conversion. I built a small voltage regulator, as explained here, and put everything on the same plexiglass board.


The voltage regulator

The new setting

In the boat

Summary

Top

Resources

Top
The pdf documentation of the NMEA Console (included in the Navigation Desktop) can be found here.

Some last comments

Top

Originally, the software (the NMEA Console) was written to run on a laptop.
Putting the Raspberry PI in the picture substancially changed the paradigm, the architecture clearly became hub-and-spoke oriented.
The cache architecture was also quite impacted. An easy way around the problems raised by this hub-and-spoke architecture is to generate new NMEA Strings from the Raspberry PI, and inject them into the NMEA Stream. This is the case for the Atmospheric Pressure, the True Wind computation, the Current computation (with time buffer), and the list is not closed.
For the data that do not have an NMEA equivalent (like the battery load), I just came up with my own ones. All it requires is to have the software reading them to be aware of those (like the character console).

All the software used here is Open Source software, and as such, is free.
The hardware follows the same path (beside the boat itself, of course, and the NMEA electronics), the price for a Raspberry PI is ridiculous, the extra sensors, boards, small keyboards, small screens, and various components you would need to do the same will fit more than once in a $100 budget.
It is interesting though, to notice that this architecture is the exact same one that was used during the recent 34th America's Cup by those multi-million$ fantastic cats - including the glorious winner.
Well, now you can get to the data, you have to analyze them. And the next America's Cup is all yours.

Enjoy!


Oliv fecit, AD 2014, 2015.