Der Heading NMEA2000 Datensatz 127250 wird zu NMEA0183 übersetzt und ausgegeben

Der Vessel Heading PGN 127250 wird mit dem NMEA Shield eingelesen, zerlegt und als NMEA0183 Datensatz auf TX1 wieder ausgegeben. Bei einem Magnetkompass wird HDM (Magnetic) ausgegeben und bei einem Satelliten- oder Kreiselkompass HDT (True).

Genau so können auch andere NMEA2000 Daten übersetzt werden.

Diese Übersetzung wird benötigt wenn man von einem neuen Autopiloten mit NMEA2000 Verkabelung ein schnelles Heading für ein altes Radar benötigt. Die Kompaßdaten werden typisch 10x pro Sekunde ausgegeben.

Die NMEA0183 Datensätze sind hier beschrieben:
http://nmea.de/nmea0183datensaetze.html#hdm

Hier das Programm:

// Die Kompassrichtung vom PGN 127250 NMEA2000 wird mit dem 
// NMEA Shield in den Arduino eingelesen und dann als NMEA0183 
// Datensatz HDM oder HDT ausgegeben.
// 
// PGN 127250 : Vessel heading, typisch 10x pro Sek.
//
// Matthias Busse 14.04.2017 Version 1.0

#include <SPI.h>
#include <Arduino.h>
#include <NMEA2000_CAN.h>
#include <N2kMessages.h>
#include <N2kMessagesEnumToStr.h>

#define N2k_CAN_INT_PIN 21
#define MCP_CAN_RX_BUFFER_SIZE 100

typedef struct {
  unsigned long PGN;
  void (*Handler)(const tN2kMsg &N2kMsg); 
} tNMEA2000Handler;

//void PositionRapid(const tN2kMsg &N2kMsg);
void VesselHeading(const tN2kMsg &N2kMsg);

tNMEA2000Handler NMEA2000Handlers[]={
  {127250L,&VesselHeading},
  {0,0}
};

unsigned long now, last;
double head, var, dev, ref;

template<typename T> void PrintLabelValWithConversionCheckUnDef(const char* label, T val, double (*ConvFunc)(double val)=0, bool AddLf=false ) {
  Serial.print(label);
  if (!N2kIsNA(val)) {
    if (ConvFunc) { Serial.print(ConvFunc(val)); } 
    else { Serial.print(val); }
  } 
  else Serial.print("not available");
  if (AddLf) Serial.println();
}

void setup() {
  Serial.begin(115200); // USB
  Serial3.begin(4800); // NMEA0183
  Serial.println("NMEA2000 PGN 127250 Vessel Heading als NMEA0183 ausgeben");
  NMEA2000.EnableForward(false);
  NMEA2000.SetMsgHandler(HandleNMEA2000Msg);
  NMEA2000.Open();
  last=millis();
}

void loop() {
  NMEA2000.ParseMessages();
  if(millis()-last > 100) { // 10x pro Sekunde
    last=millis();
    if(ref==1) HdmOutput(); // Magnetisch ausgeben
    if(ref==0) HdtOutput(); // True ausgeben
  }
}

void VesselHeading(const tN2kMsg &N2kMsg) {
// PGN 127250 VesselHeading.
// kommt typisch 10x pro Sekunde
unsigned char SID;
double Heading;
double Deviation;
double Variation;
tN2kHeadingReference HeadingReference;
    
  if (ParseN2kHeading(N2kMsg,SID,Heading,Deviation,Variation,HeadingReference) ) {
    head=RadToDeg(Heading);
    dev=RadToDeg(Deviation);
    var=RadToDeg(Variation);
    ref=HeadingReference; // 0:True, 1:Magnetic
  }
  else {
    Serial.print("Fehler PGN: ");
    Serial.println(N2kMsg.PGN);
  }
}

void HdmOutput() {
// NMEA0183 Datensatz HDM ausgeben
// http://nmea.de/nmea0183datensaetze.html#hdm
//
// Matthias Busse 14.4.2017
int cs;
String out = "$HCHDM,";
  out += head;
  out += ",M*";
  cs=getCheckSum(out);
  if(cs<16) out += "0"; 
  Serial.print(out); // USB Ausgabe
  Serial.println(cs,HEX);
  Serial3.print(out); // NMEA0183 Ausgabe
  Serial3.println(cs,HEX);
}

void HdtOutput() {
// NMEA0183 Datensatz HDT ausgeben
// http://nmea.de/nmea0183datensaetze.html#hdt
//
// Matthias Busse 14.4.2017
int cs;
String out = "$HCHDT,";
  out += head;
  out += ",T*";
  cs=getCheckSum(out);
  if(cs<16) out += "0"; 
  Serial.print(out); // USB Ausgabe
  Serial.println(cs,HEX);
  Serial2.print(out); // NMEA0183 Ausgabe
  Serial2.println(cs,HEX);
}

int getCheckSum(String s) {
// Checksum berechnen und als int ausgeben
// wird als HEX benötigt im NMEA Datensatz
// zwischen $ oder ! und * rechnen
//
// Matthias Busse 18.05.2014 Version 1.1

int i, XOR, c;

  for (XOR = 0, i = 0; i < s.length(); i++) {
    c = (unsigned char)s.charAt(i);
    if (c == '*') break;
    if ((c!='$') && (c!='!')) XOR ^= c;
  }
  return XOR; 
}

void HandleNMEA2000Msg(const tN2kMsg &N2kMsg) {
int iHandler;
  
  for (iHandler=0; NMEA2000Handlers[iHandler].PGN!=0 && !(N2kMsg.PGN==NMEA2000Handlers[iHandler].PGN); iHandler++);
  if (NMEA2000Handlers[iHandler].PGN!=0) {
    NMEA2000Handlers[iHandler].Handler(N2kMsg); 
  }
}

Verwendet wurden:
Arduino Software 1.8.0
NMEA Shield Version 1.7
Arduino Mega 2560
NMEA2000 GPS Antenne mit Kompaß

von Matthias Busse

Ein Gedanke zu „Der Heading NMEA2000 Datensatz 127250 wird zu NMEA0183 übersetzt und ausgegeben

  1. Pingback: Das NMEA Shield für den Arduino Mega 2560 ist fertig | Shelvin – Elektronik ausprobiert und erläutert

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.