PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Optischen Drehencoder auswerten ohne Interrupt?!



Janiiix3
14.09.2014, 12:51
Hallo,

Ich möchte gerne meinen optischen Drehencoder auswerten.
Dafür habe ich dieses mal keinen Interrupt genommen sondern habe ihn direkt an den PORTD angeschlossen (Bit 0 & 1)

Nun habe ich das Problem, die Drehrichtung richtig auszuwerten.
Kann mir dort jemand weiterhelfen?

Mein Code :



Enc_State_new = (PIND & 0b00000011);

if (Enc_State_new != Enc_State_old)
{
Enc_Counter++;
}
Enc_State_old = Enc_State_new;


Jetzt wird "hochgezählt" egal in welcher Drehrichtung.

PICture
14.09.2014, 13:01
Hallo!

Hoffentlich hilft's: http://rn-wissen.de/wiki/index.php/PIC_Assembler#Mausrad_bzw._Drehencoder . :confused:

Janiiix3
14.09.2014, 13:04
Sorry...

Von "PIC´s & ASM" habe ich noch weniger Ahnung.

PICture
14.09.2014, 13:11
Du solltest nur den von µC und Programmierungsprache unabhängigen Programmablaufdiagram (PAD) genau anschauen. ;)

oberallgeier
14.09.2014, 16:54
/*Ich möchte gerne die Welt verändern, doch Gott gibt den Quelltext nicht frei.*/Deshalb untersuchen, forschen, testen und experimentieren wir ja - auf IT heißt das sozusagen: Disassemblierern des Quellcodes.


... Von "PIC´s & ASM" habe ich noch weniger Ahnung.Wie schon PICture meint: das Arbeitsschema sagt ja alles in Kürze, und das sollte man können/kennen. Der Informationsauswertung bleibt die verwendete Programmiersprache nämlich ziemlich egal. Aber vielleicht nutzt Dir meine Lösung für nen magnetischen Encoder (https://www.roboternetz.de/community/threads/65601-Arduino-Leistungsf%C3%A4hig-genug-6-Schrittmotoren-Inkrementalgeber?p=604655&viewfull=1#post604655) (der Information bleibts ziemlich egal, ob die Abtastung magnetisch, optisch oder mit nem Stöckchen erfolgt).

Peter(TOO)
14.09.2014, 17:11
Hallo,

So gehts auch nicht ;-)

Du musst den einen Kanal nehmen und dort die Flanke suchen, welche ist egal, aber immer die selbe.
Dann bestimmt der zweite Kanal obs rauf oder runter geht, je nachdem ob der 0 oder 1 ist.
http://rn-wissen.de/wiki/index.php/Beispiel_Drehzahlmessung_mit_Drehgeber#Zwei_Lichts chranken_liefern_vier_Zust.C3.A4nde



Enc_State_new = (PIND & 0b00000011);
if ( (((Enc_State_new ^ Enc_State_old) & Enc_State_new) & 0x01) )
{
if ( Enc_State_new & 0x02 )
Enc_Counter++;
else
Enc_Counter--;
}
Enc_State_old = Enc_State_new;


MfG Peter(TOO)

Janiiix3
14.09.2014, 17:31
Das bringt nicht wirklich was. Das gleiche habe ich mit meinem Code auch bezweckt ^^

Egal ob ich jetzt "links" oder "rechts" drehe... er zählt hoch (++)

oberallgeier
14.09.2014, 17:54
Das bringt nicht wirklich was. Das gleiche habe ich mit meinem Code auch bezweckt ... Egal ob ich jetzt "links" oder "rechts" drehe ...Im Prinzip hast Du dieses Informationsmuster wie unten dargestellt. Ich bezeichne mal einen Kanal als A, Yellow, den andern als Kanal B, White (z.B. die Kabelfarben *gg*) :


-------+ +----------------+ +----------------+
| Kanal A, yellow | | Kanal A, yellow | |
+-----------------+ +------------------+ +
Rechtslauf (math neg) >>> <<<<<<<< Linkslauf (math pos)
---------------+ +-----------------+ +---------
| Kanal B, white | | Kanal B, white |
+----------------+ +------------------+
--------------------- Pegelzustände A/B direkt darüber sind : -----------------
LH low/high LL HL HH LH LL HL HH

Du siehst, dass die Zustände beim Vergleichen der beiden Kanäle (stets auf EIN UND DENSELBEN!! zuerst schauen) je nach Drehrichtung unterschiedliche Pegelfolgen entstehen. Prüfen wir mal Kanal A auf steigende Flanke und schauen auf Kanal B - wenn wir die steigende Flanke entdecken. Steht beim Erreichen/Überfahren der steigenden Flanke von A der Kanal B auf low, dann hast Du in diesem Schema Rechtslauf. Steht beim Erreichen/Überfahren der steigenden Flanke von A der Kanal B auf high dann hast Du in diesem Schema Linkslauf *ggg*.

Ist das so verständlich ?

Janiiix3
14.09.2014, 18:51
Ja klar, verstehen tuh ich das...
Ich bekomme es halt nicht ordentlich in "C" umgesetzt.

oberallgeier
14.09.2014, 18:56
Ja klar, verstehen tuh ich das ... bekomme es halt nicht ordentlich in "C" umgesetzt.Sagen wir mal so - wenn ich Dir nen Link sende, dann liest Du das Zeugs nicht durch :-/

Janiiix3
14.09.2014, 19:01
Doch habe ich. verstehe allerdings nur "Bahnhof"...

Wo ist bei dir denn die Auswertung der "Phasen" ?

- - - Aktualisiert - - -

Doch habe ich. verstehe allerdings nur "Bahnhof"...

Wo ist bei dir denn die Auswertung der "Phasen" ?

oberallgeier
14.09.2014, 19:10
Doch habe ich. verstehe allerdings nur "Bahnhof" ... Wo ist ... die Auswertung der "Phasen" ?Was hast Du denn gelesen?

Janiiix3
14.09.2014, 19:12
// === Nicht unterbrechbare ISR für timer2 =================================== */ // Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für // EXT_INT0 und -INT1 ausgelesen ISR(TIMER2_COMPA_vect) // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { // Izeit_1 --; // ###>>> Izeit_1 ist aktuell int16_t ==>> // Izeit_1 bleibt bis 32000 in der int16-Grenze tupUM0 ++; // Tupsicounter für Umdrehungsmessung(en) tmrE0 ++; // Encodertimer hochtickern tmrE1 ++; // Encodertimer hochtickern //RCzeit1 ++; // Tupsicounter uint16_t für RC-5-Decoding if ( Izeit_1 ) // Interrupt-Timer = 1 ... 20 000 ... (1 sec blink) { } // WENN Izeit_1 =|= Null => wahr => Anweisung ausgeführen else // Izeit_1 = Null = unwahr, daher "else" ausführen { // Eine Sekunde ist voll => Izeit_1 = Izthrznt; // ansonsten: Rückstellen auf Zeithorizont ToggleBit (PgLED, L1g); // gnLED toggeln HEARTBEAT <<####, aktuell PC1 Isecundn ++; // Sekundenzähler hochtackern, max 9 Std } // Ende if (Izeit_1 ) if (tmrE0 > 2000) // Grenzwert für Stillstand // ... usf

schorsch_76
14.09.2014, 19:30
Wenn du das ganze in [code] tags packst, bleibt es lesbar

oberallgeier
14.09.2014, 19:35
Da steht aber nur was von Encodertimern. Nimm mal die Zeilen:

// Encoderticks Iencdrx nur hochzählen, IencBx rauf- od runterzählen
Iz_diff0 = tmrE0; // Abspeichern Zeit seit dem letzten ISR-Aufruf
tmrE0 = 0; // Resetten ##>> IN der ISR ohne CLI/SEI möglich
Iencdr0 ++; // Incrementiere Encodercounter, zählt NUR aufwärts
if (IsBitSet (PIND, 4)) IencB0++; // Rad treibt vorwärts, math. negativ
else IencB0--; // Rad treibt rückwärts, math. positivin dem Fenster wo drüber steht: "Die vollständige ISR für (m)einen Encoder bei Archie ..." - das ist GENAU das Vorgehen wie weiter oben mit der Kanalskizze beschrieben.

Sisor
14.09.2014, 20:29
Nun habe ich das Problem, die Drehrichtung richtig auszuwerten.
Kann mir dort jemand weiterhelfen?




Enc_State_new = (PIND & 0b00000011);

unsigned char changedBits = Enc_State_old^Enc_State_new;
if(changedBits) {
if (Enc_State_new & 1)
if (changedBits == 1) Enc_Counter++;
else Enc_Counter--;
else
if (changedBits == 1) Enc_Counter--;
else Enc_Counter++;

Enc_State_old = Enc_State_new;
}