Hallo,
ich habe ein Problem. Es sollen Daten von einem GPS Sensor gelesen
werden. Speziell brauche ich nur die GPRMC und GPGGA Strings. Der Sensor
sendet im NMEA format.
Allerdings wird irgendwie die Hälfte vom Empfang verschluckt, manchmal
funktioniert es auch. Es scheint irgendein Timingproblem zu sein.
Hier ist der Code:
Hi,
nein, daran dürfte es normallerweise nicht liegen, denn laut
http://tiny.cc/sMC3B
Auf Seite 7 sollte die Ausgabe bei etwa 68 Zeichen liegen. Das spricht
auch dafür, dass es so ja auch schon funktioniert hat.
Kann es etwas mit dem voreilenden bzw nacheilenden Input-Problem zu tun
haben?
Wenn ich das richtig sehe, dann greifst du direkt auf den Buffer zu, den
die RS232 benutzt um die Zeichen zu empfangen.
Jetzt sendet aber dein GPS weiter, während du noch den vorhergehenden
String bearbeitest. D.h. während du einen String auswertest, wird der
Anfang des Strings schon von den nächsten eintreffenden Zeichen
überschrieben.
Nicht mit Overlay arbeiten, sondern den String umkopieren. Dann hast du
Zeit den String zu bearbeiten, während im Hintergrund die nächsten
Zeichen eintrudeln.
Denk auch drann, dass die Ausgabe des Strings auch Zeit braucht. Zeit in
der wiederrum weitere Zeichen eintrudeln.
Und wer sagt dir, dass in der Zeit die vergeht, bis BASCOM die Funktion
aufruft und den PushAll gemacht hat, der Anfang von buff_str_ovrl nicht
schon von den nächsten Zeichen überschrieben wurde?
Wie gehts denn weiter?
Id_str = Mid(buff_str_ovrl , C_st , Id_str_lg) ' ID String
holen, ab 2tem Zeichen, ohne $
Print #2 , Buff_str_ovrl
Du gibst danach den kompletten Buff_str_ovrl aus und anhand deines Logs
ist ersichtlich
<\n>$GPGGA,205133.560,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*46<
\r>
<\n><\r>
<\n>$G33.560,V,8960.0000,N,00000.0000,E,0.00,0.00,190110,,,N*7C<\r>
dass da offenbar schon mit dem Buffer irgendwas passiert ist. Meines
wissens beginnt kein NMEA Datensatz mit $G33.560
Etwas später machst du dann
Clear Serialin
wodurch du alle Zeichen des nächsten Datensatzes, die in der
Zwischenzeit eingetrudelt sind, verwirfst. Wenn also dein GPS in der
ZWischenzeit gesendet hat (nur als Beispiel)
$GPGGA,205133.560,8960.0000,N,00
dann verwirfst du das. Dein GPS Gerät kriegt das aber nicht mit und
sendet munter weiter
00.0000,E,0,0,,137.0,M,13.0,M,,*46
Bis irgendwann ein Zeilenende kommt und du anfängst diese Zeile
auszuwerten. Die fängt jetzt aber nicht mit &GPGGA oder $GPRMC an,
sondern mit 00.0000 weil du ja schlauerweise alles vorhergehende
gelöscht hast :-)
> Oder reicht es so nicht? Wie würdest du es lösen?
Abchecken, ob das GPS Gerät Handshake unterstützt und es sofort nach dem
Empfang einer Zeile zum Schweigen bringen.
Wenn das nicht geht, dann wirds wohl darauf hinauslaufen, die empfangene
Zeile sofort in einem String in Sicherheit zu bringen und mit der Kopie
zu arbeiten. Auf jeden Fall aber nicht dem BASCOM mit irgendwelchen
clear Aktionen in die Buffer Verwaltung hineinpfuschen, BASCOM muss die
volle Kontrolle über den Inhalt des Buffers haben, nur dann hast du eine
Chance, dass die Zeilen auch vollständig sind.
Wenn sich das zeitlich nicht ausgeht, und das erste eintrudelnde Zeichen
schon kommt, ehe die Zeile in Sicherheit gebracht werden kann, dann
kannst du den BASCOM Mechanismus zum Empfang einer Zeile überhaupt nicht
benutzten sondern musst dir selbst was machen, das mittels Double
Buffering das Problem löst.
Deine ISR läuft an, sobald die erste Zeile empfangen wurde. Derweil Du
den uC in der ISR beschäftigst, rauscht die 2. Zeile an Dir vorbei.
Vermute ich mal.. :-)
Wozu brauchst Du interrupts und der ganzen config .. Schnickschnack? Du
wirst ohnehin nicht jede Zeile interpretieren können. Einfacher so
(Pseudocode, aber einfach umzusetzen:
do
Emfangen:
do
do:loop until rxd
loop until UDR = 10
do
if rxd then stringbuffer = stringbuffer + UDR
loop until <Zeilenende "10" empfangen>
do
if rxd then stringbuffer = stringbuffer + UDR
loop until <Zeilenende "10" empfangen>
'jetzt haben wir mit Sicherheit 2 vollständige Zeilen
Verarbeiten:
'alles bis zum ersten Zeilenende wegwerfen
'Stringbuffer enthält jetzt 2 saubere Zeilen
loop
Das Empfangen kann man natürlich noch schöner machen mit einer
Schleife..
Sub Serial0bytereceived(s As String)
S = ""
Do
B = Inkey()
Select Case B
Case 0
Case 13
Case 10 : If S <> "" Then Exit Do
Case Else
S = S + Chr(b)
End Select
Loop
End Sub