Hallo Freunde, ich bin etwas ratlos, deshalb schreibe ich euch jetzt hier. An meiner Stereoanlage ist ein Poti zur Lautstärkeregelung. Wenn ich schnell am Poti drehe steigt die Lautstärke überproportional schnell an. Wenn ich langsam drehe dann ist der Anstieg vermutlich nahezu linear über der Drehgeschwindigkeit. Ich möchte die gleiche Funktionalität in einer Microcontrollerschaltung realisieren. Allerdings sollen damit Parameter im Microcontroller eingestellt werden können. Ein entsprechendes Display zur Anzeige ist vorhanden. Leider habe ich trotz Maschinenbaustudium nur noch rudimentäre Kenntnisse in Regelungstechnik und kann mir grade auch keine Reim draus machen, wie ich an einen solchen Regelansatz herangehe. Außerdem habe ich folgenden Drehencoder zu Hause: KY040 Kann jemand sagen ob solch ein "Regelverhalten" mit einem solchen Encoder möglich ist und wie ich am besten vorgehe? Grüße Manuel
Manuel K. schrieb: > Ich möchte die gleiche Funktionalität in einer Microcontrollerschaltung > realisieren. Allerdings sollen damit Parameter im Microcontroller > eingestellt werden können. Ein entsprechendes Display zur Anzeige ist > vorhanden. > > Leider habe ich trotz Maschinenbaustudium nur noch rudimentäre > Kenntnisse in Regelungstechnik und kann mir grade auch keine Reim draus > machen, wie ich an einen solchen Regelansatz herangehe. Als "Masch-Ing" solltest Du zumindestens den Unterschied zwischen Regelung und Steuerung kennen. Hier handelt es sich um eine reine Steuerung. Der Rest ist nur richtige Programmierung Deines µCs. Kannst Du denn µCs prorammieren? Wie man Drehencoder richtig aus- wertet, wird u.a. in den DSE-FAQ beschrieben. Die unterschiedliche Auswertung je nach Drehgeschwindigkeit kann man einfach erreichen, indem man die Drehgeschwindigkeit mit Hilfe des µC misst.
Das hat nichts mit Tegelungstechnik zu tun, fas idt simpeldzes programmieten. Man fragt den Drehencoder int table[4][4]={{0,1,-1,0},{-1,0,0,1},{1,0,0,-1},{0,-1,1,0}}; int position=0,steps=0; volatile int quadrature_input; // bit 0 und bit 1 sind Quadratureingaenge int new_quadrature_value, last_quadrature_value=quadrature_input; ab, z.B. jede Millisekunde: new_quadrature_value=quadrature_input; steps+=table[last_quadrature_value][new_quadrature_value]; last_quadrature_value=new_quadrature_value; https://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29 und überprüft nach 100 solcher Durchläufe, wieviel zusammengekommen ist, "steps" können ja nur maximal 100 sein die vielleicht aber zu 10000 führen sollen. Das macht dann eine exponentielle Formel position += 1.095^steps; steps=0;
Manuel K. schrieb: > Kann jemand sagen ob solch ein "Regelverhalten" mit einem solchen > Encoder möglich ist Warum nicht möglich? Das ist ja nur ein Programm. Was einprogrammiert wird, so wird man auch bekommen. Manuel K. schrieb: > und wie ich am besten vorgehe? Es gibt viele Möglichkeiten. Z.B. diese: 1. jede ca.1ms Encoder überprüfen, eine Variable entsprechend ändern. 2. jede z.B. 100 ms Variable prüfen. Wenn sie stärker geändert wurde (im Vergleich mit dem früheren Wert), dann sollte Lautstärke-Zähler überproportional incrementiert oder decrementiert werden. Sonst proportional.
Manuel K. schrieb: > rudimentäre Kenntnisse in Regelungstechnik Der Drehgeber an der Stereoanlage ist genau genommen auch eine Steuerung. Eine Regelung wäre es, wenn abgeleitet von einer Schallpegelmessung der Verstärkungsfaktor nachgestellt würde. Genug klug geschi##en. Idee zu einem Ansatz: Der Drehgeber wird zyklisch (sagen wir Mal alle 20msec), hierbei wird das Quadratursignal in eine Zahl in zyklischem Zahlensystem umgewandelt. Also 0, 1, 2, ..., 254, 255, 0, 1, ... Davon wird ebenso zyklisch (sagen wir Mal 200msec) die Ableitung berechnet, also Delta = Zähler_vorher - Zähler_jetzt Zähler_vorher = Zähler_jetzt Abhängig vom Betrag des Delta kann man jetzt die eigentliche Stellgröße schneller oder langsamer zählen lassen, z.B. if (abs(Delta) > 20) { Stellgröße += Delta * 10 } else { Stellgröße += Delta } mfg mf
huiuiui hier bekommt man ja super schnell eine Antwort. Vielen Dank für die guten Ideen. Vermutlich habe ich einfach zu kompliziert gedacht. Ich denke das bekomme ich jetzt hin. Grüße und Danke Manuel
Manuel K. schrieb: > Ideen Ich hatte dieselbe Idee wie Maxim... Allerdings kann man, statt wie mit dem "if" unstetig, mit z.B. f(x)= x³ einen stetigen nichtlinearen Zusammenhang darstellen. Vorteil wäre, dass der Übergang von "normal" nach "schnell" weicher und weniger abrupt erscheint. mfg mf
:
Bearbeitet durch User
Viel leichter wäre es, umgekehrt zu machen: bei Langsamdrehen proportional, bei Schnelldrehen unterproportional. Dafür reicht es, Kontroller so mit anderen Aufgaben zu belasten, daß nur wenig Zeit für Drehgeber-Abtasten bleibt :)
Manuel K. schrieb: > An meiner Stereoanlage ist ein Poti zur Lautstärkeregelung. Wenn ich > schnell am Poti drehe steigt die Lautstärke überproportional schnell an. > Wenn ich langsam drehe dann ist der Anstieg vermutlich nahezu linear > über der Drehgeschwindigkeit. > Kann jemand sagen ob solch ein "Regelverhalten" mit einem solchen > Encoder möglich ist und wie ich am besten vorgehe? Das ist eine reine Software-Sache. Die Auswertung schaut darauf, wie "schnell" der Encoder gedreht wird und macht beim schnellen Drehen größere Sprünge. Praktisch habe ich das mal so umgesetzt, daß zwischen der Drehzahl des Encoders und der "Drehzahl" der zugehörigen Variable ein Faktor "Geschwindigkeit" sitzt. Im einfachsten Fall ist der Faktor konstant 1. Dann kriegst du das bekannte, langweilige Verhalten. Interessanter wird es, wenn man den Faktor dynamisch verändert. Sehr gute Ergebnisse hatte ich mit diesem Verfahren: 1. der Encoder wird in einem festen Zeitintervall abgetastet. Ein zweckmäßiger Wert ist 1ms. 2. die Geschwindigkeit wird als Festkomma-Wert, z.B. in 1/32 Auflösung aufgelöst. Ein Wert von 32 enstspricht dann 1.0. 33 wäre 1 + 1/32 = 1.03125 etc. Damit läßt sich leicht rechnen. Fließkomma würde auch gehen, ist aber auf µC ohne Fließkomma-Hardware zu teuer. 3. immer, wenn der Encoder einen Schritt gemacht hat, wird die Geschwindigkeit um einen bestimmten Betrag erhöht. 4. bei jeder Abtastung (im festen 1ms Raster!) ohne einen Encoder-Schritt wird die Geschwindigkeit um 1 vermindert. im Ergebnis kriegt man das gewünschte Verhalten. Wird der Encoder nur langsam gedreht, ändert sich die Variable in 1-er Schritten. Je schneller (und je länger schnell) der Encoder gedreht wird, desto größer werden die Schritte. Die Grundidee wurde schon mehrfach beschrieben, z.B. von Lothar im Beitrag "Dynamische "Beschleunigung" bei Encoder-Eingabe" Meine Variante (mit funktionsfähigem Quellcode für ATTiny2313) findest du im Beitrag "Kurzzeittimer (z.B. für Platinenbelichter)". Das ist wie beschrieben mit Festkomma-Arithmetik mit Skalierung 1/32 (#define SCALE). Die Beschleunigung bei jedem Encoder-Schritt ist 24/32 (#define ACCEL). Und die maximale Geschwindigkeit ist 30 (#define VMAX). Der Code paßt auf eine Bildschirmseite:
1 | /* encoder acceleration characteristics */
|
2 | #define ACCEL 24 /* acceleration */ |
3 | #define SCALE 32 /* speed scale, power of 2 recommended */ |
4 | #define VMAX 30 /* max speed */ |
5 | |
6 | /* rotary encoder decoding table */
|
7 | const int8_t enc_table[16] = |
8 | {
|
9 | 0, 0, -1, 0, |
10 | 0, 0, 0, 1, |
11 | 1, 0, 0, 0, |
12 | 0, -1, 0, 0 |
13 | };
|
14 | |
15 | /* encoder status */
|
16 | volatile int8_t enc_delta; /* -128..+127 */ |
17 | |
18 | void debounce_encoder(void) |
19 | {
|
20 | static uint8_t last; /* encoder status */ |
21 | static int16_t spd; /* encoder speed */ |
22 | |
23 | last = ((last << 2) | (phase_A ? 2 : 0) | (phase_B ? 1 : 0)) & 0x0F; |
24 | int8_t delta = enc_table[last]; |
25 | |
26 | if (delta) { |
27 | /* accelerate, with saturation @ VMAX*SCALE */
|
28 | spd = (spd < (VMAX*SCALE-ACCEL) ? spd+ACCEL : VMAX*SCALE); |
29 | |
30 | if (delta > 0) { |
31 | enc_delta += (spd/SCALE); |
32 | } else { |
33 | enc_delta -= (spd/SCALE); |
34 | }
|
35 | |
36 | } else { |
37 | /* decelerate, but not below SCALE */
|
38 | spd = (spd > SCALE ? spd-1 : SCALE); |
39 | }
|
40 | }
|
Den kompletten Code findest du als ZIP im o.g. Beitrag.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.