Forum: Compiler & IDEs Potentiometer und Festwerte


von Pinkuss (Gast)


Lesenswert?

Hallo zusammen,

ich habe einen Potentiometer und 5 verschiedene Taster für feste Werte 
an einem ATmega128 angeschlossen und möchte nun folgende Featurette in 
mein Dimmerprogramm einbauen:

Startet man den Controller, wird ganz normal der Potiwert verwendet 
(verstellt die PWM...). Drückt man einen der Taster wird der fest 
einprogrammierte Wert übernommen und der Poti wird erstmal deaktiviert.

Nun kommts: Dreht man wieder an dem Poti, soll verhindert werden, daß 
Sprünge in den Helligkeitswerten auftreten. Ich hatte es mir so 
vorgestellt, daß man entweder den Poti zuerst auf 0 drehen muss um dann 
den per Taster eingestellten Wert beim Hochdrehen zu "fangen" (vgl. mit 
einem mechanischem Mitnehmer, o.Ä.) oder der Poti erst wieder aktiv 
wird, wenn der Wert sich in der Nähe des Festwertes befindet.

Jetzt habe ich folgendes Codefragment, aber es funktioniert nicht 
zufriedenstellend, weil wenn der Poti nahe einem Tasterwert steht, 
dieser nicht immer übernommen wird... Problem ist, daß ich eine 
Gammakorrektur eingebaut habe (Poti ist linear, Helligkeit soll aber 
logarithmisch sein) und der Poti nicht immer fängt, zumal meine 
Abfrageroutine nur alle 50ms erfolgt, was einerseits die Entprellung der 
Taster brachte, andererseits aber zu große Abstände liefert, wenn man zu 
schnell am Poti dreht.
1
  switch ( index )
2
  {
3
    case 19 : pwm_setting[0] = BEDECKT; moon_status = 1; break;
4
    case 20 : pwm_setting[0] = NEUMOND; moon_status = 1; break;
5
    case 21 : pwm_setting[0] = HALBMOND1; moon_status = 1; break;
6
    case 22 : pwm_setting[0] = HALBMOND2; moon_status = 1; break;
7
    case 23 : pwm_setting[0] = VOLLMOND; moon_status = 1; break;
8
  }
9
10
  if ( moon_status != 1 ) {
11
    pwm_setting[0] = gamma_pwm(7,0);    // Value Poti 7 to PWM-Channel 0
12
  }
13
  
14
  if ( (abs(pwm_setting[0] - gamma_pwm(7,0))) < 16  ) {
15
    moon_status = 0;  
16
  }
17
18
  pwm_update();

Hat jemand vielleicht eine Idee, wie man das eleganter lösen könnte, 
bzw. das wie man die Rückkehr zur Poti-Bedienung am besten realisieren 
könnte.

Herzlichen Dank schonmal für Eure Kommentare.

von Karl H. (kbuchegg)


Lesenswert?

Pinkuss wrote:

> Hat jemand vielleicht eine Idee, wie man das eleganter lösen könnte,
> bzw. das wie man die Rückkehr zur Poti-Bedienung am besten realisieren
> könnte.

Schmeiss das Poti raus und hol dir einen Drehgeber.
Das Problem ist, dass ein Poti einen Absolutwert liefert, du in dieser 
Aufgabenstellung aber mit einem relativen Wert (User dreht nach links, 
User dreht nach rechts, dementsprechend erhöht/erniedrigt sich ein Wert) 
besser bedient bist.

von liinterpo (Gast)


Lesenswert?

oder du interpolierst über eine bestimmte zeit hinweg die geänderten 
werte. so kriegst du immer einen weichen übergang.

von liinterpo (Gast)


Lesenswert?

t = (aktuellezeit - übergangsstartzeit) / übergangsdauer
wert = alterwert * (1-t) + neuerwert * t

von was-willst-du (Gast)


Lesenswert?

Wenn Du schon beim Ändern bist: Verkürz auch die Zeit von 50ms.

Tasten prellen nicht so lange, wenn es Deine doch tun, schmeiß sie 
einfach weg.

von Karl H. (kbuchegg)


Lesenswert?

liinterpo wrote:
> t = (aktuellezeit - übergangsstartzeit) / übergangsdauer
> wert = alterwert * (1-t) + neuerwert * t

Kann man so machen, würd ich aber nicht tun.

Ich würd so machen:
Eine ISR wird in regelmässigen Zeitabständen aufgerufen, damit hab ich 
mal eine Zeitbasis.

Dazu gibt es dann noch für den interessierenden Wert 2 Variablen. Eine 
die den tatsächlichen Wert enthält und der mit der PWM-Stellung 
korrespondiert. Die 2-te Variable enthält die Benutzervorgabe.
In der ISR wird dann ganz einfach festgestellt, ob der tatsächliche Wert 
von der Benutzervorgabe abweicht. Tut er das, wird der tatsächliche Wert 
ein klein wenig in Richtung der Benutzervorgabe nachgestellt. Über viele 
ISR Aufrufe gesehen wird also der tatsächliche Wert immer auf den vom 
Benutzer vorgegebenen Wert nachgeführt.

Vorteil:
* wenig zu rechnen
* unkompliziert
* die Benutzervorgaben können sich in schneller Folge in jede beliebige 
Richtung verändern, ohne dass das für mich ein rechnerischer Mehraufwand 
bedeutet.
* Durch Steuerung der ISR-Aufruffrequenz kann man ganz leicht bestimmen, 
wie schnell dieser Nachführvorgang abläuft
* Die Nachführung ist ohne sonstiges Zutun automatisch linear
* Falls gewünscht, ist es auch kein Problem bei großen Differenzen eine 
schnelle Nachführung zu realisieren, die sich verlangsamt, wenn die 
Benutzervorgabe nahezu erreicht ist.
* Auf und Ab-Dimmen kann trivial mit unterschiedlichen Raten 
implementiert werden.
1
uint16_t actValue;
2
volatile uint16_t userWants;
3
4
5
...
6
ISR( .... )   // zb. ein Overflow oder ein CTC-Interrupt
7
{
8
  if( actValue != userWants ) {
9
    if( actValue < userWants )
10
      actValue++;
11
    else
12
      actValue--;
13
14
    SetPWMValue( actValue );
15
  }
16
}

Durch Zuweisungen an userWants wird die PWM 'langsam' an genau diesen 
Wert herangeführt.

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
Noch kein Account? Hier anmelden.