Ich habe einen Dreh-Encoder, mit dem die Frequenz eines DDS-Generators
eingestellt werden soll. Nun soll man diese Frequenz einerseits auf
1 Hz genau eingeben können, andererseits ist das Teil so im Bereich
100 kHz bis 30 MHz benutzbar, man sollte also beim schnellen Drehen
am Rädchen schon auch maximal in 1-MHz-Schritten hüpfen können.
Meine ersten Versuche, sowas basierend auf Peters Encoder-Routinen
aufzusetzen, sehen erstmal nicht so glücklich aus. Hat jemand
eventuell sowas schon einmal gemacht und wäre gewillt, mir entweder
ein paar Zeilen Code dafür zu schenken oder kurz den gewählten
Algorithmus zu erläutern? Wenn sich's vermeiden lässt, würde ich
dafür ungern das Fahrrad nochmal erfinden.
Hallo Jörg!
Hab ich schonmal gemacht.
Ist aber schon ein paar Tage her und hab ich grad nicht zur Hand.
Schlummert in der Quellcodeverwaltung auf Arbeit.
Aber du kannst wie folgt vorgehen:
Du beachtest sowohl die Zählimpulse als auch die Drehgeschwindigkeit.
Also Impulse/Zeit.
Für kleine Drehgeschwindigkeiten des Enkoders gibst du für eine
präzise Sollwersteuerung die Impulse 1:1 weiter.
Ab einer bestimmten Schwelle gehst du zur Geschwindigkeitssteuerung
über. Die gewünschte Progression kannst du dann über eine Formel
oder lookup table einbringen.
Hoffe, das war einigermaßen verständlich rekapituliert... ;-)
Hi.
Ist nicht 100% was du suchst, aber du könntest auch einen Drehencoder
mit eingebautem Taster nutzen. Wenn man bei gedrücktem Taster dreht
gehts zb in 10er Schritten, sonst in einern...
Gruß
>Wenn man bei gedrücktem Taster dreht>gehts zb in 10er Schritten, sonst in einern...
Das reicht nicht bei so einem großen "Dynamikumfang" über
mehrere 10er Potenzen hinweg.
Eine progressiv arbeitende Steuerung ist da schon eine gute
Lösung, aber eben nicht einfach zu implementieren wenn sie
intuitiv bedienbar sein soll.
Ich denke mal nicht umsonst sieht man bei vielen Fertiggeräten
wie Frequenzgeneratoren oder "digitalen" Labornetzteilen eine
Sollwertvorgabe über 10er Tastatur oder Enkoder PLUS Tasten,
mit denen man die zu verändernde Vor- oder Nachkommastelle
auswählt.
Encoder mit Taste wär natürlich am einfachsten, davon abgesehen: Je
länger man in eine Richtung dreht, desto größer werden die Schritte wär
jetzt mein Alternativ-Vorschlag.
Kriegt man auch durch rumspielen schnell raus, man braucht keinerlei
weitere Taster und lässt sich leicht Programmieren.
Könnte man eventuell auch mit der Drehgeschwindigkeit des Encoders
kombinieren, wenn man schnell genug dreht gehts nochmal ums 50-fache
schneller.
>Je länger man in eine Richtung dreht, desto größer werden die>Schritte wär jetzt mein Alternativ-Vorschlag.
Wenn es sich nicht gerade um einen leicht laufenden Enkoder mit einem
Bedienrad mit Fingermulde handelt, das man ohne abzusetzen immer im
Kreis drehen kann, wird das auch schwierig.
Wenn du absetzen/umgreifen mußt, dann mußt du alles innerhalb einer
halben Umdrehung des Enkoders abhandeln.
Naja, vom Ansatz her würde ich es so machen:
1.) Timer mitlaufen lassen der einen Wert X (angefangen z.B. bei 6)
runterzählt bis 0
2.) Bei Betätigung des Encoder um 10^X hochzählen und X wieder auf den
Startwert setzen.
Um diese Dynamik zu bekommen, muß man dem Drehgeber eine Schwungmasse
verpassen. Dazu muß die Drehgeschwindigkeit ermittelt und auch gemittelt
werden, sodaß die Stellschritte nicht sofort kräftig erhöht werden,
sondern erst nach ca. 0,3 bis 0,5 Sekunden. Die Schwungmasse sorgt
dafür, dass auch mehrere Umdrehungen des Drehgebers in einem Rutsch
passieren und die Auswertung der Geschwindigkeit einen Sinn ergibt.
Optimal sind optische Drehgeber, die minimale Reibung aufweisen. Die
Auflösung sollte nicht zu klein. Für Einzelschritte werden die Impulse
z.B. durch 10 geteilt und für höhere Drehgeschwindigkeit vervielfacht.
Ganz wichtig ist, dem Drehgeber eine Hysterese zu verpassen, die
verzögert beim Stillstand einsetzt. Damit verhindert man ein Springen um
den letzten Schaltpunkt.
Meine Routinen würden Deinen Dynamikbereich nicht abdecken.
Hier mal etwas Code den ich immer verwende:
Die Beschleunigung erfolgt zwar nur etwa um den Faktor 200, aber das
kann man ja alles anpassen. Weiterhin ist der Code aus Sicht einiger
Leute hier im Forum ein schlimmes Verbrechen. Ich habe dagegen die
Erfahrung mit dem Pollin Panasonic Inkrementalgeber gemacht, dass der
Coder sehr viel besser funktioniert als der von Danegger. Bei dessen
Code hatte ich Sprünge, die ich mit diesem Code nicht habe. Dafür
erfordert dieser Code aber eine richtige Belegung der beiden Phasen,
damit der Interupt nicht um den Einrastpunkt herum erfolgt, sondern auf
dem "Hügel". Weiterhin sollte man eine Entprellung aus 10k 10nF
vorsehen.
Man benötigt dazu einen Timerinterrupt mit etwa 1kHz in dem die
Beschleunigungswerte berechnet werden (eventuell könnte man auch hier
den Inkrementalgeber samplen und auswerten, so wie in Daneggers Code,
bei mir hat es mit dem Pollin Inkrementalgeber aber jedenfalls nicht
funktioniert):
1
if(inkrem_speed>1)
2
inkrem_speed-=1+inkrem_speed/16;
und dann noch die eigentliche Routine, die je nach Typ auf 1 oder 2
flankigem Interrupt eingestellt ist:
Das Hauptproblem von Daneggers Code dürfte daran liegen, dass er erstmal
die volle Auflösung einliest und am Ende teilt, was für die
Beschleunigung eher ungünstig ist, da sich das Prellen stark auswirkt.
PS: Bitte jetzt keine Diskussion zu diesem leidigen Thema dass man es so
nicht machen sollte. Falls doch jemand anfängt, dann soll er erstmal
eine "ordentliche Version" mit dynamischer Beschleunigung vorlegen die
mit dem Pollin Inkrementalgeber funktioniert.
Das sollte eigentlich ganz einfach sein.
Man darf dann nicht jeden einzelnen Schritt übernehmen, sondern muß sie
über eine Zeit aufaddieren, z.B. 200ms.
Das kann man mit im Encoderinterrupt (1ms) machen und dann je nach Wert
mit nem Faktor multiplizieren.
Peter
@Jörg,
der Hannes Lux hat das mit dem taster gemacht.
Bei Drehung mit gedrücktem Taster hat der die 10fache Auflösung.
Sollte sich Softwaretechnisch am einfachsten machen.
Der Port wird ja eh begragt. Ist halt nur ein Bit mehr.
@ Peter
Hast du das zufällig schonmal ausprobiert?
Falls du irgendwann mal dazu kommst, wäre eine Erweiterung von deinen
Routinen mit einer Beschleunigung echt nett. Ich hatte es schon mehrmals
mit deinen Routinen Versucht, bin aber immer gescheitert und habe daher
wieder meine alten Routinen verwendet. Ein Problem liegt u.a. daran,
dass die Phasenverschiebung der beiden Signale bei dem Pollin Encoder
nicht 90° sondern viel weniger beträgt, was dazu führt, dass die Signale
stark asymmetrisch sind, weshalb man die Samplerate sehr hoch (>10kHz)
drehen muss, damit das ganze sicher funktioniert.
Benedikt K. wrote:
> Die Beschleunigung erfolgt zwar nur etwa um den Faktor 200, aber das> kann man ja alles anpassen. Weiterhin ist der Code aus Sicht einiger> Leute hier im Forum ein schlimmes Verbrechen.
Nö, sie haben eben diesen Code als sehr zuverlässig erfahren und haben
daher keine Lust, Probleme mit anderen Codes zu lösen. Warum etwas
lösen, wofür es schon eine Lösung gibt?
Ein "Verbrechen" ist es erst, wenn Du damit Geräte für teuer Geld
verkaufst und dann der Kunde damit Probleme hat.
> Ich habe dagegen die> Erfahrung mit dem Pollin Panasonic Inkrementalgeber gemacht, dass der> Coder sehr viel besser funktioniert als der von Danegger. Bei dessen> Code hatte ich Sprünge, die ich mit diesem Code nicht habe.
Generell ist eine schlechte Idee, Codebeispiele als Blackbox zu
betrachten. Wenn Du Probleme hast, überlege, woran das liegen könnte.
Wenn Du Schritte verlierst, verkürze das Abtastintervall. Wenn Du zu
selten im Main einliest, daß +/-127 Schritte nicht ausreichen,
vergrößere die Variable auf 16 Bit.
Peter
Benedikt K. wrote:
> Ein Problem liegt u.a. daran,> dass die Phasenverschiebung der beiden Signale bei dem Pollin Encoder> nicht 90° sondern viel weniger beträgt, was dazu führt, dass die Signale> stark asymmetrisch sind, weshalb man die Samplerate sehr hoch (>10kHz)> drehen muss, damit das ganze sicher funktioniert.
Du kannst auch den Pin-Change-Interrupt nehmen und auf beide Pins
aktivieren.
Was sind denn das für Drehgeber (Piher, Alps)?
Peter
> der Hannes Lux hat das mit dem taster gemacht.
Das ist für Jörgs Anwendung aber keine gute Idee.
Nun weiß ich auch nicht, welches Codebeispiel Du meinst, ich habe da
(aus heutiger Sicht gesehen) auch viel Suboptimales veröffentlicht.
Inzwischen lese ich Drehgeber nur noch durch zyklische Abfrage (1ms) und
4-Bit-LUT (2 alte und 2 neue Stati als Index) ein.
Hier könnte aber ein Zähler angesetzt werden, der herunter zählt, wenn
der Drehgeber nicht betätigt wurde und bei Betätigung auf Startwert
gesetzt wird (ob betätigt oder nicht, erkennt man am Inc-Wert, den man
aus der LUT ausliest). Bei langsamem Drehen ist der Zähler jeweils
abgelaufen, bei schnellem Drehen noch nicht. Somit kann der Zählerstand
(evtl auch als Index für weitere LUT) als Maß für die Dynamisierung
genutzt werden.
Dies nur so als Idee, ist mangels Bedarf nicht getestet.
...
> Eine Look-up-Tabelle.
Ich habe den Begriff auch nur über das Forum kennen gelernt, steter
Tropfen höhlt bekanntlich den Stein (oder: wenn man lange genug mit
Sch.. beschmissen wird, fängt man eines Tages an zu stinken...).
;-)
...
Benedikt K. wrote:
>> Du kannst auch den Pin-Change-Interrupt nehmen und auf beide Pins>> aktivieren.>> Ich dachte genau das sei verboten:
Verbieten kann Dir niemand was.
Man sollte aber um die Probleme bescheid wissen, wenn man eine bestimmte
Methode verwendet.
Theoretisch besteht beim PCI die Möglichkeit, sich mit Interrupts zu
überlasten.
Praktisch ist das bei manuell betätigten Kontaktencodern nicht möglich,
die maximale Prellfrequenz ist durch den AVR verkraftbar.
Die Möglichkeit besteht nur bei nicht rastenden optischen Encodern, z.B.
durch hochfrequente Vibrationen.
Man könnte dann in den PCI einen Zähler einbauen, wenn der überläuft,
sperrt er weitere Interrupts und ein Timer setzt diesen Zähler zyklisch
zurück. Damit ist eine hohe Peakfrequenz möglich, aber die mittlere
Interruptrate wird begrenzt.
Peter
Paul Baumann wrote:
> Für Jemanden, der (wie ich) aus dem Hut nicht weiß, was ein "LUT" ist:
Das kennen wohl nur noch ältere Semester aus den PC-Anfängen.
Da waren pro Bildpunkt nur 4 Bits verfügbar, d.h. 16 Farben gleichzeitig
darstellbar. Und damit wurde eine LUT auf der Grafikkarte adressiert,
die daraus 3*6Bit Farben ausgewählt hat.
Fotos sahen daher auf dem PC etwa so aus:
http://www.poster.de/Warhol-Andy/Warhol-Andy-Marilyn-Monroe-1967-2108274.html
Peter
Du könntest es auch einfach so machen das sich der Multiplikator nur
erhöht (mehr als X Schritte / 100ms = Multiplikator mal 2) und man den
Multiplikator per Knopfdruck zurücksetzen kann... Oder halt das man per
knopfdruck das Erhöhungsintervall druchschalten kanna (Hz, khz, Mhz)...
Vielen Dank erstmal für die rege Anteilnahme. ;-)
Ja, rein vom Algorithmus ist mir schon ungefähr klar, wie's geht, nur
die tatsächliche Implementierung hatte erstmal nur Mist gemacht.
Ich nehme Peters Code, und ja, es sind die Pollin-Drehgeber (sowohl
Panasonic als auch ALPS kommen in Frage, da bin ich noch nicht ganz
sicher, welcher es wird). Wie ich schon mal in einem anderen Thread
geschrieben habe, prellen die Teile erstaunlich wenig. Der Panasonic
prellt im Bereich von einigen 100 ns, der ALPS maximal so < 5 µs.
Im Moment ist die Interruptfrequenz zur Abfrage 800 Hz. Ich werd
dann mal sehen, wie ich Benedikts Vorschlag in die Poll-Routine
eingearbeitet bekomme.
Die Benutzung des Tasters habe ich auch schon in Erwägung gezogen,
aber nur eine Dekade umschalten hat wenig Sinn. Wenn, dann würde
ich wohl nach Tastendruck von initial 1-Hz-Schritten auf 1-kHz-
Schritte schalten, und dann aber von da aus noch weiter dynamisch
beschleunigen. Wenn 1 s lang nichts mehr geändert worden ist, kann
man dann ja wieder auf 1-Hz-Schritte zurück fallen für die Feinein-
stellung.
Eine Tastatur kommt vielleicht trotzdem noch dran für die genaue
Einstellung der Frequenz, aber so'n richtiger Knopf zum Drehen ist
halt was anderes, den möchte ich als Alternative nicht missen.
*.* wrote:
> Öhm... sowas hatte ich doch letztens mal!
Danke! Verstehe ich noch nicht ganz.
> //Beschleunigung Drehgeber> if(!(prescaler % (DEBOUNCE / 8))) {> accelerateCounter = FALSE;
Wofür sind hier `prescaler' und `DEBOUNCE' gut?
> if(volume != lastcnt) {
Auch hier: wie hängen diese Variablen mit enc_delta bzw. last
zusammen?
>> *.* wrote:>> > Öhm... sowas hatte ich doch letztens mal!>>>> Danke! Verstehe ich noch nicht ganz.
Soll heißen, ich stand letztens vor einem ähnlichen Problem.
>> > //Beschleunigung Drehgeber>> > if(!(prescaler % (DEBOUNCE / 8))) {>> > accelerateCounter = FALSE;>>>> Wofür sind hier `prescaler' und `DEBOUNCE' gut?
Das habe ich aus P. Dannegger's "Die genaue Sekunde" verwendet.
Hier mal ein paar größere Codefetzen.
if((b=encode_read2())){// read a single step encoder
16
17
if(accelerateCounter==TRUE){
18
b*=4;
19
accelerateCounter=FALSE;
20
}
21
22
23
if(b>0){
24
if((volume+b)<255)volume+=b;
25
elsevolume=255;
26
}
27
28
if(b<0){
29
if((volume+b)>=0)volume+=b;
30
elsevolume=0;
31
}
32
/*...*/
33
}
34
/*...*/
35
}
In meinem Codebeispiel ist die Beschleunigung lediglich 4-fach, ich muß
nur zwischen 0 und 255 hin-und herpendeln.
Ich hoffe, nun sieht man die Zusammenhänge etwas besser.
Mal ne andere Frage: Warum denn die Beschleunigung messen? Die
Geschwindigkeit reicht doch auch aus.
Dreht man langsam-> 10^0 Änderung pro Drehschritt
Dreht man schnell-> 10^X Änderungen pro Drehschritt.
> Warum denn die Beschleunigung messen? Die> Geschwindigkeit reicht doch auch aus.
Ich glaube kaum, dass es um die (physikalisch korrekte) Beschleunigung
geht, vielmehr darum, das Zählen bei schnellerem Drehen zu
"beschleunigen", also mehr Schritte zu zählen als aufgetreten sind.
Umsonst hat Jörg das nicht in Gänsefüßchen gesetzt.
;-)
...
Hannes Lux wrote:
>> Warum denn die Beschleunigung messen? Die>> Geschwindigkeit reicht doch auch aus.>> Ich glaube kaum, dass es um die (physikalisch korrekte) Beschleunigung> geht, vielmehr darum, das Zählen bei schnellerem Drehen zu> "beschleunigen", also mehr Schritte zu zählen als aufgetreten sind.> Umsonst hat Jörg das nicht in Gänsefüßchen gesetzt.>> ;-)>> ...
Achso. Kann allerdings gut sein. Jaja, a = dv/dt und so ;)
Ich kann mir eigentlich nicht vorstellen, dass Danneggers vorschlagene
Methode so kompliziert sein soll. Über nen definierten Zeitraum von
100ms (oder so) immer von Danneggers Drehencoder Code auslesen und
gucken, wie groß der Betrag in den 100ms geworden ist.
"Um diese Dynamik zu bekommen, muß man dem Drehgeber eine Schwungmasse
verpassen. Dazu muß die Drehgeschwindigkeit ermittelt und auch
gemittelt"
Für die Dynamik nicht sooo wichtig, aber für den Bedienkomfort.
Ich erinnere mich an die alten Röhrenradios, die hatten dicke
Schwungräder drin, da konnte man mit einem beherzten Dreh ans andere
Ende der Skala drehen.
Unser HP-MessSender hat auch ein ähnliches Rad mit Schwungmasse und
magnetischer Rastung. Wenn Du da mal dran gedreht hast, willst Du nichts
anderes mehr.
Bei den einfacheren würde ich überlegen, ob man entweder
- durch Drücken der Mitteltaste die Srungweite z.B. in 5-8 Stufen
ändert
- bei gedrückter Taste das Rad die Sprungweite einstellt.
Ein wenig Dynamik würde ich trotzdem einbauen.
Bei unserem LeCroy ist das auch nicht optimal gelungen, ist zwar
dynamisch, aber die Sprungweite kann man nur auf 2 Weiten einstellen
(grob und fein, genauer gesagt fixed (1-2-5) und variable (mal ca.
1.01)). Das ist mir zu wenig.
Zum Vorgehen: eigentlich ganz einfach: Zeit für den jeweiligen Schritt
messen und in einer LUT nachschauen, um wieviel addiert / subtrahiert
werden soll.
Würde ich mit PinChange-Interrupt lösen.
Viel Erfolg
Ich würde das nicht so kompliziert machen. Bei langsamer Drehung
Einzelschritte, bei schnellerer Drehung erst 5..15 Einzelschritte, dann
eine Zehnerpotenz erhöhen und wieder 5..15 Schritte, wieder eine
Zehnerpotenz erhöhen usw.
@eProfi
>Für die Dynamik nicht sooo wichtig, aber für den Bedienkomfort.
Beides geht Hand in Hand. Erst wenn man mit einem Schwung einen Bereich
von - sagen wir - 20-30% einstellen kann, wird die Bedienung angenehm.
Wenn aber, wie aus dem Pollin-Link ersichtlich, ein Drehgeber mit 16
Impulsen/360° verwendet wird, kann das nicht klappen. Der Mensch ist
keine Maschine und bei zuwenig Feingefühl der Einstellung verkrampft
sich die Hand (meine Erfahrung mit schlechter Mausanpassung unter
Linux).
Ohne Schwungmasse wäre noch ein größerer Drehknopf mit Fingermulde
praktikabel, bei dem man mehrere Umdrehungen ohne abzusetzen machen
kann. Ab der 2. Umdrehung könnte man die Schrittweite deutlich erhöhen
und dennoch feinfühlig gekommen. Aber der Drehgeber sollte schon 200-400
Impulse/Umdrehung liefern.
Achso, wenn ihr schon alle mit den Alternativen anfangt:
Ich hatte es damals bei meinem Funktionsgenerator (der leider nie fertig
geworden ist wegen dem Analogdreck) so gemacht:
Das ganze lief "menüartig" ab. Also: Es gab zwei Eingabeebenen. Man
wechselte (togglete) mit einem Druck auf den eingebauten Knopf des
Encoders.
Eingabeebene1: Man konnte durch Drehen des Encoders die Dezimalstellen
(mit blinkendem Cursor auf dem HD44780 markiert) durchrollen. Man konnte
also sagen, welche 10er Stelle der Frequenz man verändern wollte.
Eingabeebene2: Durch das Drehen am Encoder konnte man die in
Eingabeebene1 markierte bzw. gewählte Dezimalstelle verändern.
Um zum Beispiel von 0000001Hz auf 1000000Hz (1Hz auf 1MHz) zu wechseln,
wählte man zuerst die Dezimalstelle ganz links und drehte um eine
Rastposition, sodass man 1000001Hz hatte und anschließend verringerte
man die ganz rechte Stelle um 1.
flätz wrote:
> Ich würde das nicht so kompliziert machen. Bei langsamer Drehung> Einzelschritte, bei schnellerer Drehung erst 5..15 Einzelschritte, dann> eine Zehnerpotenz erhöhen und wieder 5..15 Schritte, wieder eine> Zehnerpotenz erhöhen usw.
Klappt mit rastenden Drehgebern (wie den beiden Pollin-Typen) nicht:
du musst zu oft nachfassen, und so groß ist die mögliche Variation
der Winkelgeschwindigkeiten nicht, die man erreichen kann.
Sowas wäre wirklich nur für nichtrastende Typen und eine Schwungmasse
machbar. Bei den rastenden Teilen muss man zumindest ein wenig
,,Erinnerungsvermögen'' implementieren, so in der Art: ,,Hat der
Bediener jetzt nur eine kurze Pause zum Nachfassen gemacht?''
> Klappt mit rastenden Drehgebern (wie den beiden Pollin-Typen) nicht:
Ja, ich dachte eher an einen leichtgängigen Typen, wenigstens mit
Fingermulde oder Kurbel.
Mit dem von mir geposteten Code und dem Pollin Drehgeber ist ein
Wertebereich von etwa 1000-10000 sinnvoll:
Pro Umdrehung gibt es 32 Rastpunkte, macht zusammen mit der 200x
Beschleunigung und etwa einer Umdrehung die man auf einmal schafft
theoretisch etwa 6400 Schritte. In der Praxis kommt man auf rund
1000-3000 Schritte. Mehr als 3-4x neu Ansetzen für den Kompletten
Wertebereich macht die Bedienung sehr umständlich.
Von daher baue ich bei größeren Wertebereichen eine Funktion ein, die
durch Drehen bei gedrücktem Knopf die Stelle verschiebt, so dass man in
10er, 100er, 1000er usw. Schritten einstellen kann.
Ist nicht wirklich perfekt, aber man kommt mit einem einzelnen Knopf aus
und kann problemlos einen Wertebereich von >10 Dekaden leicht und
schnell eingeben.
Hi!
Wäre es eventuell eine Möglichkeit das Quadrat der Impulse, die über
eine feste Tastzeit reinkommen, zu bilden?
Also Tastzeit: 100ms,
Impulse -> Ausgabe
1 1
2 4
10 100
.
.
.
Könnte ich mir jedenfalls vorstellen
Viel Erfolg, Uwe
Ich habe mir gerade mal einen Pollin-Panasonic-Drehgeber aus der
Ramschkiste rausgesucht. Mehr als vielleicht eine 1/4 bis eine 1/2
Drehung gelingt mir nicht ohne Umgreifen, wenn es bequem bleiben soll.
Bei 16 Impulsen/360° ergibt das grob 4 bis 8 Impulse. Das halte ich für
sehr wenig um eine Geschwindigkeitssteigerung zu detektieren, also jenen
"Kick" den man dem Drehgeber gegen ende der 1/2 oder 1/4 Drehung mitgibt
um zu sagen, dass man es gerne etwas schneller hätte.
Ich würde in eine andere Richtung gehen: Zwei Drehgeber. Einen um die
Stelle (Auflösung) einzustellen an der man dreht - dass, was sonst bei
Geräten mit zwei separaten Tasten gemacht wird. Der andere dient ganz
normal dazu die gewählte Stelle hoch oder runter zu drehen.
Man könnte den ersten Drehgeber auch einsetzen um die gewünschte
"Geschwindigkeit" einzustellen, also einen Multiplikationsfaktor, mit
dem die Schritte vom zweiten Drehgeber multipliziert werden. Vielleicht
würde sich ein 1-2-5-10-20-... Multiplikationsraster gut eignen.
Das wäre nicht ganz so bequem wie ein einziger Drehgeber, doch immer
noch etwas bequemer als die normalerweise verwendete Kombination aus
einem Drehgeber und zwei Tasten.
Hannes Jaeger wrote:
> Bei 16 Impulsen/360° ergibt das grob 4 bis 8 Impulse.
Wie zuvor geschrieben: Es sind 32 Rastpunkte was die ganze Sache
schonmal verbessert. Wenn man beide Phasen abfragt, kommt man sogar auf
64 Schritte pro Umdrehung.
Hannes Jaeger wrote:
> Ich würde in eine andere Richtung gehen: Zwei Drehgeber. Einen um die> Stelle (Auflösung) einzustellen an der man dreht - dass, was sonst bei> Geräten mit zwei separaten Tasten gemacht wird. Der andere dient ganz> normal dazu die gewählte Stelle hoch oder runter zu drehen.
So meinte ich das oben, nur halt über einen Drehencoder, wo man zwischen
den beiden Modi togglet (durch externe Taste). Aber mit zwei
Drehencodern geht natürlich auch!
Benedikt K. wrote:
> Mit dem von mir geposteten Code und dem Pollin Drehgeber ist ein> Wertebereich von etwa 1000-10000 sinnvoll:
Nun, dann könnte man ja mit der Taste noch einigermaßen arbeiten,
wenn man diese als Faktor 1000 benutzt. Werd ich mich nochmal
ranmachen.
Für eine exakte Eingabe ist eine richtige Tastatur natürlich allemal
besser, die würde ich dann parallel zum Drehknopf lieber haben wollen
als die Variante, mit dem Encoderknopf die 1er/10er/100er/1000er
durchzuschalten.
Falls jemand mal noch sowas sucht, hier meine Lösung aufbauend auf Peter
Danneggers Code:
1
volatileshortenc_delta;
2
// ISR wird jede ms ausgeführt
3
ISR(SIG_OUTPUT_COMPARE1A)
4
{
5
#define DYNAMIK 40
6
staticcharenc_state=0x01;
7
staticuint8enc_accel=0;
8
signedshorted;
9
chari=0;
10
11
if(enc_accel>0)enc_accel--;
12
13
if(PHASE_A)i=1;
14
if(PHASE_B)i^=3;// convert gray to binary
15
i-=enc_state;// difference new - last
16
if(i&1){// bit 0 = value (1)
17
ed=enc_delta;
18
if(enc_accel<(255-DYNAMIK))enc_accel+=DYNAMIK;
19
enc_state+=i;// store new as next last
20
if(i&2)ed+=1+(enc_accel>>6);// bit 1 = direction (+/-)
21
elseed-=1+(enc_accel>>6);
22
enc_delta=ed;
23
}
Mit dem #define Dynamik lässt sich der "Biss", also die Beschleunigung
einstellen. Leider funktioniert das mit den billigen Pollin-Dingern nur
eingeschränkt, weil die pro Raste zwei Schritte machen. Also ist da
etwas Spielen mit dem Wert angesagt.
Mit einem u16 für enc_accel kann der Dynamikbereich wesentlich
ausgeweitet werden.
Ich hab jetzt mal die Beschleunigung programmiert, um nen 16Bit-DAC zu
setzen.
Funktioniert sehr schön.
Das Beispiel macht 3 Stufen, man sollte aber erstmal 2 Stufen probieren.
Hier nur die Erweiterung zu meinem Code:
1
#include<util\atomic.h>
2
3
4
uint8_tenc_acc_t10ms;// count down per timer interrupt 10ms
5
uint8_tenc_delta;
6
uint8_tlast;
7
8
9
int8_tencode_read2(void)// 2 edge per detent, 24 detent
10
{
11
int8_tval;
12
13
ATOMIC_BLOCK(ATOMIC_FORCEON){
14
val=enc_delta;
15
enc_delta&=1;
16
}
17
returnval>>1;
18
}
19
20
21
#define ACC_TIME 0.05 // 50ms
22
#define ACC_SLOW 3
23
#define ACC_FAST 8
24
#define ACC_BIG 128
25
#define ACC_HUGE 1024
26
27
28
int16_tencode_read_acc(void)// Acceleration
29
{
30
int8_tval;
31
32
if(enc_acc_t10ms)// time to accumulate counts
33
return0;
34
enc_acc_t10ms=1/10e-3*ACC_TIME;
35
val=encode_read2();
36
switch(val){
37
case-ACC_SLOW...ACC_SLOW:returnval;
38
caseACC_SLOW+1...ACC_FAST:returnACC_BIG;
39
case-ACC_FAST...-ACC_SLOW-1:return-ACC_BIG;
40
caseACC_FAST+1...127:returnACC_HUGE;
41
default:return-ACC_HUGE;
42
}
43
}
Dazu wird noch ein 10ms Timer-Interrupt benötigt für die 50ms Meßzeit.
Da die neueren AVRs alle Pin-Change-Interrupts haben, habe ich den
Encoder-Interrupt als Pin-Change-Interrupt (beide Anschlüsse)
ausgeführt, anstatt mit 1ms Timerinterrupt. Dadurch entsteht nur beim
Drehen eine Interruptlast und es gehen keine Schritte verloren.
Peter