PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Menüsteuerung mit Drehencoder ?



Blamaster
05.06.2009, 12:13
Hi,

ich versuche gerade mit diesem Drehencoder:

http://www.pollin.de/shop/shop.php?cf=detail.php&pg=NQ==&a=MDY2OTU3OTk=

eine Menüsteuerung zu programmieren. Mein Code dafür sieht bisher so aus:



Do
B = Encoder(pinc.7 , Pinc.6 , Links , Rechts , 1)

Select Case M_pointer

Case 1:
Cls
Locate 1 , 1
Lcd "> Programm 1"
Locate 2 , 1
Lcd "Programm 2"

Case 2:
Cls
Locate 1 , 1
Lcd "> Programm 2"
Locate 2 , 1
Lcd "Programm 3"

Case 3:
Cls
Locate 1 , 1
Lcd "> Programm 3"
Locate 2 , 1
Lcd "Programm 4"

Case 4:
Cls
Locate 1 , 1
Lcd "> Programm 4"
Locate 2 , 1
Lcd "Programm 1"

End Select

Loop

Rechts:
If M_pointer < 5 Then
Incr M_pointer
Else
M_pointer = 1
End If

waitms 10
Return

Links:
If M_pointer < 5 Then
Decr M_pointer
Else
M_pointer = 4
End If
Waitms 10
Return


Mein Problem ist nun, dass der Encoder die Links bzw. Rechts Sub 2x pro Rastpunkt aufruft.

Wenn ich also nach rechts drehe wird immer jeder 2. Menüpunkt angezeigt, also einer übersprungen.

Weiß jemand woran das liegt, bzw wie man es beheben kann ?

mfg Yannic

MelMan
05.06.2009, 12:24
Kommt das vllt durch Prellen des Drehcoders? Versuch mal eine längere Waitpause vllt gehts dann. Und musst du nicht beim Linksmenu auf < 1 abfragen?

Blamaster
05.06.2009, 12:37
Hi,

die If Abfrage stimmt so schon.

Ich habe jetzt die waitms nochmal auf 50 erhöht und auch ein Waitms 50 in die Do Loop Hauptschleife gesetzt.

Er zählt immernoch doppelt.

vklaffehn
05.06.2009, 13:44
Moin!
Zählt er immer doppelt? Dann teil doch durch 2, mach ich bei meinem MiniPanoBot auch, der zählt immer 4 Impulse...
MfG
Volker

Blamaster
05.06.2009, 14:18
Jap er zählt soweit ich das richtig sehe immer doppelt. Durch
teilen möchte ich nur ungern, denn falls mal ein Impuls verloren geht würde das Programm durch ungerade zahlen komplett durcheinanderkommen.

Ich habe gerade nach etwas suchen noch diesen thread hier gefunden:

https://www.roboternetz.de/phpBB2/viewtopic.php?p=180862

Dort schien es um das ähnliche Problem zu geben, nur irgendwie kann ich noch nicht ganz erkennen ob aus diesem Thread nun eine Lösung für das "problem" hervor ging.

for_ro
05.06.2009, 14:35
Hi,

die If Abfrage stimmt so schon.


Nein, die If-Abfrage macht nicht das, was du möchtest.
Stell dir vor, M_pointer steht auf 0 und du drehst links.
Da M_pointer < 5 ist, wird Decr M_pointer ausgeführt.
Damit wird M_pointer=-1 oder 255, je nachdem, welcher Typ es ist.
Egal was, kein Case wird zutreffen.
Wenn M_pointer=4 ist und du drehst rechts, wird M_pointer auf 5 gesetzt, weil es vorher < 5 war. Auch in diesem Fall trifft kein Fall zu.
Deine Abfragen müssten also <4 und >1 sein.

Beides erklärt aber dein 2-fach Problem noch nicht.
Hast du die PullUps eingeschaltet oder extern welche dran?

Gruß

Rolf

Blamaster
05.06.2009, 14:44
Hi,

es sind externe 10k Pulldowns dran.

Stimmt mit der If hast du recht, aber wie schon gesagt löst das leider das eigentliche Problem nicht.

for_ro
05.06.2009, 14:54
Laut dem anderen Thread war es zumindest in der damaligen Version so, dass für jede Flanke die Routine zweimal aufgerufen wurde. Dann wäre die Krücke /2 ok.

Gruß

Rolf

Blamaster
05.06.2009, 15:04
Hm meiner Meinung nach kann die Krückemit /2 aber nicht funktionieren, denn wenn ich das richtig sehe wird die Sub Rechts bzw. Links 2 mal aufgerufen somit würde mal angenommen man startet bei 0 durch einen Rechtsdreh 1. Aufruf 1/2 = 0,5 2. Aufruf 1,5/2 = 0,75 also nur noch "mist" bei rauskommen.

Gibt es zufällig eine Beschreibung wie man den Drehencoder manuell abfragen könnte um das Problem zu lösen, bzw. andere Lösungsansätze mit denen ich arbeiten könnte ?

mfg Yannic

Edit. aus dem Bascom Beispiel hatte ich es so übernommen das man dem byte B die Encoder funktion "zuweist". Was übergibt die Funktion überhaupt an das Byte B ?

for_ro
05.06.2009, 16:35
1. Aufruf 1/2 = 0,5 2. Aufruf 1,5/2 = 0,75 also nur noch "mist" bei rauskommen.

ich glaube, das war eher so gemeint, dass du nur jeden zweiten Aufruf ausführen sollst.


Gibt es zufällig eine Beschreibung wie man den Drehencoder manuell abfragen könnte um das Problem zu lösen, bzw. andere Lösungsansätze mit denen ich arbeiten könnte ?

Du könntest die beiden Eingänge abfragen.
Bei 00 und 11 merkst du dir den Zustand.
Bei 01 und 10 setzt du eine Variable für die entsprechende Richtung, abhängig vom vorher gemerkten Zustand.
Bei 00 oder 11 und vorher die richtige Variable gesetzt, hast du einen kompletten Wechsel erkannt und führst die zugehörige Bewegung aus.
Es sind dann Wechsel wie 00-10-00 geblockt, während 00-10-11 erkannt wird.
Um die Drehung auch etwas schneller machen zu können, kannst du die Eingänge auf externe Interrupts legen und die Abfragen in der ISR machen. Dann kannst du auch noch etwas anderes tun als nur die Pins abfragen.

Gruß

Rolf

Blamaster
05.06.2009, 17:23
Hi,

Danke für die Hilfe, dass hört sich ja schonmal gut an :)

Ich habe gerade noch ein Codebeispiel gefunden in dem ich etwas nicht verstehe und somit nochmal auf meine Frage im Edit zurück komme.



_encoder = Encoder(pinc.7 , Pinc.6 , Links , Rechts , 1)
.
.
.
Rechts:
While Auswahl < 5 And _encoder = 2
Incr Auswahl
_encoder = 3
Waitms 50
Wend
Return


Wozu dort das "And _encoder = 2" in der Sub ?

mfg Yannic

Rone
05.06.2009, 20:06
Hallo!

Wenn Du ein LCD am µC hängen hast, lass Dir die Variable
_encoder oder B oder wie auch immer anzeigen.
Wenn Du den Encoder ganz langsam drehst, zeigt Dir das Display
3 2 1 0 (sehr wahrscheinlich nicht in dieser Reihenfolge).
Ist ganz einfach nur der Zustand der beiden Pins an denen der Encoder
hängt.
Wenn ich mich jetzt nicht ganz irre macht dieser Encoder zwei Schritte,
dann folgt eine Rastung, wieder zwei Schritte, eine Rastung usw.

Das alles brauchst Du jetzt nur mehr auswerten.
Der Encoder Befehl verträgt allerdings keine schnellen Drehungen.

MfG
Rone

StevieL
05.06.2009, 20:50
Hallo,

ich habe auch so einen ähnlichen Encoder. Ich löse das über eine Bit-Variable:



Dim X As Byte
Dim Encbit As Bit

links:
Toggle Encbit
If Encbit = 1 Then
decr X
End If
Return
rechts:
Toggle Encbit
If Encbit = 1 Then
incr X
End If
Return

Blamaster
05.06.2009, 22:16
Hi,

wie ich rausgefunden habe geht es mit einem

If B = 1 Or B = 2 Then in den Subs für Links und Rechts. Wieso das so ist kann ich zwar noch nicht ganz nachvollziehen, aber hausptsache ist ja das es so geht.

Würde mich aber natürlich über eine Erklärung zum verständnis freuen :)

mfg Yannic

peterfido
07.06.2009, 09:45
Die Encoder-Routine hat bei mir noch nie zufriedenstellend funktioniert.

Ich nutze sehr zuverlässig folgendes:


Dim Drehung As Integer

Dim Linksrechts As Byte
Links Alias Pind.3
Rechts Alias Pind.4


do
Gosub Rad
.
.
.
.

loop
end

Rad:
If Linksrechts = 0 Then
If Links = 0 And Rechts = 1 Then
Linksrechts = 1
End If
If Rechts = 0 And Links = 1 Then
Linksrechts = 11
End If
End If
If Linksrechts = 1 And Links = 0 And Rechts = 0 Then
Linksrechts = 0
Drehung = 0 - 1
End If



If Linksrechts = 11 And Links = 0 And Rechts = 0 Then
Linksrechts = 0
Drehung = 1
End If

If Links = 1 And Rechts = 1 Then Linksrechts = 0



Return


Der Encoder zieht die PINS auf GND. bei links und rechts werden die pullups aktiviert.

screwdriver
07.06.2009, 09:46
Ich habe auch bei einem Bastelprojekt mal einen (Billig-)Encoder von Pollin eingesetzt. Mittlerweile benutze ich wieder Tasten.

Zur Erklärung:
Die Encoder haben zwei Signalausgänge, namentlich A und B. Durch drehen ergibt sich folgender Signalwechsel (siehe auch Datenblatt zu deinem Encoder)

Rechtsrum: (A,B)= (1,1)-(0,1)-(0,0)-(1,0) usw.
Linksrum: (A,B)= (1,1)-(1,0)-(0,0)-(0,1) usw.

Dein Modell durchläuft auch alle diese Signalzustände, rastet jedoch nur in den Zuständen A=B, also (0,0) und (1,1) ein.
Es gibt aber auch Encodermodelle, die bei allen vier möglichen Zuständen einrasten, und dafür wurde die Encoder-Funktion von Bascom auch geschrieben.

Ich habe auch mit der Encoderfunktion ein bischen rumgespielt bin aber dann bei einer selbstgeschriebenen Funktion gelandet. Obwohl die auf der Benutzung von externen Interrupts basiert (was zwar von den Profis zu Recht verpöhnt wird) fahre ich damit eigentlich ganz gut. Ich mußte jedoch die Kontakte durch RC-Glieder entprellen.

Das ganze sieht dann etwa so aus:





Config Int2 = Falling 'Ph_a an ext. Int2
On Int2 Isr_int2
Enable Int2
Enable interrupts

Dim Rotary as byte 'Bit0= Ph_a, Bit1= Ph_b
Dim Enc_down as bit 'Flag Runterzählen
Dim Enc_up as bit 'Flag Hochzählen
Dim Encoderstand as byte

'Hauptprogramm
Do
If Enc_down=1 then
reset Enc_down
if Encoderstand>0 then decr Encoderstand
Elseif Enc_up=1 then
reset Enc_up
if Encoderstand<255 then incr Encoderstand
Endif
Loop
End.

Isr_int2: 'Externer Interrupt von Ph_a
Rotary.0 = Ph_a 'Signal A lesen
Rotary.1 = Ph_b 'Signal B lesen
Rotary = Rotary And &B00000011
If Rotary = 0 Or Rotary = 3 Then 'Ph_a = Ph_b
Set Enc_down
Else
Set Enc_up
End If
Toggle Mcucsr.isc2 'Umschaltung steigende/fallende Flanke Int2
Return

screwdriver
28.06.2009, 08:25
Das Thema Drehgeber ließ mir nun doch keine Ruhe mehr. Also habe ich einen von diesen (Billig-)Drehgeber von Pollin (Best.Nr. 240 313) ausgekramt und an mein AVR-Bastelboard nach angehängtem Plan angeschlossen.

R1 ist lediglich ein Schutzwiderstand, falls einer der Eingänge PD4..PD6 versehentlich doch mal als Ausgang konfiguriert ist. Es befinden sich bis auf die aktivierten internen PullUp-Widerstände des AVR keine weiteren Bauteile (zwecks Entprellung) im Signalweg des Dreh-Encoders.

Wie ich schon im vorigen Post schrieb, setze ich diesen Drehgebertyp in einem Projekt in der von dort beschriebenen Weise mittels externem Interrupt ein. Das Prinzip und auch der Nachteil dieser Lösung ist, dass jeder Signalwechsel am Interrupteingang die zugehörige Interrupt-Service-Routine (ISR) ausführen lässt. Was heute noch scheinbar einwandfrei funktioniert, kann bei einem ausgelutschtem Drehgeber mit ggf. starkem Kontaktprellen zu einer unkontrollierbaren Prozessorlast führen. Aus diesem Grund werden in Expertenkreisen generell Kontakte mittels einer Timer-Interrupt gesteuerten Routine entprellt.

Die Bascom-eigene Lösung mit dem Encoder-Befehl arbeitete bei mir noch nie zufriedenstellend - egal ob in der Hauptprogrammschleife oder per Timerinterrupt ausgeführt - traten immer Sprünge oder Impulsverluste am Drehgeber auf. Daraufhin habe ich die untenstehende Lösung ausgearbeitet. Beim Testen konnte ich bisher absolut keine Fehler erkennen. Kritik und Verbesserungsvorschläge sind gerne willkommen.

Lösungsweg:
Zur Entprellung werden die beiden Drehgebersignalpaar (A,B) alle 0.5ms in der Timer0-ISR abgefragt und im Schieberegister-Byte ROTARY im Format AAAABBBB abgelegt. Nur wenn alle A's und alle B's gleich sind, also (0000_0000), (0000_1111), (1111_1111) oder (1111_0000) gilt das Encodersignalpaar als stabil.

Außer dem Kontaktprellen besitzt dieser Drehgebertyp aber noch ein weiteres zu beseitigendes Übel:
Grundsätzlich stehen in den Rastungen des Drehknopfes die Signalpaarungen (A,B)=(0,0) bzw. (A,B)=(1,1) stabil an. Einige der 16 Rastungen sind aber so unpräzise, das schon durch bloßes Anfassen des Drehknopfes ein Signalwechsel zu (A,B)=(1,0) bzw. (A,B)=(0,1) und beim Loslassen wieder zurück nach (A,B)=(0,0) bzw. (A,B)=(1,1) erfolgt. Dies wird in vielen Routinen (so auch in meiner vom Externen Interrupt gesteuerten Routine) fälschlicherweise als Drehbewegung des Knopfes interpretiert.

Um diesen Fehler zu beheben muß eine Encoderauswertung drei aufeinanderfolgende Signalpaarungen berücksichtigen. Bei mir geschieht das mittels den Variablen
ROTARY: Signalpaarung (A,B) in der aktuellen Rastung
ROTARY1: (A,B) im Übergang zwischen zwei Rastungen (Drehrichtungserkennung)
ROTARY2: Signalpaarung (A,B) in der vorherigen Rastung

Befindet sich der Drehknopf in der Rastung mit (A,B)=(0,0) bzw. (A,B)=(1,1) so muß bei einer Drehung um eine Rastung anschliessend genau die entgegengesetzte Signalpaarung vorliegen, nämlich (A,B)=(1,1) bzw. (A,B)=(0,0). D.h. eine Drehbewegung kann nur stattgefunden haben wenn ROTARY ungleich ROTARY2 ist. Abhängig von der Signalpaarung ROTARY1 beim Übergang zwischen den Rastungen (A,B)=(0,1) bzw. (A,B)=(1,0) wird die Drehrichtung erkannt.
Zur Auswertung des Encoders werden nach vollzogener Rastung entsprechend der Drehrichtung die Flags R_Flag bei Rechtsdrehung und L_Flag bei Linksdrehung gesetzt und der Encoderwert ROTARY_VALUE bei Rechtsdrehung inkrementiert bzw. bei Linksdrehung dekrementiert und können in der Hauptprogrammschleife abgefragt und zurückgesetzt werden.



'************************************************* ******************************
'*** Testprogramm für POLLIN Dreh-Encoder PANASONIC EVEQDBRL416B ***
'*** Best.Nr. 240 313 ***
'************************************************* ******************************
'*** Author: Screwdriver ***
'*** Datum: 28.06.2009 ***
'************************************************* ******************************

'************************************************* ******************************
'*** Konfiguration ***
'************************************************* ******************************
'AVR
$regfile = "m644def.dat"
$crystal = 20e6

'System-Timer für periodische Encoder-Abfrage
Config Timer0 = Timer , Prescale = 256
On Timer0 Isr_timer0
Enable Timer0
Const Timer0_reload = 217 'Wert für 0.5ms

'Drehencoder
Config Portd.4 = Input : Set Portd.4 : Rotary_button Alias Pind.4 'Taste
Config Portd.5 = Input : Set Portd.5 : Ph_a Alias Pind.5 'Encoder Signal A
Config Portd.6 = Input : Set Portd.6 : Ph_b Alias Pind.6 'Encoder Signal B

'************************************************* ******************************
'*** Variablen ***
'************************************************* ******************************
'Variablen
Dim Rotary As Byte 'Aktuelles Rasterwert (A,B)
Dim Rotary1 As Byte 'Übergangswert (A,B) zwischen Rastungen
Dim Rotary2 As Byte 'Letzter Rasterwert (A,B)
Dim R_flag As Bit , L_flag As Bit 'Flags für Links- / Rechtsdrehung
Dim Rotary_value As Byte 'Zahlenwert des Encoders

Dim Rotary_key As Byte : Rotary_key = &HFF 'Schieberegister Taste, &HFF: nicht gedrückt
Dim Press_flag As Bit 'Flag Taste wurde gedrückt
Dim Release_flag As Bit 'Flag Taste wurde losgelassen

'************************************************* ******************************
'*** HAUPTPROGRAMM ***
'************************************************* ******************************

Enable Interrupts

Do
'Beispiel zur Auswertung der Flags und des Encoder-Werts im Hauptprogramm
If R_flag = 1 Then 'Drehung nach Rechts
Reset R_flag
Print "Rechts"
Print Rotary_value
End If
If L_flag = 1 Then 'Drehung nach Links
Reset L_flag
Print "Links"
Print Rotary_value
End If
If Press_flag = 1 Then 'Taste wurde gedrückt
Reset Press_flag
Print "gedrueckt"
End If
If Release_flag = 1 Then 'Taste wurde losgelassen
Reset Release_flag
Print "losgelassen"
End If
Loop
End

'************************************************* ******************************
'*** ISR_TIMER0 ***
'*** Periodische Auswertung des Dreh-Encoders ***
'************************************************* ******************************
Isr_timer0:
Timer0 = Timer0_reload

Shift Rotary , Left , 1 'Schieberegister für Entprellung (A,B)
Rotary.4 = Ph_a 'Phase A lesen -> Bit 4
Rotary.0 = Ph_b 'Phase B lesen -> Bit 0

If Rotary <> Rotary2 Then 'Neues Signalpaar (A,B) ?
Select Case Rotary
Case &B0000_0000 'Aktuell (A,B)= (0,0)
If Rotary1 = &B1111_0000 Then 'Übergang war (A,B)= (1,0), also
Set R_flag 'Rechtsdrehung
Incr Rotary_value 'Encoder-Wert erhöhen
Elseif Rotary1 = &B0000_1111 Then 'Übergang (A,B)= (0,1), also
Set L_flag 'Linksdrehung
Decr Rotary_value 'Encoder-Wert verringern
End If
Rotary2 = &B0000_0000 'Aktuelles (A,B) in vorheriges (A,B)
Case &B0000_1111 'Übergang (A,B)= (0,1) zwischen Rastungen
Rotary1 = &B0000_1111 'erkennen und in abspeichern
Case &B1111_0000 'Übergang (A,B)= (1,0) zwischen Rastungen
Rotary1 = &B1111_0000 'erkennen und abspeichern
Case &B1111_1111 'Aktuell (A,B)= (1,1)
If Rotary1 = &B0000_1111 Then 'Übergang war (A,B)= (0,1), also
Set R_flag 'Rechtsdrehung
Incr Rotary_value 'Encoder-Wert erhöhen
Elseif Rotary1 = &B1111_0000 Then 'Übergang war (A,B)= (1,0), also
Set L_flag 'Linksdrehung
Decr Rotary_value 'Encoder-Wert verringern
End If
Rotary2 = &B1111_1111 'Aktuelles (A,B) in vorheriges (A,B)
End Select
End If

Shift Rotary_key , Left , 1 'Schieberegister für Entprellung Taste Encoder
Rotary_key.0 = Rotary_button 'Taste lesen -> Bit 0

If Rotary_key = &B1000_0000 Then 'Taste wurde gedrückt
Set Press_flag
Elseif Rotary_key = &B0111_1111 Then 'Taste wurde losgelassen
Set Release_flag
End If
Return

kesi
28.06.2009, 13:57
@screwdiver

Hab Deinen Code gerade mal an meinen Atmega8 angepasst und muß sagen "das läuft super!".
Keinerlei Aussetzer, einfach geschmeidig.
Wenn mir jetzt noch jemand erklären könnte wie ich das für andere Encoder zB. http://www.watterott.com/download/PEC12-1.pdf
anpassen kann dann wäre ich echt happy!?

Grüße,
kesi

stefan_Z
28.06.2009, 16:54
Andere Encoder brauchen das ja nicht, weil sie weniger schrottig sind - bzw. man weiß ja nicht genau, was der Encoder von Pollin im früheren Leben mal war - ggfs. was spezielles.

Hat schonmal jemand den anderen Encoder von Pollin getestet?
http://www.pollin.de/shop/shop.php?cf=detail.php&pg=NQ==&a=MDY2OTU3OTk=
Sieht gut aus....

screwdriver
28.06.2009, 18:43
@kesi
Danke, für Deine Rückmeldung. Hast Du da jetzt den gleichen Drehgeber wie ich angeschlossen oder einen anderen?



Wenn mir jetzt noch jemand erklären könnte wie ich das für andere Encoder zB. http://www.watterott.com/download/PEC12-1.pdf
anpassen kann dann wäre ich echt happy!?

Das Datenblatt ist nicht ganz eindeutig. Meine Timer-Interrupt-gesteuerte Lösung ist für alle Drehgeber, die nur bei jedem zweitem Signalwechsel einrasten passend, und meiner Meinung nach auch notwendig. Ob Dein genannter Drehgeber so einer ist, geht nicht klar aus dem Datenblatt hervor.

@stefan_Z


Andere Encoder brauchen das ja nicht, weil sie weniger schrottig sind - bzw. man weiß ja nicht genau, was der Encoder von Pollin im früheren Leben mal war - ggfs. was spezielles.

Leider doch.
Auch der von Dir alternativ genannte Drehgeber rastet nur in den Stellungen 00 und 11 ein. Eine sichere Auswertung verlangt dann - auch bei einem noch so hochwertigem Drehgeber - die Berücksichtigung der letzen drei Signalpaare. Die üblichen Routinen machen das nicht. Sieht aber wirklich edler aus, das Teil.

kesi
28.06.2009, 19:10
@kesi
Danke, für Deine Rückmeldung. Hast Du da jetzt den gleichen Drehgeber wie ich angeschlossen oder einen anderen?

Ja das habe ich mit dem gleichen getested. Klappt wie gesagt "geschmeidig"!
Vielen Dank für Deinen Code. Das ist das beste was ich dazu bisher gefunden habe! O:)



Das Datenblatt ist nicht ganz eindeutig. Meine Timer-Interrupt-gesteuerte Lösung ist für alle Drehgeber, die nur bei jedem zweitem Signalwechsel einrasten passend, und meiner Meinung nach auch notwendig. Ob Dein genannter Drehgeber so einer ist, geht nicht klar aus dem Datenblatt hervor.


Ja, das Problem bei dem ist das die Drehungen doppelt gezählt werden!?




Leider doch.
Auch der von Dir alternativ genannte Drehgeber rastet nur in den Stellungen 00 und 11 ein. Eine sichere Auswertung verlangt dann - auch bei einem noch so hochwertigem Drehgeber - die Berücksichtigung der letzen drei Signalpaare. Die üblichen Routinen machen das nicht. Sieht aber wirklich edler aus, das Teil.

voll und ganz meine Meinung. Alle von mir bisher getesteten im "Billigpreissegment" sind mindestens genauso "schrottig"! O:)

screwdriver
28.06.2009, 20:01
@kesi

Ja, das Problem bei dem ist das die Drehungen doppelt gezählt werden!?

Also vorausgesetzt, der im Datenblatt beschriebene Encoder rastet bei jeder Signalpaarung ein, müßte der bei meinem Timer-gesteuerten-Code zwei Rastungen brauchen um eins weiterzuzählen.
Oder ich versteh' jetzt meinen eigenen Code nicht mehr? ;-)

So einen Typen kann man leider nicht per Software sicherer abfragen, weil hier eben jeder Signalwechsel eine gültige Rasterstellung ist, bzw. sein muß.
Ggf. könnte mann die Signalentprellung aus meinem letzten Code übernehmen und dann die Auswertung der Signalzustände wie in meinem Externen-Interrupt-gesteuerten Code machen. Dann ist man aber auch nicht besser bedient wie bei anderen Auswerte-Routinen auch.

Fazit: Bei Drehgebern, die bei jedem Signalwechsel einrasten, ist die Fehlerhäufigkeit direkt von der Herstellerqualität abhängig. Per Software läßt sich da meines Erachtens nichts mehr verbessern.

screwdriver

PICture
28.06.2009, 21:17
Hallo!

Ich kann dem screwdriver nur zustimmen. Ich hatte schon mehrere Drehgeber probiert und habe z.B. unsymmetrie festgestellt, d.h. zwischen zwei stabilen Einrastungen werden z.B. beim Linksdrehen 1 und Rechtstdrehen 2 Impulse gezählt. Am schlimmsten finde ich, dass es zwischen Drehgeber von gleichem Typ Unterschiede gibt.

MfG

screwdriver
30.06.2009, 21:00
Dann kannst du auch noch etwas anderes tun als nur die Pins abfragen.
Rolf gibt hier zu Recht zu bedenken, dass der Rechenaufwand für eine Encoderauswertung nicht gerade unerheblich ist. Auch wenn mein Beispielprogramm zur Encoderauswertung "geschmeidig" läuft - nun ja, es macht ja auch nichts anderes!
Also habe ich mein Beispielprogramm im Simulator laufenlassen um mal ein paar Zyklen zu zählen.
Die gesamte ISR zur Encoderauswertung braucht im ungünstigsten Fall (Rotary=FF, Rotary1=0F, Rotary2=00) inklusive Auswertung der Encodertaste sowie Pushen/Poppen 197 Prozessortakte. Das sind 197/(20MHz)= 9,85µs.
Wenn diese 10µs alle 0,5ms ausgeführt werden habe ich eine Prozessorauslastung von rund 10µs/500µs= 2%. Im Mittel sinds vermutlich 1% oder weniger. Ist also nicht so viel.

Aber die eigentliche Frage lautet doch:
Kann ich es meinem AVR erlauben sich ganze 10µs ausschließlich der Encoderauswertung zu widmen und alles drumrum zu vernachlässigen?

MFG
screwdriver

kesi
30.06.2009, 21:59
Aber die eigentliche Frage lautet doch:
Kann ich es meinem AVR erlauben sich ganze 10µs ausschließlich der Encoderauswertung zu widmen und alles drumrum zu vernachlässigen?

MFG
screwdriver

ja, aber muß man es denn ständig laufen haben?
Kann ich nicht erst durch einen Druck auf den Taser via Int. in eine
Subroutine springen und hier dann meine Einstellungen tätigen und dann wieder zurück. Die eigentliche Encoderauswertung muß doch nur dann laufen wenn ich Änderungen vornehmen will und nicht ständig im Hintergrung!?

Fragende Grüße?

screwdriver
30.06.2009, 22:34
ja, aber muß man es denn ständig laufen haben?
Kann ich nicht erst durch einen Druck auf den Taser via Int. in eine
Subroutine springen und hier dann meine Einstellungen tätigen und dann wieder zurück. Die eigentliche Encoderauswertung muß doch nur dann laufen wenn ich Änderungen vornehmen will und nicht ständig im Hintergrung!?


Einen Drehgeber an einen µC pappen und ein bischen rumspielen ist eine Sache, ein Drehgeber in eine µC-Applikation integeriert, die als Hauptaufgabe auch "was anderes macht", wie
Impulse verarbeiten (DCF-77, Durchflußmesser, etc) oder
serielle Kommunikation,
Nulldurchgangserkennung usw. usw.
ist was ganz anderes.

Es ist also egal, ob die Encoderauswertung alle 0.5ms oder einal am Tag für 10s ausgeführt wird. Ihre Ausführungsdauer muß immer so kurz sein, dass sie die anderen vom µC zu bewältigen Arbeiten nicht beeinträchtigt.

Gute Nacht,
screwdriver