Thursday, April 14, 2016

Building your own NMEA 2000 Device

The hard work has already been done, first by the pioneering efforts of Kees Verruijt at canboat , and now by the development of a NMEA2000 Arduino library by Timo Lappalainen.


I am using the NMEA2000 library with an Arduino Due board. The Due has a built-in CAN controller (in fact 2 of them), missing only an external CAN transceiver to get attached to a N2K backbone. With the arrangement described below, I first ran the library example ‘TemperatureMonitor’, sending 2 fixed temperature values to the N2K network. The result can be seen in the following screen capture of the B&G Touch 7 display, showing the sea and cabin temperature values sent by this example.



I then proceeded to develop a replacement for the Actisense NGW-1, which translates fast NMEA 0183 heading sentences to their equivalent N2K PGN. For this, I also made use of the TinyGPS++ library, which takes care of parsing the NMEA 0183 sentences. 




All this is done with a deceptively short Arduino sketch (‘Heading Converter’), which I reproduce in its entirety here.

// Convert fast heading data from NMEA 0183 to NMEA 2000

#include <Arduino.h>
#include <NMEA2000_CAN.h>
#include <N2kMessages.h>
#include <TinyGPS++.h>

TinyGPSPlus gps;
TinyGPSCustom heading(gps, "HCHDG", 1); // $HCHDG sentence, 1st element

void setup() {
  Serial2.begin(9600);
  
  NMEA2000.SetProductInformation("00000001", 100,"Heading converter", "1.0.0.11 (2016-04-13)", "1.0.0.0 (2016-04-13)");
  NMEA2000.SetDeviceInformation(1, 140, 60, 2046);
  NMEA2000.SetForwardOwnMessages();
  NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly,22);
  NMEA2000.EnableForward(false);
  NMEA2000.Open();
}

void loop() 
{
  tN2kMsg N2kMsg;
  if (heading.isUpdated())
  {
    SetN2kMagneticHeading(N2kMsg, 1, DegToRad(atof(heading.value())));
    NMEA2000.SendMsg(N2kMsg);
    NMEA2000.ParseMessages(); 
  }
  
  while (Serial2.available() > 0)
    gps.encode(Serial2.read());
}

2 comments: