Arduino


von Prof. Jürgen Plate

Farbwechsel

Mit drei LEDs in den Farben rot, grün und blau oder einer RGB-LED, bei der die drei LED-Farben in einem Gehäse vereint sind, läßt sich ein Regenbogen-Farbwechsel realisieren. In der Funktion setLeds() gibt es eine sinnvolle Anwendung der Speicherklasse static. Die aktuellen LED-Farbintensitäten werden in den Variablen red, green und blue von Aufruf zu Aufruf weitergegeben. Ohne static funktioniert es nicht, es würde immer mit Rot begonnen werden. Die Funktion kann mit Werten zwischen 0 und 764 aufgerufen werden.
// Pinzuordnung der LEDs
#define LEDBlau  11
#define LEDGruen 10
#define LEDRot   9

void setup()
  {
  pinMode(LEDBlau, OUTPUT);
  pinMode(LEDGruen, OUTPUT);
  pinMode(LEDRot, OUTPUT);
  }

void loop()
  {
  int licht;
  for (licht = 0; licht < 765; licht++)
    {
    setLEDs(licht);
    delay(20);
    }
  }

void setLEDs(int i)
  {
  // Farbwerte mit Vorbesetzung, begonnen wird mit rot
  static int red   = 255;
  static int green = 0;
  static int blue  = 0;

  if (i < 255)      // Phase 1: von rot nach grün
    {
    red--;       // red down
    green++;     // green up
    blue = 0;    // blue low
    }
  else if (i < 510) // Phase 2: von grün nach blau
    {
    red = 0;     // red low
    green--;     // green down
    blue++;      // blue up
    } 
  else if (i < 766) // Phase 3: von blau nach rot
    {
    red++;       // red up
    green = 0;   // green low
    blue--;      // blue down
    }
  analogWrite(LEDRot,   red);
  analogWrite(LEDGruen, green);
  analogWrite(LEDBlau,  blue);
  }
In vorangegangenen Beispiel sind die Farbübergänge zwischen den LEDs nicht gleichmäßig. Das liegt daran, dass das Auge die Lichtintensität nicht linear, sondern eher logarithmisch wahrnimmt. Ist die LED ganz dunkel, werden kleine Änderungen gut wahrgenommen, ist die LED dagegen schon ziemlich hell, merkt man die Zu- oder Abnahme erst nach mehreren Schritten.

Um das auszugleichen, kann bei der Ausgabe der Farbwert entsprechend angepasst werden. Dies erfolgt am Besten mithilfe einer Umrechnungstabelle, die in einem Array gespeichert wird. So ist es im folgenden Programm realisiert. Die Umcodierung erfolgt in der Funktion setColor(), in der auch die Ausgabe erfolgt.

In setLEDs() wird dann der auszugebende Farbwert berechnet. Im Gegensatz zum vorhergehenden Programm kann hier jeder individuelle Wert gesetzt werden. Für die Eingabewerte von 0 bis 255 durchläuft die Funktion einmal den Farbkreis.

// Pinzuordnung der LEDs
#define LEDBlau  9
#define LEDGruen 10
#define LEDRot   11

void setup()
  {
  pinMode(LEDBlau, OUTPUT);
  pinMode(LEDGruen, OUTPUT);
  pinMode(LEDRot, OUTPUT);
  }

void loop()
  {
  int licht;
  for (licht = 0; licht < 256; licht++)
    {
    setLEDs(licht);
    delay(100);
    }
  }

// Wählt für einen Wert (0 .. 255) eine Farbe aus dem Farbkreis
void setLEDs(int value)
  {
  int red, green, blue;

  if(value < 64)           // rot nach gruen
    {
    red = 63 - value;
    green = value;
    blue = 0;
    }
  else if(value < 128)     // gruen nach blau
    {
    red = 0;
    green = 127 - value;
    blue = value - 64;
    }
  else if(value < 192)     // blau nach rot
    {
    red = value - 128;
    green = 0;
    blue = 191 - value;
    }
  else                     // rot nach weiss
    {
    red = 63;
    green = 255 - value;
    blue = 255 - value;
    }
  setColor(red, green, blue);
  }

// Stellt die LED-Helligkeiten logarithmisch ein
void setColor(int red, int green, int blue)
  {
  // Tabelle der Helligkeitswerte, 
  // logarithmisch ansteigend
  int logValue[64] = 
    { 0,  1,  2,  3,  4,  5,  6,  7,
      8,  9, 10, 11, 12, 13, 14, 16,
     18, 20, 22, 25, 28, 30, 33, 36,
     39, 42, 46, 53, 56, 60, 64, 68,
     72, 77, 81, 86, 90, 95,100,105,
     110,116,121,127,132,138,144,150,
     156,163,169,176,182,189,196,203,
     210,218,225,233,240,248,253,255  };

  analogWrite(LEDBlau, logValue[blue]);
  analogWrite(LEDGruen, logValue[green]);
  analogWrite(LEDRot, logValue[red]);
  }
Manchmal ist das RGB-Farbschema jedoch hinderlich. Es wäre viel praktischer, wenn man im Programm nur einen einzigen Wert für die Farbe hätte und nicht drei. Genau das erreichen Sie mit dem HSV-Farbschema. Der HSV-Farbraum beschreibt eine Farbe mit Hilfe des Farbtons (englisch hue), der Farbsättigung (saturation) und des Hellwerts (value).

Bei der Farbdarstellung wird der HSV-Farbraum gegenüber den Alternativen RGB (Rot, Grün, Blau) und CMYK (Cyan, Magenta, Yellow, Black) bevorzugt, weil es leichter fällt, eine Farbe zu finden: Man kann für die Farbmischung unmittelbar den Farbton wählen und dann entscheiden, wie gesättigt und wie hell (oder dunkel) dieser sein soll.

Für die Beschreibung des Farbortes im HSV-Farbraum werden folgende Parameter benutzt:

Das Programm weicht vom oben angegebenen Schema insofern ab, als dass anstelle der Prozentangaben bereits die bei der Ausgabe möglichen Werte 0 bis 255 verwendet werden. Auf diese Weise kommt das Programm auch mit Integer-Arithmetik aus, was der Rechenzeit und dem Speicherbedarf zu Gute kommt.
// Pinzuordnung der LEDs
#define LEDBlau  9
#define LEDGruen 10
#define LEDRot   11

void setup()
  {
  pinMode(LedBlau, OUTPUT);
  pinMode(LedGruen, OUTPUT);
  pinMode(LedRot, OUTPUT);
  }

void loop()
  {
  int licht;
  for (licht = 0; licht < 360; licht++)
    { // kompletten Farbkreis durchlaufen
    setLED(licht,255);
    delay(100);
    }
  }

void setLED(int hue, int l)
  {  // LED-Farben festlegen nach HUE und Intensität. 
     // Sättigung ist hier immer auf Maximum gesetzt
  int col[3] = { 0,0,0 };
  
  getRGB(hue, 255, l, col);             // HSV in RGB umrechen
  analogWrite(LedRot, 255 - col[0]);    // und ausgeben
  analogWrite(LedGruen, 255 - col[1]);
  analogWrite(LedBlau, 255 - col[2]);
  }

void getRGB(int hue, int sat, int val, int colors[3]) 
  {  // Diese Funktion rechnet einen HSV-Wert in die ensprechenden
     // RGB-Werte um. Diese werden im Array ‚colors' zurückgegeben
     // colors[0] = ROg, colors[1]} = Gruen, colors[2] = Blau
     // hue: 0 - 359, saturation: 0 - 255, val (lightness): 0 - 255
  int r, g, b, base;

  if (sat == 0) 
    { // Sättigung = 0 --> Grauwert
    colors[0] = val;
    colors[1] = val;
    colors[2] = val;
    } 
  else  
    {
    base = ((255 - sat) * val) >> 8;
    if (hue < 60)
      {
      red = val;
      green = (((val - base)*hue)/60) + base;
      blue = base;
      }
    else if (hue < 120)
      {
      red = (((val - base)*(60-(hue%60)))/60) + base;
      green = val;
      blue = base;
      }
    else if (hue < 180)
      {
      red = base;
      green = val;
      blue = (((val - base)*(hue%60))/60) + base;
      }
    else if (hue < 240)
      {
      red = base;
      green = (((val - base)*(60 - (hue%60)))/60) + base;
      blue = val;
      }
    else if (hue < 300)
      {
      red = (((val - base)*(hue%60))/60) + base;
      green = base;
      blue = val;
      }
    else if (hue < 360)
      {
      red = val;
      green = base;
      blue = (((val - base)*(60 - (hue%60)))/60) + base;
      }
    colors[0] = red;
    colors[1] = green;
    colors[2] = blue;
    }
  }


Copyright © Hochschule München, FK 04, Prof. Jürgen Plate und die Autoren
Letzte Aktualisierung: