Linke Lichtschranke | Rechte LichtschrankeB | Code |
---|---|---|
liefert 0 (LOW) | liefert 0 (LOW) | 0*10+0=0 |
liefert 1 (HIGH) | liefert 0 (LOW) | 1*10+0=10 |
liefert 1 (HIGH) | liefert 1 (HIGH) | 1*10+1=11 |
liefert 0 (LOW) | liefert 1 (HIGH) | 0*10+1=1 |
Die einfachste Art, die Lichtschrankenzustände zu codieren, wäre einfach die Zustände als Dezimalzahl zu interpretieren.
Allerdings sind Berechnungen im Dezimalsystem wesentlich langsamer als Berechnungen im Binärsystem (2-er System). Und bei sich schnell drehenden Motoren muss sehr oft der Zustand der Lichtschranken berechnet werden
Linke Lichtschranke | Rechte LichtschrankeB | Code |
---|---|---|
liefert 0 (LOW) | liefert 0 (LOW) | 0*2+0=0 |
liefert 1 (HIGH) | liefert 0 (LOW) | 1*2+0=2 |
liefert 1 (HIGH) | liefert 1 (HIGH) | 1*2+1=3 |
liefert 0 (LOW) | liefert 1 (HIGH) | 0*2+1=1 |
Im Binärsystem (2-er System) wird die 10 lediglich durch die 2 ersetzt.
Erweiterung der Header-Datei
class Motor { private: int en,m1,m2,i1,i2; const int st[4]={0,2,3,1}; // Abfolge der Zustände volatile int pos; // Aktueller Zustand volatile long steps=0; // Einzelschritte (steps) public: Motor(int e,int a,int b,int c,int d); void power(int p); void richtung(); /* * Wird immer ausgeführt, wenn eine Änderung bei * i1 oder i2 auftritt */ long getSteps(); // Liefert die bisher gemachten Eintelschritte };
In der Klasse werden jetzt ein paar Daten mehr gespeichert:
i1
undi2
sind die InputPins der beiden Lichtschrankken.st[]
ist ein Array, in dem die möglichen Zustände der Lichtschranken gespeichert sind.pos
ist die Position des letzten Lichtschrankenzustands inst[]
.steps
ist die Anzahl der Schritte, die der Motor bereits gemacht hat.
Die Konstruktormethode Motor
erwartet jetzt zusätzlich noch die beiden Pins der Lichtschranken.
Neu hinzugekommen sind die Methoden richtung()
und getSteps()
.
richtung()
wird immer dann aufgerufen, wenn sich der Zustrand der Lichtschranken geändert hat. Dann wird die Laufrichtung des Motors ermittelt undsteps
um 1 erhöht oder erniedrigt.getSteps()
liefert die Anzahl der Motorschritte.
Die cpp-Datei
Motor::Motor(int e, int a,int b,int c,int d) { en=e; // Motorpins merken m1=a; m2=b; i1=c; i2=d; pinMode(en,OUTPUT); // Pins konfigurieren pinMode(m1,OUTPUT); pinMode(m2,OUTPUT); pinMode(i1,INPUT); pinMode(i2,INPUT); digitalWrite(en,LOW); // Motor erst mal ausschalten digitalWrite(m1,LOW); digitalWrite(m2,LOW); int h = digitalRead(i1)+2*digitalRead(i2); // Aktuellen Zustand ermitteln int i; for(i=0;i<3;i++) if (st[i]==h) pos=i; }
Im Konstruktor werden werden die Inputpins gespeichert und der Pinmode auf INPUT gesetzt.
Neu sind die letzten drei Zeilen.
Zunächst wird, wie oben beschrieben, der Zustand der Lichtschranken codiert. Anschließend wird die Position des aktuellen Zustands in st[]
ermittelt und
in pos
gespeichert.
void Motor::richtung() { int h = digitalRead(i1)+2*digitalRead(i2); if (st[(pos+3)%4]==h) { steps--; pos=(pos+3)%4; } else if (st[(pos+1)%4]==h) { steps++; pos=(pos+1)%4; } }
Die Methode richtung()
ermittelt zunächst den Zustand der Lichtschranken und speichert ihn in h
.
In der Tabelle ist der Inhalt des Arrays st[]
dargestellt.
pos |
st[pos] |
---|---|
0 | 0 |
1 | 2 |
2 | 3 |
3 | 1 |
pos zeigt auf den letzten Zustand und h stellt den aktuellen Zustand der Lichtschranken dar. Ist beispielsweise pos==2 und h==2, so hat sich der Motor um einen Schritt rückwärts gedreht, steps muss um 1 verringert werden. Ist h==1, so hat sich der Motor um einen Schritt vorwärts gedreht, steps muss um 1 erhöht werden.
Man muss den aktuellen Zustand h mit st[pos-1] und st[pos+1] vergleichen. Das geht aber schief, wenn pos auf den Rand zeigt, also 0 oder 3 ist. Dann zeigt pos+1=4 oder pos-1=-1 außerhalb des Arrays st[].
-4/4=-1 Rest 0 | 0/4=0 Rest 0 | 4/4=1 Rest 0 |
-3/4=0 Rest -3 | 1/4=0 Rest 1 | 5/4=1 Rest 1 |
-2/4=0 Rest -2 | 2/4=0 Rest 2 | 6/4=1 Rest 2 |
-1/4=0 Rest -1 | 3/4=0 Rest 3 | 7/4=1 Rest 3 |
Eine Lösung ist das Rechnen mit Rest. Bei int-Variablen ergibt die Division eine ganze Zahl. Beispiel 7/4=1
Mit %
lässt sich der Rest einer Division berechnen. Beispiel 7%4=3
Wenn st[pos]
der letzten Zustands der Lichtschranken ist, dann ist st[(pos+1)%4]
der nächste und st[(pos+3)%4]
der vorherige Zustand.
long Motor::getSteps() { return steps; }
Die Methode getSteps()
liefert die Anzahl der bisherigen Motorschritte.
Anwendung der Klasse Motor und Interrupts
#include"motor.h" #include <EnableInterrupt.h> // en,m1,m2,i1,i2 /* * en EnablePin * m1 Motorpin1 * m2 Motorpin2 * i1 Inputpin1 (Lichtschranke oder Encoder) * i2 Inputpin2 */ Motor M1(6 ,7 ,8 ,2 ,3 ); void setup() { Serial.begin(9600); enableInterrupt(2,iRoutine,CHANGE); // Wenn sich i1 oder i2 ändern, sollen die enableInterrupt(3,iRoutine,CHANGE); // Motorsteps weitergezählt werden. } void loop() { delay(1000); Serial.println(M1.getSteps()); } void iRoutine() { M1.richtung(); }
Wie ist es möglich, genau zu dem Zeitpunkte, an dem sich der Zustand einer der Lichtschranken ändert, die Methode richtung()
von M1 auszuführen?
Genau das können Interrupts.
Wird durch eine Veränderrung an Pin 2 ein Interrupt ausgelöst, wird das aktuelle Programm unterbrochen und die Interrupt-Routine iRoutine()
ausgeführt.
Danach wird das Programm an der Stelle fortgesetzt, an der es unterbrochen wurde.
Mit #include <EnableInterrupt.h>
wird die Interrupt-Bibliothek eingebunden.
enableInterrupt(2,iRoutine,CHANGE);
aktiviert den Interrupt für eine Änderung des Zustandes von Pin 2. iRoutine()
wird dann als Interrupt-Routine ausgeführt.
iRoutine()
führt lediglich M1.richtung()
aus.
Die Bibliothek EnableInterrupt kann von dieser Seite als zip-Datei heruntergeladen werden.
Die zip-Datei muss in das Verzeichnis Arduino/libraries/ entpackt werden.
Das Beispiel kann hier heruntergeladen werden.