RoPi - Autonomer Roboter mit RaspberryPI & Arduino

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Vorwort:

    Fragen usw bitte im Entwicklungs Thread (*klick*) stellen!


    Dieses Projekt ist noch nicht abgeschlossen, möchte aber schon mal eine übersichtlichere Zusammenfassung erstellen. Also stay tune :cool:

    Auch tue ich mich aktuell etwas schwer das doch sehr umfassende Projekt in gut übersichtlicher Reihenfolge zusammen zu tragen... Deshalb ist das Index erst noch leer bzw ändert sich von Zeit zu Zeit die Reinfolge der Beiträge usw... Ich arbeite dran ;)

    Das Recht der Veröffentlichung dieses Inhalts an anderen Orten im Internet, aber auch drucktechnisch, behalte ich mir ausnahmslos vor. Die Inhalte dürfen lediglich für private Zwecke verwendet werden.


    Einleitung:

    Ziel dieses Projekts ist es einen Autonomen Roboter zu erschaffen.
    Der Roboter soll selbstständig umherfahren und die Umgebung erkunden, sowie Berechnungen anstellen um möglichst Effektiv zu einem Ziel zu gelangen. Also nicht jede Bewegung ferngesteuert werden sondern tatsächlich Autonom handeln und bewegen.
    Es gibt aber auch ein cooles Web-Interface mit dem man das Gefährt auch manuell steuern kann - wem also die Autonomität zu kompliziert ist lässt das einfach weg :D


    Index:

    • [al=Features]Features[/al]
    • [al=TechAblauf]Technischer Ablauf[/al]
    • [al=Chassis]Chassis[/al]
    • [al=Sensoren]Sensoren[/al]
    • [al=OtherHW]Andere Hardware[/al]
    • [al=PowerSupply]Stromversorgung[/al]
    • [al=HardwareGamePlay]Hardware Zusammenspiel[/al]
    • [al=Architecture_Overview]Aufbau Übersicht[/al]
    • [al=SoftwareGamePlay]Software Zusammenspiel[/al]
    • [al=SoftwareInstall]Software Installation[/al]

      • [al=SoftwareBasics]Voraussetzungen auf dem PI[/al]
      • [al=prepareWI]Vorbereitungen fürs Web-Interface[/al]
      • [al=configWebServer]WebServer konfigurieren[/al]
    • [al=Links]Links[/al]


    [al=ChangeLog]ChangeLog[/al]


    [an=Features](geplante oder bereits umgesetzte) Features:[/an]

    • Modularer Aufbau:
      Ein Hauptprogramm ('the Brain'). Optionale Nebenprogramme, wie z.B. Web-Interface etc.

      • Interne Kommunikation zwischen den Programmen mithilfe Socket's (wie bei ROS)
    • Kommunikation zwischen RaspberryPI <-> Arduino über USB.

      • Sofortige Verarbeitung neuer Daten/Befehle (dank threading)
    • Web-Interface dient nur zur Kontrolle. Im Notfall kann aber auch eingegriffen werden oder der Roboter vollständig darüber gesteuert werden.

      • Kommunikation zwischen Web-Interface und RaspberryPI über WebSocket (extra Script. interne Anbindung an Hauptprogramm via Socket). Dadurch kann das Web-Interface bzw der Webserver auch auf einem anderen Rechner im Netzwerk laufen.
      • Kein ständiges neu laden der Webseite dank Javascript und WebSocket.
      • RaspiCam auf Pan/Tilt mit eigenem Ultraschall Sensor. Kann ebenfalls im Web-Interface über Schieberegler gesteuert werden.
      • Motor Geschwindigkeit pro Seite, oder alle zusammen über Schieberegler einstellbar.
      • Ständiges aktualisieren (500ms) der Sensor- / Fahrt- Werte.
      • GRID-MAP Aktualisierung bzw Anzeige.
      • Kompass Anzeige.
    • Verschiedene Mode's:

      • Explore: Umgebung erkunden und Map erstellen.
      • AutoDrive: Selbstständig durch Umgebung fahren um definiertes Ziel zu finden.
      • Und natürlich auch manuelles steuern übers Web-Interface.
    • Veränderbare Regeln die der Roboter nach einstellbaren Kriterien verändern kann.

      • z.B. die Standardaktion beim erkennen eines Hindernisses zu verändern wenn diese 10x fehl schlug: Standardmäßig nach rechts zu fahren. Wenn sich herausstellt das rechts aber auch ständig ein Hindernis ist, kann der Roboter nach 10 Fehlversuchen die Regel auf "Standardmäßig nach Links" o.ä. ändern.
    • Globale Regeln die der Roboter nicht verändern kann.

      • z.B. nicht über Bereiche zu fahren die als "Abgrund" gekennzeichnet sind.
    • Lokale und Globale Map.

      • Die Lokale Grid-Map befindet sich im Speicher des Arduino's und wird stetig aktualisiert sowie an 'the Brain' übermittelt. Diese repräsentiert die aktuelle, unmittelbare Umgebung.
      • Die Globale Grid-Map wird erst aktualisiert wenn Objekte bzw Wegpunkte 2x verifiziert wurden. Diese wächst dynamisch.
        Außerdem wird wärend des AutoDrive Modes die Globale-Map zu Rate gezogen um sicher zu stellen keinen Fehler zu machen, wie z.B. ein Abgrund den der Arduino aber noch nicht kennt.
        Bei der Verwendung von 2 Karten steigt die Genauigkeit, wie man zB auch hier nachlesen kann.
    • Manuelle Anpassung der Globalen GRID-Map.
      Um Räumen sowie Objekten einen Namen geben zu können, sowie Gefahrenbereiche wie "Abgrund" (grob) zu kennzeichnen.
    • Angabe eines Ziels durch GRID-Map.

      • Wahlweise durch anklicken auf GRID-Map, oder als Sprachbefehle wie z.B. "Fahre ins Wohnzimmer unter den Esstisch".
        Voraussetzung hierfür ist natürlich ein bereits benannter Raum sowie Objekt.



    = Fertig/Vollständig umgesetzt.
    = Noch nicht, oder nur teilweise, umgesetzt


    [an="Links"]Weitere Links:[/an]


    Ein Projekt hier im Forum auf Basis des gleichen Chassis von 'Wolfgang Glück': Roboter auf Basis Rover-5 chassis


    [an=ChangeLog]ChangeLog:[/an]

  • RoPi - Autonomer Roboter mit RaspberryPI & Arduino? Schau mal ob du hier fündig wirst!

  • [an=TechAblauf]Technischer Ablauf:[/an]

    Auf der Roboter Plattform sind ein bis zwei Arduino's verbaut die das ansteuern der Sensoren und Motoren übernehmen, und an den RaspberryPI angeschlossen sind.
    Die Arduino's schicken ihre Daten, was sie machen oder von den Sensoren an den RaspberryPI, aber sollen selber nichts entscheiden sondern nur der PI.
    Der RaspberryPI entscheidet dann zum Beispiel, dass das Objekt (eine Wand oder allg. Hindernis) zu nah ist und übermittelt an den jeweiligen Arduino mit der Motorsteuerung entsprechende Befehle das Objekt zu umfahren.

    Zur Orientierung bedarf es mindestens einen Ultraschall Sensor um Hindernisse zu erkennen, bei nur einem Ultraschall Sensor auch einen Pan/Tilt.
    Desweiteren benötigt man einen Kompass um die Himmelsrichtung, in die der Roboter guckt, bestimmen zu können und entsprechend zu wissen wo genau sich ein Hindernis befindet usw.

    Man muss sich aber auch auf mehrere Sensoren stützen, da nur einer nie perfekt präzise ist. Zusätzlich kämen also auch noch Odometriedaten in Frage, um die zurückgelegte Stecke zu kennen, und damit diese möglichst genau sind sollte die Roboter Plattform Reifen statt Ketten haben, denn Ketten haben einen gewissen Schlupf und rutschen, in Kurvenfahrten haben die Encoder zudem Abweichungen...

    Das schwierigste ist die Software.
    Die Arduino's brauchen nur die Sensoren und Motoren ansprechen, die Daten werden bei mir über die Serielle Schnittstelle (USB) in beide Richtungen verschicken.
    Der RaspberryPI muss diese Daten möglichst schnell und permanent empfangen (quasi in Echtzeit, wobei das nicht wirklich geht), aber muss gleichzeitig auch in der Lage sein etwas zurück zu schicken also Befehle für die Arduino's.

    Desweiteren möchte man den Roboter ja auch mal selber steuern bzw dem PI Befehle geben die er dann umsetzt.. Dafür benötigt man bei der PI-->Arduino Kommunikation also auch noch eine Schnittstelle um über Funk/WLAN Befehle umzusetzen. Dabei erscheint mir der Weg über einen Socket-Server am einfachsten.


    In Punkto Wegfindung (PathMap, Karten) und Lernmodus will ich sowas wie folgendes erreichen: http://www.societyofrobots.com/images/sensors_IRSLAM.gif
    Dabei wird das sog. SLAM (Simultaneous Localization And Mapping) verwendet, was Bestandteil der aktuellen Robotik Forschung und sehr komplex ist...

    Um also nicht gleich von 0 auf 100 durchzustarten werde ich zunächst mit dem sog. wavefront algorithm anfangen (der Link beschreibt das recht gut mit Codebeispielen)
    Soweit ich das verstanden habe wird das in etwas so aussehen:

    Ein Raum wird in viele kleine Quadrate eingeteilt (sog. Nodes), die von der Größe her die Abmessungen des RoPi's entsprechen (so lässt es sich präziser navigieren) und als X und Y Koordinaten festgelegt werden.
    Dann werden die Quadrate in denen Objekte bzw Hindernisse stehen rot markiert bzw mit einer 1 versehen. Quadrate mit einer 0 darf er befahren, mit einer 1 nicht.

    Im Algorithmus sind diese Werte allerdings etwas anders:
    Nicht befahrbare Quadrate haben den Wert 255
    Befahrbare Quadrate haben den Wert 0
    Der Roboter selbst hat den Wert 254
    Das Ziel wohin der Roboter fahren soll hat den Wert 1

    Der Algorithmus fängt nun ab seiner Position (oder oben rechts) an zu zählen und geht jede einzelne Node Wellenförmig durch, ignoriert alle 255'er Werte und natürlich auch sich selbst, zählt die dann zusammen und legt den kürzesten Weg zum Ziel fest (geringste Zahl an Nodes die durchfahren werden müssen).

    Auch wird der RoPi ausgebremst wenn man nach jeder Fahrbewegung stehen bleiben muss um den Bereich in Fahrtrichtung nach unbekannten Objekten zu scannen.. Aus diesem Grund möchte ich den vorderen Bereich mit 3 Ultraschall Sensoren versehen (einer Mittig und die anderen im 45° Winkel jeweils zur Seite) und diese ständig auslesen um möglichst schnell auf Veränderungen reagieren können.

  • [an=Chassis]Chassis:[/an]

    Die Basis bildet der DAGU - Rover 5 Robot Platform (2 motors + 2 encoders) (aber gekauft bei HobbyKing).

    Vorteil bei diesem Chassis sind die bereits integrierten Encoder und einige gute Beispiele vom Hersteller oder andere Projekte mit diesem Chassis wie z.B. dieses.

    Aber auch die zusätzliche DAGU - Rover 5 Explorer PCB für dieses Chassis bietet eine sehr gute Basis sowie Anschlussmöglichkeiten.
    Dort sind auch bereits Bereiche vorgesehen um einen Pan/Tilt sowie Arduino zu befestigen, sowie den im Chassis beigefügten Akku-Halter anzuschließen sowie aufzuladen usw. Es können bis zu 4 Motoren inkl. Encoder angesprochen werden, wobei die Handhabung ziemlich einfach gehalten wurde und für die Motoren auch ein current-Pin vorhanden ist um 'stall' oder andere Probleme feststellen zu können (wenn die Motoren in 'stall' geraten verbrauchen sie schlagartig viel Strom und können die Antriebs-Akkus sehr schnell leer saugen).
    Auch die bereits jeweils in den Ecken befindlichen IR-Sensoren sowie leistungsstarker MotorDriver runden das ganze angenehm ab. Das PCB ist ebenfalls sehr gut dokumentiert und vom Hersteller mit Beispielen gut verständlich illustriert.

    Der Stromverbrauch des Explorer PCB's ist minimal und soll laut Hersteller 50mA betragen, wobei die IR-LEDs am meisten verbrauchen sollen - diese aber ja auch nicht ständig an sind sondern wenn dann nur maximal 100ms.

    Bei dem Explorer PCB waren auch einige Steckbrücken in verschiedenen Längen dabei..

    SparkFun hat zu diesem Chassis (aber einem eigenen MotorDriver) auch ein kurzes Video gemacht:

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne deine Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklärst du dich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.


    Wie eingangs bereits erwähnt sollte man lieber Reifen anstatt Ketten verwenden. Man muss sich deshalb aber nicht nach einem anderen Chassis umsehen sondern kann sich zum Beispiel > diese < von SparkFun kaufen - die passen super für das Rover5 Chassis :)
    Man kann aber auch andere Reifen verwenden solange sie für eine 4mm dicke Welle ausgelegt sind. Orientiert euch dabei aber an besagten Reifen und derer Befestigung!


    [an=Sensoren]Sensoren:[/an]

    Als Kompass kommt bei mir der CMPS10 zum Einsatz der hervorragend dokumentiert ist und sowohl I2C als auch UART oder PWM unterstützt. Ich verwende ihn über I2C: default address: 0x60
    Wie man die I2C Adresse ändern kann wird >> hier << beschrieben. > Hier < ist auch noch ein guter Artikel zu dem Module.

    Davon verwende ich zwei Stück:
    * Einer zeigt die Ausrichtung des Chassis an.
    * Ein anderer ist vorne am Pan/Tilt angebracht um die Blick-Richtung des abgeschickten Pings zu kennen. Dies ist wichtig um kontrollierter zu wissen um wie viel Grad ein Objekt geortet wurde, auch um z.B. Kontrollmessungen zu den fest montierten US-Sensoren durch zu führen. Aber auch um Objekten oben oder unten einen Winkel zuordnen zu können (durch den Pitch Wert). Das ist auch für die Kartenerstellung wichtig.

    Allerdings muss ich an dieser Stelle anmerken das die Produktion des CMPS10 eingestellt wurde, es sollten aber noch etliche im Umlauf sein. Der Nachfolger ist der CMPS11


    Beim Kompass muss man darauf achten das dieser das Erdmagnetfeld verwendet - andere Magnetfeld-Quellen stören also die Genauigkeit, weswegen dieser auch etwas oberhalb des Konstrukts angebracht werden muss, also nicht direkt über dem PI oder Arduino.


    Bezüglich Ultraschall Sensor (berührungslose Abstandsmessung. Sonar) sei gesagt das es viele verschiedene Ausführungen gibt, die alle ihre Vor- aber auch Nachteile haben. Die meisten jedoch haben einen Erkennungswinkel von ca.15°; eine maximale Reichweite von ca. 4 Metern und eine minimale Reichweite von 2cm.
    Leider kann der Ultraschall von glatten Flächen abgelenkt werden.

    Generell habe ich die weit verbreiteten HC-SR04 im Einsatz, die eine maximale Reichweite von 4 Metern und einen Verbrauch von ca. 15mA haben.
    Mittlerweile habe ich auf dem Pan/Tilt aber den etwas besseren US-015 verbaut. Der hat eine maximale Reichweite von 7 Metern und verbraucht nur ca. 2,2mA! (leider habe ich den Link wo ein genauer Vergleich zu sehen war verramscht :( vllt finde ich den wieder..). Entgegen der meisten Beschreibungen hat der US-015 tatsächlich eine Reichweite von 7 Metern, also nicht wundern, das ist kein Schreibfehler meinerseits :)

    Von den US hatte ich anfangs nur einen auf dem Pan/Tilt.
    Dazu hatte ich im Arduino-Sketch ein Abschnitt programmiert damit sich der Pan/Tilt in einem definierten Bereich in 20er Schritten von links nach rechts Bewegt, dann 10 Schritte nach oben versetzt, dann von rechts nach links scanned, wieder 10 Schritte nach oben - bis das definierten Ende erreicht wurde und dann das Spiel wieder Rückwärts fortsetzte.
    Da diese Prozedur aber viel Zeit kostet und die Fahrbewegungen ausbremst, habe ich mich später dafür entschiedene mehrere Ultraschall-Sensoren anzubringen. Vorne 3, jeweils im 45° Winkel versetzt und hinten zZt nur einen, der aber eigentlich überflüssig ist sobald GRID-Map verwendet wird. Den Beweglichen US auf dem Pan/Tilt behalte ich aber um auch Prüfungen nach oben/unten durchführen zu können.


    Die IR-Sensoren an den Ecken des Explorer PCB's haben eine (zuverlässige) maximale Reichweite von ca. 1 Meter, aber keine minimale Reichweite. Da die US-Sensoren nichts näher als 2cm erkennen ist es also gut auch IR zu haben.
    Allerdings funktionieren diese Sensoren sowohl draussen als auch bei direkter Sonnenbestrahlung nicht mehr (oder wenn andere IR-Quellen im Spiel sind). Deshalb darf/kann man sich wie eingangs erwähnt nicht nur auf einen Sensor-Typ verlassen.
    Die Genauigkeit kann durch stärkere IR-LEDs verbessert/erhöht werden, aber da ich mich hauptsächlich auf US stütze kann ich darauf erst mal verzichten.


    Damit der Roboter weiß wie viel Strecke er zurück gelegt hat - was wichtig für die GRID-Map Erstellung ist - befinden sich wie erwähnt in den Motoren sog. Odometrie-Sensoren.

    Diese zu kalibrieren hat mich einiges an Nerven gekostet, da nicht ein Signal auch eine Umdrehung bedeutet: ca. 1000 wechsel zwischen HIGH und LOW (Flankenwechsel) beziffern 6 Umdrehungen der Motoren. Das sagt aber noch nichts darüber aus wie viel Strecke das Gefährt zurückgelegt hat und kann je nach Untergrund (rutschen) variieren.
    Ich musste also auf Millimeter genau jeden Untergrund den ich in meiner Wohnung habe genauestens ausmessen bzw den Roboter eine bestimmte Strecke abfahren lassen, die Flankenwechsel zählen und dann konnte ich ermitteln wieviel Impulse 1mm entspricht... :-/ Man mag es kaum glauben, aber ich hatte tatsächlich je nach Untergrund Abweichungen, zwar minimal aber man will's ja auch irgendwie möglichst genau haben :D


    [an=OtherHW]Andere Hardware:[/an]

    Beim Pan/Tilt habe ich mich für das kleine, ebenfalls von DAGU stammende, Sensor Pan/Tilt Kit mit Servomotoren entschieden. Das hat dann auch die passende Größe um es auf der Explorer PCB zu befestigen.
    Vorteil ist das der Rahmen aus Aluminium und kein Plastik besteht.
    Ein Nachteil, den ich aber auch erst wärend der Entwicklung festgestellt habe ist, dass die Servo's keine analoge Rückmeldung ausgeben. Also nicht kontrolliert werden kann ob sie wirklich an die gewünschte Position gefahren sind, bzw bräuchte man dann im Programm nur solange warten bis sie die vorgegebene Position erreicht haben bevor man eine US-Messung o.ä. durchführt... Allerdings sind solche Servo's mit Rückmeldung relativ teuer und müssen dann auch noch die richtigen Abmessungen haben um in den Pan/Tilt zu passen...
    Ein weiteres Manko von diesem Pan/Tilt sind leider auch die billigen Schrauben. Bei der Montage sind mir 3 Schraubenköpfe abgerissen, obwohl ich die nicht wirklich 'zu fest' gezogen habe :(

    Auf der schwenkbaren Pan/Tilt Befestigung ist oben der Ultraschall Sensor und da drunter die RaspiCam angebracht (derzeit noch provisorisch mit einem doppelseitigem Klebeband-Streifen)


    Als RaspiCam verwende ich einen China-Nachbau, die als rev1.3 beziffert wird.
    Die Kamera ist kleiner als rev1.0 und hat eine für mich ausreichende Bildqualität, wobei diese etwas verrauschter als beim Original sein soll. Stört mich aber derzeit nicht wirklich :)

    Zusätzlich verwende ich ein längeres (30cm) Flex-Kabel damit die Kamera problemlos um 180° geschwenkt werden kann - diese ist nämlich ca. 10cm über dem Explorer PCB befestigt und wenn sie ganz nach rechts oder links geschwenkt wird, ist bereits das 30cm Flex-Kabel schon fast zu stramm.


    Als WLAN-Stick verwende ich den Edimax EW-7612UAN V2 [Anzeige] der eine wesentlich bessere Reichweite und Empfangsqualität besitzt (dank Antenne) als der winzige Edimax EW-7811Un (Nano), aber den selben Chipsatz 8192cu verwendet wodurch er sich ohne aufwendige Treiberinstallation sofort plug&play nutzen lässt.
    Aber da er auch wie sein kleiner Bruder nach einiger Zeit in einen Energiesparmodus geht, muss man auch hier den suspend-Mode abschalten.


    Als USB-Hub kommt ein kleiner passiver 4-Port USB-Hub zum Einsatz, der schön kompakt ist. Beachten sollte man das dieser auch Zurückspeisen kann - man könnte darüber also auch den PI mit Strom versorgen anstatt über microUSB.


    [an=PowerSupply]Stromversorgung:[/an]

    Für den RaspberryPI und Arduino habe ich eine separate Stromversorgung (30Ah Powerbank) vorgesehen, da diese ja permanent laufen muss, auch dann wenn der Antrieb nicht mehr geht.

    Wichtig für den Antrieb ist es gute NiMh oder Lithium Akkus zu verwenden, dessen ich mir Anfangs nicht bewusst war. Ich hab mich letztlich für 6x Oege, 2800mAh entschieden. Diese versorgen Motoren + Explorer PCB.
    Als Netzteil für das Explorer-PCB, um die 6 Akkus wieder aufzuladen, habe ich mich für ein Universal Netzteil 3-12V AC/DC 1500mA entschieden - da ist ein genau passender Hohlstecker bei und damit lässt sich auch die PowerBank aufladen ;)

    Wer vor hat LiPo's zu verwenden sollte sich zunächst mit der besonderen Problematik auseinander setzen. Siehe dazu > hier <


    [an=PowerUsage]Stromverbrauch überwachen:[/an]

    Um den Strom-bedarf/verbrauch zu überwachen verwende ich derzeit Adafruit USB Power Gauge Mini-Kit. Damit kann über UART überwacht werden wie viel Strom/Volt das über USB angeschlossene Gerät schluckt/benötigt/zieht.
    Den "USB Power Gauge" habe ich zwischen PowerBank und RaspberryPI angeschlossen und kann somit überwachen wie viel Ampere der PI aktuell zieht. Siehe dazu auch hier.
    Wichtig hierbei ist das zusätzlich auch noch mal GND über ein JumperKabel mit dem PI verbunden wird.

    Zusätzlich habe ich mir aber auch noch das INA219 High Side DC Current Sensor Breakout zugelegt, welches man in Reihe zwischen den Pluspol der Stromversorgung und den Verbraucher anschließt. Ein Kabel kommt vom PowerSupply, geht auf V+ am INA219 und V- geht dann zum Verbraucher. Also: V+ = Eingang von Batterie. V- = Ausgang zum Verbraucher. GND muss gemeinsam zusammengeführt werden.
    Wenn man dies nun ebenfalls an die USB-PowerBank anschließen würde, kriegt man aber nur die zur Verfügung stehenden Ampere des gewählten Ausgangs der PowerBank angezeigt (entweder 1A oder 2.1A), da die PowerBank das ja bereits intern reguliert.
    Schließt man das INA219 Module an den "Batterie" Ausgang vom Explorer PCB an werden aber die tatsächlich zur Verfügung stehenden Ampere der "Antriebs Akkus" (der Batteriehalter vom Chassis) angezeigt, da es hier keine Begrenzung gibt.

    Wichtig ist dass das INA219 Modul mit nur 3V3 betrieben wird (VCC) da sonst die I2C Ausgänge nicht auch 3V3 ausgeben sondern 5V. Wenn man nur 5V für VCC zur Verfügung hat brauch mal also noch einen Levelshifter (Logic Level Converter) um es gefahrlos an den PI anschließen zu können!

    Eine Alternative zu diesen Modulen wären ggf auch sog. Hall-Effekt Sensoren, worüber ich zwar auch schon einiges gelesen aber bisher nicht ausprobiert habe..

  • [an=HardwareGamePlay][/an]
    Hardware Zusammenspiel:

    Anfangs habe ich einen alten RaspberryPI Model-B verwendet, den ich jetzt aber durch einen sparsameren RaspberryPI A+ ersetzt habe.
    Der RaspberryPI hat in der aktuellen Entwicklungsphase kaum etwas zu tun:
    Die CPU Auslastung liegt bei 30% und die RAM Auslastung begnügt sich mit nur 10% Auslastung. Deshalb reicht ein A+ völlig aus.

    An den PI ist auch noch eine RaspiCam angeschlossen, die aber derzeit nur fürs Optionale Web-Interface (welches nur zur Kontrolle dienen soll, da das Projekt sonst nichts mehr mit Autonom zu tun hätte) verwendet wird.

    Anfangs hatte ich noch einen Arduino-UNO R3, den ich aber schnell durch den Mega2560 R3 ersetzen musste da ich viel mehr I/O's benötigte:


    Der neue A+ kann über den einen USB-Port problemlos 600mA ausgeben, was ausreicht um einen kleinen passiven USB-Hub mit 2 USB-Geräten zu versorgen: WLAN Stick und Arduino. Desweiteren könnte man das aber auch noch Softwareseitig auf 1.2A hoch setzen.

    Ich nutze absichtlich USB zur Anbindung des Arduino's um diesen auch jederzeit neu programmieren/flashen zu können. (hatte aber auch über I2C einige Probleme und es war bei weitem nicht so flexibel.)
    Dafür verzichte ich auf eine unnötig CPU/RAM fressende X11 Umgebung sondern nutze legentlich die Arduino-IDE auf dem PI in Verbindung mit X11-Forwarding und Xming (ich brauch also nur arduino ausführen und kriege dann auf meinem PC das IDE Fenster angezeigt).

    Der aktuelle Stromverbrauch (gemessen mit "Adafruit USB Power Gauge Mini-Kit") des Konstrukts (A+, passiver USB-Hub, Arduino, WLAN-Stick, RaspiCam) im Ruhezustand beträgt:
    ca. 395 bis 432 mA.
    Mit einem alten B rev2 hatte das selbe Konstrukt einen Verbrauch von:
    ca. 487 bis 652 mA.

  • [an=SoftwareGamePlay][/an]
    Software Zusammenspiel:

    Habe versucht das gesamte Konstrukt möglichst Modular aufzubauen.

    Die Basis bildet ein Python-Script ('the Brain') zur Seriellen Kommunikation zum Arduino. Der Arduino verschickt kontinuierlich/ungefragt seine Werte an dieses Python Script, welches die Werte in Dictionary's (sowas wie Arrays) zwischenspeichert. Diese Werte kann man dann an X-beliebiger Stelle abrufen und weiterverarbeiten.

    Das optionale Web-Interface verbindet sich intern über einen Socket und kann diese Werte ebenfalls abrufen, ebenso wie natürlich auch Steuerbefehle vom WebIf verarbeitet werden können.
    Und das alles natürlich ebenfalls in nahezu Realtime :fies:

    Auch ist eine möglichst flexible Konfiguration vorgesehen:
    Der Arduino übermittelt Standard Werte ans Hauptscript, die vom WebIf dann vor dem tatsächlichen laden ausgelesen werden. So brauch man nur im Sketch z.B. die Pan/Tilt Start-/End-Positionen ändern ohne diese auch noch mal manuell im WebIf anpassen zu müssen (für die Schieberegler).

    Desweiteren habe ich versucht möglichst wenig Datenverkehr zu verursachen - es können mehrere Befehle auf ein mal verschickt/verarbeitet werden, indem ich eine sprichwörtliche Liste übermittel und beim Empfänger anhand eines Trennzeichens ( \n ) aufsplitte.


    Während der Entwicklungsphase ist mir schnell klar geworden das ich möglichst auf künstliche Verzögerungen verzichten muss - weshalb ich eine Abneigung gegen delay / time.sleep 's entwickelt habe :fies:

    Deshalb habe ich das Arduino-Programm so gestaltet das kaum bis gar keine Verzögerungen verwendet werden und der loop() sozusagen ungebremst durchlaufen kann. Einzig wenn Anweisungen (Functions) ausgeführt werden, muss eben solange gewartet werden bis diese abgehandelt sind, da der Arduino leider kein echtes Threading/parallelisieren beherrscht.
    Aber auch in den Anweisungen verzichte ich auf Verzögerungen - einzig für Pan/Tilt musste ich welche verwenden da ich keine mit Abtastung (analoge Rückmeldung) nutze und diese leider nicht immer an die gewünschte Position gedreht sind.

  • [an=SoftwareInstall]Software Installation:[/an]

    Hinweis: Alle Befehle werden als root ausgeführt. Also entweder als solcher direkt anmelden, oder vorher zu diesem mit sudo su wechseln.

    Als Image kommt bei mir das Raspbian Minimal von DarkBasic zum Einsatz.
    Beachten sollte man hierbei die weiter unten in dem Thread erwähnten Schritte durch zu gehen um die Zeitzone, Tastatur usw anzupassen.

    Hinweis: Beim Raspbian Minimal Image vom 26.07.2014 besteht ein Bug in der Firmware bezüglich der ACT LED, welche nur beim Einschalten kurz aufleuchtet aber nicht bei Activity der SD. Um das zu beheben mithilfe von rpi-update einfach die aktuelle Firmware aufspielen. Nicht vergessen anschließend /boot/config.txt neu zu erstellen bzw anzupassen, denn sonst nimmt sich die GPU 128MB Ram.

    &quot;config.txt&quot;
    Code
    arm_freq=900
    core_freq=250
    sdram_freq=450
    over_voltage=2
    gpu_mem=16
    temp_limit=68

    Zusätzlich habe ich selbstverständlich auch noch mein varlog Script eingerichtet und einige weitere Optimierungen (die dort auch beschrieben sind) durchgeführt.


    Generell ist es auch fürs System wichtig SWAP zu haben, es nicht zu haben kann das System ausbremsen und sogar die SD mehr belasten als wenn man SWAP hat. Denn SWAP hat 2 Existenzberechtigung:

    1. Libraries usw die längere Zeit nicht verwendet wurde, werden vom RAM in den SWAP ausgelagert, bleiben dadurch aber weiterhin für das System kurzfristig verfügbar. Gäbe es kein SWAP müssten diese also immer wieder ent- und wieder ge-laden werden.
    2. Ist nicht mehr genug RAM frei so kann das System auf den SWAP ausweichen und funktioniert weiter. Gibt es aber kein SWAP und der RAM läuft voll kommt es zu Programm-Abstürzen bis hin zum kompletten Crash des Systems.

    &quot;swap erstellen&quot;
    Code
    # 512MB grosse Datei erzeugen
    dd if=/dev/zero of=/var/swapfile bs=1024 count=524288
    # SWAP Dateisystem erzeugen
    mkswap /var/swapfile
    # Rechte setzen
    chmod 0600 /var/swapfile
    # SWAP aktivieren
    swapon /var/swapfile
    # SWAP fuer naechste Systemstarts automatisch einhaengen
    echo "/var/swapfile swap swap defaults 0 0" >> /etc/fstab


    [an=SoftwareBasics]Voraussetzungen auf dem PI:[/an]

    Als erstes installiert man die Voraussetzungen damit die Python Scripts funktionieren und mit dem Arduino "sprechen" können. Das optionale Web-Interface benötigt übrigens das Paket python-tornado

    Code
    apt-get install python-pip python-serial python-dev python-tornado


    Desweiteren mag ich keine unnötigen Dienste die permanent laufen obwohl sie das nicht müssten. In diesem Fall beziehe ich mich auf ntp welcher die ganze Zeit im Hintergrund läuft um die Systemzeit zu aktualisieren...
    Stattdessen nutze ich lieber rdate oder man geht dazu über und kauft sich ein RTC Module wie z.B. das ZS-042 (DS3231 RTC @ I2C)

    ntpd deinstallieren:

    Code
    apt-get remove --purge ntp && apt-get autoremove

    rdate installieren:

    Code
    apt-get install rdate -y

    rdate einrichten:

    Code
    crontab -e
    
    
    @reboot		/usr/bin/rdate -s chronos.zedat.fu-berlin.de >/dev/null 2>&1
    */5 * * * *	/usr/bin/rdate -s chronos.zedat.fu-berlin.de >/dev/null 2>&1

    (Update bei Systemstart und alle 5 Minuten)

  • [an=prepareWI]Vorbereitungen fürs Web-Interface:[/an]

    Vorab:
    Ich kompiliere mir die Sources von nginx und ffmpeg selber, da ich eine möglichst niedrige Verzögerung von der RaspiCam benötige - mit den Versionen aus dem Repository hatte ich unakzeptabel hohe Verzögerungen. Schließlich möchte man jetzt genau in diesem Moment sehen was beim Roboter vorgeht aber nicht erst 5 Sekunden später...

    Dann an dieser Stelle der Hinweiß das man gcc-4.7 und g++-4.7 installieren sollte, denn aktuell wird noch gcc-4.6 verwendet was aber langsamer ist. Mit 4.7 wird schneller (und besser) kompiliert. Das macht sich inbesondere später beim kompilieren von ffmpeg für die RaspiCam bemerkbar.

    Code
    apt-get install gcc-4.7 g++-4.7
    export CC=gcc-4.7
    export GCC=g++-4.7

    Bevor wir uns jetzt aber an den WebServer nginx machen, starten wir das kompilieren von ffmpeg da dies am längsten dauert: ca. 4 Stunden!
    Gerade das selber kompilieren von ffmpeg ist wichtig, da wir dort ein 'Feature' ausschalten welches bei der precompiled Version aber nicht abzuschalten geht. Durch abschalten dieses 'Features' gewinnen wir ca. 2 Sekunden weniger Verzögerung und landen letztlich bei ca. 0,5 Sekunden was einiger maßen akzeptabel ist...
    Damit wir nicht die ganze Zeit zugucken müssen bzw auch das Terminal zu machen können wärend er weiter kompiliert, verwende ich screen.

    Voraussetzungen installieren:

    Code
    apt-get install -y curl build-essential libpcre3-dev libpcre++-dev zlib1g-dev libcurl4-openssl-dev libssl-dev git-core screen

    Jetzt den Source von ffmpeg laden und das Kompilieren in einem screen starten:

    Code
    cd /usr/src
    git clone git://source.ffmpeg.org/ffmpeg.git
    screen -dmS ffmpeg bash
    screen -S ffmpeg -X stuff $'export CC=gcc-4.7\n'
    screen -S ffmpeg -X stuff $'export GCC=g++-4.7\n'
    screen -S ffmpeg -X stuff $'cd /usr/src/ffmpeg && ./configure --disable-librtmp && make && make install\n'


    In ca. 4 Stunden könnt ihr dann mit dem Befehl screen -x ffmpeg wieder in den screen wechseln und gucken ob er fertig ist :)


    Als WebServer verwende ich den sehr sparsamen nginx mit dem rtmp Module.
    Dabei nutze ich einen kleinen dirty Trick um die Scripts in " /etc/init.d/ " nicht auch noch selber erstellen zu müssen: Erst nginx über apt-get installieren, danach wieder deinstallieren (aber kein purge!) und dann erst den Source installieren :fies:

    Zunächst nginx installieren und gleich danach wieder deinstallieren:

    Code
    apt-get install nginx -y && apt-get remove nginx && apt-get autoremove

    Jetzt den Source laden und kompilieren, was ca. 15 Minuten dauert.

    Code
    cd /usr/src
    git clone https://github.com/nginx/nginx
    cd nginx
    git clone https://github.com/arut/nginx-rtmp-module.git
    ./configure --prefix=/var/www --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_ssl_module --without-http_proxy_module --add-module=/usr/src/nginx/nginx-rtmp-module
    mkdir -p /var/www && chown www-data:www-data /var/www && chmod 775 /var/www
    make && make install
    usermod -G video -a www-data

    Nun noch ein paar Pakete für nginx installieren:

    Code
    apt-get install php5-fpm


    Optional(!):

    Code
    apt-get install php5-cgi php5-mysql php5-curl php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl


    [an=configWebServer]WebServer konfigurieren:[/an]

    Nun die Konfiguration anpassen: nano /etc/nginx/nginx.conf

    &quot;nginx.conf&quot;

    Die default Seite anpassen: nano /etc/nginx/sites-enabled/default

    &quot;default&quot;

    Script zum starten des Streams anlegen: nano /usr/local/bin/rtmp-nginx.sh && chmod a+x /usr/local/bin/rtmp-nginx.sh

    &quot;rtmp-nginx.sh&quot;

    Die Zeile mit FFREPORT sorgt dafür das ein Logfile angelegt wird was ihr kontrollieren solltet. Wenn es aussieht als würde es funktionieren würde ich diese Zeile im Script auskommentieren da das Log nach ner Zeit ziemlich groß wird!

    Anschließend die beiden Dienste neu starten um die Änderungen zu übernehmen:

    Code
    /etc/init.d/nginx restart
    /etc/init.d/php5-fpm restart


    Manchmal kommt es vor dass das Script nicht mit nginx gestartet wird. Um das temporär zu beheben schickt man das Script separat/manuell in den Hintergrund:

    Code
    nohup /usr/local/bin/rtmp-nginx.sh &

    (Voraussetzung hierfür ist aber natürlich das ffmpeg fertig kompiliert + installiert ist)

    Beachtet dass das DocumentRoot Verzeichnis /var/www/html/ ist!

  • Ich hab meinen Source von diesem Projekt auf Github frei gegeben, da ich nicht weiß wann ich damit weiter machen und es vollenden werde... Derweil könnt aber zumindest Ihr davon profitieren ;) --> https://github.com/meigrafd/RoPi


    Fragen usw bitte im Entwicklungs Thread (*klick*) stellen!

    :danke_ATDE: und ...Viel Erfolg... :fies:

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!