Autoren:
Datum: 31.01.1996
Das Stichwortregister steht hier.Zusammenfassung:
In diesem Dokument soll die Funktionalität des Beta-Knotens vorgestellt werden, der für die Odometriesensoren zuständig ist. Der Bericht gliedert sich dabei grob in die 2 Punkte: Soft- und Hardwareentwicklung.
Im ersten Teil erfolgt eine Beschreibung des Programms und der verwendeten Algorithmen. Ferner wird eine Einführung in die Funktionsweise des Timer-Interrupts gegeben, der das automatische Versenden der Odometrie-Daten in geregelten Abständen erlaubt. Anschließend sollen die notwendigen Hardwareanpassungen für die Odometrieauswertung dargelegt und allgemeine Aspekte der verwendeten Knoten behandelt werden.
Bevor die Erläuterung zum Programm-Code beginnt, soll zunächst beschrieben werden, was das Programm leisten soll. Dazu werden die einzelnen Aufgaben des Knotens, die die Odometriesensoren betreffen, kurz informell spezifiziert.
Die Werte der im folgenden erwähnten Konstanten können im Kap. Konstanten nachgeschlagen werden. Weiterhin gilt, daß alle Nachrichten, die von oder zu dem Beta-Knoten gesendet werden, den Identifier BETA_ID tragen müssen.
Der MC erwartet eine Nachricht mit der Sub-ID ODO_DATA. Daraufhin wird im DEFAULT-Zeitintervall die Geschwindigkeit des Rollstuhls ermittelt und anschließend eine Nachricht mit der Sub-ID ODO_DATA gesendet, die die in 8 Bytes verpackten Odometrie-Daten beinhaltet (Vgl. Tabelle Odo-Daten).
Das Zeitintervall zwischen den zu versendenen Nachrichten muß dem Knoten in einer CAN-Bus-Message (Sub-ID = ODO_MODE) mitgeteilt werden. Die Zeitspanne (in Sekunden) zwischen 2 Übermittlungen ergibt sich aus dem 1. Daten-Byte der Nachricht multipliziert mit 0.1, wobei 0 das automatische Senden beendet. Das Verpacken der Odometrie-Daten erfolgt wie beim einmaligen Senden.
Empfängt der MC eine Nachricht mit der Sub-ID RESET_ODO werden die Strecken- und Fehlerzähler auf Null gesetzt und das Senden eingestellt.
Stellt der Beta-Knoten einen Überlauf eines Streckenzählers fest, wird dieser mit Null initialisiert und eine Nachricht (Sub-ID=OVERFLOW) mit dem Überlauf-Flag overflow (1. Daten-Byte der Nachricht) abgesetzt.
Das auf dem MC verfügbare MICRO/C-51 ("Kernighan & Ritchie C") läßt eine Definition eigener Datentypen oder die Einschränkung von Wertebereichen vorhandener Datentypen nicht zu. Aus diesem Grund mußten z.B. Flag-Variablen, wie send, als char deklariert werden, obwohl send lediglich die Werte von 0 bis 2 annehmen kann. Zum besseren Verständnis wurden jedoch die einzelnen, bedeutsamen Werte derartiger Flag-Variablen als Konstanten definiert. Weiterhin sind alle als char definierten Variablen in diesem Programm als "Byte"-Werte zu verstehen.
In mccan.h sind Prozeduren zum Senden und Empfangen von Nachrichten über den CAN-Bus vereinigt. Dieses Programm benötigt aus mccan.h: CANPutBuffer, CANTrRequest, CANRecBuffer, CANGetBuffer, CANReleaseBuffer, initCAN. Auf diese Prozeduren wird im folgenden nur oberflächlich eingegangen. Eine genaue Beschreibung liefert die Dokumentation zum "mccan.h"-Modul.
Zur übersichtlichen und flexiblen Handhabung des Programms folgt nun die Definition einiger Konstanten. Die zugewiesenen Werte ergeben sich aus ...
Da dem Timer-Interrupt keine Variablen übergeben werden können, ist es notwendig Variablen, die sowohl im Hauptprogramm als auch in der Interrupt-Routine benötigt werden, global zu definieren. Beispiele derartiger Variablen sind : errcntright, fwdcntright, send, corrmod ... . Überdies mußten Variablen, deren Werte bis zum nächsten Interruptaufruf erhalten bleiben sollten (static), global deklariert werden (sec).
Der Timer-Interrupt (hier: Timer-0-Interrupt = Interrupt 1) wird bei jedem Überlauf des TL0-Registers aufgerufen (Vgl. Kap. Timer) und soll somit das periodische Versenden der Odometrie-Daten realiseren.
Der Zusatz "using 1" gibt dabei noch zusätzlich an, welche Registerbank (0 bis 3) angesprochen werden soll. Bei 8051-Architekturen kann bei jeder Funktion durch die Angabe des Attributes using angegeben werden, welche Register-Bank gewählt werden soll. Wird keine Angabe gemacht, wird automatisch die Register-Bank 0 verwendet. Nach Beendigung der Funktion wird zur vorherigen Einstellung zurückgewechselt. Das using-Attribut wird im allgemeinen dazu benutzt, in Interrupt-Funktionen Registerkonflikte zu vermeiden.
Bei der Programmentwicklung traten an dieser Stelle erhebliche Probleme auf, da die zunächst aus einem vorliegenden Beispiel-Programm übernommene Einstellung "using 2" für eine Vielzahl von Programmabstürzen verantwortlich war. So hatten beispielsweise kleinste Änderungen/Verkürzungen der Interrupt-Routine oder eine Umstellung in der Variablendeklaration dramatische Programmreaktionen zur Folge. Durch Experimentieren sind wir schließlich zur Einstellung "using 1" gekommen, die sich für unsere Zwecke als unproblematisch und sicher erwies.
Beginn des Hauptprogramms, das im wesentlichen für das Empfangen und Auswerten von Nachrichten sowie für die Odometrie-Messungen zuständig ist. Dies bedarf jedoch zuvor der Deklaration einiger Variablen.
Bemerkenswert dabei ist, daß das Array data[8] im Programm nie benutzt wird, jedoch das Fehlen dieser Deklaration den Empfang von Nachrichten verhindert. Ohne das Array sind sämtliche nachfolgend definierte Variablen bei der Entgegennahme von (korrekt versendeten) Nachrichten mit der Funktion CANGetBuffer(...) stets Null, was dementsprechend eine Auswertung von Nachrichten unmöglich macht. Mit der Deklaration des Feldes tritt dieser Fehler nicht auf.
Das Überlaufflag wird auf NO_OverFLow und die Odometrie-Variablen auf Null gesetzt.
Im MC P8xC592 stehen insgesamt drei 16-Bit Timer (T0, T1 und T2) zur Verfügung. Die Timer 0 und 1 können als Ereignis- oder aber als Zeitzähler eingesetzt werden. Das Zählen von Ereignissen bedeutet in diesem Zusammenhang, daß fallende Pegel an bestimmten Portpins (Pin 4 bzw. 5 vom Port 3) zur Inkrementierung des Timers führen. Die Funktionsweise kann mittels dreier Modi definiert werden:
Das LSB des Timer 0 (tl0) wird mit einer Frequenz von 1,33 MHz inkrementiert. Wird tl0 zu Beginn z.B. mit 5 initialisiert, müssen 250 Takte abgewartet werden, bis der erste Überlauf erfolgt. Beim Überlauf wird tl0 auf den "reload"-Wert (th0 ebenfalls mit 5 initialisiert) gesetzt, so daß wiederum 250 Takte gezählt werden müssen, bis zum nächsten Überlauf usw.. Bei jedem Überlauf wird der Timer-Interrupt aufgerufen. Damit läßt sich jetzt auch die Festlegung der Zeitbasis (corrmod) für das periodische Versenden der Odometriedaten erklären:
Wenn die Taktfrequenz bei 1.33 MHz liegt und sich alle 250 Takte einmal ein Überlauf ereignet, folgt daraus, daß 5333 (=1.333.333/250) mal in der Sekunde der Timer-Interrupt ausgelöst wird. Ein corrmod-Wert von beispielsweise 533 gestattet das Versenden der Daten nur jedes 533ste Mal, wodurch etwa alle 5333/533 = 0,1 Sekunden gegebenenfalls eine Nachricht zum PC gesendet werden kann. Die momentane Belastung des CAN-Busses beeinflußt jedoch die Ankunft der vom Knoten übermittelten Daten, so daß die Einhaltung der gewünschten Zeitintervalle zwischen den Odometrie-Nachrichten nicht garantiert werden kann. Weitere Einzelheiten und eine Erklärung des Timer T2 liefert die Beschreibung zum CAN-Modul-592.
Indem im Register TMOD das 2. Bit gesetzt wird, stellt man den Timer 0 auf den Mode 2 ein. Ferner wird der eigentliche Timer-Counter TL0 (LSB) und der "reload"-Wert TH0 (HSB) mit dem anfangs definierten PERIOD-Wert (=5) initialisiert. Das Setzten von ET0 und TR0 bewirkt, daß der Timer 0 eingeschaltet und dann gestartet wird.
Im folgenden sollen ankommende Nachrichten ausgewertet und die Odometriemessungen gezählt werden. Diese Aufgaben des Knotens müssen stets wiederholt werden, so daß sie in eine Endlos-Schleife eingeschlossen sind.
Die exakte Beschreibung der aus mccan.h importierten Funktionen CANRecBuffer, CANGetBuffer und CANReleaseRecBuffer kann der Dokumentation zu mccan.h entnommen werden.
In dieser zu empfangenen Nachricht sollte das RTR-Bit auf 1 gesetzt sein, so daß eine Anforderung der Odo.-Daten bei gleichzeitigem Versenden der entsprechenden Nachricht unterdrückt werden kann.
Zur Erkennung von Bewegung und Bewegungsrichtung separat für die beiden Antriebsräder sind auf jeder Seite des Rollstuhls 2 Induktivsensoren notwendig. Insgesamt gibt es somit 4 dieser Sensoren, wobei jeder Sensor einen Port-Pin benötigt.
Die Induktivsensoren für die Odometrie-Messungen wurden an dem digitalen Port 4 angeschlossen. Der Zustand der Sensoren kann somit aus dem Register P4 entnommen werden. Die Konstanten ODO_LEFT und ODO_RIGHT geben an, an welchen Pins die Sensoren des jeweiligen Rades angeschlossen sind. Ein Port-Pin wird auf LOW (0) gesetzt, wenn ein Loch detektiert wird, sonst auf HIGH (1).
Um das Auslesen des Eingabeports zu ermöglichen, müssen zunächst die entsprechenden Bits für das linke und rechte Rad auf HIGH gesetzt werden, weil der Port sonst u.U. einen so geringen Widerstand aufweist, daß keine meßbare Spannung (>2.5 V) am Port anliegt.
Da für die Bewegungserkennung aber die aktuellen Werte nicht ausreichen, müssen auch die Sensordaten der vorherigen Messung gespeichert und mit den aktuellen Werten verglichen werden. Deshalb werden die Variablen valleft und valright bevor die neuen Werte gespeichert werden um 2 Bits nach rechts geshiftet, so daß die Werte der vorherigen Messung im 1. und 2. Bit beider Variablen gesichert sind.
Auswertung: Rechtes Rad
Zunächst wird geprüft, ob sich das rechte Rad bewegt hat, d.h. ob die aktuelle Messung mit der vorherigen nicht übereinstimmt, da nur in diesem Fall eine nähere Auswertung Sinn macht. Demzufolge werden die ersten beiden Bits mit den 3. und 4. Bits verglichen.
| aktuelle | vorherige |
| Messung | Messung |
| 00 | 10 |
| aktuelle | vorherige |
| Messung | Messung |
| 10 | 00 |
| valright | Bedeutung |
| 0000 | keine Bewegung |
| 0001 | rückwärts |
| 0010 | vorwärts |
| 0011 | Fehler |
| 0100 | vorwärts |
| 0101 | keine Bewegung |
| 0110 | Fehler |
| 0111 | rückwärts |
| 1000 | rückwärts |
| 1001 | Fehler |
| 1010 | keine Bewegung |
| 1011 | vorwärts |
| 1100 | Fehler |
| 1101 | vorwärts |
| 1110 | rückwärts |
| 1111 | keine Bewegung |
In diesem Kapitel soll zunächst auf einige allgemeine Eigenarten der verwendeten Knoten eingegangen werden. Anschließend erfolgt dann die den Beta-Knoten betreffende Hardwarebeschreibung.
Bei der Benutzung der Ports bietet sich hauptsächlich der Port 4 an, da Experimente mit den anderen Ports oft Abstürze des Knotens verursachten. Die übrigen Ports sind gemäß Phytec-Unterlagen (Schaltplan) auch für andere IO-Aufgaben verwendet, z.B. RAM-MC-IO.
Die Ports müssen um ein korrektes zu bekommen zunächst auf HIGH gesetzt werden, d.h. man schreibt zunächst eine 1 in das Bit, welches man auswerten will und liest es direkt danach wieder aus. Diese Vorgehensweise ist zumindest bei hochohmigen Eingangssignalen notwendig, denn u.U. kann über den Port soviel Strom abfließen, daß die Eingangsspannung zum Schalten nicht mehr ausreicht.
Der Beta-Knoten übernimmt die Kontrolle über die Odometriesensoren, also über die Induktionsschalter. Die Beschreibung des Widerstandsnetzwerks läßt sich aus dem folgenden Absatz entnehmen.
Die Induktionsschalter (bzw. Induktivsensoren ) reagieren, wie der Name schon sagt, durch Induktion auf die Anwesenheit von Metall. Dazu wird ein hochfrequentes elektrisches Feld erzeugt, wobei in dieses Feld eindringendes Metall den Polaritätswechsel erschwert. Dies registrieren die Induktionsschalter und liefern ein digitales Ausganssignal (ein bzw. aus). Die vier digitalen Ausgangssignale zwischen 0V und 9V werden dann über die vier auf der Karte aufgebauten Spannungsteiler auf etwa 3,5 V heruntergeteit. Die nahe an der Schaltschwelle von 2,5 V liegende Spannung erfordert bei der Software vor dem Auslesen das Setzen auf 5 V, ist die Spannung am Mittelabgriff des Spannungsteilers ausreichend, so bleibt das Signal in jedem Fall über 3,5 V, andernfalls fließt der Strom über den Spannungsteiler (evtl. auch über die Sensoren) nach Masse ab. Die Schaltskizze des Beta-Knotens ist in der Abbildung Schaltskizze dargestellt.
Die Induktionsschalter sind aus technischen Gründen (s.o.) an Port 4
angeschlossen.
(Abbildung:
Die Messung der Geschwindigkeit und der zurückgelegten Entfernung geschieht auf dieselbe Weise, wie sie in Mäusen und anderen Eingabegeräten tausendfach zum Einsatz kommt: Es gibt zwei Sensoren mit je zwei Zuständen, die z.B. nach dem Lichtschrankenprinzip das Eintreffen von Licht oder die Okklusion durch eine Lochscheibe (oder auch Schlitzscheibe) erkennen können.
Die Sensoren sind so angebracht, daß einer gerade umschaltet, wenn der andere gerade "in der Mitte " des jeweiligen Zustandes ist. So wird erreicht, daß die zeitlichen Abstände zwischen den Zustandswechseln des Sensorenpaares gleich groß sind. Dies ist natürlich nur dann möglich, wenn die An- und die Auszeiten des Sensors gleich lang sind. Diese Forderung ist schon aus Performace-Gründen wichtig, ganz zu schweigen davon, daß dies die Justage enorm erleichtert.
Zwei Beispiele: Ist das An-Aus Verhältnis 1:1 reichen im Idealfall 4 periodische Zustandsabfragen, um alle Sensorübergänge zu registrieren. Ist das Verhältnis 4 : 1, was von unser ersten Lochscheibe eher noch übertroffen wurde, so muß man im günstigsten Fall 10 Abfragen machen.
Die Lochscheibe wurde zu Beginn des Projekts mit 30 Löchern zu 16 mm gebohrt. Dies schien aus zwei Gründen recht sinnvoll zu sein: Zum einen waren die Löcher somit etwas größer, als der Durchmesser der Sensoren, zum anderen waren damit Metall und Löcher im Bereich der Sensoren in etwa gleichverteilt. Für Lichtsensoren beispielsweise wäre dies auch genau die richtige Größe gewesen. Die Induktivsensoren schalten jedoch schon bei entfernter Anwesenheit von Metall. Da der Schaltpunkt sich nicht einstellen ließ, versuchten wir zunächst, das Problem dadurch zu umgehen, daß wir die Sensoren weiter von der Lochscheibe entfernten. Dadurch "verschwomm" aber der Unterschied zwischen Loch und Metall, d.h. war die Lochscheibe nur etwas weiter von dem Sensor entfernt (weil das Rad unruhig lief oder eine Kurve gefahren wurde), so wurde überhaupt kein Metall mehr detektiert. Dies führte dann zu solchen Ergebnissen, daß die Odometrie für einen halben Radumlauf gut funktionierte, während sie bei der nächsten halben Radumdrehung überhaupt keine Bewegung mehr registrierte.
Im 3. Projekt-Semester, als der Rollstuhl quasi zum ersten Mal auf seine Odometrie- und Lenkwinkeleinstellungsmöglichkeiten getestet wurde, sind solche Effekte aufgetreten, nachdem der Rollstuhl auf den Rädern umherbewegt wurde. Zu dieser Zeit blieben noch zwei Optionen offen: Das Anpassen des Metall-Loch-Verhältnisses durch das Aufbohren der Löcher oder die Verwendung neuer Sensoren. Wir entschieden uns aus Kosten und Zeitgründen für die erste Lösung, obwohl die Gefahr bestand, daß das Verhältnis immer noch nicht ausgewogen genug war. Die bisherigen Tests geben jedoch Grund zu Optimismus.