Grüß Gott, hab die ganze Nacht versucht eine entsprechende Routine in C zu schreiben, aber mir will es einfach nicht gelingen - sapperlot! Ich will alle RGB Möglichkeiten durchlaufen.. Also Von RGB(0;0;0), RGB(0;0;1), RGB(0;0;2) ... über RGB(0;10;10), RGB(0;10;11),... bis RGB(255;255;255) Selbst ein Soft PWM samt Timer Interrupts laufen - nur eben das "Farbspiel" nicht. Ich weiß, es ist eigentlich ganz banal, aber kann mir da jemand aushelfen?
Pfunk schrieb: > Ich will alle RGB Möglichkeiten durchlaufen.. Also Von RGB(0;0;0), > RGB(0;0;1), RGB(0;0;2) ... über RGB(0;10;10), RGB(0;10;11),... bis > RGB(255;255;255) Hmm, wo ist denn dein Problem? Ohne das ganze drum herum zu kennen, sieht das fuer mich erst mal nach drei schleifen aus:
1 | for(uint16_t i = 0; i < 256; i++) |
2 | {
|
3 | for(uint16_t j = 0; j < 256; j++) |
4 | {
|
5 | for(uint16_t k = 0; k < 256; k++) |
6 | {
|
7 | RGB(i, j, k); |
8 | }
|
9 | }
|
10 | }
|
Vielleicht versteh ich ja aber dein Problem auch nicht richtig :-/ Gruesse
:
Bearbeitet durch User
Ist die Frage, was du über haupt genau willst. So wie du es beschrieben hast wäre es von dunkel nach hell. Wenn du alle Farben haben willst, musst du das anders machen. Also SAG mal, was denn genau raus kommen soll.. Dennis
Kaj G. schrieb: > Hmm, wo ist denn dein Problem? Ohne das ganze drum herum zu kennen, > sieht das fuer mich erst mal nach drei schleifen aus:for(uint16_t i = 0; > i < 256; i++) > { > for(uint16_t j = 0; j < 256; j++) > { > for(uint16_t k = 0; k < 256; k++) > { > RGB(i, j, k); > } > } > } > Vielleicht versteh ich ja aber dein Problem auch nicht richtig :-/ Okay, Also ich habe zwei Timer, einen schnellen der die I/Os schaltet und einen langsameren, der das "Faden" steuern soll. Aber ein Faden gibt es nicht... maximal ein hochzählen :-( Der µC ist ein PIC18F2550 interner Osc und der Compiler ein XC8.
Also ich würde gerne wie zuvor schon angedeutet (Also Von RGB(0;0;0), RGB(0;0;1), RGB(0;0;2) ... über RGB(0;10;10), RGB(0;10;11),... bis RGB(255;255;255)) durch den ganzen Farbbaum durch-faden, wenn möglich.
Such mal nach HSV Farbraum, ist es das was Du möchtest ?
http://de.m.wikipedia.org/wiki/HSV-Farbraum Entweder Farbwert H oder Dunkelstufe V (das spezifizierst du ja nicht so genau in deiner frage) durchlaufen und dann nach rgb umrechnen und ausgeben
Pfunk schrieb: > Also ich würde gerne wie zuvor schon angedeutet (Also Von RGB(0;0;0), > RGB(0;0;1), RGB(0;0;2) ... über RGB(0;10;10), RGB(0;10;11),... bis > RGB(255;255;255)) durch den ganzen Farbbaum durch-faden, wenn möglich. Hallo, die Frage ist, ob RGB(255;255;255) Sinn macht... das wäre ja weiß und kommt in den Spektralfarben nicht vor (weiß ist ja schließlich die Summe aus den Spektralfarben) Wenn du eine Art Regenbogen-Fader aufbauen möchtest, reicht es wenn du z.B. mit rot (255;0;0) startest, dann den grün-Anteil von 0 - 255 ansteigen lässt (=> Fade zu gelb). Anschließend nimmst du den rot-Anteil von 255 zurück zu 0 (=> Fade zu grün). Dann nimmst den blau-Anteil von 0 zu 255 zu (=> Fade zu türkis), dann grün weg (Fade zu blau) dann rot dazu (=> Fade zu pink) und schlussendlich blau wieder weg (=> Fade zurück zu rot). Damit hast du insgesamt 6 Schleifen, in der du jeweils eine Farbe im Bereich 0 <=> 255 dazu oder weg nimmst. Soll weiß tatsächlich dabei sein, könntest du einfach nach blau (0, 0, 255) rot und grün gleichzeitig ansteigen lassen (=> Fade zu weiß) und anschließend blau und grün absteigen lassen (=> Fade zu rot) um wieder an den Anfang zu kommen. Das würde dann nochmal zwei zusätzliche Schleifen zur Folge haben. Gruß Andi
Hallo, .... schrieb: > http://de.m.wikipedia.org/wiki/HSV-Farbraum > > Entweder Farbwert H oder Dunkelstufe V (das spezifizierst du ja nicht so > genau in deiner frage) durchlaufen und dann nach rgb umrechnen und > ausgeben Aus Erfahrung mit einer Steuerung für LED-Kannen kann ich sagen, dass HSV am intuitivsten zu bedienen ist und auch bei der Wahrnehmung den besten Eindruck macht. Also den Farbton (H) ändern ergibt einen Regenbogen, Sättigung (S) ergibt den Übergang zu weiss und die Helligkeit stellst Du mit V ein. Bei einfachen LED-Kannen kannst Du Dich auf den Farbton H beschränken, bei sehr guten LED-Quellen kann man alle drei Komponenten nutzen. Grüße, Kurt
Hi, in tc_int() (höhere Prio als LowIsr(void)?) zählst Du einmal fast (nur bis 254) komplett durch. Wann kommt LowIsr(void) dran? Erst wenn tc_int() fertig ist? Wenn der TO meint, er wolle RGB trivial von 0 bis 255 durchlaufen lassen, warum wird ihm hier von Regenbogen und HSV gefaselt? Hat wohl keiner in den Code geguckt. Grüße, Markus
Pfunk schrieb: > Ich will alle RGB Möglichkeiten durchlaufen.. Also Von RGB(0;0;0), > RGB(0;0;1), RGB(0;0;2) ... über RGB(0;10;10), RGB(0;10;11),... bis > RGB(255;255;255) > Ich weiß, es ist eigentlich ganz banal, aber kann mir da jemand > aushelfen? Entweder 3 geschachtelte Schleifen wie oben oder - wenn dir das besser gefällt - ein long int (irgendwas >=24 Bit) hochzählen und je 8 beliebige Bits auf die 3 Farbkanäle mappen. Die viel entscheidendere Frage ist jedoch, ob das entstehende Farbenspiel auch ästhetischen Gesichtspunkten genügt. Und da versagen die einfachen Methoden. Es gibt dann ein paar weitere Varianten: 1. den Farbwechsel im HSV-Modell machen (da muß man nur einen Parameter ändern) und in RGB umrechnen. Gibt halt nur den Regenbogen. 2. nur Farbwechsel zwischen je zwei Primärfarben machen. Also z.B. von Rot über Zwischenstufen zu Grün. Von da zu Blau. Und wieder zurück zu Rot. Das machen viele einfache Moodlights so. 3. eine Farbe zufällig auswürfeln und dann von der aktuellen Farbe dahin faden, wenn angekommen kurz warten und neue zufällige Farbe auswürfeln.
Pfunk schrieb: > Also ich habe zwei Timer, einen schnellen der die I/Os schaltet und > einen langsameren, der das "Faden" steuern soll. Wenn man dann das auch noch mit dazu nimmt, dann musst du eben die entsprechenden Schleifen in Increments samt Logik umwandeln, die bei jedem Interrupt Aufruf des langsamen Timers einmal ausgeführt wird und dann eben den jeweils nächsten Fading Schritt realisiert. Denn genau das hier
1 | void interrupt tc_int() |
2 | {
|
3 | if(TMR1IE && TMR1IF) |
4 | {
|
5 | LATB3 = ~LATB3; |
6 | |
7 | for(uint8_t i = 0; i < 255; i++) |
8 | {
|
9 | for(uint8_t j = 0; j < 255; j++) |
10 | {
|
11 | for(uint8_t k = 0; k < 255; k++) |
12 | {
|
13 | RGB(i, j, k); |
14 | }
|
15 | }
|
16 | }
|
17 | TMR1IF = 0; |
18 | WriteTimer1(0xF0BD); //Please use HEX. Decimal don't work |
19 | }
|
20 | }
|
willst du nicht machen. Bei jedem Interrupt Aufruf wird zur genau nächsten Farbe weitergeschaltet. Aber nicht in Schleifen alle Farben durchspielen. Dazu musst du dir eben überlegen, wie das geht, wenn r/g/b gerade auf 248/26/27 steht, welches dann die nächste Farbe laut deinem Verlaufsschema ist.
1 | void interrupt tc_int() |
2 | {
|
3 | static uint8_t red, green, blue; |
4 | |
5 | if(TMR1IE && TMR1IF) |
6 | {
|
7 | LATB3 = ~LATB3; |
8 | |
9 | if( blue != 255 ) |
10 | blue++; |
11 | else { |
12 | blue = 0; |
13 | |
14 | if( green != 255 ) |
15 | green++; |
16 | else { |
17 | green = 0; |
18 | |
19 | if( red != 255 ) |
20 | red++; |
21 | else
|
22 | red = 0; |
23 | }
|
24 | }
|
25 | }
|
26 | |
27 | RGB( red, green, blue ); |
28 | |
29 | TMR1IF = 0; |
30 | WriteTimer1(0xF0BD); //Please use HEX. Decimal don't work |
31 | }
|
32 | }
|
Das ist ein generelles Prinzip. In einer Interruptroutine willst du diese Schleifen eben nicht haben. Sondern was du statt dessen haben willst, ist ein Schema, bei dem du in der Nacht geweckt wirst, du dir die Situation ansiehst und anhand der Situation entscheidest, was als nächstes zu geschehen hat. Das machst du und dann legst du dich wieder schlafen. Bis du 10 Minten später wieder geweckt wirst, dich wieder umsiehst wie die Situation jetzt ist, entscheidest was es genau jetzt zu tun gibt und dich wieder schlafen legst. Und so geht das die ganze Nacht durch. Aber du bleibst nicht die ganze Nacht über auf sondern unterbrichst deinen Schlaf alle 10 Minuten um 'die Arbeit ein kleines Stück fortzusetzen'. Ob das jetzt das gezielte Weiterschalten einer Uhr, bestehend aus Sekunden, Minuten und Stunden ist, oder das Durchlaufen von Temperaturkurven oder eben bei dir das Abarbeiten von Farbschemata ist, spielt keine Rolle. Das generelle Prinzip ist immer dasselbe. Und wenn du mal genau überlegst: deine Software-PWM beruht im Prinzip auf genau dem gleichen Grund-Prinzip. Bei jedem Interrupt Aufruf wird erneut entschieden, ob die jeweilige LED aufgrund ihres PWM Wertes noch brennen soll oder nicht. Die Interrupt Routine, die entspricht genau dem Wecker, der dich alle 10 Minuten aus dem Schlaf holt. Nur das das bei einem µC eben nicht 10 Minuten sind, sondern alle paar Sekundenbruchteile passiert. Je nachdem, wie du den Timer konfiguriert hast.
255 mal 255 mal 255 = 16 Mio Werte In welcher Zeit willst du das durchfahren? Selbst bei einer Stunde Zeit würdest du die letzte Farbe 16 mal komplett (0 bis 255) durchlaufen. Das kann das Auge nicht auseinanderhalten. Das sind zuviele Werte, sichtbarmachen in einer sinnvollen Zeit dürfte nicht gehen.
Korrektur: Selbst bei einer Stunde Zeit würdest du die letzte Farbe 16 mal komplett (0 bis 255) IN EINER SEKUNDE durchlaufen.
Tontechniker schrieb: > Also größere Schritte machen. Wobei man auch sagen muss, dass das gezielte Durchiterieren aller RGB Werte noch so einem Schema ein höchst unbefriedigendes fades Ergebnis liefert. D.h hier wäre zumindest der Wechsel auf ein 'Regenbogen'-System anzuraten. Dann sind es bei einem ganz einfachen Schema nur noch zb 1536 (=6*256) unterschiedliche Farben. Die allerdings sind um einiges 'interessanter' zum zusehen.
Karl Heinz schrieb: > if( blue != 255 ) > blue++; > else { Wiso werden immer die einzelnen Komponenten inkrementiert, statt alle komponenten als ein Integer aufzufassen, und diesen zu Inkrementieren?
1 | // ungetestet
|
2 | |
3 | #define RGB(r,g,b) (r|g<<8|b<<16)
|
4 | #define COLOR_TYPE uint32_t
|
5 | #define COLOR_UINT(x) x
|
6 | #define COLOR_BITS 24
|
7 | #define COLOR_STEP_SIZE 1
|
8 | |
9 | inline bool nextColor(COLOR_TYPE*color){ |
10 | return COLOR_UINT(*color)>(COLOR_UINT(*color)=(COLOR_UINT(*color)+COLOR_STEP_SIZE) & ((1ul<<COLOR_BITS)-1)); |
11 | }
|
12 | |
13 | inline bool updateColor(*color){ |
14 | |
15 | // <code, der color ausgibt>
|
16 | // ...
|
17 | |
18 | return nextColor(color); |
19 | }
|
20 | |
21 | int main(){ |
22 | COLOR_TYPE color=RGB(0,0,0); |
23 | while(updateColor(&color)); |
24 | }
|
Ist doch einfacher, oder?
Pfunk schrieb: > Also ich würde gerne wie zuvor schon angedeutet (Also Von RGB(0;0;0), > RGB(0;0;1), RGB(0;0;2) ... über RGB(0;10;10), RGB(0;10;11),... bis > RGB(255;255;255)) durch den ganzen Farbbaum durch-faden, wenn möglich. Mit "durch-faden" verstehst du wohl, ohne Übergänge (bzw. mit möglichst kleinen Übergängen) und ohne Farben mehrfach anzuzeigen, den ganzen Farbraum von Schwarz nach Weiß zu durchwandern? Im Grenzfall ist das eine Peano-Kurve: Eine 1-zu-1 Abbildung eines Intervalls (bei dir die Zeit) ein eine kompakte Teilmenge des R³ (bei dir der Farbraum, also RGB, HSV, HSB, YUV, CMY oder was auch immer). Die oben angegebenen 3-fach Schleifen führen übrigens nicht zu einer Lösung in diesem Sinne. Die Konstruktion kannst du nach endlich vielen Schritten abbrechen, nämlich dann, wenn die Granularität fein genug ist. Da es einige Zeit dauert, ca. 16 Mio. Farben zu durchlaufen, wirst du also nicht alle Werte durchlaufen wollen, sondern z.B. jede Farbkomponente nicht in 256 Teile aufteilen sondern z.B. nur in 32 oder 64. Weil das menschliche Auge Farbabstufungen unterschiedlich wahrnimmt, ist es bestimmt besser, zunächst in einen Farbraum zu transformieren, in dem der "Unterschied" der Farben ihrem Abstand entspricht. Nahe der Grauachse nimmt man z.B. viel feinere Farbabstufungen wahr als bei voll aufgedrehter Sättigung. Hier die Animation einer solchen Kurve von [0,1] -> [0,1]², d.h. für den 2-dimensionalen Fall. I.W. wird die Binärdarstellung einer Zahl verwendet, um daraus den Zielpunkt zu erhalten. Eine entsprechende Entwicklung für den 3-dimensionalen Fall, die ebenfalls von Pixel zu Nachbarpixel ist, fällt mir auf Anhieb keine ein. :-) http://commons.wikimedia.org/wiki/File:Peano-curve_animated_(140x120).gif Ganz interessant in dem Zusammenhang ist auch http://allrgb.com/ wo es Bilder gibt, die alle 2^24 Farben des 8-Bit RGB-Farbraums verwenden.
Johann L. schrieb: > Eine entsprechende Entwicklung für den 3-dimensionalen Fall, die > ebenfalls von Pixel zu Nachbarpixel ist, fällt mir auf Anhieb keine ein. Ok, folgendes sollte gehen: 1) Man zerlegt den Würfel (RGB-Farbraum) in 8 gleich große Teilwürfel. 2) Man wählt einen Weg von einer Ecke des Würfels zur diametral gegenüberliegenden Ecke, so dass der Weg aus 8 Flächendiagonalen der Teilwürfel besteht. Jede Flächendiagonale muss sich einem anderen Teilwürfel zuordnen lassen, d.h. auf dessen Oberfläche verlaufen. 3) Für alle 8 Teilwürfel analog zu 2), allerdings führt der Weg nicht zu einer diametral gegenüberliegenden (3 Kanten entfernten) Ecke, sondern zu einer der 3 Ecken, die nur 2 Kanten von der Ausgangsecke entfernt sind. Wieder besteht der Weg aus 8 Flächendiagonalen von Teilwürfeln. 4) Gehe zu 3) Dabei verläuft der Weg immer zwischen den Ecken, die im darüberliegenden Schritt bestimmt wurden. Beispielsweite kann 3) durch folgenden Weg realisiert werden. Der zu durchwanderne Würfel ist [0,2]^3. Die 8 Teilwürfel werden mit Tripeln aus {0,1}^3 bezeichnet. In der linken Spalte steht der Weg, und rechts daneben der Teilwürfel, auf dessen Oberfläche die Flächendiagonale verläuft:
1 | (0,0,0) -> (1,1,0) 000 |
2 | -> (2,1,1) 110 |
3 | -> (1,2,1) 111 |
4 | -> (0,1,1) 011 |
5 | -> (1,1,0) 010 |
6 | -> (1,0,1) 100 |
7 | -> (1,1,2) 001 |
8 | -> (2,0,2) 101 |
Dass die Wege auf Flächendiagonalen von Teilwürfeln sind, erkennt man daran, dass ein "->" Teilweg 2 Koordinaten um 1 ändert und eine Koordinate unverändert lässt. Dass ein Teilweg auf dem in der 2. Spalte stehenden Teilwürfel verläuft, erkennt man daran, dass wenn links ein "0" steht, an der entsprechenden Stelle der Würfel-Nr. eine "0" steht, und dass wo links eine "2" steht, rechts eine "1" steht. (1,0,1)->(1,1,2) gehört also zum Teilwürfel 001 oder 101 (im Beispiel 001). Zudem tauchen in der 2. Spalte alle 8 Teilwürfel auf, d.h. der ganze Farbraum wird abgedeckt. Dieses Verfahren wendet man nur folgendermaßen rekursiv an, wobei der Weg durch das Intervall [0,1] parametrisiert sei: Für ein x in [0,1] schaut man sich dessen Oktalentwicklung an und wählt anhand der nächsten Ziffer den (nächst kleineren) Teilwürfel, aus dem die Farben darzustellen sind. Beispiel: 1/3 = 0,2525... Man startet also mit Teilwürfel 2 (010), darin nimmt man Teilwürfel 5 (101), darin Teilwürfel 2 (010), usw. Mit 8 Iterationsebenen und damit 8^8 = 256^3 Farben ist die übliche Farbauflösung (3*8 Bit) erreicht; für schnelleres Durchnudeln bzw. gröbere Auflösung iteriert man entsprechend weniger. Bei nur 1 Iterationsschritt, also nur 2), ist ein möglicher Weg schwarz-rot-magenta-blau-cyan-grün-gelb-weiß. Ob das zu einem ansprechenden Ergebnis führt, kann ich allerdings nicht versprechen. Einfach ausprobieren :-) Prinzipiell lässt sich auch das Problem unterschiedlicher Farbwahrnehmung lösen, d.h. dass Farbunterschiede zwischen Punkten gleichen Abstands (im Farbraum) unterschiedlich stark wahrgenommen werden. Dazu müsste man aber zunächst mal die entsprechende Metrik kennen. Kennt die jemand?
Schau Dir mal das an: Beitrag "Re: Deckenumbau: 180 Leds wie verbauen? 230VAC Dimmbar? Touchdisplay, Bluetooth"
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.