Forum: Projekte & Code Erweiterung zum Artikel LED Fading


von Guido (Gast)


Lesenswert?

Hallo,
habe eine Alternative zur Tabelle die man für die log. Ansteuerung der 
Fading-PWM braucht. Warum nicht eine nette kleine Formel benutzen? Vor 
einiger Zeit hatte ich das Problem eine Werteingabe über einen
Schieberegler zu steuern wobei der untere Wertebereich zu grob 
einstellbar war. Also musste ein exponentielles Verhalten des Potis her 
wie man es auch im RC-Bereich von den Servos her kennt. Ich habe im 
Internet nach lägerer Suche folgende Formel gefunden. Bitte keinen 
Schreck kriegen, alles wird sich in Wohlgefallen auflösen:

Expo-Poti-Formel:
-----------------

 y = max / (efunc (expo) - 1) * (efunc (expo * x / max) - 1)

 wobei x der lineare Potiwert zw. 0 und 100 ist und
 expo der Exponentialwert (Hängebauchwert) zw. 1 und 100 ist (0 ist
 linear).
 efunc () ist die e-Funktion (keine Angst wir rechnen nicht real
 sondern int).
 Y ist der Exponential-Wert (wird x linear vergrössert bewegt sich Y
 am Anfang sehr langsam und hinkt hinterher um am Ende x wieder 
einzuholen)

 Wir formen um:
 Nach Taylor gilt:
 exp (x) = 1 + x/1! + x*x/2! [ + x*x*x/3! + ... ] wir brechen nach
 der 3. Iteration ab (Abbruch nach der 2. reicht nicht !).

 Setzen wir nun 1 + x + x*x/2 für efunc () ein und vereinfachen die
 Gleichung (vereinfachen ist garnicht so einfach, habe mich ca. 10 mal
 verrechnet, jetzt kann ichs wieder) so kommt folgende wunderschöne
 Formel raus:

 y = (2*max*x + expo*x*x) / (max * (expo + 2))

 Das lässt sich mit Integern berrechnen !
 Will man nun eine LED dimmen so muss man eine Umkehrung dieser Funktion
 bilden. Man schiebt also das Poti von hinten nach vorne also von max 
nach
 0 und dreht Y genauso um und erhält eine log. Charakteristik.

#define LEDAn     PORTB |= (1<<PB3)  // muss an Hadware angepasst werden
#define LEDAus    PORTB &= ~(1<<PB3)

void LedDimmen (void) // dimmt die LED einmal hoch, qick and dirty
{
  uint8_t cnt = 0,
          comp = 0,
          acomp = 255;
  int32_t max = 255,
          b = 90,        // Expowert
    x, vcomp;
  while (comp < 255)
  {
    _delay_us (80);
    if (cnt == 254)
    {
      cnt = 0;
      LEDAus;
      comp++;
      x = max - 255 + comp; // dimmt hoch
      // x = max - comp;    // dimmt runter
      vcomp = (2*max*x + b*x*x) / (max * (b + 2)); // Expoformel
      acomp = max - vcomp;
    }
    if (cnt == acomp)
      LEDAn;
    cnt++;
  }
  LEDAn;
}

Probiert es mal aus. Bei mir sieht es richtig gut aus. Eure Meinung 
interssiert mich. Viel Spass.
  Guido

von Lupin (Gast)


Lesenswert?

Interessant wäre es vielleicht eine Funktion zu haben, die einen 
linearen PWM Wert entgegen nimmt und dann den exponentiellen Wert zurück 
gibt.

Woher weiss ich, welchen Expowert ich wählen muss?

von Falk B. (falk)


Lesenswert?

Lupin (Gast)

>Woher weiss ich, welchen Expowert ich wählen muss?

Na dann schau mal in die Exceltabelle im Artikel . . .

http://www.mikrocontroller.net/wikifiles/e/e4/Pwm_table.zip

Die Berechnung in den AVR zu legen ist nicht sonderlich sinnvoll. Die 
paar Bytes Programmspeicher für die Tabelle sind kleiner und deutlich 
schneller als die Berechnung.

MFG
Falk

von Guido (Gast)


Lesenswert?

Hallo,
der Expowert ist frei wählbar (die Variable b im Code) und sollte zw.
1 und 100 liegen, bei größeren Werten sollte man darauf achten einen 
Integer-Overflow zu vermeiden.


>> Die Berechnung in den AVR zu legen ist nicht sonderlich sinnvoll. Die
>> paar Bytes Programmspeicher für die Tabelle sind kleiner und deutlich
>> schneller als die Berechnung.

Das kann man so sehen, aber:
Der Code braucht weniger Speicherplatz als eine vernünftige Tabelle, bei
kleinen Controllern sehr nützlich.
Die Dimm-Kurve ist einstellbar mit dem Faktor b, hier wären mehrere 
Tabellen
notwendig.
Die Geschwindigkeit ist zwar langsamer aber spielt hinsichtlich einer f.
LEDs typischen PWM-Frequent von ca. 100 Hz keine bedeutende Rolle.

Diese Alternative soll nur zeigen dass es eben auch andere Möglichkeiten 
gibt
LEDs zu dimmen, ich finde sie mathematisch interessant.

noch was:
Die Codezeile:      x = max - 255 + comp; // dimmt hoch
kann vereinfacht werden, da max = 255 ist, also reicht:  x = comp;

Gruss
  Guido

von Alex R. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

also ich muss schon sagen, dass es oft einfacher geht eine Formel selbst 
aufzustellen, als eine ewig im Internet zu suchen. im Anhang ist ein 
Bild mit der Erklaerung wie ich zu mein Formel komme. Noch dazu ist sie 
bedeutend einfacher als die bereits vorgeschlagene. Andererseits dauert 
die berechnung im µC viel laenger.

Mein Ergebnis für eine lineare Helligkeitssteigerung ist:

exponentialwert=e^(linearwert/k)
wobei k=Helligkeitsmaximum/ln(Helligkeitsmaximum)  ist.

e = Eulersche Zahl = 2,71828
ln() ist der natürliche Logarithmus.

mfg
Alex R.

von Falk B. (falk)


Lesenswert?

@  Guido (Gast)

>Der Code braucht weniger Speicherplatz als eine vernünftige Tabelle, bei
>kleinen Controllern sehr nützlich.

Beweis?

>Die Dimm-Kurve ist einstellbar mit dem Faktor b, hier wären mehrere
>Tabellen notwendig.

Wer braucht diese Einstellung?

MfG
Falk

von Guido (Gast)


Lesenswert?

Hallo,
die werte in Fliesskommaarithmetik zu berechnen kostet viel Code wenn
nicht sowieso Fliesskommazahlen benutzt werden und ist sehr langsam.

Der code f. die formal ist weniger als 100 Byte während eine vernünftige
Tabelle ca. 255 Byte braucht.
Wer die dimmkurve anpassen möchte kann dies tun, kostet keinen 
zusätzlichen
Aufwand.
Gruss
  Guido

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.