Pingpong-Lampe mit Arduino

Projektziel

Arduino-Pingpong-Lampe mit Farbwechsel

Die Erwähnung von Pingpongbällen im Arduino-Buch animierte mich zu diesem Projekt. Ziel ist es, ein RGB-Lämpchen mit einem aufgeschnittenen Pingpong-Ball als Lampenschirm zu basteln. Die Lampe soll selbstverständlich die Farbe wechseln. Sie hat zusätzlich einen Kipp-Schalter zum an- und abschalten und ein Potentiometer, mit dem man den Farbwechsel beschleunigen oder verlangsamen kann.

Komponenten

  • 1 Arduino UNO
  • 1 Steckbrett
  • diverse Jumperkabel M/M
  • 1 RGB-LED
  • 3 Widerstände 560 Ohm (Grün-Blau-Braun)
  • 1 Potentiometer
  • 1 Kippschalter (z.B. von Modelleisenbahn)
  • 1 aufgeschnittener weisser Tennisball

Bestückungsplan

Der Bestückungsplan braucht keinen grossen Kommentar: oben ist der Kippschalter, unten das Potentiometer. Wichtig ist, dass man die Widerstände für die RGB-Beinchen des LEDs nicht vergisst.

Bestückungsplan für RGB-LED mit Schalter und Potentiometer

Und falls sich jemand fragt, was das Schwarze unter dem Pingpong-Ball ist: Aus dem Styropor einer Pizzaverpackung habe ich der Lampe ein kleines Podest gebastelt. Erstaunlich, wie man Verpackungsmüll kreativ umnutzen kann!

Code

Der Code ist für den Farbwechsel des RGB-LED zuständig. Der aus dem Potentiometer ausgelesene Wert wird dabei in einen Delay von 1 bis 100 umgerechnet. Und je nach Farbprogramm wird dieser Wert noch mit einem Delay-Faktor verrechnet, denn bei einem Farbverlauf mit 255 Schritten macht ein Delay von 100 Sinn, aber bei einem Wechsel zwischen 6 Farben wird ein solch kurzer Delay ziemlich hektisch.

Übrigens noch ein kleiner Stolperstein, wenn man die Länge eines zweidimensionaen Arrays mit sizeof misst: sizeof gibt die Länge in Byte des gesamten Arrays zurück! Wenn ich also ein Array mit 6 Farben à je 3 Farbwerten habe und diese als Integer-Typen definiert habe, dann muss ich sizeof(meinArray) / (Länge des inneren Array * 2) rechnen, um die effektive Länge zu erhalten, weil ein Array 2 Byte lang ist!

int length = sizeof(colorSequence) / (3 * 2);

Das reicht aber noch nicht: Mein Code funktionierte wunderbar, bis ich das sizeof-Statement dahin verschob, wo es eigentlich hingehört, nämlich in die Methode playColorSequence. Und siehe da, es ging gar nichts mehr. Mit Serial.print fand ich heraus, dass der Wert plötzlich 0 wird. Erst Google half mir weiter. Unter http://www.hackerboard.de/code-kitchen/36875-c-array-uebergeben.html fand ich den schönen Satz: “hierbei ist zu beachten das sizeof(menge)/sizeof(int) bei arrays zur größenbestimmung nur funktioniert wenn sie im selben bereich deklariert wurden, sonst geht das ganze nach hinten los.” Langsam begreife ich, weshalb Leute C hassen!
Der Code für den Farbwechsel enthält im Moment 2 Varianten:

  • playColorSequence: fixe Abfolge von Farben, z.B. Rot, Grün, Blau, oder Rot, Gelb, Grün, Cyan (Hellblau), Blau, Magenta
  • continuousColorChange: Farbverlauf von Rot über Grün zu Blau und zurück zu Rot
/*
 * RGB-LED with color change
 * - with toggle switch
 * - tempo of color change regulated by potentiometer
 * Author: Silvia Rothen, rothen ecotronics, Bern, Switzerland
 * https://blog.ecotronics.ch/wordpress/category/physical-computing/
 */

int ledAnalogOne[] = {3, 5, 6}; //3 PWM-LEDs: 3 Rot, 5 Grün, 6 Blau

int colorSequenceRGB[3][3] = {{255, 0, 0}, {0, 255, 0}, {0, 0, 255}};
int colorSequence[6][3] = {{255, 0, 0}, {255, 255, 0}, {0, 255, 0},
  {0, 255, 255}, {0, 0, 255}, {255, 0, 255}};
//Poti bestimmt Delay
int sensorPin = A0;    // select the input pin for the potentiometer

int red = 0;
int green = 0;
int blue = 0;
int mydelay = 100;
int analogIn = 0;

byte  black[] = {0, 0, 0};

void setup(){
  Serial.begin(9600);
  for(int i = 0; i < 3; i++){
   pinMode(ledAnalogOne[i], OUTPUT);   //Set the three LED pins as outputs
  }
  setColor(ledAnalogOne, black);
}

void loop(){
  //geht nicht anders, sizeof funktioniert nur hier!
  int lengthRGB = sizeof(colorSequenceRGB) / (3 * 2);
  onlyRGB(lengthRGB);

  int length = sizeof(colorSequence) / (3 * 2);
  playColorSequence(colorSequence, length);
  //continuousColorChange();
}

void playColorSequence(int colorSequence[][3], int length) {
  Serial.print("Length: ");
  Serial.println(length);
  for (int counter =  0; counter < length; counter++){
   changeColor(colorSequence[counter][0],
      colorSequence[counter][1],
      colorSequence[counter][2], 5);
  }
}

void onlyRGB(int length) {
  playColorSequence(colorSequenceRGB, length);
}

void continuousColorChange() {
  //Red to green
  for (int counter =  0; counter < 256; counter++){
    changeColor(255 - counter, counter, 0, 1);
  }
  //Green to blue
  for (int counter =  0; counter < 256; counter++){
    changeColor(0, 255 - counter, counter, 1);
  }
  //Blue to Red
  for (int counter =  0; counter < 256; counter++){
    changeColor(counter, 0, 255 - counter, 1);
  }
}

void changeColor(int red, int green, int blue, int delayfactor) {
  //read the delay from potentiometer
  analogIn = analogRead(sensorPin);
  mydelay = analogIn / 10;
  if (mydelay < 1) { mydelay = 1;}
  if (mydelay > 100) { mydelay = 100;}

  //change the colors
  byte color[] = {red, green, blue};
  printToSerial(color);
  setColor(ledAnalogOne, color);
  delay(mydelay * delayfactor);
}

void setColor(int* led, byte* color){
 for(int i = 0; i < 3; i++){             //Iteration durch die 3 Pins
   analogWrite(led[i], 255 - color[i]);
 }
}

//prints input value and RGB values at the serial interface
//just for debugging
void printToSerial(byte* color) {
  Serial.print("Analog In: ");
  Serial.print(analogIn);
  Serial.print("; Delay: ");
  Serial.print(mydelay);
  Serial.print("; RGB: ");
  Serial.print(color[0]);
  Serial.print("/");
  Serial.print(color[1]);
  Serial.print("/");
  Serial.println(color[2]);
}

Demo

Im Video sieht man den Farbwechsel und den Frequenzwechsel beim Hochschrauben des Potentiometers.

Comments are closed.