Motoren mit Rotationsencodern für ft per Arduino
Forumsregeln
Bitte beachte die Forumsregeln!
Bitte beachte die Forumsregeln!
Re: Motoren mit Rotationsencodern für ft per Arduino
Statt TimerInterrupt hätte ich den PinChangeInterrupt genommen. Mit jeder Interrupt wird ein Zähler um eins erhöht oder verringert (abhängig der Zustand der Eingänge).
Re: Motoren mit Rotationsencodern für ft per Arduino
Natürlich, wenn's funktioniert, funktioniert's. Die Vorrang von PCINT ist aber höher als der TimerInterrupts und wird nur ausgelösst wenn sich tatsächlich etwas ändert. Und mann spart ein Timer.
Re: Motoren mit Rotationsencodern für ft per Arduino
Hallo,
eine Menge Fragen. Ja jede Flanke lösst ein Interrupt aus. Ich hatte mir das zuerst für nur ein Encoder gedacht, dann ist jede Interrupt ein +1 oder -1 für den Zähler. Mit mehr als eins geht es natürlich auch, muss mann aber im betracht nehmen das es für eine oder mehrere Encoder keine änderung gibt. Die Analyse der Bemusterung (ist das Deutsch?) ist wahrscheinlich korrekt (habe es nicht nachgerechnet). Ein kleines Problem kann es noch geben wann die Motor richtung wechselt oder still steht gerade auf eine Flanke. Solche Pulsen können theoretisch sehr kurz sein (und deshalb unsichtbar bleiben), sollten aber nur abwechselnt +1 und -1 auslösen.
Ich hatte mir folgendes gedacht (in WINAVR C, atmel studio), habe es nicht ausprobiert:
Natürlich gibt es das Problem das während das abarbeiten der Interrupt sich die Eingänge nochmal ändern. Das wird hier in meisten Fälle nich bemerkt weil PORTB nur einmal gelesen wird. Die normale Sequenz ist:
Eingang ändert sich
PCINT flag wird aktiv
Nach einige Zeit wird die ISR angerufen, in die zwischenzeit kann sich noch etwas geändert haben, PCINT flag wird zurück gesetzt
PORT wird gelesen, nur diese Zustand wird im betracht genommen
Zähler werden angepasst, weitere änderungen können stattfinden (in diesem Fall wird PCINT wieder aktiv)
Zurückkehr von ISR
Wenn PCINT aktiv wird ein neue Interrupt ausgelösst, Jetzt werden die spätere änderungen bemerkt und verarbeitet.
Nächste mal auf Englisch
eine Menge Fragen. Ja jede Flanke lösst ein Interrupt aus. Ich hatte mir das zuerst für nur ein Encoder gedacht, dann ist jede Interrupt ein +1 oder -1 für den Zähler. Mit mehr als eins geht es natürlich auch, muss mann aber im betracht nehmen das es für eine oder mehrere Encoder keine änderung gibt. Die Analyse der Bemusterung (ist das Deutsch?) ist wahrscheinlich korrekt (habe es nicht nachgerechnet). Ein kleines Problem kann es noch geben wann die Motor richtung wechselt oder still steht gerade auf eine Flanke. Solche Pulsen können theoretisch sehr kurz sein (und deshalb unsichtbar bleiben), sollten aber nur abwechselnt +1 und -1 auslösen.
Ich hatte mir folgendes gedacht (in WINAVR C, atmel studio), habe es nicht ausprobiert:
Code: Alles auswählen
//for encoders on port B (a3 b3 a2 b2 a1 b1 a0 b0)
int counter[4];
ISR PCINT() //the interrupt service routine
{ static char old; //previous input state
char new = PORTB; //read all inputs
char change = old ^ new; //compute the changed bits
char dir = (old>>1) ^ new; //compute the direction
for (int i = 0; I < 4; i++)
{ if (change & 3) //this encoder has changed
if (dir & 1) counter[i]++; else counter[i]--;
change >>= 2;
dir >>= 2;
}
old = new;
}
Eingang ändert sich
PCINT flag wird aktiv
Nach einige Zeit wird die ISR angerufen, in die zwischenzeit kann sich noch etwas geändert haben, PCINT flag wird zurück gesetzt
PORT wird gelesen, nur diese Zustand wird im betracht genommen
Zähler werden angepasst, weitere änderungen können stattfinden (in diesem Fall wird PCINT wieder aktiv)
Zurückkehr von ISR
Wenn PCINT aktiv wird ein neue Interrupt ausgelösst, Jetzt werden die spätere änderungen bemerkt und verarbeitet.
Nächste mal auf Englisch
Re: Motoren mit Rotationsencodern für ft per Arduino
Moin,
beide Varianten haben ihre Vor- und Nachteile. Etwas habt ihr aber vergessen: Eine Plausibiltätskontrolle, die Fehlimpulse erkennt und entsprechend behandelt...
Die I²C-Kommunikation ist im Übrigen eher nicht zeitkritisch. Sollte es einmal vorkommen, dass die Software nicht schnell genug ist, gibt es entsprechende Maßnahmen ("Clock stretching"), die Datenverluste verhindern können. Natürlich muss das in den I²C Funktionen entsprechend behandelt werden...
Unterm Strich scheint der Pin-Change-Interrupt die bequemere Variante, aber ich würde die Timer-Variante bevorzugen, damit ist die Laufzeit besser vorhersagbar. Üblicherweise wird in der Interrupt-Routine nur das notwendigste erledigt (z.B. aktuellen Stand der Eingänge einlesen) um dann im Main-Loop verarbeitet zu werden, wenn Zeit dafür ist.
beide Varianten haben ihre Vor- und Nachteile. Etwas habt ihr aber vergessen: Eine Plausibiltätskontrolle, die Fehlimpulse erkennt und entsprechend behandelt...
Die I²C-Kommunikation ist im Übrigen eher nicht zeitkritisch. Sollte es einmal vorkommen, dass die Software nicht schnell genug ist, gibt es entsprechende Maßnahmen ("Clock stretching"), die Datenverluste verhindern können. Natürlich muss das in den I²C Funktionen entsprechend behandelt werden...
Unterm Strich scheint der Pin-Change-Interrupt die bequemere Variante, aber ich würde die Timer-Variante bevorzugen, damit ist die Laufzeit besser vorhersagbar. Üblicherweise wird in der Interrupt-Routine nur das notwendigste erledigt (z.B. aktuellen Stand der Eingänge einlesen) um dann im Main-Loop verarbeitet zu werden, wenn Zeit dafür ist.
Gruß
Thomas
Thomas
Re: Motoren mit Rotationsencodern für ft per Arduino
No, the pcint need not be extremely fast. The change condition itself is latched in the flag. You can process multiple changes in the same interrupt invocation. The main difference with the timer interrupt method is that the interrupt is not invoked when there is no change and that you don't need to define a hard limit on the frequency. The max frequency by pcint is defined by the total load on the cpu but is always better than with the timer due to higher priority of the pcint.
Re: Motoren mit Rotationsencodern für ft per Arduino
Regarding the fehlimpulse, the only things that can be checked are:
Was it really a change or just a glitch, and
Has more than one bit changed.
The first is important in the pcint method but the proposed program takes care of it by testing for change and not assuming a change, the timer method does not really have the problem.
The second can be easily resolved in either method by testing for change==3 meaning that both A and B have changed. What to do when you detect this is the next question. The best would be to assume that you missed a pulse and to add +2 or -2 depending on the last direction. At least we could set a flag that we know we are exceeding the limits of the system.
Was it really a change or just a glitch, and
Has more than one bit changed.
The first is important in the pcint method but the proposed program takes care of it by testing for change and not assuming a change, the timer method does not really have the problem.
The second can be easily resolved in either method by testing for change==3 meaning that both A and B have changed. What to do when you detect this is the next question. The best would be to assume that you missed a pulse and to add +2 or -2 depending on the last direction. At least we could set a flag that we know we are exceeding the limits of the system.