NMEA 0183 sentences recording
Recording NMEA 0183 data on a SD card
English version of the page below in pfd Recording NMEA 0183 sentences on an SD card for a depth survey. An Arduino type microprocessor is used.
( 5 pages)
Voorbeeld: Ondiepte Slotermeer (FR) Recordings afgelopen jaren
NMEA 0183 sentences recording
Doel
Het bewaren van NMEA 0183 sentences in een TXT bestand ten behoeve van bijvoorbeeld een waterdiepte survey.
Gebruikte databronnen
Voor de positie: De GPS positie van/via een Em-trak B-100 AIS
(Een Raymarine GPS met Raymarine AIS ontvanger werkt ook)
Voor de waterdiepte: Een Raymarine echolood gekoppeld aan een Multi Function Display (MFD).
Interfacing
De Em-trak AIS communiceert met een baudrate van 38400 baud met het MFD.
Het echolood staat via de Seatalk link gekoppeld aan het MFD.
Indien het MFD en AIS correct functioneren, wordt de diepte-informatie van het echolood via de SeaTalk verbinding aan het MFD geleverd en vandaar af via NMEA 38400 baud aan de AIS.
Met de andere NMEA 0183 sentences van de AIS wordt deze diepte informatie in één NMEA datastroom opgenomen. Deze is via de 38400 baud en de 4800 baud poort van de AIS toegankelijk. De uitgaande NMEA 4800 datastroom, wordt door de recorder gebruikt.
Los van de positiedata wordt de AIS in dit geval niet voor haar specifieke AIS data gebruikt maar vooral voor het samenvoegen van de twee NMEA datastromen tot èèn NMEA datastroom.
Datarecording
De datarecorder leest de NMEA 0183 sentences en bewaart ze op een SD kaartje. Alleen de datum, positie en diepte zijn voor ons doel van belang, dus alleen de daarvoor benodigde zinnen worden bewaard. (GPRMC en SDDBT) Het schrijven op het kaartje kost tijd en ruimte, dus hoe minder ongebruikte zinnen opgeschreven worden, des te meer tijd er is voor de te gebruiken strings. Bij de verwerking van de data, op een later tijdstip, worden de positie en waterdiepte uit de strings gehaald.
Fileformat en naam
De data wordt automatisch in tekstbestand opgeslagen met de bestandsnaam MMDDUUmm.txt waarin:
MM maand van het jaar
DD dag van MM
UU uren van UTC
mm minuten van UU (De bestandsnaam is beperkt tot 8 karakters)
De datarecorder heeft geen eigen klok of geheugen. Datum en tijd worden daarom bij aanvang van het programma uit een ontvangen GPRMC sentence gehaald om de bestandsnaam te kunnen maken. Het is daarom van belang dat de datastromen correct lopen op het moment dat de datarecorder aangezet wordt.
Voorbeeld van een opname
10231110.TXT (start van de opname 23 oktober om 11:10 UTC)
$GPRMC,111018.00,A,5253.79623,N,00538.73222,E,0.030,,231021,,,A*78
$GPRMC,111019.00,A,5253.79624,N,00538.73222,E,0.022,,231021,,,A*7D
$SDDBT,5.8,f,1.7,M,1.0,F*0C
$GPRMC,111020.00,A,5253.79624,N,00538.73220,E,0.018,,231021,,,A*7C
...... en zo verder
De automatisch gegenereerde bestandsnamen hebben geen jaar aanduiding. De opnames zet ik daarom af en toe handmatig in een filefolder met het betreffende jaartal. In bovenstaand voorbeeld is de datum 231021 (zie de GPRMC string) en is de opname naar de filefolder 2021 verplaatst.
BUG: Wij hebben ons Raymarine echolood gecorrigeerd voor de diepte van de transducer (offset), zodat het scherm de diepte vanaf het wateroppervlak aangeeft. De sentence identifier DBT in voorgaand voorbeeld, waarin de waterdiepte 1.7 m vanaf het wateroppervlak is, behoort door de correctie nu feitelijk DBS (Depth Below Surface) te heten in plaats van DBT (Depth below Transducer).
Of andere Raymarine software versies de identifier na correctie ook niet herbenoemen is mij niet bekend.
Het is daarom verstandig om, vóór gebruik van de diepte informatie, een controlepeiling te maken om te zien welke waarde in werkelijkheid gegeven wordt en opgenomen is.
NOOT: De waarden van de dieptes in de SDDBT sentence hebben in het officiële NMEA 0183 format slechts één decimaal. Bij de verwerking van de data op een later tijdstip gebruik ik daarom de diepte in voet en reken die zelf om naar centimeters. Dit geeft me een grotere nauwkeurigheid. (1/10 voet is ca 3 cm en 1/10 meter is 10 cm)
De data recorder.
Als datarecorder gebruik ik een Arduino Uno type microcontroller board, een SD kaart module en een MAX485 module. (op de foto vertikaal, linksboven, ietwat verstopt tussen de kabeltjes)
De NMEA 4800 baud datastroom is een differentieel systeem met twee datalijnen A en B. Ze liggen niet aan aarde om beter bestand te zijn tegen storing. Als lijn A 5 volt is, is lijn B 0 volt en andersom. De MAX 485 module zet deze NMEA datastroom om in TTL met 5 volt ten opzichte van aarde. De ontvangen NMEA datastroom loopt daarom via de MAX485 naar de digitale datapoort D1 van de Arduino. De NMEA sentences die ik later wil gebruiken, worden op het SD kaartje geschreven.
De datastroom is gelijktijdig via de USB poort met een Serial Monitor programma op de computer te volgen. Andere computer programma''s, die NMEA input via de USB poort kunnen gebruiken, zouden er ook gebruik van kunnen maken. (Zorg hierbij wel, bij de computer, de juiste COM poort en baudrate te kiezen).
Het programma waarmee de het microcontroller board wordt aangestuurd is in de Arduino IDE op een windows computer geschreven en wordt via een USB connectie op het microcontroller board geladen. Het programma wordt daar bewaard en begint te lopen wanneer er spanning op de Arduino gezet wordt. De voeding loopt via een 7808 stabilisor om overspanning tijdens acculaden te voorkomen.
Het programma
/*
The MAX 485 module is connected to the Arduino as follows
RO Receive Out to D1 purple (Hardware Serial connection)
DI Data In to D2 grey
RE Receive Enable D5 grey
DE Data Enable D6 yellow
5V 5V red
GND GND black
The SDCard connection to the Arduino:
CS yellow to D10 sdPin
MOSI blue to D11
MISO white to D12
SCK orange to D13
5V red to 5V
GND black to GND
The MAX485 Module
A NMEA+ green
B NMEA- white
*/
#include <SPI.h>
#include <SD.h>
#define REPin 5 // Receive Enable
#define DEPin 6 // Data Enable
#define sdPin 10 // SDCard
File myFile;
String inputString = "";
char charReceived = "A";
bool txtnameExcist = false;
char txtname[15]; // filename
void setup()
{
pinMode(sdPin, OUTPUT);
pinMode(REPin, OUTPUT);
pinMode(DEPin, OUTPUT);
digitalWrite(REPin, LOW); // receive mode
digitalWrite(DEPin, LOW);
inputString = "";
inputString.reserve(200);
Serial.begin(4800); // baudrate
if (!SD.begin(sdPin))
{
Serial.println("startup failed");
return;
}
strcpy(txtname, "MoDDHrMi.TXT"); // Month, Day, GMT Hour, Minutes.TXT
}
void loop()
{
if(Serial.available())
{
charReceived = (char)Serial.read();
inputString += charReceived;
if(charReceived == '\n') // end of NMEA sentence - start checking it out
{
if((inputString.substring(0,6) == String("$GPRMC")) && (txtnameExcist == false))
// start with extracting the day and time if this is the RMC string and create the filename
{
txtname[0] = inputString.charAt(55);
txtname[1] = inputString.charAt(56);
txtname[2] = inputString.charAt(53);
txtname[3] = inputString.charAt(54);
txtname[4] = inputString.charAt(7);
txtname[5] = inputString.charAt(8);
txtname[6] = inputString.charAt(9);
txtname[7] = inputString.charAt(10);
myFile = SD.open(txtname, FILE_WRITE);
if( ! myFile )
{
Serial.print("Couldnt create ");
Serial.println(txtname);
}
myFile.println(txtname); // print the filename in the file
myFile.println(""); // print a bank line
myFile.flush(); // print to the SD card
txtnameExcist = true; // skip filename creating and start recording
}
if( (inputString.substring(0,6) == String("$GPRMC")) ||
(inputString.substring(0,6) == String("$SDDBT"))) // avoid unneeded strings
{
if(txtnameExcist == true)
{
myFile.println(inputString); // print the inputstring in the file
myFile.println(""); // print a blank line
myFile.flush(); // print to the SD card
Serial.println(inputString); // print the sentence to the USB exit
}
}
inputString = ""; // clear the inputstring
}
}
}
Uit de opgenomen stringen kan in een later stadium de positie en de diepte geplot worden.
Bijvoorbeeld:
De laterale betonning geeft de zijdelingse begrenzing van het vaarwater aan.
De diepte in deze vaarwateren behoort minimaal 1.7 m te zijn (gele of grijze meetpunten)
De ondiepte (ca 1.35) oost van de SM 24 was in 2022 niet op de waterkaarten aangegeven.
Noot: Bij aanwezigheid van andere vaartuigen volgen we, voor de duidelijkheid, de SB zijde van het vaarwater. Dit vermijdt tevens de plicht tot uitwijken voor bijvoorbeeld veelvuldig voor oefening van koers veranderende zeilschoolboten.
Jeroen Droogh bootprojecten@gmail.com