PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Encoder / Endlosdrehknopf in eine Richtung sehr ungenau



Spanky
03.09.2009, 22:10
Hiho,

ich hab seit längerem den Encoder von Pollin (Best.Nr. 240 313) hier rumliegen. Vorgestern hab ich den dann an meinen RP6 angeschlossen.

Gestern hab ich dann das Programm zum Auswerten der Drehrichtung fertig bekommen. Aber es ist ungenau.

Hier mal ein Ausschnitt aus dem Log:
Rechtsdrehung mit ca. 1 Raster / 500ms

Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Linksrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Rechtsrum
Sieht soweit ja ganz gut aus. Das eine ma falsch nehm ich in kauf.
Jetzt Linksrum:

Linksrum
Linksrum
Rechtsrum
Linksrum
Linksrum
Rechtsrum
Linksrum
Linksrum
Rechtsrum
Linksrum
Linksrum
Rechtsrum
Linksrum
Linksrum
Linksrum
Linksrum
Linksrum
Linksrum
Rechtsrum
Linksrum
Linksrum
Linksrum
Linksrum
Das wiederrum find ich net so gut.

Hier mein Code

#include "RP6ControlLib.h"

int main(void)
{
initRP6Control();

writeString_P("\n\nEncoder Testing\n");

// Play two sounds:
sound(180,80,25);
sound(220,80,25);

setLEDs(0b1111); // Turn all LEDs on!
initLCD();
showScreenLCD("################", "################");
mSleep(500);
showScreenLCD("Encoder Testing", "");
mSleep(1000);

DDRD &= ~IO_PD6; //PD6 als Eingang
DDRC &= ~IO_PC2; //PC2 als Eingang


setLEDs(0b0000); // All LEDs off!

uint8_t laststate = 0b111;

while(true) {

// Encoder auswerten

if(((PIND & IO_PD6) == 0b0) & ((PINC & IO_PC2) == 0b100) & (laststate != 0b01)) {
laststate = 0b01;
}

if(((PIND & IO_PD6) == 0b1000000) & ((PINC & IO_PC2) == 0b100) & (laststate != 0b11)) {
if(laststate == 0b01) {
writeString_P("Rechtsrum\n");
laststate = 0b111;
} else if(laststate == 0b10) {
writeString_P("Linksrum\n");
laststate = 0b111;
} else {
laststate = 0b11;
}
}


if(((PIND & IO_PD6) == 0b1000000) & ((PINC & IO_PC2) == 0b0) & (laststate != 0b10)) {
laststate = 0b10;
}


if(((PIND & IO_PD6) == 0b0) & ((PINC & IO_PC2) == 0b0) & (laststate != 0b00)) {
if(laststate == 0b10) {
writeString_P("Rechtsrum\n");
laststate = 0b111;
} else if(laststate == 0b01) {
writeString_P("Linksrum\n");
laststate = 0b111;
} else {
laststate = 0b00;
}
}

}
return 0;
}
Der Encoder gibt bei einer Rastung zwei Zustände von sich.
Und jeweils zwei verschiedene Zustände für jede Richtung.
Das lässt sich mit zwei Bit am besten Darstellen. Bit1 = PD6 | Bit2 = PC2
Zustand1 - Zustand2 bei einer Rastung.
1-Rechts: 01 - 11
2-Rechts: 10 - 00

1-Links: 10 - 11
2-Links: 01 - 00

Soviel zur Funktion des Encoders.

Ich bin mir nicht sicher ob das an meinem Programm oder am Encoder liegt.
Vielleicht kann man noch etwas verbessern / verändern. Bin für alles offen.

Gruß
Spanky

PicNick
04.09.2009, 10:06
Pass' bei den "IF"s auf.


if ((trallala == 1) && (hoppsassa == 1) ) // && statt & !!!!
{
}


etc.

Spanky
04.09.2009, 16:11
Danke
Ich hab mal Visual Basic gelernt. Da war das nur mit einem &

Habs jetzt geändert. Problem besteht weiterhin.
Ich vermute, das es am Encoder liegt, weils eben nur in eine Richtung so schlecht ist ...

Wenn noch einer ne Idee hat ...
Ansonsten muss ich mich halt damit abfinden.

BTW: Ist es normal das ich die Pins mit GND auf Low ziehen muss und nicht mit VCC auf High?

Gruß
Spanky

PicNick
04.09.2009, 16:42
--> BTW: Es geht beides. Da aber ein Mega eingebaute PullupWiderstände hat, wird gerne A, B auf zwei Pins gelegt, C auf GND.
(auf A u.B ev. noch zwei Kondensatoren 0.01 µF gegen GND, wegen entprellen)
Dann die Pullups für die Pins aufgedreht, Pins auf Input (logo) und sonst braucht man eigentlich nix.
Im Datenblatt gibt einen "TestCircuit", den kannst du natürlich auch nehmen, braucht aber eben extra Pullups.

sast
04.09.2009, 17:00
Wo setzt du denn die Pullups? Oder hast du die in der Hardware?

Interessant bezüglich Encodern ist auch http://www.mikrocontroller.net/articles/Drehgeber#Differenzierung_von_Drehgebern

sast

PicNick
04.09.2009, 17:00
Ich empfehle, die A u B Signal auf einen Wert zusammenzufassen, dann ist die Auswertung weniger verwirrend
z.B:


while (1)
{
newstate = 0;
if (PIND & IO_PD6) newstate |= 2; // A ist 0/1
if (PINC & IO_PC2) newstate |= 1; // B ist 0/1
if (newstate == laststate)
continue;
// jetzt enthält newstate die werte 0 , 1, 3, 2
switch (newstate)
{
case 0:
if (laststate == 2) "rechts"
else "links"
break;
case 1:
if (laststate == 0) "rechts"
else "links"
break;
case 3:
if (laststate == 1) "rechts"
else "links"
break;
case 2:
if (laststate == 3) "rechts"
else "links"
break;
}
laststate = newstate;
}



Links u. rechst muss man ev. je nach polarität auswechseln