Hallo zusammen,
[right:abd365b507]http://3.bp.blogspot.com/_qPTJUGegS5w/RfvkFxfGqDI/AAAAAAAAABE/nWNJ4RsGsVU/s200/DSC00519.jpg[/right:abd365b507]


mein Bruder und ich habe Probleme mit unseren Encodern und wir wissen noch nicht einmal ob es ein Denk, Rechen oder Mechanischer Fehler ist. Die Encoder haben wir auf unserem Blog wsgs.blogspot.com ausführlich beschrieben.

Es handelt sich um Encoder für RB-40 Motoren, die am Ende des Motors befestigt werden. Zwei Gabellichtschranken und eine Schlitzscheibe erzeugen zwei um 90° verschobene Signale. Ein Schmitttrigger säubert die Signale für einen µC. Die Auswertung wird durch einen der neueren ATmega328P durchgeführt. Dessen Eingänge lassen sich als Interrupt für steigende und fallende Flanke konfigurieren. Bei jeder Flanke von Signal A oder B wird die Interrupt Service Routine gestartet und die Drehung ausgewertet.
[right:abd365b507]http://1.bp.blogspot.com/_qPTJUGegS5w/SW98EhOdfNI/AAAAAAAAAHs/1M6r8rg5IF8/s320/DSC01080_filtered.jpg[/right:abd365b507]
Die Rechnung:
Da ich mich schon einige male verrechnet habe wollte ich euch bitten über meine Rechnung zu schauen. Meist hilft es ja schon, wenn man es ausführlich hinschreibt.
Die Schlitzscheibe hat 32 schwarze Felder. Bei jedem Feld werden 4 Flanken erzeugt (steigend, fallend Lichtschranke A und steigend, fallend Lichtschranke B). Der Motor macht bis zu 5000 Upm.

Bild hier  

Es werden also fast 11 tausend Interrupts pro Sekunde erzeugt. Der µC läuft deswegen mit 20Mhz und soll dabei zwei Motoren auswerten können (erst mal reicht einer).

Bild hier  

Zwischen jedem Interrupt können also 1875 Maschienenbefehle ausgeführt werden. Nun hängt es von der ISR ab, wie viele Maschinenbefehle sie braucht und wie viele für andere Programmaufgaben übrig bleiben.

Die ISR
Die Interrupt Service Routine erzeugt zwei Werte die zum Test alle 100ms über UART ausgegeben werden.
Code:
public volatile long lEncoder;
public volatile long lError;

ISR(PCINT0_vect)   
{   
// lookup table   
 static const int8_t aSteps[] = { 0, -1, 1, ENC_INV, 1, 0, ENC_INV, -1, -1, ENC_INV, 0, 1, ENC_INV, 1, -1, 0 };   
 int8_t iStep = 0; // Schrittweite des Motors   
  
 // alte Phase um zwei Bit nach links verschieben   
 bPhase.bRow = (bPhase.bRow << 2);   
 // alles ausser a und b löschen   
 bPhase.bRow &= 0x0C;    // 0000 1100 = 0x0C   
 // Signal A einlesen   
 bPhase.x.Signal_A = IS_SET_MOT1_SIG_A ? true : false;   
 // Signal B einlesen   
 bPhase.x.Signal_B = IS_SET_MOT1_SIG_B ? true : false;   
  
  // Schrittweite aus Tabelle auslesen   
 iStep = aSteps[bPhase.bRow];   
 if (iStep != ENC_INV)   
 {   
  lEncoder += iStep;   
 }   
 else  
 {   
  lError++;   
 }   
}
Das Problem:
Wenn ich jetzt die Geschwindigkeit des Motors über 2000Upm hoch drehe kommen immer mehr Fehler (lError steigt), bis keine Auswertung mehr möglich ist. Ist der µC zu langsam für die Aufgabe? Oder kann man ihn noch etwas endlasten, wir ISR in Assembler oder Vorteiler?

Vielen Dank schon mal für eure Mühe
Guß Xaver