www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RGB LED Algorithmus zur Farberzeugung


Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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
if(ucDirR == 0)
      {
        if(uiR < ucMax) uiR+=2;
        else ucDirR = 1;
      }
      else
      {
        if(uiR > 2) uiR--;
        else ucDirR = 0;
      }
      
      if(ucDirG == 0)
      {
        if(uiG < ucMax) uiG+=2;
        else ucDirG = 1;
      }
      else
      {
        if(uiG > 2) uiG-=2;
        else ucDirG = 0;
      }
      
      if(ucDirB == 0)
      {
        if(uiB < ucMax) uiB++;
        else ucDirB = 1;
      }
      else
      {
        if(uiB > 2) uiB--;
        else ucDirB = 0;
      }
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

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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-curv...

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

Autor: Maxxie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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
if ( S == 0 )                       //HSL from 0 to 1
{
   R = L * 255                      //RGB results from 0 to 255
   G = L * 255
   B = L * 255
}
else
{
   if ( L < 0.5 ) var_2 = L * ( 1 + S )
   else           var_2 = ( L + S ) - ( S * L )

   var_1 = 2 * L - var_2

   R = 255 * Hue_2_RGB( var_1, var_2, H + ( 1 / 3 ) )
   G = 255 * Hue_2_RGB( var_1, var_2, H )
   B = 255 * Hue_2_RGB( var_1, var_2, H - ( 1 / 3 ) )
}

Hue_2_RGB( v1, v2, vH )             //Function Hue_2_RGB
{
   if ( vH < 0 ) vH += 1
   if ( vH > 1 ) vH -= 1
   if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH )
   if ( ( 2 * vH ) < 1 ) return ( v2 )
   if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 )
   return ( v1 )
}

was ist der rückgabe wert v1?

kann mir bitte jemand helfen den code umzustellen?

Autor: Maxxie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
// Sei fp ein fixed-point Datentyp
// fpmul, fpdiv die multiplikation/division zweier fp werte
// fp(int) die Wandlung von int zu fp
// fp2u8(fp) wandelt fixed point in u8, schneidet fractions ab

fp Hue_2_RGB(fp v1,fp v2,fp vH )             //Function Hue_2_RGB
{
   if ( vH < 0 ) vH += fp(1) ;
   if ( vH > 1 ) vH -= fp(1) ;
   if ( ( 6 * vH ) < 1 ) return ( v1 + fpmul(fpmul(( v2 - v1 ),fp(6)),vH)) ;
   if ( ( 2 * vH ) < 1 ) return ( v2 ) ;
   if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ), fpmul(( fpdiv((fp(2),fp(3)) ) - vH ),fp(6)) ;
   return ( v1 ) ;
}

void HSL2RGB(u8 h, u8 s, u8 l, u8 &r, u8 &g, u8 &b)
{
  if ( S == 0 )                       //HSL from 0 to 1
  {
     r = fp2u8(fpmul(l,fp(255)));                      //RGB results from 0 to 255
     g = fp2u8(fpmul(l,fp(255)));
     b = fp2u8(fpmul(l,fp(255)));
  }
  else
  {
    u16 var_1,var_2 ;
    if ( l < fpdiv(fp(1),fp(2)) ) var_2 = fpmul(l,( fp(1) + s )) ;
    else           var_2 = ( l + s ) - fpmul(s,l ) ;
  
    var_1 = fpmul(fp(2),l) - var_2 ;
  
     r = fpmul(fp(255) , Hue_2_RGB( var_1, var_2, h + ( 1 / 3 ) )) ;
     g = fpmul(fp(255) , Hue_2_RGB( var_1, var_2, h )) ;
     b = fpmul(fp(255) , Hue_2_RGB( var_1, var_2, h - ( 1 / 3 ) )) ;
  }
}

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm ok dan nehm ich also Float...

Doch wie müsste dan mein code aussehen?

Irgendwie erscheind mir der grundcode etwas kryptisch...

Autor: Maxxie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
typedef fp u16;

fp u8tofp(u8 wert)
{
  return (fp)wert * 256 ;
}

u8 fptou8(fp wert)
{
  return (u8)(wert / 256) ;
}

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)
fp fpmul(a,b)
{
  return (fp)((u32)(a * b) / 256) ;
}

fp fpdiv(a,b)
{
  return (fp)((u32)(256 * a) / b) ;
}

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hier hast du das ganze in  integer:
#define HUE_MAX  (6*256)

/**
 *  generates the waveform for the green color 
 */
static inline uint8 hueWaveform(uint16 x)
{
  if(x < HUE_MAX/6){
    return x*((256*6)/HUE_MAX);
  }else if(x< (HUE_MAX*3)/6){
    return 255;
  }else if(x< (HUE_MAX*4)/6){
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
  }else{
    return 0;
  }
}

/**
 * generates rgb from hue with saturation 1 and brightness 1
 */
static inline void hue2rgb(
              uint16 h, /*uint8  s, uint8  v,*/
              uint8* r,  uint8* g,  uint8* b
              /* ,sint32 relsat= -1 */ )
{
  uint8 gr = hueWaveform(h);
  *g = gr;  
//  *g = (gr>50)?gr-50:0; // hack because green is too bright
  *b = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
  *r = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
}


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

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für dein Code

ich hab den mal so angepasst
unsigned char hueWaveform(unsigned int x)
{
  if(x < HUE_MAX/6){
    return x*((256*6)/HUE_MAX);
  }else if(x< (HUE_MAX*3)/6){
    return 255;
  }else if(x< (HUE_MAX*4)/6){
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
  }else{
    return 0;
  }
}

/**
 * generates rgb from hue with saturation 1 and brightness 1
 */
void hue2rgb(unsigned int h, /*uint8  s, uint8  v,*/unsigned char* r,  unsigned char* g,  unsigned char* b/* ,sint32 relsat= -1 */ )
{
  unsigned char gr = hueWaveform(h);
  *g = gr;  
//  *g = (gr>50)?gr-50:0; // hack because green is too bright
  *b = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
  *r = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
}

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

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht 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
>
>
> ...
> 
>
> 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:HS...

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.

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Vlad Tepesch (vlad_tepesch)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
  MODE_fade = 0,  /* walk through hue-cycle */

  MODE_red          ,  /* simple colors */
  MODE_green        ,
  MODE_yellow       ,
  MODE_blue         ,
  MODE_violet       ,
  MODE_cyane        ,
  MODE_white        ,

  MODE_fade_pulse   ,  /* walk pulsing through hue-cycle */
  MODE_red_pulse    ,  /* pulsing colors */
  MODE_green_pulse  ,
  MODE_yellow_pulse ,
  MODE_blue_pulse   ,
  MODE_violet_pulse ,
  MODE_cyane_pulse  ,
  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...
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.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich amache das so

uiR = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
uiG = hueWaveform(h);
uiB = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);

if(h == 1530) h=0;
else h++;
unsigned char hueWaveform(unsigned int x)
{
  if(x < HUE_MAX/6){
    return x*((256*6)/HUE_MAX);
  }else if(x< (HUE_MAX*3)/6){
    return 255;
  }else if(x< (HUE_MAX*4)/6){
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
  }else{
    return 0;
  }
}

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Claudio H. schrieb:
> also ich amache das so
>
>

> if(h == 1530) h=0;
> else h++;
> 
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

Autor: Claudio H. (hedie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok habs angepasst
#include <avr/io.h>    
#include <util/delay.h>

#define G_AUS     PORTB |= (1<<PB0);      //Alles Invertiert da PNP Transistor!
#define G_EIN     PORTB &= ~(1<<PB0);
#define R_AUS    PORTB |= (1<<PB1);
#define R_EIN    PORTB &= ~(1<<PB1);
#define B_AUS    PORTB |= (1<<PB2);
#define B_EIN    PORTB &= ~(1<<PB2);

#define SW_DOWN      (PIND & (1<<PIND3))
#define SW_SET      (PIND & (1<<PIND4))
#define SW_UP      (PIND & (1<<PIND2))

#define HUE_MAX  (6*256)

/**
 *  generates the waveform for the green color 
 */
unsigned char hueWaveform(unsigned int x)
{
  if(x < HUE_MAX/6){
    return x*((256*6)/HUE_MAX);
  }else if(x< (HUE_MAX*3)/6){
    return 255;
  }else if(x< (HUE_MAX*4)/6){
    return (((HUE_MAX*4)/6)-1-x)*((256*6)/HUE_MAX);
  }else{
    return 0;
  }
}

/**
 * generates rgb from hue with saturation 1 and brightness 1
 */
void hue2rgb(unsigned int h, /*uint8  s, uint8  v,*/unsigned int* r,  unsigned int* g,  unsigned int* b/* ,sint32 relsat= -1 */ )
{
  unsigned char gr = hueWaveform(h);
  *g = gr;  
//  *g = (gr>50)?gr-50:0; // hack because green is too bright
  *b = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
  *r = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
}


void main(void)
{
  DDRB = 0xFF;      //Alles Ausgänge
  DDRD = 0x00;      //Alles Eingänge
  
  unsigned int  uiCount = 0;
  unsigned int   uiR    = 290;
  unsigned int  uiG    = 290;
  unsigned int  uiB    = 290;
  
  unsigned int  uiMax  = 300;
  unsigned char  ucLoop  = 10;
  unsigned char  ucCount  = 0;
  
  unsigned int   h    = 0;
  
  G_AUS;
  R_AUS;
  B_AUS;
  
  while(1)        //Endlos
  {
    uiCount = 0;
    G_EIN;
    R_EIN;
    B_EIN;
    
    uiR = hueWaveform((h+HUE_MAX/3)%HUE_MAX );
    uiG = hueWaveform(h);
    uiB = hueWaveform((h+2*HUE_MAX/3)%HUE_MAX);
    
    if(ucCount == ucLoop)
    {
      ucCount = 0;
      if(h == HUE_MAX) h=0;
      else h++;
    }
    
    ucCount ++;
    
    while(uiCount != uiMax)
    {
      uiCount ++;
      if(uiCount == uiR) R_AUS;
      if(uiCount == uiG) G_AUS;
      if(uiCount == uiB) B_AUS;
    }
  }
}

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo schreibt ihr eigentlich alle so ab?
)((256*6)/HUE_MAX);

wie wäre es mit 1?

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.