Ich habe kürzlich an einem Projekt gearbeitet und es war das erste, das so involviert war, dass die Sensornetzwerke kompliziert wurden. Letztendlich denke ich, dass die Kommunikation der Engpass in Bezug auf die Gesamtleistung war, und ich frage mich, wie erfahrenere Leute dieses Problem gelöst hätten. Dies ist eine lange Lektüre, aber ich denke, es ist ziemlich interessant, also bleiben Sie bitte dabei. Das Problem bestand darin, ein autonomes Luftschiff zu entwerfen, das in der Lage ist, auf einem Hindernisparcours zu navigieren und Tischtennisbälle in braune Box-Ziele zu werfen. Hier geht:
Sensoren
- 4D Systems uCAM-TTL-Kameramodul - UART-Schnittstelle
- HMC6352 Digital Compass - I2C-Schnittstelle
- Maxbotix Sonar ez4 - 1-polige analoge Schnittstelle
Aktoren
- 2x L293D-Motortreiber (verbunden mit einfachen Hobby-Motoren) - Diese wurden verwendet, um 6 Motoren bidirektional anzutreiben. Sie benötigten PWM-Eingänge, um die Geschwindigkeit zu variieren. Jetzt machten 3 unserer Motoren immer das Gleiche (diejenigen, die die Auf- / Abbewegung kontrollierten), sodass sie nur 2 PWM-Ausgänge von unseren Controllern benötigten, um alle 3 Motoren zu steuern. Die anderen 3 Motoren, die die seitliche Bewegung steuerten, benötigten alle eine individuelle Steuerung (für eine Bewegung in alle Richtungen), so dass weitere 6 PWM-Ausgänge von unseren Steuerungen benötigt wurden.
- Servomotor - PWM-Schnittstelle
Controller
Aus Gründen, die später klar werden, haben wir letztendlich 2x ATmega328Ps verwendet. Wir haben ein Arduino Uno verwendet, um sie zu programmieren (wir hatten keinen Zugriff auf einen ISP), aber wir haben eine benutzerdefinierte Platine hergestellt, sodass wir keine Arduino-Boards verwenden mussten, da dies unserem Luftschiff nur unnötiges Gewicht hinzufügen würde. Warum wir uns für den ATmega328P entschieden haben, war mir mit der Arduino-Umgebung sehr vertraut, und ich denke, das hat die Codeentwicklung viel schneller und einfacher gemacht.
Kommunikation & Verarbeitung
- 2x Xbee Basic
- 2x ATmega328P
- Desktop-Computer mit C ++ mit openCV
Wie Sie dem Kameramodul entnehmen können, stützte sich der größte Teil unseres Projekts auf Computer Vision. Die Luftschiffe konnten nur so viel Gewicht tragen und wir fühlten uns nicht wohl dabei, Computer Vision auf einem Mikrocontroller zu implementieren. Am Ende haben wir XBee's verwendet, um die Bilddaten an einen Desktop-Computer weiterzuleiten. Auf der Serverseite haben wir also Bilddaten empfangen und openCV verwendet, um das Bild zu verarbeiten und Dinge daraus herauszufinden. Jetzt musste die Serverseite auch Höheninformationen (vom Sonar) und Kompassinformationen kennen.
Die erste Falte war, dass wir die Kamera aus mehreren Gründen nicht von einem Mikrocontroller steuern konnten. Das Hauptproblem war, dass der interne Speicher auf dem uP nicht in der Lage war, einen gesamten Frame zu speichern. Es mag Wege gegeben haben, dies durch geschickte Codierung zu umgehen, aber für die Zwecke dieser Frage tun wir so, als wäre es unmöglich. Um dieses Problem zu lösen, ließen wir die serverseitigen Kamerabefehle über den XBee-Transceiver senden, und der Ausgang des XBee-Empfängers (an Bord des Luftschiffes) war mit dem Eingang der Kamera verbunden.
Die nächste Falte war, dass es nicht genug PWMs auf einem einzelnen ATmega328P gibt, um alle Motoren zu steuern, WEIL die I2C-Schnittstelle einen der PWM-Pins verwendet (verdammt noch mal ...). Deshalb haben wir uns für einen zweiten entschieden. Der Code bot sich ohnehin perfekt für die Parallelverarbeitung an, da die Höhensteuerung völlig unabhängig von der seitlichen Bewegungssteuerung war (also waren 2 Mikros wahrscheinlich besser als eines, das an einen PWM-Controller angeschlossen war). Daher war U1 für 2 PWM-Ausgänge (auf / ab) und das Lesen des Sonars verantwortlich. U2 war verantwortlich für das Lesen des Kompasses, die Steuerung von 6 PWM-Ausgängen (die seitlichen Motoren) und auch für das Lesen des Sonars. U2 war auch für den Empfang von Befehlen vom Server über XBee verantwortlich.
Das führte zu unserem ersten Kommunikationsproblem. Die XBee DOUT-Leitung wurde sowohl an den Mikrocontroller als auch an die Kamera angeschlossen. Jetzt haben wir natürlich ein Protokoll entworfen, damit unsere Mikrobefehle Kamerabefehle ignorieren und Kamerabefehle Mikrobefehle ignorieren, so dass das in Ordnung war. Wenn die Kamera jedoch unsere Mikrobefehle ignoriert, sendet sie NAK-Daten auf ihrer Ausgangsleitung zurück. Da der Befehl für das Mikro bestimmt war, mussten wir den Kameraausgang zum XBee irgendwie ausschalten. Um dies zu lösen, haben wir die Mikrosteuerung 2 FETs hergestellt, die sich zwischen der Kamera und XBee (das ist der erste FET) und auch zwischen U2 und dem XBee (das ist der zweite FET) befanden. Wenn die Kamera versuchte, Informationen an den Server zurückzusenden, war der erste FET eingeschaltet und der zweite FET ausgeschaltet.
Um Ihnen eine Vorstellung davon zu geben, wie dies hier funktioniert hat, sind einige Beispiele:
- Server fordert ein Bild an - PIC_REQUEST durchläuft XBee und erreicht U2 und Kamera. U2 ignoriert es und die Kamera sendet Bilddaten zurück.
- Der Server hat gerade die Verarbeitung eines Bildes beendet und sendet Motordaten, um Blimp anzuweisen, nach rechts abzubiegen. MOTOR_ANGLE (70) geht durch XBee und erreicht U2 und Kamera. U2 erkennt als Mikrobefehl und schaltet somit den FET der Kamera aus (aber vielleicht hat die Kamera bereits mit einem NAK geantwortet? Wer weiß ...). U2 reagiert dann auf den Befehl durch Ändern der Motor-PWM-Ausgänge. Anschließend wird der FET der Kamera wieder eingeschaltet (dies war die Standardeinstellung, da Bilddaten am wichtigsten waren).
- Der Server erkennt, dass wir an einem Punkt im Hindernisparcours angelangt sind, an dem unsere Standard-Schwebehöhe jetzt 90 Zoll statt 50 Zoll betragen muss. SET_HEIGHT durchläuft XBee und es passiert dasselbe wie in Beispiel 2. U2 erkennt den Befehl SET_HEIGHT und löst einen Interrupt an U1 aus. U1 verlässt nun seinen Höhenregelkreis und wartet auf den Empfang serieller Daten von U2. Das ist richtig, mehr serielle Daten. Zu diesem Zeitpunkt ist der FET des U2 eingeschaltet (und der FET der Kamera ist ausgeschaltet), sodass der Server die Höhe empfängt, die U2 auch an U1 sendet. Das war zu Überprüfungszwecken. Jetzt setzt U1 seine interne Variable für height2HoverAt zurück. U2 schaltet jetzt den FET aus und den Kamera-FET wieder ein.
Ich habe definitiv eine Menge Informationen ausgelassen, aber ich denke, das reicht aus, um einige der Komplikationen zu verstehen. Am Ende haben unsere Probleme einfach alles synchronisiert. Manchmal blieben Daten in Puffern übrig, aber nur 3 Bytes (alle unsere Befehle waren 6-Byte-Sequenzen). Manchmal verlieren wir die Verbindung zu unserer Kamera und müssen sie erneut synchronisieren.
Meine Frage lautet also: Welche Techniken würden Sie vorschlagen, um die Kommunikation zwischen all diesen Komponenten zuverlässiger / robuster / einfacher / besser zu machen?
Ich weiß zum Beispiel, dass man eine Verzögerungsschaltung zwischen dem integrierten XBee-Ausgang und der Kamera hinzufügen musste, damit das Mikro die Gesprächsleitung der Kamera ausschalten konnte, bevor es auf Mikrobefehle mit NAKs reagierte. Irgendwelche anderen Ideen?
Vielen Dank und ich bin sicher, dass dies viele Änderungen erfordern wird. Bleiben Sie also auf dem Laufenden.
Edit1:Das Spleißen der UART-Daten der Kamera durch eines der Mikros schien uns nicht möglich zu sein. Es gab zwei Optionen für Kameradaten: Rohbitmap oder JPEG. Für eine rohe Bitmap sendet die Kamera nur so schnell wie möglich Daten an Sie. Der ATmega328P hat nur 128 Bytes für einen seriellen Puffer (technisch ist dies konfigurierbar, aber ich bin nicht sicher, wie) und wir dachten nicht, dass wir ihn schnell genug aus dem Puffer heraus und zum XBee durchbringen könnten. Damit blieb die JPEG-Methode übrig, bei der jedes Paket gesendet wird und darauf gewartet wird, dass der Controller es bestätigt (kleines Handshaking-Protokoll). Die schnellste Geschwindigkeit war 115200 Baud. Aus irgendeinem Grund war die schnellste Möglichkeit, große Datenmengen zuverlässig über den XBee zu übertragen, 57600 Baud (dies gilt auch, nachdem wir die Knoten / Netzwerk-Kopplung durchgeführt haben, um die automatische erneute Sendefunktion zu ermöglichen). Das Hinzufügen des zusätzlichen Stopps in unserem Netzwerk (Kamera zu Mikro zu XBee im Gegensatz zu nur Kamera zu XBee) für das Mikro verlangsamte einfach die Zeit, die für die Übertragung eines Bildes zu viel benötigt wurde. Wir brauchten eine bestimmte Bildwiederholfrequenz für Bilder, damit unser Motorsteuerungsalgorithmus funktioniert.