Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »turi« (2. Februar 2010, 23:51)
Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von »turi« (23. Dezember 2010, 11:50)
Orca hatte hier im Forum den Wunsch, die RGB-Farben in der Helligkeit bei Farbtreue zu dimmen. Dies habe ich experimentell schon mal aufgebaut. Allerdings stößt man da teilweise an technische Grenzen. Aber die Ergebnisse waren z.T. besser als erwartet. Wenn ich z.B. einen gelben Farbton einstelle, kann ich die Helligkeit dessen sehr gut dimmen. Es hängt eben immer von der jeweiligen Farbzusammensetzung ab und davon, wie die Dimm-Strategie im Programm arbeitet.
Ich hätte mir das so vorgestellt, dass man eine Farbe mit den 3 Kanälen(PWMs) einstellt und dann eine PWM vor die 3 Kanäle hängt und mit der dann dimmt. Allerdings habe ich keine Ahnung wie sich PWMs in Serie verhalten und ob das überhaupt möglich ist. Jedenfalls wäre es in diesem Fall auch egal, wie viele Schritte bis Null die jeweilige Farbe noch hat.Es gibt wie gesagt beim farbechten Dimmen technische Grenzen. Wenn z.B. die Farbe sich aus den Prozentwerten 80/60/10 zusammen setzt, kann man nur so lange einigermaßen farbgetreu dimmen, bis eine Farbe auf Null geht.

), damit ich wieder auf 0-255 pro Kanal (8-Bit-PWM) komme... (also die PWM-Werte, 255 = 100%) - wenn man 16-Bit-PWM nehmen würde, könnte man diese Werte direkt benutzen, hätte dann auch ne höhere Auflösung... bei mir wird's halt schon etwas arg abgestuft, wenn sowohl Dimmer als auch Farbwert sehr niedrig sind...Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Pesi« (22. Juni 2009, 23:44)
- hier geht's (zumindest vom Ansatz her) um was anderes: eine eingestellte Farbe (hier in RGB) *nochmals* in der Helligkeit *extra* zu dimmen, und das geht nur mit einem 4. ("Dimmer")-Kanal, mit dem man diese Werte multipliziert. So wie bei meinem DMX-Receiver auch.Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Pesi« (23. Juni 2009, 01:22)
.|
|
Quellcode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
if (hue > 1529) hue = 0;
if (hue < 255) {
red_val = 255;
green_val = (65280 - sat * (255 - hue)) >> 8;
blue_val = 255 - sat;
}
elseif (hue < 510) {
red_val = (65280 - sat * (hue - 255)) >> 8;
green_val = 255;
blue_val = 255 - sat;
}
elseif (hue < 765) {
red_val = 255 - sat;
green_val = 255;
blue_val = (65280 - sat * (765 - hue)) >> 8;
}
elseif (hue < 1020) {
red_val = 255 - sat;
green_val = (65280 - sat * (hue - 765)) >> 8;
blue_val = 255;
}
elseif (hue < 1275) {
red_val = (65280 - sat * (1275 - hue)) >> 8;
green_val = 255 - sat;
blue_val = 255;
}
else {
red_val = 255;
green_val = 255 - sat;
blue_val = (65280 - sat * (hue - 1275)) >> 8;
}
|
|
|
Quellcode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if (hue > 764) hue = 0;
if (hue < 255) {
red_val = (10880 - sat * (hue - 170)) >> 7;
green_val = (10880 - sat * (85 - hue)) >> 7;
blue_val = (10880 - sat * 85) >> 7;
}
elseif (hue < 510) {
red_val = (10880 - sat * 85) >> 7;
green_val = (10880 - sat * (hue - 425)) >> 7;
blue_val = (10880 - sat * (340 - hue)) >> 7;
}
else {
red_val = (10880 - sat * (595 - hue)) >> 7;
green_val = (10880 - sat * 85) >> 7;
blue_val = (10880 - sat * (hue - 680)) >> 7;
}
|
|
|
Quellcode |
1 2 3 |
red = ((bri + 1) * red_val) >> 8; green = ((bri + 1) * green_val) >> 8; blue = ((bri + 1) * blue_val) >> 8; |
.Zumindest die trigonometrischen Funktionen bekommt man aber auch mit Ganzzahlen und einer Tabelle hin. Das braucht sogar weniger Speicher, weil Tabelle und Code kleiner ist, als die entsprechenden Fließkommafunktionen.... Bei meiner RGB-Wall-Plasma-Software ist Fliesskomma erforderlich, da ich trigonometrische und andere, komplexe Berechnungen benötige, ...
also im Endeffekt dimmst Du dann genauso wie ich die Gesamthelligkeit per Multiplikation der RGB-Werte mit dem Helligkeitswert, hier kommt halt *davor* noch die Umrechnung von HSB in RGB...
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »turi« (5. September 2009, 17:03)
|
|
Quellcode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
int main (void) {
DDRB = 0xff;
PORTB = 0b00001111;
PORTB = 0x07;
uint16_t ADCval, ADCvalC1, ADCvalC2, ADCvalC3, ADCvalC0 ; //Werte des ADC
uint8_t code, addr; //RC5-Code, Adresse
int ADCdiff=0;
int16_t hue, sat, bri, red, blue, green, red_val, green_val, blue_val;
uint8_t key=0; //Taste für Farbwahl (1,2,3); Taste 5 zum Einleiten Speichern
uint8_t iProg=0; //Programmart (0/9,6)
//10 Bit PWM mit 64 Stufen initialisieren
pwm_10_64init();
//Fernbedinung aktivieren
rc5_init (RC5_ALL);
/* Interrupts zulassen */
sei();
// Kanal 0,1 ADC einmalig lesen, um Startwerte zu lesen
//...
while(1) {
if (-1 == rc5.flip) //keine FB - Potiabfrage
{
//keine FB-Taste gedrückt: Kanal 0,1 ADC lesen
ADCval = ReadChannel(3);
//Differenz zum vorhergehenden Wert? -> Poti wurde verändert
if(ADCvalC3<20) ADCdiff=ADCvalC3; else ADCdiff=20;
if ((ADCval > ADCvalC3+20) || (ADCval < ADCvalC3-ADCdiff))
{
//Helligkeit gesamt
ADCvalC3=ADCval;
bri=ADCvalC3/16; //0..64
}
ADCval = ReadChannel(2); /* MUX-Bits auf 0b0000 -> Channel 1 */
//Differenz zum vorhergehenden Wert? -> Poti wurde verändert
if(ADCvalC2<20) ADCdiff=ADCvalC2; else ADCdiff=20;
if ((ADCval > ADCvalC2+20) || (ADCval < ADCvalC2-ADCdiff))
{
//ADC-Wert speichern
ADCvalC2=ADCval;
blue_val=ADCvalC2/16; //0..64
}
ADCval = ReadChannel(1); /* MUX-Bits auf 0b0000 -> Channel 1 */
//Differenz zum vorhergehenden Wert? -> Poti wurde verändert
if(ADCvalC1<20) ADCdiff=ADCvalC1; else ADCdiff=20;
if ((ADCval > ADCvalC1+20) || (ADCval < ADCvalC1-ADCdiff))
{
//ADC-Wert speichern
ADCvalC1=ADCval;
green_val=ADCvalC1/16; //0..64
hue = ADCvalC1/4*3; //0..765
}
ADCval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0 */
//Differenz zum vorhergehenden Wert? -> Poti wurde verändert
if(ADCvalC0<20) ADCdiff=ADCvalC0; else ADCdiff=20;
if ((ADCval > ADCvalC0+20) || (ADCval < ADCvalC0-ADCdiff))
{
//ADC-Wert speichern
ADCvalC0=ADCval;
red_val=ADCvalC0/16; //0..64
sat = ADCvalC0/8; //0..128
}
} //keine FB - Potiabfrage
else
{ //FB verarbeiten
/* Ja, dann rc5.code merken und evtl. rc5.addr */
code = rc5.code;
addr = rc5.addr;
/* und auf naechstes Zeichen warten */
rc5.flip = -1;
if (addr==0) //TV-Modus
{
switch (code)
{
case 12: { red_val=0;green_val=0;blue_val=0;
break;} // Aus
//FB-Code entfernt
case 1: { key=1; break;} //Farbe1
case 2: { key=2; break;} //Farbe 2
case 3: { key=3; break;} //Farbe 3
case 5: { key=5; break;} //Speichern einleiten
case 6: { iProg=6; break;} //Prog HSB
case 9: { iProg=9; break;} //Prog RGB / bri
case 0: { iProg=0; break;} //Prog RGB
default: ;
} //switch (code)
} //addr==0
} //FB-Verarbeitung
//HSB-Werte aus Potis interpretieren (Taste 6 an FB gedrückt)
if (iProg==6)
{
if (hue > 764) hue = 0;
if (hue < 255) {
red_val = (10880 - sat * (hue - 170)) >> 7;
green_val = (10880 - sat * (85 - hue)) >> 7;
blue_val = (10880 - sat * 85) >> 7;
}
else if (hue < 510) {
red_val = (10880 - sat * 85) >> 7;
green_val = (10880 - sat * (hue - 425)) >> 7;
blue_val = (10880 - sat * (340 - hue)) >> 7;
}
else {
red_val = (10880 - sat * (595 - hue)) >> 7;
green_val = (10880 - sat * 85) >> 7;
blue_val = (10880 - sat * (hue - 680)) >> 7;
}
//im HSB-Programm geht Helligkeit bis 255 (*4)
red = (((bri*4) + 1) * red_val) >> 8;
green = (((bri*4) + 1) * green_val) >> 8;
blue = (((bri*4) + 1) * blue_val) >> 8;
OCR1A = red;
OCR1B = green;
OCR2 = blue;
}
else if (iProg==0) //RGB-Werte verarbeiten Prog 0
{
//Helligkeit Multiplizieren für Prog 0
red = ((bri + 1) * red_val) >> 6;
green = ((bri + 1) * green_val) >> 6;
blue = ((bri + 1) * blue_val) >> 6;
pwm_10_64(red, 1);
pwm_10_64(green, 2);
pwm_10_64(blue, 3);
}
else if (iProg==9) //ohne Helligkeitsregelung
{
//direkte Ausgabe der Werte
pwm_10_64(red_val, 1);
pwm_10_64(green_val, 2);
pwm_10_64(blue_val, 3);
}
//else Fernbedienung
} //while
return 0;
}
|

