PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : gps datensätze auswerten wie macht ihr das



yak
12.06.2006, 19:35
hallo

Habe noch folgendes Problem

die Daten kommen so rein es sieht so aus als ob der Atmega nicht
hinterher kommt

GPGGA,235947.000,0000.0000,N,0000.0000,E,017*00
,071000,,*1C
,M,,N,,K*4E
GPGGA,235947.000,0000.0000,N,0000.0000,E,0170
,,,071000,,*1C
,,N,,K*4E
GPGGA,235947.000,0000.0000,N,0000.0000,E,01700
,,071000,,*1C
M,,N,,K*4E
GPGGA,235947.000,0000.0000,N,0000.0000,E,017038,M ,,,,0000*00
000,*4C
C,235947.000,V,0000.0000,N,0000.0000,E,,,017*1C
GPGGA,235947.000,0000.0000,N,0000.0000,E,017038
,071000,,*1C
,M,,N,,K*4E
GPGGA,235947.000,0000.0000,N,0000.0000,E,01703800 0*00
0,,*1C
TG,,T,,M,,N,,K*4E

$regfile = "m128def.dat"
$crystal = 16000000
$baud = 4800
$baud1 = 4800

On Urxc Onrxd 'InterruptRoutine setzen
Enable Urxc 'Interupt URXC einschalten
Enable Interrupts


Dim Buffer As Byte
Dim Str1 As String * 30
Dim Counter As Byte

Open "COM1:" For Binary As #1
Open "COM2:" For Binary As #2

Do
Loop


Onrxd:
Buffer = Udr


Select Case Buffer
Case Asc( "$")
Str1 = ""
Case 13
Counter = 1
Case Else
Str1 = Str1 + Chr(buffer)
End Select

If Counter = 1 Then

Print #2 , Str1
Str1 = ""
Buffer = ""
Counter = 0
End If
Return



sollte aber mit anfang $ und ende line feed das scheint ja zu klappen
aber das $ nicht.

hat jemand eine idee mit bascom


vielen dank

Stromi
13.06.2006, 01:08
Zitat:
sollte aber mit anfang $ und ende line feed das scheint ja zu klappen
aber das $ nicht.

Verstehe nicht was du willst, was willst du wissen?

luma
13.06.2006, 13:37
Hio.
Mit Bascom kenne ich mich nicht aus. Ich könnte dir aber meine kleine opensource Bibliothek schicken, bei der das alles implementiert ist. Die Bib ist aber in Java geschrieben, wobei ich mir denken kann, dass es nicht sonderlich schwer für dich ist, die paar relevanten Codezeilen zu lesen.

Was genau da oben in dem Code für ein Problem vorliegt kann ich dir nicht sagen. Hab halt GPS im Titel des Themas gesehen und sofort drauf geklickt.

Gruß
Lutz

Dani-Bruchflieger
17.06.2006, 23:44
Hi,

ich vermute mal ganz stark, daß deine ISR zu lang ist.
es wäre sicherlich günstiger einen Weg zu suchen, die Auswertung der empfangenen Bytes im Hauptprogramm durchzuführen. Dazu wirst du ein oder mehrere Hilfsvariablen benötigen...
wenn der Datensatz vom GPS immer gleich lang ist (in diesem Beispielcode 40 Stellen incl Startbyte und Line Feed), kannst das ganze sehr einfach in ein Array von Bytes schieben.



Dim Buffer(40) as Byte at &H60
Dim Gps as String * 40 at &H60
Dim a as Byte
Dim b as Byte

do
if a = 41 or b = 13 then
Print #2 , Gps
Gps = ""
end if
loop

onrxd:
b = udr
if b = asc("$") then
a = 1
end if
if a < 41 then
Buffer(a) = B
incr a
end if
return


die ISR in diesem Beispiel prüft das Startbyte und beginnt die Zuweisung dann erneut beim 1. Byte (das Startbyte wird mit in den String übernommen - ansonsten Dim Gps as String * 39 at &H61).
Wenn der String komplett empfangen wurde, oder vorzeitig das Line Feed empfangen wurde, wird der String vom Hauptprogramm ausgegeben. Das nachfolgende $ startet die Zuweisung dann erneut...

PS: hab das jetzt in Adaption meiner Programme mal eben schnell eingetippt - kann nicht garantieren, daß es so zu 100% funzt - mußt mal etwas probieren - allerdings die ISR hab ich bei meinen Progs fast genau so, und das funzt sogar mit Baudraten um die 19200 einwandfrei - sogar wenn der Chip dabei nur mit 7,3728 MHz taktet...

yak
18.06.2006, 21:27
beim kompilieren kommt fehler adress out of bounds bei derclaration buffer und gps


was bedeutet es at $H60 ???

Habe einen mega 128

Dani-Bruchflieger
18.06.2006, 22:47
Hi,

ähm OK - das &H60 ist die Position im Speicher, wo die Variable abgelegt wird - beim Mega8 beginnt das eben bei &H60 - darum hatte ich gehofft, daß es beim Mega128 auch so wäre...

Edit: so, ich habe mal verschiedene Werte ausprobiert - jedesmal ohne Erfolg - bin da jetzt auch etwas ratlos...

Edit2:
so habs jetzt doch hinbekommen... probier mal das - wird jetzt ohne Fehler compiliert...

$regfile = "m128def.dat"
$crystal = 16000000
$baud = 4800
$baud1 = 4800

On Urxc Onrxd 'InterruptRoutine setzen
Enable Urxc 'Interupt URXC einschalten
Enable Interrupts

Open "COM1:" For Binary As #1
Open "COM2:" For Binary As #2

Dim Buffer(40) As Byte At &H0110
Dim Gps As String * 40 At &H0110 Overlay
Dim a as Byte
Dim b as Byte


do
if a = 41 or b = 13 then
Print #2 , Gps
Gps = ""
End If
Loop

onrxd:
b = udr
if b = asc("$") then
a = 1
end if
if a < 41 then
Buffer(a) = B
incr a
end if
Return

-tomas-
20.06.2006, 08:20
Du kannst solche Stolperfallen umgehen mit:

Dim Buffer(40) As Byte
Dim Gps As String * 40 At Buffer Overlay

oe9vfj
20.06.2006, 14:54
Du hast str1, wo du den GPS String hineinschreibst auf 30 Zeichen Länge dimensioniert. Ich vermute mal, dass der GPS String länger ist als 30 Zeichen ist und du überschreibst dann die nachfolgenden Variablen.

Mach str1 mindestens so groß wie der längste GPS String plus einige Zeichen dazu zur Sicherheit.
Natürlich muss auch der HW-Stack entsprechend groß genug sein, um im ISR die Rettung der Register aufnehmen zu können, für diese Test-Stellung würde ich mal mindestens 48 Bytes vorschlagen.

Dani-Bruchflieger
20.06.2006, 16:46
Hi,

Naja, das mit den 40 Stellen Länge war ja nur ein Schätzwert - ich habe noch nicht mit GPS rumgespielt, und daher weiß ich nicht wie lang da so ein Datensatz wirklich ist... aber das kann man ja leicht anpassen - sollte außerdem auch nur ein Beispiel sein, wie es hoffentlich funzen tut, die empfangenen Bytes schnell einem String zuzuordnen... - und es gibt da mit Sicherheit auch noch andere und bessere Möglichkeiten dazu, die mir als Anfänger für AVRs, auch noch nicht bekannt sind ... ;)

Crazy Harry
21.06.2006, 07:28
ist zwar nicht bascom, aber vielleicht hilft dir das was



Process ReadGPS(20,20:iData);
Begin
WaitPipe(RXBuffer); // Warte auf Daten im Puffer
Read(SerInp, Temp); // Puffer lesen

If Temp='$' // Wenn Puffer='$' (Datensatzanfang)
then
Read(SerInp, Temp6);
If Temp6 = 'GPRMC,'
then
Read(SerInp, NMEA.Time_UTC, ','); // GSP Time in UTC
Read(SerInp, NMEA.Status, ','); // A=data valid or V=data not valid
Read(SerInp, NMEA.Latitude, ','); // ddmm.mmmm
Read(SerInp, NMEA.Lat_Ind, ','); // N=north or S=south
Read(SerInp, NMEA.Longitude, ','); // dddmm.mmmm
Read(SerInp, NMEA.Log_Ind, ','); // E=east or W=west
Read(SerInp, NMEA.Speed, ','); // variable speed in knots
Read(SerInp, NMEA.Angle, ','); // variable lenght in degrees
Read(SerInp, NMEA.Date, ','); // GPS Date ddmmyy
//Read(SerInp, NMEA.Magnetic, ','); // Magnetic declinason
//Read(SerInp, NMEA.Checksum, ',');
EndIf;

If Temp6 = 'GPGGA,'
then
Read(SerInp, NMEA.Time_UTC, ','); // GSP Time in UTC hhmmss.sss
Read(SerInp, NMEA.Latitude, ','); // ddmm.mmmm
Read(SerInp, NMEA.Lat_Ind, ','); // N=north or S=south
Read(SerInp, NMEA.Longitude, ','); // dddmm.mmmm
Read(SerInp, NMEA.Log_Ind, ','); // E=east or W=west
Read(SerInp, NMEA.Status, ','); // 0=Invalid, 1=Valid SPS, 2=Valid DGPS, 3=Valid PPS
Read(SerInp, NMEA.Sat_Track, ','); // Number of sat in view and used in solution
Read(SerInp, NMEA.H_Dilution, ','); // dilution error
Read(SerInp, NMEA.Height, ','); // height over see
//Read(SerInp, NMEA.Height_Unit, ',');
//Read(SerInp, NMEA.DGPS_Time, ',');
//Read(SerInp, NMEA.DGPS_ID, ',');
//Read(SerInp, NMEA.Checksum, ',');
EndIf;
EndIf;
End ReadGPS;



die variablen sind so deklariert:


Temp : String[1];
Temp6 : String[6];
NMEA : Record
Message_ID : String[6]; // RMC protocol header
Time_UTC : String[9]; // hhmmss.sss
Status : String[1]; // A=data valid or V=data not valid
Latitude : String[9]; // ddmm.mmmm
Lat_Ind : String[1]; // N=north or S=south
Longitude : String[10]; // dddmm.mmmm
Log_Ind : String[1]; // E=east or W=west
Speed : String[6]; // variable lenght in knots
Angle : String[6]; // variable lenght in degrees
Date : String[6]; // ddmmyy
Magnetic : String[5]; // trash this one ..... not suported on SiRF GPS
Sat_Track : String[2]; // Number of sat in view and used in solution
H_Dilution : String[6]; // dilution error
Height : String[7]; // height over see
//Height_Unit : String[1]; // height-unit
//DGPS_time : String[6]; // trash this one
//DGPS_ID : String[6]; // trash this one
//Checksum : String[2]; // *10
End;


die rs232 hat einen eingangspuffer von 128 Byte. das prog läuft auf einem mega32 @ 16MHz

xunwichtig
02.10.2007, 07:14
sry. das ich das hier ausgrabe, aber mir fällt auf anhieb der Datensatz auf, der doch recht kaput zu sein scheint.

Grundsätzlich miss der Datensatz mit "$" beginnen, und endet IMMER mit einem Zeilenumbruch (CR & LF)

Vor dem zeilenumbruch kann (muss nicht) eine Checksumme hinzu kommen, die mit einem * gekennzeichnet 2 Bytes vor dem zeilenumbruch endet und mit 2 Hexadezimalwerte bis zum zeilenumbruch endet.

ein Datensatz hat auserdem eine reguläre maximale Grösse von 32 Bytes.

Die Einzelnen Parameter sind anschliessend mit Kommas (,) getrennt. Es kann ebenfalls sein, das ein Datenfeld nicht vollständig, bzw. leer sind. dieses feld wird jedoch nicht weg gelassen, sondern einfach nur leer. z.B. (,,)

Wenn du die unterschiedlichen Datensätze auswerten willst, empfielt sich die studie dieser dokumentation: http://www.nmea.de/nmea0183datensaetze.html#osd


JimJim
XUN

chr-mt
02.10.2007, 08:22
ein Datensatz hat auserdem eine reguläre maximale Grösse von 32 Bytes
Das ist aber zB. ein String mit 63 Zeichen (inklusive CrLf):
GPGGA,235947.000,0000.0000,N,0000.0000,E,017038,M ,,,,0000*00
Die StringVariable sollte also höher dimensioniert werden als 30.

Gruß
Christopher

raggy
02.10.2007, 17:21
Hier ein Programm war ein Versuch es ist nicht Dokumentiert aber ich hoffe es hilft Dir weiter
Gruß raggy



'Programm für GPS_Modul HI-204S******************
'kann an jeden anderen GPS Empfaenger angepaßt werden.
'Getestet auf Atmega16/32 und Atmega168
$regfile = "m16def.dat"
$crystal = 10000000
$baud = 4800
$hwstack = 32 'hardware stack
$swstack = 8 'software stack
$framesize = 44 'frame space

Dim K As String * 10
Dim S As String * 72

Dim N_grad As String * 2
Dim E_grad As String * 3
Dim N_min As String * 2
Dim N_ablage As String * 3
Dim E_min As String * 2
Dim Nord As String * 2
Dim Ost As String * 3
Dim Nord_rest As String * 7
Dim Ost_rest As String * 7
Dim E_ablage As String * 3
Dim N As String * 1
Dim O As String * 1
Dim Av As String * 1
Dim N_sec As Single
Dim E_sec As Single
Dim Runden As Single
Dim Ablage As Integer
Dim Ergebnis As Single

Const T = 1000
Const Time = 60

'Fuer Atmega168
'Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0

'Fuer Atmega16/32
Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.3 , Rs = Porta.2

Config Lcd = 40 * 2
Cls
Cursor Off

On Urxc Onrxd
Enable Urxc
Enable Interrupts

Main:

Goto Main


Onrxd:
'S = "$GPRMC,104549.04,A,2447.2038,N,12100.4990,E,016.0, 221.0,250304,003.3;W;A"
S = S + Chr(udr)
If Len(s) = 72 Then
S = Mid(s , 2 , 71)
End If
K = Mid(s , 1 , 6)
'******Position In Grad und Minuten******Auslesen**
Nord = Mid(s , 21 , 2)
Ost = Mid(s , 33 , 3)
Nord_rest = Mid(s , 23 , 7)
Ost_rest = Mid(s , 36 , 7)
'**************Ende Position Auslesen***********************
'---------------------------------------------------------------
'****Daten Auslesen und in Grad Minuten u.Sec. umrechnen********

'Daten** Nord-Süd** Grad**Minuten**Auslesen******
N_grad = Mid(s , 21 , 2)
N_min = Mid(s , 23 , 2)
N_ablage = Mid(s , 26 , 3)
N = Mid(s , 31 , 1)

'***********Status A oder V***Auslesen********
Av = Mid(s , 19 , 1)
'**************************************
'******** OST**West**Auslesen***************
E_grad = Mid(s , 33 , 3)
E_min = Mid(s , 36 , 2 )
E_ablage = Mid(s , 39 , 3)
O = Mid(s , 44 , 1)
'****************Rechnen umwandeln in Secunde***********************
' drei Stellen hinter dem Punkt in Sec umrechnen
' geteilt durch tausend Mal 60 = SEKUNDEN!
'Fuer Top50 Karten WSG84*********************************************

'********Umrechnen Nord Sued In Sec**************************
Ablage = Val(n_ablage)
Ergebnis = Ablage / T
Runden = Ergebnis * Time
N_sec = Round(runden)
'***************************************
Ablage = Val(e_ablage)
Ergebnis = Ablage / T
Runden = Ergebnis * Time
E_sec = Round(runden)
'*****************Ende Rechnen**************************************


'*******Auf Display ausgeben****************************************

If K = "$GPRMC" Then

Upperline
Lcd "" ; Ost ; Chr(223) ; Ost_rest ; Chr(39) ; O ; " " ; Nord ; Chr(223) ; Nord_rest ; Chr(39) ; N ; " " ; "STATUS=" ; Av

Lowerline
'Lcd E_grad ; " " ; E_min ; " " ; E_sec ; " " ; O ; " " ; N_grad ; " " ; N_min ; " " ; N_sec ; " " ; N
Lcd E_grad ; Chr(223) ; E_min ; Chr(39) ; " " ; E_sec ; Chr(34) ; " " ; O ; " " ; N_grad ; Chr(223) ; N_min ; Chr(39) ; " " ; N_sec ; Chr(34) ; " " ; N

End If
Return

xunwichtig
02.10.2007, 21:29
ein Datensatz hat auserdem eine reguläre maximale Grösse von 32 Bytes
Das ist aber zB. ein String mit 63 Zeichen (inklusive CrLf):
...
Die StringVariable sollte also höher dimensioniert werden als 30.


Ups .. hab mich verschrieben ... nicht 32 sondern 82 Bytes ... so ... sry.!


JimJim
XUN