Forum: Projekte & Code LED-Lampe mit RGB-LEDs, simultanem Fading und Gammakorrektur


von Christoph B. (nuke)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe nun endlich meine tolle, aber leider kaputte, LED-Lampe 
repariert und bei dieser Gelegenheit gleich eine kleine Steuerung mit 
einem Attiny45 gebaut.

Folgende Features sind im Code enthalten:

- 3-Kanal PWM für die RGB-LEDs (theoretisch beliebig erweiterbar)
- Gammakorrektur der Helligkeit, da die Lichtempfindlichkeit des Auges 
eher logarithmischer denn linearer Natur ist
- simultanes Fading der LEDs an einer Rampe von einem beliebigen Istwert 
zu einem beliebigen Sollwert in einer beliebigen Zeit

Mit dem Code könnte man recht einfach mit einem größeren Controller ein 
Moodlight nachbauen, bei mir soll es bei der Lampe bleiben ;-)

Viel Spaß beim Verwenden, Kommentare sind höchst erwünscht...


Grüße,
Christoph

von Daniel J. (n0i5ebreak3r)


Lesenswert?

Hallo Christoph,

Ich habe heute mal deine Schaltung probiert, ich hatte mir 2 neue 
Atiny'45 zukommen lassen. Den habe ich mit AVR Studio 5 dann 
programmiert bzw das Programm kompiliert. Leider Funktioniert es nicht 
so wie gedacht. Die Led bei mir ist es jetzt die Rote an Pin5 des MC, 
blitz nur ganz kurz auf, so ca. alle 2 sek. wenn ich auf die Taster 
drücke und festhalte tut sich etwas so das die anderen auch aufblitzen 
bzw ganz schnell flackern. Muss ich bei den Fuses etwas beachten habe 
diese auf Standart gelassen und er läuft jetzt mit int Takt bei 8Mhz.

Gruß, Daniel J.

von Daniel J. (n0i5ebreak3r)


Lesenswert?

Problem gefunden, läuft nun Super. Echt tolle Sache, wobei ich die 
Taster noch nicht ganz verstanden habe was die machen sollen.

Trotzdem ein Lob an dich.

Grüße, Daniel J.

von Martin S. (der_nachbauer)


Lesenswert?

abo

von Christoph B. (nuke)


Angehängte Dateien:

Lesenswert?

Daniel Joachims schrieb:
> Echt tolle Sache, wobei ich die
> Taster noch nicht ganz verstanden habe was die machen sollen.

Die Sache mit den Tastern ist ein Problem, das speziell bei mir auftrat:
Meine Lampe hat ein Gehäuse, wo bereits 3 Taster eingebaut waren. Einer 
ging drauf für an und aus, die anderen beiden habe ich dann einfach 
genutzt, um damit "binär" den Modus auszuwählen. Ich wollte einfach mehr 
als 2 Modi haben und kam so mit 2 Tastern auf 4 Modi ;-) Außerdem hatte 
ich keine Portpins mehr frei, hat also super gepasst...
Drum die etwas umständliche Modusauswahl.

Grüße,
Christoph

von Daniel J. (n0i5ebreak3r)


Lesenswert?

Ja das habe ich auch herausgefunden mit der Mehrfachbelegung der Taste 
nur ich habe noch nicht raus bekommen mit welcher Taste ich welchen Modi 
einstelle bzw was die genauen Funktionen der Taser kombinationen ist. 
Habe jetzt etwas rum probiert und auch den Source Code mal 
durchgeschaut. Da kann ich halt die einzelnen Farben durchgehen und nach 
einer Zeit läuft der Fading wieder weiter. Vielleicht könntes du ja 
freundlicherweise noch ein paar Info's zu den Modi's geben. Ich habe 
zurzeit die Tastenfunktion komplett rausgenommen sowie die Modi's 
rausgenommen die ich eigentlich nicht brauche. Dann habe ich noch die 
Fading Zeit vergrößert somit läuft jetzt ein ganz langsamer Fading wobei 
ich noch den zustand weiß eingebaut habe :)

Auf jedenfall eine Super Sache.

von Christoph B. (nuke)


Lesenswert?

Die Buttons werden bei einem Pin Change Interrupt abgefragt mit
1
input = (PINB >> 3) & 3;
und dieser Wert wird weiter unten mit den Konstanten
1
#define ALL 3
2
#define RED 2
3
#define GRN 0
4
#define BLU 1
verglichen. Die Taster sind low-aktiv, deshalb ist der Modus ALL aktiv, 
wenn beide Taster nicht gedrückt sind, RED ist aktiv wenn der erste 
Taster gedrückt ist (binär 2: 10 also erster Taster low, zweiter high) 
und so weiter...

Dabei ist mir auch gleich aufgefallen, dass die beiden Zeilen
1
#define BUTTON1 PB3
2
#define BUTTON2 PB4
nutzlos sind, die können gelöscht werden.

Ich hoffe das war etwas verständlich ;-)

von Daniel J. (n0i5ebreak3r)


Lesenswert?

Ja ich habe es soweit verstanden, gut ich hatte eine anderen Funktion 
erwartet deshalb habe ich es nicht verstanden. Ja dein Programm habe ich 
in soweit abgeändert das ein normaler RGB-Moodlight ist welches ganz 
langsam die Farben durchgeht. Habe noch den Zustand Weiß hinzugefügt und 
die Funktion der Taster entfernt. Ich bin am überlegen wie ich es nun 
hinbekomme das ich mit einem Taster das Programm pausier, wenn zb die 
Farbe orange leuchtet das ich eine Taste drücke und dann bleibt er dort 
stehen bis er erneut gedrückt wird.

Ansonsten Super Arbeit dein Programm.

Gruß, Daniel J.

von Timo S. (tom_green1980)


Lesenswert?

Moin Christoph Brennig,

ich finde dein Projekt klasse und würde das am wochenende mal schnell 
zusammen stecken.
ich werde nen atmega8 verwenden und hoffe das der code so 1 zu 1 
übernommen werden kann!?

ich hab mich jetzt duch den quellcode gekämpft und ihn hoffentlich 
ausreichend verstanden, was ich absolut nicht verstanden habe ist die 
"rasterization algorithms"! wie funtioniert der und was macht der????

wenn ich kurz kritisch werden darf, du hast an machen stellen zu dürftig 
kommentare verwendet, gerade wenn es darum geht das du makros 
verwendest, oder so "einfache" sachen, warum du gerade das so gemacht 
hast, wie du es gemacht hast, z.B. mit dem "temp = SREG;" und "SREG = 
temp;" befehlen.

ich würde mich freuen wenn du mir noch ein paar hinweise geben kannst!

mfg timo

von Christoph B. (nuke)


Lesenswert?

Hi Timo,

ja das mit der Kommentierung ist eine schlechte Angewohnheit, häufig 
mach ich garkeine Kommentare ;-)

Also zum Rasterungs-Algorithmus:
Das Problem besteht ja darin, mit dem PWM-Sollwert in einer vorgegebenen 
Zeit von einem Startwert zu einem Endwert zu gelangen, und das möglichst 
gleichmäßig, also linear. Da ist mir eingefallen, dass es die gleiche 
Problematik ist, wie wenn man z.B. im Paint eine Linie zieht (ohne 
Kantenglättung), es musste also ein Algorithmus her, der das 
Stufenpattern erzeugt. Ich bin im Wikipedia-Eintrag 
http://de.wikipedia.org/wiki/Rasterung_von_Linien fündig geworden und 
habe den dort beschriebenen einfachen Algorithmus für Linien zwischen 0° 
und 45° verwendet (Anstieg m zwischen -1 und 1, negativ für die negative 
Richtung).
Und das funktioniert so:

Es wird eine Hilfsvariable mit 0,5 initialisiert (im Programm aX mit X 
für die Farben R,G,B) und der Anstieg der Linie mX ausgerechnet (im 
Programm in der fade-Funktion). m wird in jedem Schritt auf a addiert. 
Wenn a>=1, wird der PWM-Sollwert um 1 erhöht und a um 1 dekrementiert. 
Danach folgt der nächste Schritt, bis der PWM-Endwert erreicht ist.
Ich habe für den ganzen Spaß Ganzzahlen verwendet, mit der Konstante 
MULTI entsprechend der 1 und MULTI/2 entsprechend der 0,5 um es für den 
AVR einfacher und schneller zu gestalten. Zusätzlich habe ich noch eine 
Fallunterscheidung für die Abwärtsrichtung (m negativ) eingebaut. Und 
das ist der ganze Zauber dahinter.
(Mir ist eben aufgefallen, dass ich aX nicht mit MULTI/2, sondern mit 
127 initialisiere, das heißt der erste Schritt wird falsch errechnet 
>facepalm< )

Ach ja: MULTI ist kleiner als 127, da bei der Berechnung von mX eine 
Multiplikation ausgeführt wird, die bei höheren Werten größer als 32768 
werden kann, was aber der höchste Wert in einer int16_t-Variable ist.

Als nächste mögliche Unklarheit ist da vielleicht noch die 
Gammakorrektur. Das menschliche Auge hat eine eher logarithmische als 
eine lineare Helligkeitswahrnehmung, also würde ein linear ansteigender 
PWM-Sollwert so wahrgenommen, als ob die LED anfangs schnell an 
Helligkeit gewinnen würde, im oberen Bereich jedoch immer langsamer hell 
wird.
Um diesen Effekt zu eliminieren, wird der (lineare) PWM-Sollwert 
zwischen 0 und 255 anschließend über eine Vergleichstabelle durch eine 
vorher errechnete Logarithmusfunktion gejagt.
Auch beschrieben im Artikel LED-Fading

Wenn noch mehr Fragen bestehen, immer her damit ;-)

Grüße,
Christoph

edit:
Zur Portabilität müssten wahrscheinlich nur die Timer-Register-Namen 
abgeändert werden, ggf. noch die Prescaler. Sonst kanns denk ich gleich 
bleiben.

nochmal edit:
Wenn man so viel schreibt, vergisst man trotzdem die Hälfte ;-)
Zu der temp = SREG-Geschichte:
Das ist im Prinzip eine Sicherheitsmaßnahme bei Interrupts. Falls der 
Interrupt während einer umfangreicheren Berechnung ausgelöst wird und 
diese unterbricht, wird z.B. das Vorzeichenflag auf diesem Wege 
erhalten. Ob das an der Stelle wirklich notwendig ist, weiß ich nicht, 
es schadet auf jeden Fall nicht...

von Timo S. (tom_green1980)


Lesenswert?

moin christoph,

das ging ja schnell ;-)

das mit dem algorythmus nehme ich jetzt so mal hin, ich selber wäre 
warscheinlich net in der lage das so umzusetzten???

die gamma korrektur war mir schon bekannt, ich kenne den forumsbeitrag 
von hier.

ich werde das morgen vormittag mal versuchen in betrieb zu nehmen, mal 
sehen ob das funzt ;-)

mfg timo

PS: Doch einen hab ich noch....

dieser befehl "R_g = pgm_read_byte(&led_gamma[R]);" ruft doch die 
adresse des arrays auf um die wert zu übergeben!!!???? sehe ich das 
richtig????
gibt es dafür noch eine einfache variante, die ohne makros in c++ 
geschriebn werden kann???

von Thomas D. (thomasderbastler)


Lesenswert?

Christoph : Könntest für nicht C Benutzer eine HEX File noch anfügen ?

Wäre suppa..!!

von Christoph B. (nuke)


Angehängte Dateien:

Lesenswert?

@ Timo:
Das große Array steht nur im Flash drin, weil der Attiny45 nur 256 Byte 
SRAM hat und das Array aber schon so groß ist, somit bleibt kein Platz 
für andere Variablen.

Der Atmega8 z.B. hat 1K SRAM, dann ist pgm_read_byte() nicht nötig und 
es kann einfach das Array ohne das Schlüsselwort PROGMEM initialisiert 
werden und wie jedes andere Array auch aufgerufen werden. Das 
entsprechende #include kann dann natürlich auch entfallen.

Das & vor dem Array wird von pgm_read_byte() benötigt, da es die 
Start-Adresse des Arrays erwartet.


@ Thomas:
Bitteschön ;-)

von Thomas D. (thomasderbastler)


Lesenswert?

Christoph : ILY..LoL

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.