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.