Da ich in letzter Zeit wieder etwas mehr Freiraum hatte, habe ich den Bau
meines Roboters fortgesetzt. Den ersten Fehlschlag erlebte ich bei der
Verwendung von Steppern als Antriebsmotoren. Diese hielten leider nicht, was ich
mir von ihnen versprochen hatte, ihr Drehmoment war zu niedrig, so dass erste
Fahrversuche an einer Teppichkante scheiterten ;-)
Doch das sollte der Sache keinen Abbruch tun, es wurden RB35 Motoren und ein
paar Getriebe bestellt (www.embedit.de).
Diese zeigten schon in ersten Versuchen, dass sie mehr als ausreichend waren,
meine kleine Versuchsplattform durch die Gegend zu fahren. Zur Ansteuerung
verwende ich den unter der Rubrik Mechanik erwähnten Baustein L293D.
Das Gehirn von Homer bildet ein ATMEGA32L mit 16MHz, es sollten also mehr als
genug Leistungsreserven aus rechentechnischer Sicht verfügbar sein. Die
Programmierung dieses Controllers unterscheidet sich im Prinzip in fast keinem
Punkt zu der des ATMEGA8, welcher hier bereits vorgestellt wurde.
Als Benutzerinterface dient ein HD44780 LCD mit 4*16 Zeichen.
Die Augen des Roboters bilden vorerst zwei SHARP GP2D120 Infrarotsensoren,
welche ein distanzproportionales Analogsignal an ihrem Ausgang zur Verfügung
stellen. Zusätzlich verfügt er über mehrer Näherungsschalter auf Basis des
IS471F zur Kollisionserkennung und -vermeidung.
Motorisiert ist er wie bereits erwähnt mit Hilfe von zwei DC-Motoren (hinten rechts
und links) sowie eines Stützrades (vorne Mitte).
Hier eine schematische Zeichnung:
Wie ersichtlich ist, sind 6 Infrarot-Kollisionssensoren vorgesehen. Diese
ziehen jeweils etwa 10mA Strom, was bei 5V Betriebsspannung einen
Leistungsumsatz von 50mW je Sensor bedeutet. Insgesamt kommen so also 0,3W
zusammen.
Für die beiden Sharp Sensoren sind jeweils etwa 26mA zu veranschlagen. Daraus
folgt eine Leistung von gesamt 5V*26mA*2=0,26W.
Meine Schaltung mit ATMega32 und LCD zieht gesamt etwa 100mA, wobei man diesen
Wert schon fast als worst case betrachten kann. Hier kommen also noch einmal
0,5W zusammen.
Gesamt lässt sich ein Strom von 212mA ausrechnen. Da für den 12V Bleigel-Akku
zusätzlich ein Spannungsregler benötigt wird um die 5V Logikspannung
bereitzustellen, muss mit einer Leistung von 12V*212mA=2,544W gerechnet werden.
Diese muss vom Akku bereitgestellt werden.
Zusätzlich wird natürlich noch Motorleistung benötigt, denn nur "rumstehen und
gucken" ist auf Dauer nicht wirklich prickelnd ;-)
Einfache Tests mit den Motoren ergaben einen Leerlaufstrom von etwa 100mA, bei
normaler Last etwa 150-200mA und unter Volllast (kurz vor Stillstand) etwa
400mA. Im weiteren wird mit 250mA je Motor gerechnet, was wieder fast einer
worst case Betrachtung entspricht. Gesamt ergeben sich also 0,5A unter Last, das
entspricht bei 12V einer Leistung von 6W.
Da der von mir benutzte Akku eine Kapazität von 1,3Ah hat, bedeutet das bei
einem Nennstrom der Schaltung von ca. 750mA, dass mein Roboter mindestens
1,3Ah/0,75=1,73h also eine Stunde und 45 Minuten "durcharbeiten" können müsste,
was ich als durchaus ausreichend betrachte.
Es darf allerdings nicht verschwiegen werden, dass ein solcher Bleiakku auch mit
einem Gewicht von 0,6kg zu Buche schlägt. Das ist im Vergleich zu anderen
Akkusorten (vgl. Racing-Packs mit NiCd bzw. NiMh) nachteilig. Für ihn spricht
der gute Preis, die einfach Handhabung und die Tatsache, dass er im Prinzip über
keinen Memory-Effekt verfügt.
Ein ähnlicher Akku mit 2,2Ah ist mit einem Gewicht von 0,8kg im Handel
verfügbar. Dies entspräche bereits einer Betriebsdauer von beinahe 3 Stunden.
Die Pinbelegung des ATMega32 sieht nun wie folgt aus:
Wie ersichtlich ist, sind die zunächst zahlreich erscheinenden Pins des Atmels relativ schnell erschöpft. Pin 1-4 dienen dem Festlegen der Drehrichtung der beiden Motoren. Pin 14,15,20 und 21 können noch zur Benutzerführung mittels Taster bzw. als Status-Anzeige mittels LEDs genutzt werden. Pin 16 und 17 dienen der Drehzahlerfassung der Motoren über auf den Wellen befestigte Encoderscheiben in Verbindung mit Gabellichtschranken. Pin 18 und 19 dienen der Drehzahlstellung. Die Pins 39 und 40 werden zur Abstandsmessung verwendet. Pin 38 soll ständig den Akku auf eine bestimmte Mindestspannung prüfen, so dass ab einer bestimmten Entladung die Motoren abgestellt und ein Warnsignal (Pin 29 --> Status-LED) ausgegeben werden kann. Pin 36 und 37 werten den Motorstrom ständig aus, um eine eventuell von den Sensoren nicht erkannte Kollision zu erkennen (Motorstrom würde steigen). Mit den Pins 22-28 wird leider fast ein kompletter Port "nur" für das Benutzerinterface LCD genutzt. Diese ist jedoch meiner Meinung nach zum Debuggen und für Statusmeldungen unerlässlich.
Motorsteuerung: siehe Seite Mechanik
IS471F: siehe Seite Sensorik
Encoder:
Als Radencoder habe ich die GP1A71R von Sharp verwendet. Dies ist
hauptsächlich darin begründet, dass ich keine Lust hatte, selbst auf
Pappscheiben entsprechende Segmente zu malen, da dabei keine entsprechend hohe
Wegauflösung zu erwarten ist. Die Encoder von Sharp werden mit einer 120er
Teilung ausgeliefert. Dies sollte eine ausreichende Wegauflösung gewährleisten.
Hauptzweck der Encoder ist die Realisierung einer simplen Geradeausfahrt
(ansonsten durch Ungleichheiten der Motoren unmöglich) sowie von Kurvenfahrten.
Der Anschluss der Sensoren kann dem beiliegenden Datenblatt entnommen werden. Es
muss für eine Betriebsspannung und Masse gesorgt werden. Die integrierte LED
benötigt zusätzlich noch einen Widerstand von etwa 190Ω
(oder etwas größer). Es können dann zwei Signale abgegriffen werden. Beide geben
eine zur Rotationsgeschwindigkeit proportionale Rechteckfunktion aus, welche
jedoch untereinander um 90° verschoben ist. So ist eine zusätzliche Bestimmung
der Drehrichtung möglich, welches jedoch hier nicht nötig sein sollte,
schließlich legt das Motorprogramm bereits die Drehrichtung fest.
Drehzahlstellung: siehe Beispielprogramm zum Thema PWM sowie Seite Timer
Sharp: siehe Seite ADC sowie Sensorik
Akkuüberprüfung:
Die Akkuüberprüfung erfolgt durch einen Spannungsteiler von zwei Widerständen
mit den Werten 22kΩ und 68kΩ.
Diese dienen dazu, die 12V Spannung des Akkus auf eine für den ADC taugliche
herunter zu skalieren.
LCD: siehe Seite LCD
Chassis:
Das Chassis habe ich mir aus einer Kunststoffplatte mit einer Stichsäge zurecht
gesägt. Das ist meiner Meinung nach für einen Prototypen kein schlechtes
Material, da es sehr leicht ist, einfach zu bearbeiten, gut zu kleben bzw. zu
schrauben. Als Räder verwende ich welche aus dem Modellbau, die ich bei Conrad
bestellt habe. Die sind zwar relativ teuer, allerdings haben sie einen
geringeren Durchmesser, laufen absolut rund und ihr Bohrungsdurchmesser war
kleiner als der meiner Motorwellen. So reichte ein leichtes Aufbohren der Räder
aus, um sie in Form einer Presspassung auf der Welle zu befestigen. Diese Lösung
ist zwar nicht unbedingt elegant aber funktioniert zuverlässig.
Die Programmierung:
Was einem bei der ersten Probefahrt sofort ins Auge
sticht ist die Kurvenfahrt des Roboters, obwohl an beiden Motoren dieselbe
Spannung anliegt. Das liegt daran, dass vergleichsweise günstige Motoren
verwendet wurden. Ich denke, dass sich dieser Effekt mit dem Kauf teurer
(drehmomentstarker) Schrittmotoren bzw. DC-Motoren minimieren ließe. Allerdings
kann man sich diese Ausgaben auch schenken und auf vergleichsweise günstige
Radencoder (Gabellichtschranke + Encoderscheibe) zurückgreifen. Diese Zählen nun
beständig die Impulse bei laufendem Motor. Anhand der gezählten Impulse muss nun
Einfluss auf die Motorgeschwindigkeiten (also Spannungen) genommen werden, so
dass sie im Falle einer Geradeausfahrt annähernd auf beiden Seiten gleiche Werte
annehmen.
Ohne näher auf die Regelungstechnik einzugehen kann die Regelstrecke mit einem
IT1-Verhalten klassifiziert werden.
Die obige Grafik zeigt die schematisierte Sprungantwort des Systems. Sprungantwort heißt, dass ich an den Eingang (also die Motorklemmen) eine definierte Spannung anlege und diese konstant halte. Nun wird betrachtet, wie sich der Ausgang (also die Encoder) verhält. Diese zählen erwartungsgemäß beständig aufwärts. Da der Motor näherungsweise PT1-Verhalten hat, also auf eine Spannung an den Klemmen leicht verzögert (also träge) reagiert, ergibt sich für die Regelstrecke das obige Aussehen. Wäre der Motor sofort auf seiner "Nenndrehzahl", so würde sich eine Gerade direkt durch den Ursprung ergeben, der Bogen im unteren Bereich könnte entfallen.
Die Zeitkonstante wird durch die Mechanik
des Motors bestimmt, die elektrischen Zeitkonstanten können vernachlässigt werden.
Einschlägiger Literatur kann entnommen werden, dass man für eine IT1-Strecke am
besten einen PI-Regler verwenden sollte. Ein D-Anteil ist überflüssig, könnte
aber nachträglich noch hinzugefügt werden.
Die Basis für einen Regelvorgang bildet immer ein Sollwert-Istwert Vergleich.
Der Sollwert wird vorgegeben, den Istwert kann man mittels der Radencoder
erfassen. Als Sollwert könnte beispielsweise angenommen werden, dass sich das
Rad in einer bestimmten Zeitspanne, also meinetwegen 0,125s, um eine bestimmte
Anzahl an Encoderschritten, also beispielsweise 5, gedreht haben soll.
Die von mir verwendete Reglerstruktur hat das folgende Aussehen:
Regelfaktor = KP*(Ist - Soll) + KI*((Ist - Soll)*Zeitintervall)
Hierbei stellen KP und KI die Proportional- bzw. Integralverstärkung dar. Der Regelfaktor ist ein direktes Maß für die Abweichung und demzufolge notwendige Nachregelung. Sind Ist- und Sollwert identisch wird er logischerweise Null. Dieser Regelfaktor muss für jede Seite (Motor rechts bzw. Motor links) getrennt berechnet werden.
Wählt man nun die Abtastzeit ausreichend fein, so erhält man eine kontinuierliche Rotation der Motorwellen. Bei praktischen Versuchen zeigte sich, dass die oben angegebene Formel noch kein ausreichend gutes Ergebnis zur Verfügung stellt. Was fehlt ist ein zusätzlicher Vergleich der absoluten Encoderwerte der rechten bzw. linken Seite. Summiert man die Abweichung zwischen beiden Seiten multipliziert mit einem bestimmten Faktor zusätzlich zum Regelfaktor, so erhält man eine nahezu perfekte Geradeausfahrt.
Die bereits erwähnte Abtastzeit sollte relativ genau sein. Deshalb liegt die Verwendung eines Timers nahe. In dessen ISR wird dann die eigentliche PI-Regler Funktion aufgerufen.
Die im folgenden verlinkte C-Datei demonstriert die Implementierung meines PI-Reglers. Die header-Datei motor.h habe ich zunächst nicht mit verlinkt, da sie je nach verwendetem Motor bzw. Treiberschaltkreis bei jemand anderem soundso nicht arbeiten würde. Entscheidend ist alleine ihre Funktionalität. Sie ist so gestaltet, dass ihr zwei Parameter übergeben werden. Einmal der gewünschte Motor (0 = links, 1 = rechts) sowie die Geschwindigkeit (0 = Stillstand, 100 = max. mögliche Geschwindigkeit).
Die Veröffentlichung der gesamten Software zu
meinem Robo erübrigt sich, da bezweifelt werden kann, dass sie jemandem einmal
nützt. Von mir gelöste Aufgaben lagen darin, geradeaus zu fahren, Kollisionen zu
vermeiden oder wenigstens zu erkennen und entsprechende Maßnahmen zu ergreifen.
Mit Hilfe der Sharp-Sensoren war auch die Wandverfolgung nicht weiter schwierig.
Für weitere Herausforderungen hat mir dann doch irgendwo die Inspiration
gefehlt, weshalb ich mich danach wieder anderen Projekten zugewandt habe.