Forum: Mikrocontroller und Digitale Elektronik RGB LED Algorithmus zur Farberzeugung


von C. H. (hedie)


Lesenswert?

Hallo

Ich habe mir mit einer 3W Led ein RGB Licht gebaut...

Funktioniert alles suuper... auch das Mischen der farben...

Doch derzeit habe ich noch sehr "statische" farb muster...

Ich verwende folgenden Code
1
if(ucDirR == 0)
2
      {
3
        if(uiR < ucMax) uiR+=2;
4
        else ucDirR = 1;
5
      }
6
      else
7
      {
8
        if(uiR > 2) uiR--;
9
        else ucDirR = 0;
10
      }
11
      
12
      if(ucDirG == 0)
13
      {
14
        if(uiG < ucMax) uiG+=2;
15
        else ucDirG = 1;
16
      }
17
      else
18
      {
19
        if(uiG > 2) uiG-=2;
20
        else ucDirG = 0;
21
      }
22
      
23
      if(ucDirB == 0)
24
      {
25
        if(uiB < ucMax) uiB++;
26
        else ucDirB = 1;
27
      }
28
      else
29
      {
30
        if(uiB > 2) uiB--;
31
        else ucDirB = 0;
32
      }
ucDir gibt die richtung an ob heller oder dunkler
uiR,G,B sind die Variablen der Helligkeiten der entsprechenden farben

Ich wollte fragen, wie ich am einfachsten alle möglichen farben einmal 
durchgehen kann...

Danke schonmal

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Lustig wär das bestimmt mit ner 3D-Version der  Peano-Kurve
   http://de.wikipedia.org/wiki/Peano-Kurve

http://commons.wikimedia.org/wiki/Image:Peano-curve_animated_%28140x120%29.gif

Mit der Peano-Kurve kann man R stetig und invertierbar nach R^2 und also 
auch nach R^3 abbilden. Dein RGB-Farbraum (oder HVV-Farbraum) ist ja ein 
Teil des R^3.

Das ist auf jedenfall intesessanter, als ne 24-Bit Variable laufen zu 
lassen und die einzelnen Bytes als R, G und B zu inerpretieren, weil 
dabei Farbsprünge entstehen, die alles verwaschen bei schnellem 
Durchlauf.

Johann

von Maxxie (Gast)


Lesenswert?

Eine Standard-Lösung ist die Umrechnung von HSL zu RGB Farbwerten.

HSL (Hue, Saturation, Lumination), hier gibst du einfach S und L 
konstant vor, und variierst den Farbton (Einfach durchlaufen lassen) 
umrechnen in RGB und für die Ausgabe nutzen.

http://www.easyrgb.com/index.php?X=MATH&H=19#text19

Damit solltest du alle Farben der geordnet Farbkreises durchgehen 
können, ohne Helligkeits/Blendvariationen.

von C. H. (hedie)


Lesenswert?

Vielen dank für die antworten...

beim Link für die HSL zu RGB konversation blick ich leider noch nicht 
ganz durch...

das ist ja der code
1
if ( S == 0 )                       //HSL from 0 to 1
2
{
3
   R = L * 255                      //RGB results from 0 to 255
4
   G = L * 255
5
   B = L * 255
6
}
7
else
8
{
9
   if ( L < 0.5 ) var_2 = L * ( 1 + S )
10
   else           var_2 = ( L + S ) - ( S * L )
11
12
   var_1 = 2 * L - var_2
13
14
   R = 255 * Hue_2_RGB( var_1, var_2, H + ( 1 / 3 ) )
15
   G = 255 * Hue_2_RGB( var_1, var_2, H )
16
   B = 255 * Hue_2_RGB( var_1, var_2, H - ( 1 / 3 ) )
17
}
18
19
Hue_2_RGB( v1, v2, vH )             //Function Hue_2_RGB
20
{
21
   if ( vH < 0 ) vH += 1
22
   if ( vH > 1 ) vH -= 1
23
   if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH )
24
   if ( ( 2 * vH ) < 1 ) return ( v2 )
25
   if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 )
26
   return ( v1 )
27
}

was ist der rückgabe wert v1?

kann mir bitte jemand helfen den code umzustellen?

von Maxxie (Gast)


Lesenswert?

Das ist natürlich Pseudocode.

Grundsätzlich:
r,g,b haben darin eine Spanne von 0..255, ordinal, ganzzahlig
die vars/h,s,l sind zahlen mit Komma, hsl im Bereich von 0.0-1.0

Hue2RGB (also dein return v1) gibt dir zu den ersten beiden Parametern 
den Farbanteil in eine bestimmte Richtung an. Auch wieder von 0.0 bis 
1.0. Ist ein wenig Trigonometrie. Kann mit anderen 3. Parametern auch 
verwendet werden um z.B. CMYK Anteile zu erzeugen.

Am einfachsten (aber für den uC am langsamsten) kannst du das einfach 
per float Variablen umsetzen. Ansonsten empfehle ich fixed-point für 
alles ausser rgb.

Ganz grob:
1
// Sei fp ein fixed-point Datentyp
2
// fpmul, fpdiv die multiplikation/division zweier fp werte
3
// fp(int) die Wandlung von int zu fp
4
// fp2u8(fp) wandelt fixed point in u8, schneidet fractions ab
5
6
fp Hue_2_RGB(fp v1,fp v2,fp vH )             //Function Hue_2_RGB
7
{
8
   if ( vH < 0 ) vH += fp(1) ;
9
   if ( vH > 1 ) vH -= fp(1) ;
10
   if ( ( 6 * vH ) < 1 ) return ( v1 + fpmul(fpmul(( v2 - v1 ),fp(6)),vH)) ;
11
   if ( ( 2 * vH ) < 1 ) return ( v2 ) ;
12
   if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ), fpmul(( fpdiv((fp(2),fp(3)) ) - vH ),fp(6)) ;
13
   return ( v1 ) ;
14
}
15
16
void HSL2RGB(u8 h, u8 s, u8 l, u8 &r, u8 &g, u8 &b)
17
{
18
  if ( S == 0 )                       //HSL from 0 to 1
19
  {
20
     r = fp2u8(fpmul(l,fp(255)));                      //RGB results from 0 to 255
21
     g = fp2u8(fpmul(l,fp(255)));
22
     b = fp2u8(fpmul(l,fp(255)));
23
  }
24
  else
25
  {
26
    u16 var_1,var_2 ;
27
    if ( l < fpdiv(fp(1),fp(2)) ) var_2 = fpmul(l,( fp(1) + s )) ;
28
    else           var_2 = ( l + s ) - fpmul(s,l ) ;
29
  
30
    var_1 = fpmul(fp(2),l) - var_2 ;
31
  
32
     r = fpmul(fp(255) , Hue_2_RGB( var_1, var_2, h + ( 1 / 3 ) )) ;
33
     g = fpmul(fp(255) , Hue_2_RGB( var_1, var_2, h )) ;
34
     b = fpmul(fp(255) , Hue_2_RGB( var_1, var_2, h - ( 1 / 3 ) )) ;
35
  }
36
}

von C. H. (hedie)


Lesenswert?

Vielen Dank für deine Antwort....

Also ich habe schon einige erfahrungen in C Programmierung
jedoch weiss ich nur sehr entfernt was FixedPoint ist...

Doch die eigentliche neue frage ist... Wie ich den Code zum laufen 
bekommen kann....

Weil wenn ich ihn übernehme gibts fehler :(

von Karl H. (kbuchegg)


Lesenswert?

Ganz ehrlich.
Bei deiner Anwendung würd ich nicht lange fackeln und floating point 
nehmen. So ein durchdimmendes Licht ist ja nicht gerade high speed. Ob 
der µC jetzt Däumchen dreht oder ob er 3 Hunderstel Sekunden länger für 
die Berechnung braucht, spielt absolut keine Rolle.

Nichtd gegen Fixpunkt Arithmetik. Aber wenn der µC sowieso massig Zeit 
hat ...

> jedoch weiss ich nur sehr entfernt was FixedPoint ist...

Im Grunde nimmst du einfach ein geeignetes Vielfaches und rechnest in 
Integer. Du kannst zb. für dich definieren, dass 256 einer 1.0 
entsprechen soll.
Addition und Subtraktion gehen wie gehabt.

  128 + 128 = 256
  (0.5 + 0.5 = 1.0)

  200 - 80 = 120
  (0.78125 - 0.3125 = 0.46875)

Nur bei Multiplikation und Division muss man aufpassen

  0.2 * 0.8 = 0.16
  ( 51 * 204 ) / 256 = 40

> Wie ich den Code zum laufen bekommen kann....

Indem du dir einen Integer Datentyp für fp aussuchst und die Funktionen 
fpmul und fpdiv definierst.

Aber wie gesagt: Ich würd ganz einfah die float Varianten nehmen.

von C. H. (hedie)


Lesenswert?

Hmmm ok dan nehm ich also Float...

Doch wie müsste dan mein code aussehen?

Irgendwie erscheind mir der grundcode etwas kryptisch...

von Maxxie (Gast)


Lesenswert?

Ja, hab auch noch ein paar gesehen, die ich eingebaut habe auf die 
Schnelle.

FixedPoint Rechnung geht wie früher in der Schule, wenn man durch 
Kommazahlen schriftlich teilen sollte.

Statt mit den Komazahlen zu rechnen, wurden beide Seiten mit 10, 100, 
1000 ... multipliziert, bis das Komma verschwunden war. Kann man im 
Computer natürlich auch, nur nimmt man hier 2,4,8, ...

Und um die Sache einfacher zu machen nimmt man immer die selbe Zahl mit 
der man multipliziert (fixed), und lässt alles weitere hinter dem Komma 
wegfallen. Die Umwandlung von einem fp zu einem "normalen" Wert ist also 
nur das multiplizieren/teilen mit dieser Konstante

Beispiel mit 256:
1
typedef fp u16;
2
3
fp u8tofp(u8 wert)
4
{
5
  return (fp)wert * 256 ;
6
}
7
8
u8 fptou8(fp wert)
9
{
10
  return (u8)(wert / 256) ;
11
}

Beim Addieren kann man die normaln Addition nutzen:
fptou8(u8tofp(a) + u8tofp(a)) = (a*256 + b*256) / 256 = (a + b) * 256 / 
256 = a + b

Sprich +/- sind lineare Abbildungen unter fp

Beim Multiplizieren/Dividieren ist das etwas schwieriger. Da benötigt es 
eine Korrektur:

fptou8(u8tofp(a) * u8tofp(a)) = (a*256) * (b*256) / 256 = (a*b) * 
256*256/256 = a*b*256, also zuviel. Deswegen braucht es hier eine 
Korrektur des Ergebnisses (analog bei der Division)
1
fp fpmul(a,b)
2
{
3
  return (fp)((u32)(a * b) / 256) ;
4
}
5
6
fp fpdiv(a,b)
7
{
8
  return (fp)((u32)(256 * a) / b) ;
9
}

von Vlad T. (vlad_tepesch)


Lesenswert?

hier hast du das ganze in  integer:
1
#define HUE_MAX  (6*256)
2
3
/**
4
 *  generates the waveform for the green color 
5
 */
6
static inline uint8 hueWaveform(uint16 x)
7
{
8
  if(x < HUE_MAX/6){
9
    return x*((256*6)/HUE_MAX);
10
  }else if(x< (HUE_MAX*3)/6){
11
    return 255;
12
  }else if(x< (HUE_MAX*4)/6){
13
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
14
  }else{
15
    return 0;
16
  }
17
}
18
19
/**
20
 * generates rgb from hue with saturation 1 and brightness 1
21
 */
22
static inline void hue2rgb(
23
              uint16 h, /*uint8  s, uint8  v,*/
24
              uint8* r,  uint8* g,  uint8* b
25
              /* ,sint32 relsat= -1 */ )
26
{
27
  uint8 gr = hueWaveform(h);
28
  *g = gr;  
29
//  *g = (gr>50)?gr-50:0; // hack because green is too bright
30
  *b = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
31
  *r = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
32
}

bin mir allerdings nicht sicher, ob das ganze noch funktioniert, wenn 
HUE_MAX geändert wird.
Ich hatte da noch arg dran rumoptimiet, da mein tiny15 voll war

von C. H. (hedie)


Lesenswert?

Danke für dein Code

ich hab den mal so angepasst
1
unsigned char hueWaveform(unsigned int x)
2
{
3
  if(x < HUE_MAX/6){
4
    return x*((256*6)/HUE_MAX);
5
  }else if(x< (HUE_MAX*3)/6){
6
    return 255;
7
  }else if(x< (HUE_MAX*4)/6){
8
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
9
  }else{
10
    return 0;
11
  }
12
}
13
14
/**
15
 * generates rgb from hue with saturation 1 and brightness 1
16
 */
17
void hue2rgb(unsigned int h, /*uint8  s, uint8  v,*/unsigned char* r,  unsigned char* g,  unsigned char* b/* ,sint32 relsat= -1 */ )
18
{
19
  unsigned char gr = hueWaveform(h);
20
  *g = gr;  
21
//  *g = (gr>50)?gr-50:0; // hack because green is too bright
22
  *b = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
23
  *r = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
24
}

es gibt auch keine fehler doch nun meine frage...

Weshalb hast du für grün etwas eigenes geschaffen?

Bei mir verhält sich grün sehr linear zu den anderen farben...
wie muss ich den code anpassen das das grün "normal" behandelt wird?

Entsprechen die variablen r, g, b meinen variablenverten für die 
helligkeit?

Von wo bis wo muss ich h durchlaufen lassen um ein schönes farbspektrum 
zu erreichen?

danke schonmal

von Vlad T. (vlad_tepesch)


Lesenswert?

Das wollte ich noch nachreichen:
Erklärung:
zwischen 0 und HUE_MAX (1536) wird einmal der gesammte kreis 
durchlaufen,
HUE_MAX ist jetzt so gewählt, dass die anstiege der Farben immer 1 bzW 
-1 sind.
wenn man HUE_MAX auf 256 setzt, kann man auch h auf uint8 setzen. Das 
sollte etwas code sparen, sieht dann aber nicht mehr so gut aus, da der 
anstieg immer 6 (bzw -6) ist. Vor allem im unteren Bereich fällt das 
auf.

Auch wird nicht berücksichtigt, dass unser helligkeitsempfinden 
nichtlinear ist und unterschiedliche Farben unterschiedlich hell 
wahrgenommen werden. (-> siehe hack mit g= g -50 :-)

Claudio H. schrieb:
> Danke für dein Code
>
> ich hab den mal so angepasst
>
>
1
> ...
2
>
>
> es gibt auch keine fehler doch nun meine frage...
>
> Weshalb hast du für grün etwas eigenes geschaffen?
wie was eigenes?
meisnt du den aukommentierten hack? siehe obige erklärung.
Auußerdem hat das grün in meiner rgb-led ne höhere leuchtkraft.


>
> Bei mir verhält sich grün sehr linear zu den anderen farben...
> wie muss ich den code anpassen das das grün "normal" behandelt wird?

der hack ist doch auskommentiert.
sollte also alles gleichbehandelt werden.

die funktion hueWafeform erzeugt den Verlauf für die grüne Kurve
http://de.wikipedia.org/w/index.php?title=Datei:HSV-RGB-comparison.svg&filetimestamp=20060830160028

Da die Kurve für alle Farben gleich aussieht und nur phasenverschoben 
ist.
Können alle anderen Farben auch damit berechnet werden.

>
> Entsprechen die variablen r, g, b meinen variablenverten für die
> helligkeit?
die entsprechen den RGB wert, also quasi dem Wert, den du in die PWM 
geben musst (bzw den invertierten, wenn deine PWM invertiert ist)
>
> Von wo bis wo muss ich h durchlaufen lassen um ein schönes farbspektrum
> zu erreichen?
>
> danke schonmal
siehe oben.

von C. H. (hedie)


Lesenswert?

Hey Vielen Dank!

Funktioniert wunderbar...

bis auf eine kleinigkeit...

Es gibt zwischendurch farbsprünge... Kann man die irgendwie vermeiden 
oder hab ich was falsch programmiert?

von Vlad T. (vlad_tepesch)


Angehängte Dateien:

Lesenswert?

hier mein ganzes projekt, falls es dich interessiert.
ziel ist ein tiny13, läuft aber nach wenigen anpassungen sicher auch auf 
anderen.

die leds können frei über den Port verteilt werden, wichitg ist nur, 
dass der schalter an int0 sitzt.

ein druck auf den schalter wechselt den modus:
1
  MODE_fade = 0,  /* walk through hue-cycle */
2
3
  MODE_red          ,  /* simple colors */
4
  MODE_green        ,
5
  MODE_yellow       ,
6
  MODE_blue         ,
7
  MODE_violet       ,
8
  MODE_cyane        ,
9
  MODE_white        ,
10
11
  MODE_fade_pulse   ,  /* walk pulsing through hue-cycle */
12
  MODE_red_pulse    ,  /* pulsing colors */
13
  MODE_green_pulse  ,
14
  MODE_yellow_pulse ,
15
  MODE_blue_pulse   ,
16
  MODE_violet_pulse ,
17
  MODE_cyane_pulse  ,
18
  MODE_white_pulse  ,

wird der schalter länger gedrückt blinkt es schnell rot und das licht 
wird ausgeschalten, wenn man losläßt.
Hält man weiter gedrückt, kann man eine Abschaltzeit in 7,5min schritten 
einstellen.
es blinkt einmal blau -> wenn man jetzt losläßt gehts in 7.5 min aus.
hällt man weiter gedrückt
blinkt es 2 mal blau -> wenn man jetzt losläßt gehts in 15 min aus.
und so weiter bis max 6 mal.

der MODE_fade_pulse  flackert aber ein bisschen bei einem Farbübergang 
im unteren helligkeitsbereich. Die ursache habe ich noch nicht gefunden.

Der Code ist teilweise etwas umständlich, das liegt daran, dass ich 
manche sachen umformuliert hab, damit es noch in das 1k reinpasst


das ganze werklet bei mir mit 3 RGB-LEDs in so einem Cube:
http://www.instructables.com/id/How-to-Make-a-TRON-Style-Lamp-The-MADYLIGHT/
der schalter ist ein in einer ecke angebrachter reedkontakt, so dass von 
außen mittels eines Magneten geschalten werden kann, ohne dass ein 
schalter die Optik beeiträchigt.

von Vlad T. (vlad_tepesch)


Lesenswert?

Claudio H. schrieb:
> Hey Vielen Dank!
>
> Funktioniert wunderbar...
>
> bis auf eine kleinigkeit...
>
> Es gibt zwischendurch farbsprünge... Kann man die irgendwie vermeiden
> oder hab ich was falsch programmiert?

Da hast du bestimmt was falsch gemacht. farbsprünge sollte es keine 
geben.
läufst du wirklich mit einer 16bit variable von 0-(HUE_MAX-1) und setzt 
sie danach wieder auf 0?

EDIT:

ergänzung zum Code:
das Licht wird mit dem schalter wieder eingeschalten.
deswegen der int0, um den tiny wieder aufzuwecken.

Der würfel wwird bei mir mit 4*AAA 900mAh akkus versorgt und ist schon 
einige stungen gelaufen und wochenlang rumgestanden.
Bisher musste ich nicht aufladen

von C. H. (hedie)


Lesenswert?

also ich amache das so
1
uiR = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
2
uiG = hueWaveform(h);
3
uiB = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
4
5
if(h == 1530) h=0;
6
else h++;
1
unsigned char hueWaveform(unsigned int x)
2
{
3
  if(x < HUE_MAX/6){
4
    return x*((256*6)/HUE_MAX);
5
  }else if(x< (HUE_MAX*3)/6){
6
    return 255;
7
  }else if(x< (HUE_MAX*4)/6){
8
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
9
  }else{
10
    return 0;
11
  }
12
}

von Vlad T. (vlad_tepesch)


Lesenswert?

Claudio H. schrieb:
> also ich amache das so
>
>
1
> if(h == 1530) h=0;
2
> else h++;
3
>
wiso testest du nicht auf h==HUE_MAX?

aber die fehlenden 6 Stufen sollte nix ausmachen.

da müsstest du den ganzen code zeigen.
Ich vermute irgendwelche verschluckten interupts

von C. H. (hedie)


Lesenswert?

ok habs angepasst
1
#include <avr/io.h>    
2
#include <util/delay.h>
3
4
#define G_AUS     PORTB |= (1<<PB0);      //Alles Invertiert da PNP Transistor!
5
#define G_EIN     PORTB &= ~(1<<PB0);
6
#define R_AUS    PORTB |= (1<<PB1);
7
#define R_EIN    PORTB &= ~(1<<PB1);
8
#define B_AUS    PORTB |= (1<<PB2);
9
#define B_EIN    PORTB &= ~(1<<PB2);
10
11
#define SW_DOWN      (PIND & (1<<PIND3))
12
#define SW_SET      (PIND & (1<<PIND4))
13
#define SW_UP      (PIND & (1<<PIND2))
14
15
#define HUE_MAX  (6*256)
16
17
/**
18
 *  generates the waveform for the green color 
19
 */
20
unsigned char hueWaveform(unsigned int x)
21
{
22
  if(x < HUE_MAX/6){
23
    return x*((256*6)/HUE_MAX);
24
  }else if(x< (HUE_MAX*3)/6){
25
    return 255;
26
  }else if(x< (HUE_MAX*4)/6){
27
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
28
  }else{
29
    return 0;
30
  }
31
}
32
33
/**
34
 * generates rgb from hue with saturation 1 and brightness 1
35
 */
36
void hue2rgb(unsigned int h, /*uint8  s, uint8  v,*/unsigned int* r,  unsigned int* g,  unsigned int* b/* ,sint32 relsat= -1 */ )
37
{
38
  unsigned char gr = hueWaveform(h);
39
  *g = gr;  
40
//  *g = (gr>50)?gr-50:0; // hack because green is too bright
41
  *b = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
42
  *r = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
43
}
44
45
46
void main(void)
47
{
48
  DDRB = 0xFF;      //Alles Ausgänge
49
  DDRD = 0x00;      //Alles Eingänge
50
  
51
  unsigned int  uiCount = 0;
52
  unsigned int   uiR    = 290;
53
  unsigned int  uiG    = 290;
54
  unsigned int  uiB    = 290;
55
  
56
  unsigned int  uiMax  = 300;
57
  unsigned char  ucLoop  = 10;
58
  unsigned char  ucCount  = 0;
59
  
60
  unsigned int   h    = 0;
61
  
62
  G_AUS;
63
  R_AUS;
64
  B_AUS;
65
  
66
  while(1)        //Endlos
67
  {
68
    uiCount = 0;
69
    G_EIN;
70
    R_EIN;
71
    B_EIN;
72
    
73
    uiR = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
74
    uiG = hueWaveform(h);
75
    uiB = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
76
    
77
    if(ucCount == ucLoop)
78
    {
79
      ucCount = 0;
80
      if(h == HUE_MAX) h=0;
81
      else h++;
82
    }
83
    
84
    ucCount ++;
85
    
86
    while(uiCount != uiMax)
87
    {
88
      uiCount ++;
89
      if(uiCount == uiR) R_AUS;
90
      if(uiCount == uiG) G_AUS;
91
      if(uiCount == uiB) B_AUS;
92
    }
93
  }
94
}

von Vlad T. (vlad_tepesch)


Lesenswert?

das sieht komich aus, was du da machst.
Blick da auch grad nicht durch.

das gibt schon mindestens deswegen komische effekte, da nicht alle 
Codezweige gleichschnell abgearbeitet werden können.
das heißt für bestimmte x braucht huewaveform länger, für andere kürzer.

mache eine hauptschleife, die eine globale volatile variable abfragt, 
die im timerinterrupt alle x interupts gesetzt.
Das schalten der LEDs gegört in die timer-ISR, damit das immer schön 
gleichmäßig passiert.

schau dir den von mir geposteten Code aus dem Zip mal an.

Folgende schritte müssen gemacht werden:

gloabele volatile variable nextAnimStep
gloabele volatile variablen r,g,b
Timer aufsetzen

in timer ISR:
internen statichen zähler hochzählen und bei bestimmten wert(abhängig 
davon wie schnell der farbwechsel sein soll) zurücksetzen, sowie 
nextAnimStep auf true setzen

die PWM (auch in der ISR)
anderer statischer uint8 zähler immer nur hochzählen
die rgb variablen jeweils extra vergleichen, ob sie kleiner sind als 
dieser Zähler und gebenenfalls auschalten, sonst anschalten.


das hauptprogramm dreht in einer while(1)schleife runden und fragt immer 
ab, ob der nächste schritt gemacht werden soll, falls ja berechnen neue 
rgb, werte und schreibe sie in die globalen rgb, variablen.
setze die nextAnimStep wieder auf false.

die hier verwendete PWM ist eine reine Software-PWM
Wennn den µC noch 3 freie PWMs hat, kannst du natürlich auch die nehmen, 
du musst dann nur den neuen rgb-wert in die Compareregister schreiben 
und kannst dir die globalen rgbvariaben sparen

von Gast (Gast)


Lesenswert?

Wo schreibt ihr eigentlich alle so ab?
1
)((256*6)/HUE_MAX);

wie wäre es mit 1?

von Vlad T. (vlad_tepesch)


Lesenswert?

Denkst du eigendlich mal nach, bevor du postest?

1. ist der Code selbstgeschrieben
2. optimiert der Compiler das weg
3. dann funktioniert das ganze mit 1 aber nicht mehr, wenn du HUE_MAX 
auf 256 änderst, weil du in 8bit bleiben willst. Da sind die benötigten 
Anstiege um trotzdem auf 255 Helligkeit zu kommen andere. Würde da ne 1 
stehen,  würde er nur bis 43, oder so gehen, anstatt auf 255.

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.