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
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.
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.
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
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.
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 ;-)
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.
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
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...
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???
Christoph : Könntest für nicht C Benutzer eine HEX File noch anfügen ? Wäre suppa..!!
@ 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 ;-)
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.