Kommunikation zwischen PC und dSpace-Karte via RS232
→ zurück zum Hauptartikel: Praktikum SDE
--Ulrich Schneider (Diskussion) 15:35, 10. Feb. 2019 (UTC)
- Bitte Rechtschreibfehler korrigieren.
Autor: Michael Deitel & Manuel Groß
Bearbeitet von: John Kneib & Lukas Honerlage
Einleitung
Das SDE-Praktikum beinhaltet die Übertragung von Daten über eine RS232 Schnittstelle. Die Vorarbeit zu diesem Thema wurde von Daniel Klein und Steffen Sander in den vorherigen Semestern durchgeführt. Im Sommersemester 2014 und Wintersemester 2015 wurde das Thema von Manuel Groß und Michael Deitel bearbeitet.
Inhalt
RS232 ist ein Standard für serielle Schnittstellen. Zur Kommunikation zwischen Rechnern und Peripherie kann man mit ihrer Hilfe leicht eine Verbindung aufbauen. Zwar sind dSpace-Karte und PC bereits über einen PCI-Bus miteinander verbunden, jedoch dient dieser als Programmierschnittstelle. Zur Datenübertragung zwischen den beiden werden zwei Softwarekomponenten benötigt, die PC-Seite soll die von den Sensoren und der Kamera berechneten Umgebungsdaten bündeln und als Nachricht an das auf der dSpace-Karte laufende Simulinkmodell schicken. Diese entschlüsselt die Nachricht und verwendet sie weiter.
PC
In folgendem Abschnitt sieht man den Aufbau des Main Programms für Kommunikation, Kamera und Lidar. Als erstes werden structs erstellt, in denen die Daten stehen, die zwischen PC und dSpace Karte übertragen werden. Anschließend werden Variablen angelegt, die an verschiedenen Zeitpunkten in der Main genutzt werden. Danach werden Lidar, Kommunikation und Kamera initialisiert und für den Fall, dass kein Lidar genutzt wird werden Dummyparameter für die Objektliste des Lidar generiert. Letztlich werden in der Endlosschleife die Algorithmen von Kamera und Lidar ausgeführt und am Ende jedes Schleifendurchlaufs die berechneten Daten mithilfe des Versandblocks der Kommunikation übertragen. Des Weiteren kann am Anfang der do-Schleife der Empfangsblock der Kommunikation aktiviert werden, wenn Daten empfangen und genutzt werden sollen.
/*----------------------------------------------------------------------------*/
/* Hauptprgramm */
/*----------------------------------------------------------------------------*/
//Globale Variablen
msg_to_pc msg_p; // Structs für die Kommunikation mit DS1104 werden deklariert
msg_to_dspace msg_d;
int main()
{
// Variablen
double koeff[3] = {0};
int skipcounter = 0; // Verarbeitung jeder x-ten Lidardaten aus Performancegründen überspringen
#ifdef LIDAR
Lidar_Init(); // Initialisierung der LIDAR-Kommunikation
#endif
#ifdef KOMMUNIKATION // Initialisierung der Kommunikation
#ifdef DUMMYLIDAR // Erzeuge Dummy-Werte wenn kein Lidar verwendet wird
#ifdef KAMERA // Initialisierung der Kamera
// Eintritt in Hauptschleife
do
{
#ifdef KAMERA // Bild aufzeichnen und vorverarbeiten
#ifdef LIDAR // Aufzeichnen von Lidardaten und erzeugen von Objektliste
#ifdef KAMERA // Ausgabe von aktuellem Bild
// CycleCount für Lidar hochzählen
CycleCount++;
#ifdef KOMMUNIKATION // Senden von Daten über RS232
} while (!CheckKey());
#ifdef KAMERA // Verbindung zu Kamera trennen
cout << "exit." << endl;
return 0;
}
Die auf dem PC verwendete Kommunikationsschnittstelle ist in C++ implementiert, dies erleichtert die spätere Integrierung in die Datenverarbeitung (LIDAR/Kamera), da diese ebenfalls in C++ verfasst ist. Grundlage für die Kommunikation ist eine Bibliothek von Teunis van Beelen [1], diese beinhaltet viele Funktionen vom Aufbau einer Verbindung bis zum senden von Daten, sowohl für Windows- als auch für Linuxsysteme. Die wichtigen Funktionen sind OpenComport
und SendBuf
.
- OpenComport(int comport_number, int baudrate)
- Mithilfe dieses Befehls wird eine Kommunikation aufgebaut über die Daten übermittelt werden können. Eine Liste der verfügbaren Comports ist am Ende dieses Abschnitts zu finden, standardgemäß wird die Verbindung mit dem Comport 1 initialisiert. Neben der Angabe eines Comports erfordert die Initialisierung eine Baudrate, diese legt die Übertragungsgeschwindigkeit während einer Übermittlung fest. Eine Liste der möglichen Baudraten ist neben der, der möglichen Comports zu sehen. Für den Fall, dass eine Verbindung mit den gegebenen Variablen nicht hergestellt werden kann liefert der Befehl eine 1 als Wert zurück.
Port | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Linux | ttyS0 | ttyS1 | ttyS2 | ttyS3 | ttyS4 | ttyS5 | ttyS6 | ttyS7 | ttyS8 | ttyS9 | ttyS10 | ttyS11 | ttyS12 | ttyS14 | ttyS15 | ttyUSB0 | ttyUSB1 | ttyUSB2 | ttyUSB3 | ttyUSB4 | ttyUSB5 | ttyAMA0 | ttyAMA1 | ttyACM0 | ttyACM1 | rfcomm0 | rfcomm1 | ircomm0 | ircomm1 |
Windows | COM1 | COM2 | COM3 | COM4 | COM5 | COM6 | COM7 | COM8 | COM9 | COM10 | COM11 | COM12 | COM13 | COM15 | COM16 | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. | n.a. |
Linux | 50 | 75 | 110 | 134 | 150 | 200 | 300 | 600 | 1200 | 1800 | 2400 | 4800 | 9600 | 19200 | 38400 | 57600 | 115200 | 230400 | 460800 | 500000 | 576000 | 921600 | 1000000 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Windows | n.a. | n.a. | 110 | n.a. | n.a. | n.a. | 300 | 600 | 1200 | n.a. | 2400 | 4800 | 9600 | 19200 | 38400 | 57600 | 115200 | 128000 | 256000 | 500000 | n.a. | n.a. | 1000000 |
- SendBuf(int comport_number, unsigned char *buf, int size)
- Dieser Befehl sendet eine zuvor definierte Anzahl an Bytes über den gegebenen Port. Die Bytes werden in ihrem Buffer Byte für Byte abgearbeitet, solange der Sendeprozess andauert wird die Verbindung geblockt. Nach Beendigung der Übertragung wird die Anzahl der Bytes bestätigt indem sie von der Funktion als Antwort zurückgegeben wird, tritt ein Fehler auf wird eine -1 übergeben.
Um Daten zu einer Nachricht zusammenzufassen, müssen sie in einem Buffer gespeichert werden und um diesen nach dem Empfangen entschlüsseln zu können wird dieser wie im Schnittstellendokument beschrieben aufgebaut. Da das Versenden der Nachrichten leicht in anderen Funktionen zu implementieren sein soll, werden alle Daten im Funktionskopf übergeben. Neben dem senden von Umgebungsdaten verfügt die Funktion über eine Dummynachricht. Im Dummybetrieb werden automatisch Daten generiert mit denen der Buffer gefüllt wird, sodass man Ein- und Ausgabe der Kommunikation im Blackbox-Verfahren kontrolliert werden können.
void send(bool dummy = 0,
float in_a = 0,
float in_b = 0,
float in_c = 0,
float in_stopplinie_entfernung = 0,
float in_x[5] = 0,
float in_y[5] = 0,
float in_breite[5] = 0,
float in_tiefe[5] = 0,
float in_objektausrichtung[5] = 0,
float in_geschwindigkeit[5] = 0,
unsigned char in_spurzuordnung = 0,
unsigned char in_stopplinie_erkannt = 0,
unsigned char in_anzahl_objekte = 0,
unsigned char in_objektnummer[5] = 0,
unsigned char in_plausibel[5] = 0)
Durch die Initialisierung mit 0 im Aufruf werden die Daten die nicht im Aufruf übergeben werden mit Null beschrieben, so ist es nicht nötig, die Werte welche im Dummymodus nicht benötigt werden, mit überflüssigen Informationen zu füllen. Eine Dummy lässt sich so mit dem Aufruf void send(1)
verwirklichen.
Im normalen Betrieb müssen sämtliche Werte in den Aufruf eingefügt werden, andernfalls kann es passieren, dass Daten an der falschen Stelle im Buffer übermittelt werden und falsch interpretiert werden oder andere Werte mit 0 übergeben werden.
Um den Buffer zu füllen gibt es von Asaad Mohammed Al-Suleihi die Funktion datatype_to_array
, diese kopiert eine gewisse Menge an Bytes in ein angegebenes Array. Der Buffer benötigt eine Gesamtgröße von 149 Bytes um alle relevanten Daten in dem gewünschten Dateiformat zu übermitteln. Ist der Buffer voll wird er verschickt.
dSpace-Karte
Die dSpace-Karte dient als zweite Hälfte der Kommunikation. Sie empfängt die Nachrichten und verarbeitet sie weiter. Die dafür nötige Software befindet sich in der Bibliothek bib_SerCom und ist im Onlinemodell des Fahrzeugs. Um eine fehlerfreie Übertragung zu gewährleisten wird vor der Übertragung ein Handshake durchgeführt. Sobald die dSPACE–Karte alles initialisiert hat und bereit für die Kommunikation ist, signalisiert sie diesen Zustand durch das Versenden eines definierten Zeichens (DS_START_BYTE 'Y'), wird dieses vom PC empfangen antwortet er mit einem entsprechenden Zeichen (PC_START_BYTE 'R'). Ist die Antwort nicht korrekt wird der Vorgang wiederholt, nach einem erfolgreichem Handshake wird das Acknowledgementbyte (DS_ACK 'A') gesendet. Gefolgt davon werden die Sensordaten übermittelt.
Die ankommenden Daten werden in einem FIFO-Speicher hinterlegt, dadurch sind bei der Weiterverarbeitung alle Bytes in derselben Reihenfolge in der sie losgeschickt wurden. Der Empfangsblock findet sich in der RTI-Library. Man kann einstellen wie groß der Speicher für empfangene Daten sein soll, bevor sie weitergegeben werden. Der Buffer wird in eine S-Function übergeben. Hier werden mithilfe des von Herrn Al-Suleihi array_to_datatype
-Befehls je eine bestimmte Anzahl an Bytes aus dem Buffer einer beliebigen Variable zugeordnet. Diese werden aus dem Block in das Modell übergeben und dort zur Berechnung von Lenkwinkel und Geschwindigkeit genutzt.
Informationen zur Konfiguration
Eine Änderung des Comports oder der Baudrate wird auf PC-Seite in der Headerdatei "all_needed.h" durchgeführt. Auf der dSpace-Seite wird die Baudrate in dem Block "DS1104SER_SETUP" geändert(zu finden in der Bibliothek "bib_Sensoren_Aktoren_online/SEN - Sensoren - online/SenKam - Kamera/rs232_com").
Ferner werden in der "all_needed.h" Strukturvariablen für Fahrspurparameter, Objektparameter, Nachricht zu PC und Nachricht zu dSpace definiert. Sollten also in Zukunft Variablen hinzugefügt, entfernt oder in Datentyp oder Namen geändert werden muss dies dort angepasst werden. Passend dazu muss auch im Simulink Modell der Parameter "buffer_size" auf die Anzahl der für den Eingangsbuffer der dSpace-Karte zu empfangenden Bytes gesetzt werden(zu finden in "bib_Sensoren_Aktoren_online/SEN - Sensoren - online/SenKam - Kamera/rs232_com/rec_block/rec_data_handler" über den Model Explorer).
Des Weiteren kann in der Headerdatei bestimmt werden, nach wie vielen Iterationen der Handshake abgebrochen werden soll, wenn er noch nicht beendet wurde. Dies wird mit dem define "BREAK_LOOP_AFTER" festgelegt.
In der "RS232Comm.cpp" gibt es die Funktion "send_data_set_unaligned" in der sich alle Daten aus den Spur- und Objektvariablen befinden und versendet werden. Hierbei ist zu beachten, dass auf der dSpace-Seite die empfangende S-Function die Variablen in der selben Reihenfolge empfängt, in der sie gesendet wurden( zu finden in "bib_Sensoren_Aktoren_online/SEN - Sensoren - online/SenKam - Kamera/rs232_com/rec_block/split_data").
Außerdem gibt es die Funktion "receive_data_set", in der die von der dSpace Karte empfangenen Daten stehen. Hierbei ist wieder auf die Reihenfolge zu achten(muss der Reihenfolge des Sendens entsprechen. Zu finden in "bib_Sensoren_Aktoren_online/SEN - Sensoren - online/SenKam - Kamera/rs232_com/merge data to chars"). Zusätzlich gibt es im "receive_data_set" den Parameter "msg_len" welcher der Größe der zu empfangenden Nachricht entsprechen muss.
Die Funktion "switch_endianness" wird zudem vor dem Senden vom PC und nach dem empfangen von der dSpace Karte genutzt, um die Byte-Reihenfolge für Datentypen die größer als 1 Byte sind zu vertauschen(PC mit Intel Prozessor nutzt Little Endian, dSpace Karte mit Motorola Prozessor nutzt Big Endian).
Übertragene Daten
dSpace zu PC
Signalname | Datentyp | Beschreibung |
---|---|---|
V_x_ego | float32 (4 Byte) | Ego-Längsgeschwindigkeit des Fahrzeugs |
alpha | float32 (4 Byte) | Lenkwinkel: α > 0 Lenkausschlag links, α < 0 Lenkausschlag rechts |
Gesamtgröße des Datenpakets | 8 Byte |
Da momentan für den Handshake 16 Byte große Pakete übertragen werden sind auch die Datenpakete von dSpace zu PC 16 Byte groß(zwei float64 Werte statt float32). Dies sollte in Zukunft geändert werden.
PC zu dSpace
Signalname | Datentyp | Beschreibung |
---|---|---|
a | float32 (4 Byte) | Fahrspurparameter |
b | float32 (4 Byte) | Fahrspurparameter |
c | float32 (4 Byte) | Fahrspurparameter |
lane_asign | bool (1 Byte) | Spurzuordnung: 1 = rechte Fahrspur, 0 = linke Fahrspur |
stop_insight | bool (1 Byte) | 1 = Stopplinie erkannt, 0 = keine Stopplinie erkannt |
stop_distance | float32 (4 Byte) | Entfernung zur Stopplinie |
n_objekte | uint8 (1 Byte) | Anzahl relevanter Objekte (maximal 5) |
number[n_objekte] | uint8 (1 Byte) | Objektzähler |
x_0[n_objekte] | float32 (4 Byte) | x-Koordinate des Objektmittelpunktes (mitte, vorn) |
y_0[n_objekte] | float32 (4 Byte) | y-Koordinate des Objektmittelpunktes (mitte, vorn) |
b[n_objekte] | float32 (4 Byte) | Objektbreite |
t[n_objekte] | float32 (4 Byte) | Objekttiefe |
alpha[n_objekte] | float32 (4 Byte) | Objektausrichtung |
v[n_objekte] | float32 (4 Byte) | Betrag des Geschwindigkeitsvektors |
plausible[n_objekte] | uint8 (1 Byte) | Vertrauenswert für das Objekt in Prozent ( 0 = minimale Vertrauen, 100 = maximale Vertrauen) |
Gesamtgröße des Datenpakets | 149 Byte |
Testen der RS232 Schnittstelle
Im Wintersemester 20/21 wurde die RS232 Schnittstelle wir in betrieb genommen. Die Geschwindigkeit wurde von vorher 19200 baut auf 115200 baut erhöht. Da ohne einen gesendeten Handshake zwischen der dSpace Karte und dem PC keine Kommunikation aufgebaut werden kann, kann das Signal nicht direkt aufgezeichnet werden. Außerdem wird ohne aufgebaute Bus Kommunikation das C++ Programm direkt nach dem starten beendet. Um Signale von der RS232 Schnittstelle auch in Zukunft mit dem Oszilloskop mit Schneiden zu können wurde ein Y-Kabel hergestellt, was es ermöglicht das Signal abzugreifen. Für weiterführende Tests wäre eine Möglichkeit einen Datenlogger zu benutzen.
Im SVN wurde das Terstprotokoll unter ....\Dokumentation\Testprotokolle\Testprotokoll_RS232_Bus hinterlegt.
Zusammenfassung & Ausblick
Zu den nächsten Schritten würde es gehören die Anzahl der korrekt übertragbaren LiDAR-Objekte zu erhöhen. Dafür müsste im Simulink-Modell zum Empfangen keine einzelnen Werte beschrieben, sondern für die LiDAR-Daten Arrays angelegt werden, die je nach Anzahl der Objekte befüllt werden oder nicht. Dies sollte schrittweise in einer Testumgebung überprüft werden, um festzustellen ob ab einer gewissen Objektanzahl eventuell noch eine kleinere Schrittweite benötigt wird um die Daten korrekt zu Übertragen. Das optimale Endergebnis wäre, wenn die maximal mögliche Anzahl von fünf LiDAR-Objekten mitsamt aller Spurparameter korrekt übertragen wird. Eine zusätzliche Erweiterung wäre das Herstellen einer zweiseitigen Kommunikation, sodass vom Online-Modell nicht nur Daten eingelesen, sondern auch Daten gesendet werden können. Eine Anforderung aus den Vorsemestern war es nämlich, dass die ermittelte Geschwindigkeit zurück zur Kamera übertragen wird, um je nach Geschwindigkeit die Bilder der Kamera und Objektdaten anders zu verarbeiten. Ebenso müssten die gesendeten Daten auch noch um eine Prüfsumme erweitert werden, welche abgefragt wird um die Korrektheit der Daten sicherzustellen.
→ zurück zum Hauptartikel: Praktikum SDE