Kommunikation zwischen PC und dSpace-Karte via RS232

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen

→ zurück zum Hauptartikel: Praktikum SDE


Autor: Michael Deitel & Manuel Groß

Bearbeitet von: John Kneib

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.
Kommunikationsports
Port Linux Windows
0 ttyS0 COM1
1 ttyS1 COM2
2 ttyS2 COM3
3 ttyS3 COM4
4 ttyS4 COM5
5 ttyS5 COM6
6 ttyS6 COM7
7 ttyS7 COM8
8 ttyS8 COM9
9 ttyS9 COM10
10 ttyS10 COM11
11 ttyS11 COM12
12 ttyS12 COM13
14 ttyS14 COM15
15 ttyS15 COM16
16 ttyUSB0 n.a.
17 ttyUSB1 n.a.
18 ttyUSB2 n.a.
19 ttyUSB3 n.a.
20 ttyUSB4 n.a.
21 ttyUSB5 n.a.
22 ttyAMA0 n.a.
23 ttyAMA1 n.a.
24 ttyACM0 n.a.
25 ttyACM1 n.a.
26 rfcomm0 n.a.
27 rfcomm1 n.a.
28 ircomm0 n.a.
29 ircomm1 n.a.
Baudrate ( ein Bit pro Sekunde )
Linux Windows
50 n.a.
75 n.a.
110 110
134 n.a.
150 n.a.
200 n.a.
300 300
600 600
1200 1200
1800 n.a.
2400 2400
4800 4800
9600 9600
19200 19200
38400 38400
57600 57600
115200 115200
230400 128000
460800 256000
500000 500000
576000 n.a.
921600 n.a.
1000000 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.

Funktionsweise des Handshake (Originaldatei)

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 18/19 wurde die RS232 Schnitstelle getestet, im Hinblick darauf, die Zykluszeit zu optimieren. 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 diese Problematik zu umgehen wurde ein Y-Kabel hergestellt, was es ermöglicht das Signal abzugreifen. Während des testens konnte eine Triggerzeit 0,52 ms des Oszilloskop festgestellt werden. Somit ist die Kommunikations Schnittstelle -der RS232 Bus- nicht das Bottelneck der Zykluszeit.

Für weiterführende Tests wäre eine Möglichkeit einen Datenlogger zu benutzen. Die in der Konsole ausgebenen Informationen entsprechen allerdings der in ControlDesk angezeigten Variabeln. Somit sollten keine Übertragungsfehler bestehen.

Y-Kabel mit Oszilloskop
Screenshot des aufgenommenen RS232 Signals

Autor: John Kneib

Zusammenfassung

Somit können die Spurparamter a, b und c und die Objektdaten von bis zu fünf Objekten, die vom C-Programm übergeben werden, übertragen werden. Es können aber auch von der dSpace-Seite die Längsgeschwindigkeit und der Winkel an die C-Seite versendet werden. Diese Richtung wird momentan aber noch nicht genutzt, weshalb hier nur Dummy-Werte anliegen.

Ausblick

Ein Punkt der noch bearbeitet werden könnte, ist die Umsetzung eines schnelleren Kommunikationsalghorithmus, der effizienter arbeitet. Denn momentan arbeitet das C-Programm auf dem Auto an seinem Ressourcenlimit. Ein zweiter Punkt wäre das Integrieren einer Kommandokonsole. Diese wäre dazu da um im laufenden Programm Parameter verändern zu können, so dass Regel- und Steuer-Alghorithmen während der Fahrt optimiert werden können.


→ zurück zum Hauptartikel: Praktikum SDE