Lichterketten Farbverläufe mit NeoPixel
Arduino-Bastelprojekt: Farbverläufe und Effekte mit WS2812b NeoPixel-LEDs.
WS2812b-LEDs (NeoPixel) ermöglichen individuelle RGB-Steuerung jeder LED über eine einzige Datenleitung. Dieses Projekt steuert eine Lichterkette oder einen LED-Strip mit sanften Farbverläufen – ideal für Lampen, Deko oder indirekte Beleuchtung. Ein Taster wechselt zwischen verschiedenen Fade-Modi und ermöglicht die Einstellung einer festen Farbe.
Materialien
- Arduino (Uno, Nano, Mega oder Digispark)
- WS2812b LED-Strip oder -Ring (Anzahl je nach Speicher anpassbar)
- Taster
- 5V Netzteil (bei vielen LEDs nötig – der Strip kann viel Strom ziehen)
Pinbelegung
| Komponente | Arduino |
|---|---|
| WS2812b DI (Daten) | Pin 1 |
| Taster (ein Anschluss) | Pin 2 |
| Taster (anderer Anschluss) | Pin 3 (als Ausgang auf GND) |
| WS2812b GND, 5V | GND, 5V |
Bedienung
- Kurz drücken: Nächster Fade-Modus (Orange, Lila, Türkis, Grün, Weiß …)
- Lang drücken: Schneller Farbwechsel – beim Loslassen bleibt die Farbe
- Doppelt drücken: Standby / Ausschalten
- Beim Einschalten 15+ Sekunden drücken: Reset
Die aktuelle Einstellung wird im EEPROM gespeichert und beim nächsten Einschalten wiederhergestellt. Die Adafruit NeoPixel-Bibliothek wird benötigt.
/* * NeoPixel Lampen & LED-Strip Steuerung mit Button * Für: Arduino UNO, Nano, Mega2560, Digispark USB, ... * Bitte beachte: je nach Programmspeicher koennen verschieden viele LED's angeschlossen werden. * * BEDIENUNGSANLEITUNG: * * WENN DIE LAMPE AN IST: * KURZ DRUECKEN: * schaltet zu den verschiedenen Fade-Modi. * Es gibt fünf Fade-Modi in den folgenden Farbstimmungen: * Orange, Lila, Türkis, Grün, Weiß (weiß= alle Farben) * LANG DRUECKEN: * die Lampen beginnen die Farbe schnell zu wechseln bis losgelassen wird. * So laesst sich eine feste Farbe einstellen. * 2X SCHNELL DRUECKEN: * Schaltet die Lampen in den Standby. * Durch einmaliges kurzes Druecken werden sie wieder eingeschalten. * Der zuletzt eingestellte Modi wird nach dem Einschalten wieder abgerufen. * * WENN DIE LAMPE AUS IST: * KURZ DRUECKEN: * Schaltet die Lampe ein. * LANG DRUECKEN: * Schaltet die Lampe ein und dimmt diese. * Die Helligkeit verändert sich, bis man die Taste los lässt. * SEHR LANGE DRÜCKEN -> RESET * Wird die Lampe beim Einschalten länger als 15 Sekunden gedrückt, wird ein Reset ausgelöst. * Die Lampe beginnt nach dem Reset weiß zu blinken, bis man loslässt * * WENN DIE LAMPE KAPUTT IST: * Sie bekommen 1 Jahr Garantie, d. h. ich repariere Ihnen defekte Lampen, * sofern Sie diese nicht aus Eigenverschulden grob fahrlässig beschädigt haben. * SELBER REPARIEREN: * Abgebrochene Teile mit farblosen Sekundenkleber oder Zweikomponentenkleber befestigen. * VERDRAHTUNG: * WS2812: DI an Pin 0, GND zu GND, VIN/5V an 5V * Button zwischen Pin 1 & Pin 2 * ENTSORGUNG: * Ich kann mich um die fachgerechte Demontage und Entsorgung kümmern. * ANSONSTEN: * Die Elektronik ausbauen und als Elektronikmüll entsorgen. * Den Lampenschirm in den gelben Sack legen. * Den Untersetzer je nach Material: * Gips zum Bauschutt, Holz zu den Gartenabfällen, Glas & Spiegel zum Altglas, Aluuntersetzer in Alusammelbehälter. * * Autor: Veit Goetz * Date: 06.01.2017 V.1.1 * 15.01.2017 V.1.2 * 20.02.2017 V.1.3 * 23.03.2017 V.1.3.1 * 27.03.2017 V.1.4 * Email: goetz@veit.tk * Web: www.goetz-veit.tk * www.3d-druck.tk */ /* ------------------ Librarys ------------------- */ //#include <avr/wdt.h> /*void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3"))); void wdt_init(void) { MCUSR = 0; wdt_disable(); return; }*/ // Include Librarys #include <EEPROM.h> #include <Adafruit_NeoPixel.h> /* ---------------- Main Settings ---------------- */ #define ledPin 1 // Pin to connect the LED's #define pixels 12 // Number of pixels - Anzahl LEDs #define buttonOut 3 // Button pin (output) #define buttonIn 2 // Button pin #define RESET_PIN 4 // Wire to reset pin /* ---------------- other Settings --------------- */ // Hier koennen Farben definiert werden, die in den Farbverlaufen vorkommen sollen const byte colors[][3] = {// Statische Farben {r, g, b}, -> Nummerierung automatisch nach Reihenfolge {255, 150, 150}, // 0=White {255, 90, 0}, // 1=Yellow {255, 60, 0}, // 2=yellow-orange {255, 40, 0}, // 3=Orange {255, 0, 0}, // 4=Red {255, 0, 80}, // 5=Pink {150, 0, 200}, // 6=Purple { 0, 0, 255}, // 7=Blue { 0, 186, 255}, // 8=Light Blue { 0, 255, 0}, // 9=Green {200, 255, 0}, // 10=Light green }; const byte colorCnt = 11; // number of colors - Anzahl der Farben // hier koennen verschiedene Farbverlaeufe erstellt werden const byte modes[][colorCnt+1] = { // Fade-Programme {Anzahl Farben, [Farbnummer] }, {10, 0,2,6,3,8,5,1,7,4,9}, // Fade each color {3, 1,10,3}, // Fade yellow {4, 3,1,2,4}, // Fade orange {3, 4,3,5}, // Fade red {4, 5,6,7}, // Fade purple {3, 7,8,6}, // Fade Blue {4, 9,10,8,1}, // Fade green }; const byte modeCnt = 7; // number of Fade-programmes - Anzahl der Fade-Programme im Array const unsigned int fadeSteps = 255; // default:255 // Anzahl Zwischenschritte zwischen zwei Farben const unsigned int fadeDelay = 20; // default:20 // Pause zwischen zwei Zwischenschritten /* LED's delay * 7 20 * 12 17 * 16 15 * 24 10 */ const unsigned int fastFade = 2; // default:2 // Pause bei schnellem Farbwechsel (bei 24 LED's:1) const float fadeSize = 0.1; // default:0.5 // Groeße des Farbverlaufs (0-1) - 1=alle LED's gleichzeitig 0=alle hintereinander const unsigned int longPress = 500; // default:500 // time (in ms) for long pressdown - Schwellwert für langen Tastendruck (in ms) const unsigned int dubblePress = 600; // default:600 // max. time for dubble pressdown - Schwellwert für zweifachen Tastendruck const byte EprAddr1 = 2; // default:2 // Eeprom address for "mode" const byte EprAddr2 = 6; // default:6 // Eeprom address for "color" const byte EprAddr3 = 10; // default:10 // Eeprom address for "pos" /* ----------------- global vars ----------------- */ unsigned int mode = 0; // current Modus (0-4=fade 5=static color) unsigned int currentColor = 0; // current color unsigned int pos = 0; // current fade Position //int intensy = 255; // current brightnes bool swichOff = false; // Standby = true, wird durch zweifachen Tastendruck geändert int fadeStartPos = 0; // Startpixel for color fade, wird automatisch (zufällig) bestimmt bool buttonPressed = false; // if the button pressed - zwischenspeicher, wenn Button gedrückt ist unsigned long downTime = 0; // time of Pressdown - Zwischenspeicher für die Dauer, die der Button gedrückt ist bool longStart = false; // did the long pressdown allready start - zwischenspeicher , ob dies jetzt ein langer Tastendruck ist bool modeSaved = true; // Zwischenspeicher, ob aktueller Mode schon im EEPROM abgelegt wurde /* ----------------- Initialize ------------------ */ Adafruit_NeoPixel strip = Adafruit_NeoPixel(pixels, ledPin, NEO_GRB + NEO_KHZ800); // initialize (LED's, pin, mode) void setup() { initVars(); #ifdef buttonOut pinMode(buttonOut, OUTPUT); // set the button as output digitalWrite(buttonOut, LOW); // Set one button PIN to LOW #endif pinMode(buttonIn, INPUT_PULLUP); // set the button as input with pullup strip.begin(); // start library strip.setBrightness(255); // set the max Brightness (0-255) } #ifdef RESET_PIN void softReset() { pinMode(RESET_PIN, OUTPUT); // sets the digital pin as output digitalWrite(RESET_PIN, LOW); // sets the LED off delay(20); digitalWrite(RESET_PIN, HIGH); // sets the LED on } #endif /* ------------------ Main Loop ------------------ */ void loop() { // code runs repeatly if(!swichOff&&(mode<modeCnt||longStart)){ // if in Fade mode pos = (pos+1) % fadeSteps; // Fade if(pos==0){ // new color currentColor = (currentColor+1) % ((mode<modeCnt)?modes[mode][0]:colorCnt); // calculate color fadeStartPos = random(pixels-1); // get random start position } setRgb(); // update LED's } delay((mode<modeCnt||swichOff)?fadeDelay:fastFade); // slow/fast fade bool btState = 1-digitalRead(buttonIn); // read button if(btState==LOW&&!swichOff&&!modeSaved&&millis()-downTime>dubblePress){ // save current mode EEPROM.write(EprAddr1, mode); // Save in EEPROM modeSaved = true; // mark data as saved } if(buttonPressed==true){ // button was still pressed down (by the last request) if(btState==LOW){ // ButtonPressUp now longStart = false; if(!swichOff){ // if LED is on -> swich of if(millis()-downTime<longPress){ // Short pressup changeMode(1); // next Fade-Mode modeSaved = false; // mode was changed but not saved in EEPROM yet }else{ // long pressup EEPROM.write(EprAddr2, currentColor); // Save current static color in EEPROM EEPROM.write(EprAddr3, pos); // save current static fade position in EEPROM } }else if(downTime>0){ // led was off -> swich on if(millis()-downTime<longPress){ // Short pressup swich_On(); // Swich the lamp on swichOff=false; // save, that lamp is now swiched on }else{ // swich on with long press #ifdef RESET_PIN softReset(); //call reset #endif } } }else if(!longStart&&millis()-downTime>longPress){ // start long Pressdown if(downTime>0){ // lamp is on longStart = true; if(!swichOff){ // if the lamp is allready on if(mode!=modeCnt){ // from fade to static mode currentColor = modes[mode][1+currentColor]; // get current color mode = modeCnt; // set to static mode (fast fade each color) EEPROM.write(EprAddr1, mode); // Save "static mode" to EEPROM } } } } } else if(buttonPressed==false&&btState==HIGH){ // new ButtonPressDown if(millis()-downTime<dubblePress&&!swichOff){ // dubble pressdown swich_Off(); // swich off downTime = 0; //asm volatile ( "jmp 0"); }else{ downTime = millis(); // save the time of Pressdown if(swichOff){ //swich_On(); // Swich the lamp on } } } if(buttonPressed!=btState) buttonPressed = btState; // ButtonChange } /* -------------------- init --------------------- */ void initVars(){ mode = EEPROM.read(EprAddr1);// %(modeCnt+1); // get the current mode currentColor = EEPROM.read(EprAddr2)%((mode<modeCnt)?modes[mode][0]:colorCnt); // get the current color pos = EEPROM.read(EprAddr3)%(fadeSteps); // get the current fade pos. strip.setBrightness(200); // set Brightness && Initialize all pixels return; } /* -------------- Lamp Swich on/off -------------- */ void swich_On(){ mode = EEPROM.read(EprAddr1);//%(modeCnt+1); // get the current mode currentColor = EEPROM.read(EprAddr2); // get the current color pos = EEPROM.read(EprAddr3)%(fadeSteps); // get the current fade pos. setRgb(); // Update mode on LED's return; } void swich_Off(){ swichOff=true; // swich off for(unsigned long n=0;n<pixels; n++){ // Set Color to each LED //strip.setPixelColor(n, 0, 0, 0); // Swich OFF strip.setPixelColor(n, strip.Color(0, 0, 0)); // Swich OFF } strip.show(); // Show update on LED-Strip return; } /* ---------- Caclculate RGB and upload ---------- */ void setRgb(){ float col[3]; float fadeStart = (0.5+fadeSize)*pos/fadeSteps; float fadeEnd = fadeStart-fadeSize; for(long n=0;n<pixels; n++){ // Set Color to each LED float distance = 1.0*abs(n-fadeStartPos)/pixels; if(distance>0.5) distance = 1-distance; float intensy = (distance>=fadeStart)?0:(distance<=fadeEnd)?1:(fadeStart-distance)/fadeSize; if(mode==modeCnt) intensy = 1.0*pos/fadeSteps; for(byte n=0;n<3;n++){ // calculate RGB-Value byte col1 = colors[ (mode<modeCnt) ? modes[mode][1+currentColor] : currentColor ][n]; byte col2 = colors[ (mode<modeCnt) ? modes[mode][1+((currentColor+1)%modes[mode][0])] : ((currentColor+1)%colorCnt) ][n]; col[n] = 1.0*(col2-col1)*intensy + col1 ; } //strip.setPixelColor(n, col[0], col[1], col[2]); strip.setPixelColor(n, strip.Color(col[0], col[1], col[2])); } strip.show(); // Show update on LED-Strip return; } /* ---------- Swich between Color-Modes ---------- */ void changeMode(int change){ // Update fade mode & LED's mode = (mode+change)%(modeCnt); pos=0; currentColor = 0; //mode%colorCnt; setRgb(); return; }
Weitere Artikel
200 kV HochspannungskaskadeAls Ansteuerung für ein aktuelles Projekt, ein Röntgengerät, habe ich diese 200 kV Hochspannungskaskade gebaut
SchwibbogenPassend zur diesjährigen Weihnachtszeit habe ich einen kleinen Schwibbogen gebastelt. Kostenlose Schnittvorlage zum Download.
DIY LasercutterEin aktuelles Projekt ist ein 15W Lasercutter.<br>
Wie so oft dient als Steuerung ein Arduino. Für ein sicheres Gehäuse habe ich extra Schutzglas anfertigen lassen. Der Laser wurde im Dezember 2019 fertig, nun arbeite ich an einer Lüftungsanlage.<br>
Gefällt dir die Webseite? Unterstütz die werbefreie Seite mit einer Spende.
Kommentare