Projektziel
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.
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
* http://ecotronics.ch.honorius.sui-inter.net/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.


Download des Artikels als PDF File