Motoren mit Rotationsencodern für ft per Arduino

Alles rund um TX(T) und RoboPro, mit ft-Hard- und Software
Computing using original ft hard- and software
Forumsregeln
Bitte beachte die Forumsregeln!
Antworten
Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Motoren mit Rotationsencodern für ft per Arduino

Beitrag von Ad2 » 17 Jul 2014, 13:54

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).

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Motoren mit Rotationsencodern für ft per Arduino

Beitrag von Ad2 » 17 Jul 2014, 16:18

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.

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Motoren mit Rotationsencodern für ft per Arduino

Beitrag von Ad2 » 19 Jul 2014, 14:53

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:

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;
}
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

thkais
Beiträge: 384
Registriert: 31 Okt 2010, 21:45

Re: Motoren mit Rotationsencodern für ft per Arduino

Beitrag von thkais » 20 Jul 2014, 09:57

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.
Gruß
Thomas

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Motoren mit Rotationsencodern für ft per Arduino

Beitrag von Ad2 » 20 Jul 2014, 10:09

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.

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Motoren mit Rotationsencodern für ft per Arduino

Beitrag von Ad2 » 20 Jul 2014, 10:29

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.

Antworten