Hallo Sebastian,
nutzt Du eine Hardware-UART? Dann solltest Du mal versuchen, die
High-Level-Funktionen zu nutzen. Das heißt in dem Fall ist es vermutlich
günstiger, Du gehst über den Linux-Treiber, genauso wie das minicom tut.
Das sollte ausreichend dokumentiert sein. Such einfach nicht nach Pi +
UART, sondern nach linux serial io. Ich würde mal vermuten, dass
gpioSerialRead eine Software-UART implementiert, das heißt, sie liest
das GPIO-Pin direkt und spielt selber UART.
Was Du nicht machen solltest, ist, Software-UART und Hardware-UART über
denselben Pin laufen zu lassen. Dann muss der Pin nämlich zwei Herren
dienen. Und jeder, der das mal versucht hat, weiß, dass es früher oder
später zu Konflikten führt. Grundsätzlich kann ein Pin zu jedem
Zeitpunkt maximal eine Funktion ausführen: GPIO oder UART oder ... (je
nachdem, was im Datenblatt steht).
Was auch nicht funktioniert: minicom und Dein Programm gleichzeitig auf
/dev/ttyS0 – oder was auch immer es ist – zuzugreifen. Die Datenströme
werden nicht dupliziert.
Eine Weitere Fehlerquelle besteht darin, wenn Du das ganze im Polling
betreibst und nicht im Interrupt. Wenn Dein Prozess aus irgendeinem
Grund zu spät aufwacht (und das ist meist erlaubt), dann kann es
passieren, dass der Empfangspuffer schon überschrieben wurde, bevor er
ausgelesen wurde (das sollte aber andere Probleme bringen). An der
Stelle solltest Du auch immer im Hinterkopf haben, dass Linux kein
Echtzeit-System ist.
Wie stellst Du sicher, dass das erste Zeichen im read_buf auch das erste
Zeichen einer neuen Zeile ist?
Wenn Du Kauderwelsch empfängst solltest Du davon ausgehen, dass die
Übertragung gestört war und warten, bis eine <Start of Record>-Nachricht
kommt (das ist hier in dem Fall gleich dem <End of Record> und wird
durch das Zeichen CR ausgedrückt).
Viele Grüße
Tobias
Am 14.05.22 um 22:13 schrieb Sebastian Reinhardt:
Hallo zusammen,
Ich sitze immer noch an meinem kleinen Programm und bin fast fertig.
Ich habe mir in Anlehnung an Andreas Beispiele ein paar eigene
Unterprogramme erstellt und kann nun die Vectordaten ordentlich
auslesen. Auch habe ich einen Beispielcode von der PiGPIO- Webseite
für das Auslesen eines Drehencoders, was auf dem "callback"- Prinzip
basiert angepasst und noch den Druckschalter des Encoder und den
Sensoreingang für den Ein-/Ausschalter zum Herunterfahren des PI
hinzugefügt. Funktioniert ganz gut und ich kann nun das rudimentäre
Menü bedienen.
Leider verbleibt noch ein Problem:
Ich lasse eine Schleife laufen, die per "gpioSerialRead" einen
Ultraschallsensor am UART-Port abfragt. Es ist ein Maxbotics
Sonar-Sensor, der nach Anlegen der Spannungsversorgung ohne weiteres
Zutun auf der RX-Leitung den gemessenen Abstand sendet. Es wird immer
"R123\CR" (R- Range, 123- 3-stelliger Wert in cm, \CR-
Carriage-return) gesendet.
Nun funktioniert meine Routine grundsätzlich, aber ich bekomme, wenn
ich mir den "read_buff" ausgeben lasse immer wieder so was:R105��v5
Je nach "Sleep"-Zeit in der Schleife verändert sich das und ich
bekomme leere Antworten oder anderes "Kauderwelsch" oder auch nur
Teile (z.B. "R1", "05R1" usw.) des 5-bit langen Wertes. Wenn ich zur
gleichen Zeit mit "minicom -D /dev/serial0 -b 9600" auf den Sensor
bzw. dessen Ausgabe ansehe, dann funktioniert das problemlos. Es muss
also an meinem Code liegen!
Auch mit Blick auf den Code des Drehencoders stellen sich mir nun mal
wieder ein paar Fragen:
1. Liegt das an der zeitlichen Abstimmung des Auslesens meiner
Schleife? Wie muss ich das auf die Baudrate von "9600" abstimmen?
2. Es kommen neue Werte nur mit Verzögerung (wenn ich z.B. meine Hand
vor den Sensor halte), bei "minicom" nicht. Hab ich da ein Problem mit
einem Puffer?
3. zu 2.: Kann ich den seriellen Puffer vor dem Lesen löschen, um
immer nur "frische" Werte zu bekommen?
4. oder ist es besser, wenn ich das nicht mit einer "Endlosschleife"
mache, sondern mit einer Callback-Funktion mache, die bei einem neuen
Wert getriggert wird (aber wie könnte so was aussehen, beim Encoder
wird das ja durch die Funktion "gpioSetAlertFuncEx" getriggert, wenn
ich das richtig verstehe....)?
Mein problematischer Code sieht so aus:
------------------------
while( i < num_samples && j < num_samples + 50 )
{
memset(&read_buf, '\0', sizeof(read_buf));
rx_stat_bytes = gpioSerialRead(RXD, read_buf,
sizeof(read_buf));
cout << " rx_stat: " << rx_stat_bytes << " readbuf: " <<
sizeof(read_buf) << endl;
cout << read_buf << endl;
if ( rx_stat_bytes > 0 )
{
if( memcmp ( read_buf, "R",
sizeof(read_buf) ) == 1 )
{
r_value.push_back(atoi(read_buf+1));
i++;
}
}
else
{
// printf("Sensor aus?\n");
}
j++;
usleep(1000);
}
------------------------
Eine Ausgabe der cout-"debug"-Zeile ist:
----------------------
rx_stat: 5 readbuf: 5
��v5
rx_stat: 5 readbuf: 5
��v5
rx_stat: 5 readbuf: 5
��v5
rx_stat: 5 readbuf: 5
��v5
rx_stat: 5 readbuf: 5
��v5
rx_stat: 5 readbuf: 5
��v5
rx_stat: 5 readbuf: 5
��v5
rx_stat: 1 readbuf: 5
R
rx_stat: 3 readbuf: 5
105
rx_stat: 1 readbuf: 5
rx_stat: 5 readbuf: 5
8�v0
rx_stat: 5 readbuf: 5
8�v0
rx_stat: 5 readbuf: 5
8�v0
rx_stat: 5 readbuf: 5
8�v0
rx_stat: 5 readbuf: 5
8�v0
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 1 readbuf: 5
R
rx_stat: 0 readbuf: 5
rx_stat: 1 readbuf: 5
1
rx_stat: 1 readbuf: 5
2
rx_stat: 1 readbuf: 5
0
rx_stat: 1 readbuf: 5
rx_stat: 0 readbuf: 5
rx_stat: 0 readbuf: 5
r_value_mean:120
----------------------
Das Blöde ist, das ich bis Montag 6.30Uhr dafür eine Lösung brauche,
das dann Abgabe ist :-(
Wäre schön, wenn ihr mich noch mal "erleuchten" könntet.