Hier werden die AIS Daten von meinem AMEC Cypho-150 AIS Empfänger eingelesen und die MMSI wird ausgegeben.
Die NMEA0183 Ausgangsleitungen vom Cypho-150 sind gelb + und grün – , wie im Handbuch angegeben.
Zur NMEA0183 > UART Pegel Wandlung nehme ich den MAX232 Chip.
Der NMEA0183 Eingang+ ist Pin 8 (R2IN) und der UART Ausgang ist Pin 9 (R2OUT). Dieser kommt an den Arduino Uno RX Eingang.
Der NMEA0183 Eingang- kommt auf den GND vom MAX232 und vom Arduino.
Für den MAX 232 wird noch die 5V Spannungsversorgung vom Arduino benötigt und natürlich die 5 Kondensatoren laut Datenblatt.
Nun zum Programm.
Erstmal wird ein ausreichend langer nmea String belegt. Dann wird die AIS Baudrate 38400 eingestellt. Danach wird die serielle Schnittstelle überwacht und wenn Datenbytes vorliegen wie $ oder !, dann wird ein neuer Datensatz gestartet (start=1) und in den nmea String eingelesen. Beim Zeilenende CR (13) wird der String abgeschlossen. start wird auf 0 gesetzt für den nächsten Zeilenanfang und der String wird ausgegeben. Wenn der aktuelle String mit VDM anfängt, dann wird die MMSI ausgerechnet und auch ausgegeben.
Die Zerlegung und Berechnung der MMSI wird in diesem Beitrag erläutert.
Hier das Programm
// Cypho-150 AIS NMEA Daten einlesen und die MMSI ausgeben // IC MAX232 als NMEA zu UART Wandler // // Matthias Busse Version 1.0 vom 2.12.2014 int inByte, start=0, ais=0; String nmea = "Daten vom Cypho-150 AIS Empfaenger einlesen Version 1.0 Matthias Busse"; // reservieren void setup() { Serial.begin(38400); // 38400 Baud Dateneingang und Konsole Serial.println(nmea); } void loop() { if (Serial.available()) { // sind Daten im Eingangspuffer inByte = Serial.read(); // dann lesen if ((start==0) && ((inByte == '$')||(inByte == '!'))) { start=1; nmea=""; // bei $ oder ! starten } if(start==1) {nmea.concat((char)inByte);} // das Zeichen anhängen if((inByte==13) && (start==1)) { // CR > Datensatzende > NMEA ausgeben start=0; Serial.println(nmea); // auf Konsole ausgeben if (nmea.substring(3,6) == "VDM") { Serial.print("Die MMSI ist: "); Serial.println(vdm_get_mmsi(nmea)); } } } } long vdm_get_mmsi(String d) { // MMSI aus dem ganzen VDM Datensatz lesen. // Eingabe : String d, nur das Datenfeld aus dem VDM Datensatz // Ausgabe : long integer MMSI (! führende Nullen fehlen) // benötigt: vdm_cut_data(String) // Getestet für Message Typ: 1-6, 8, 11, 14, 18, 19, 21, 24 // Matthias Busse 1.2013 Version 1.0 int start=8, bits=30; // MMSI startet mit Bit 8 und ist 30 Bit lang int i, stelle=0, schieben, fertig=0, durchlauf=1, modulo; long k, b=0, mmsi=0; // 32 Bit d=vdm_cut_data(d); // Datenfeld ausschneiden // erstmal weg zählen for(i=6; i < start; i += 6) stelle++; // an welcher Stelle starten modulo = start % 6; while(fertig < (bits+modulo)) { k=d.charAt(stelle)-48; if(k > 40) k -= 8; schieben= bits - (durchlauf*6) + modulo; if(schieben >= 0) {b = k << schieben;} // 26: 4 zu 30, Rest 26 else {b = k >> abs(schieben);} mmsi |= b; fertig += 6; stelle++; durchlauf++; } return mmsi; } String vdm_cut_data(String s) { // Das Datenfeld aus dem VDM String s ausschneiden // Matthias Busse 23.11.2014 Version 1.0 int i, pos1=0, pos2=0; for (i=0; i<5; i++) // 5x Komma weglesen pos1 = s.indexOf( ',', pos1+1); pos2 = s.indexOf( ',', pos1+1); return s.substring(pos1+1, pos2); }
Ich verwende die gerade aktuelle Arduino Software Version 1.5.8 . Dummerweise wird hier in der Terminalausgabe nicht mehr die Baudrate 38400 unterstützt, sodass ich auf das Terminalprogramm Putty zurück greifen musste. Hoffentlich wir die Baudrate wieder aufgenommen. Vielleicht hat hier auch jemand einen Tip, wo das eingestellt werden kann.
Hier die Ausgabe von Putty
ToDo: Unvollständige und fortlaufende (2/2) Datensätze und welche mit falschen Checksummen sollten aussortiert werden.
Hier geht es darum das Prinzip zu demonstrieren wie Datensätze eingelesen und ausgewertet werden können.
Von Matthias Busse für Johnny aus Schweden
Hallo Matthias!
Ich hat problem mit zeile 45 zu kompilieren. Viele fehler da??
Hallo Johnny,
der Fehler ist raus.
Jetzt sollte es funktionieren.
Matthias
Danke!! Jetz leuft es.