Hallo!
Ich arbeite gerade an einem Programm für einen Arduino Nano welches über
einen SoftwareSerial-Port die NMEA-Sätze von einem u-blox neo 6m
einliest und auf einem SPI-OLED ein paar der Daten anzeigt. Zum parsen
nehme ich die TinyGPS++ Lib. Das ganze funktioniert auch ganz gut.
Allerdings habe ich jetzt ein Stück Code eingefügt welches wenn für 5
Sekunden keine neuen Daten kommen eine Meldung auf das OLED schreibt.
Wenn jetzt allerdings wieder Daten kommen ollen die natürlich wieder
angezeigt werden. das funktioniert aber nicht (das programm scheint in
der "No Fix" nachricht zu hängen. Wenn Ich den Arduino resette
funktioniert das ganze wieder und die Daten werden angezeigt. Hier der
Code:
lastUpdate hat den falschen Typ. Schau mal nach, was millis zurück
liefert. Den selben Typ muss die Variable haben.
Dann musst du nach Erkennung des Fehlers die Variable lastUpdate
aktualisieren, denn sonst wird der Fehler beim nächsten
Schleifendurchlauf gleich wieder auftreten (endlos oft).
Dann hast du die Kontrolle innerhalb deine while Schleife, die nur
ausgeführt wird, solange ss.available() > 0 ist. Ich glaube nicht, dass
das so richtig ist. Du willst doch melden, wenn zu lange nichts
verfügbar ist.
Insgesamt ist dein Lösungsansatz suboptimal. Hier geht es noch, aber
wenn dein Programm noch etwas komplexer wird, kommst du mit dieser
Struktur ganz schnell in eine Sackgasse.
Es sollte besser ein "endlicher Automat" sein. Dieser hätte dann 2
Tasks:
1) Die empfangenen Daten anzeigen
2) Timeouts melden
ss.available bleibt aber TRUE, selbst wenn keine Daten mehr kommen da
der GPS-Empfänger dann weiter auf der Seriellen Schnittstelle sendet.
Warum ich lastUpdate aktualisieren soll verstehe ich nicht. Eigentlich
wird doch zuerst geschaut ob neue Daten da sind und wenn ja wird
lastUpdate aktualisiert. Nur wenn keine neuen Daten da sind kommt die
Fehlermeldung.
Was ist denn das Problem an dem Lösungsansatz
> und wenn ja wird lastUpdate aktualisiert
Ich sehe überhaupt keinen Schreibzugriff auf diese Variable.
> ss.available bleibt aber TRUE, selbst wenn keine Daten mehr kommen
Das glaube ich Dir nicht. Wenn keine Daten mehr empfangen werden, gibt
es nichts zu lesen. Stecke den Empfänger doch einfach mal ab, dann hängt
dein ganzes Programm für immer.
> Was ist denn das Problem an dem Lösungsansatz
Habe ich doch geschrieben: Dass du die Variable lastUpdate nicht
aktualisierst.
Und falls du auf meinen Kommentar zum endlichen Automaten anspielst:
Liest erstmal nach, was das ist und wozu er gut ist. Ich werde Dir hier
keine persönliche Zusammenfassung der zahlreichen verfügbaren
Beschreibungen erstellen.
Noch was zum Nachdenken:
> ss.available bleibt aber TRUE, selbst wenn keine Daten mehr kommen> Nur wenn keine neuen Daten da sind kommt die Fehlermeldung.
Das widerspricht sich.
Der GPS-Empfänger sendet die ganze Zeit NMEA-Sätze, aber die enthalten
nur Daten wenn er einen Fix hat. Wenn der Sender kein Signal hat aber
angesteckt ist sendet er auf dem seriellen Port.
Deswegen prüfe ich
Stefan U. schrieb:> Ich sehe überhaupt keinen Schreibzugriff auf diese Variable.
Im programm ist doch
lastUpdated = millis();
Stefan U. schrieb:> Das widerspricht sich.
Nein, das GPS sendet weiter auf der Seriellen schnittstelle aber ohne
sinnvolle Daten, und wenn keine sinnvollen daten kommen kommt die
Fehlermeldung.
> Im programm ist doch> lastUpdated = millis();
Aaaaaah, habe ich übersehen.
> Nur wenn keine neuen Daten da sind kommt die Fehlermeldung.> wenn keine sinnvollen Daten kommen ...
Nun kommen wie der Sache näher. Du musst es schon korrekt beschrieben,
sonst halten wir uns an Abweichungen zwischen Programm und Text auf, die
so gewollt sind.
Dein Programm tut nicht, was du willst. Also bleibt mir nichts anderes
übrig, als deine geschriebenen Anforderungen mit dem Quelltext zu
vergleichen.
Du vermutest jetzt also, dass das Programm irgendwo in diesme Block
hängen bleibt:
1
if(millis() - lastUpdated > 5000){
2
digitalWrite(13,LOW);
3
...
4
}
Richtig? Dann schalte doch mal am Anfang zusätzlich eine weitere LED aus
und am Ende wieder an. Dann sehen wir, ob deine Annahme richtig ist.
1
if(millis() - lastUpdated > 5000){
2
digitalWrite(13,LOW);
3
digitalWrite(5,LOW);
4
...
5
digitalWrite(5,HIGH);
6
}
Wenn bei Dir Pin 5 nicht frei ist, nimm halt einen anderen.
Vielen Dank schonmal, Ich habe jetzt auch ein
lastUpdated = millis();
in den Block geschrieben der für die Fehlermeldung verantwortlich ist
und so funktioniert es auch aber ich verstehe nicht warum das so ist.
Das programm scheint nicht in dem Block hängen zu bleiben sondern
einfach den oberen Block nicht auszuführen (wenn ich in den unteren
Fehleranzeigeblock ein SerialPrint mache printet er das ganze in
Dauerschleife) -> gps.location.isUpdated() wird nicht True obwohl der
GPS-fix wieder hergestellt ist. Wenn Ich in den Fehleranzeigeblock aber
lastUpdated aktualisiere geht es. Sehr komisch.
Ich vermute, dass die wiederholte Display-Ausgabe so viel Rechenzeit in
Anspruch nimmt, dass der Empfang der GPS Daten gestört wird. Der
soft-serial Port kann ja überhaupt nichts empfangen, solange die CPU mit
anderen Dingen beschäftigt ist.
Durch dein zusätzliches Update sorgst du dafür, dass die Anzeige der
Fehlermeldung nur einmal stattfindet und dann erst wieder in 5 Sekunden.
Dadurch gewinnst du 5 Sekunden Zeit, wo deine soft-serial Schnittstelle
vernünftig funktionieren/empfangen kann.
Ich habe mal weitergetestet, wenn ich in dem Fehlerblock lastUpdated
aktualisiere geht es, mein workaround wäre jetzt eine zweite Variable
für den Counter seit wann die Verbindung unterbrochen ist zu machen aber
ganz elegant ist das nicht und ich würde gerne den Fehler verstehen...
Stimmt, das könnte natürlich sein. Dann mach Ich mal eine displayChanged
flag und aktualisiere das Display nur wenn sich was ändert. Mal schauen
obs dann geht.