Irgendwie sollte doch jeden Tag Valentinstag sein, oder? Arduino Valentinstag: Den Menschen, die ihr Leben mit uns teilen, gebührt besondere Aufmerksamkeit. Wie wäre es da mit einem romantischen Wandlicht?
Bei diesem Arduino-Projekt handelt es ich um ein Herz mit eingefrästen oder gedruckten Namen. Darunter befindet sich ein WS2812-LED-Leuchtstreifen, der nach außen leuchtet und dem Herz zu einem Glow-Effekt verhilft. Wie groß das Herz wird, oder wie viele LEDs du verwenden willst, kannst du natürlich selbst entscheiden. Achte aber darauf, dass die Elektronik darunter genügend Platz hat. Das Herz ist mit einem Button ausgestattet, mit dem sich unterschiedliche Animationen durchschalten lassen. Betrieben wird das alles per Netzteil.
Bauteile
- 1x
- 1x WS2812 LED Leuchtstreifen
- 1x USB-Netzteil und weißes USB-Kabel
- 1x Elektrolyt-Kondensator 500 – 1000 uF, > 10V
- 1x Widerstand 470 Ohm (es geht auch ein Widerstandswert in der Nähe)
Schaltplan
Die Schaltung besteht aus zwei Stromkreisen. Der eine Stromkreis verbindet die WS2812-LEDs mit dem GND und dem 5V+ des Arduino-Boards. Diese beiden Anschlüsse sind zusätzlich über einen Elektrolytkondensator verbunden. Richtigerweise müsste man »nicht verbunden« sagen, da der Kondensator ja keine elektrische Verbindung herstellt. Er speichert Energie, die abgegeben wird, wenn die LEDs z.B. bei Farbwechseln besonders viel Energie benötigen (Stützkondensator). Der Daten-In-Anschluss des LED-Streifens ist über einen Widerstand (ca. 470 Ohm) mit dem digitalen Pin 6 des Arduino-Boards verbunden. Der zweite Stromkreis besteht aus einem Taster, der mit dem GND und dem digitalen Pin 2 des Arduinos verbunden ist.
Mehr Infos zu den WS2812-LEDs hab ich hier für dich: WS2812 – Der einfachste Weg, viele LEDs mit Arduino steuern.
Arduino Valentinstag: Bauanleitung
Ich habe mich für ein klassisches Herz mit eingravierten Namen entschieden, aber du kannst auch Fotos auf das Herz kleben. Es gibt unendliche Möglichkeiten, also lass deiner Fantasie freien Lauf. Ob du es aus Holz, Pappe, Papier oder anderen Materialien herstellst, ist ebenfalls komplett dir überlassen.
Wichtig ist, dass Platz für die Elektronik bleibt. Da die LEDs indirekt auf die dahinterliegende Wand scheinen sollen, verstecke ich sie hinter dem Herz.
Den Button habe ich so platziert, dass er zwischen Herz und Wand sitzt und gedrückt wird, wenn man das Herz drückt.
Code
Das Arduino-Programm ist ein Beispiel-Code der Adafruit-Nanopixel-Bibliothek. Die muss übrigens in der Arduino-Software installiert werden. Öffne dafür in der Arduino IDE (Software) das Menü Sketch>Bibliotheken einbinden>Bibliotheken verwalten … und suche im Suchfeld nach NeoPixel. Installiere die Adafruit NeoPixel-Library von Adafruit in der aktuellen Version. Öffne nun das Beispiel unter Datei>Beispiele>Adafruit NeoPixel>ButtonCycler. Ändere die Pixelanzahl in der Zeile:
#define PIXEL_COUNT 25 // Number of NeoPixels
Übertrage das Programm auf das Arduino-Board. Das war es auch schon :-)
Der Code spielt unterschiedliche Animationen ab. Am Anfang ist alles aus. Wird der Button gedrückt, ändert sich der Zähler der Variablen mode. Der Wert dieser Variablen entscheidet über die aktuelle Animation durch die Switch-Case-Abfrage.
Hier nochmal der gesamte Code der Vollständigkeit halber:
// A basic everyday NeoPixel strip test program. // NEOPIXEL BEST PRACTICES for most reliable operation: // - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections. // - MINIMIZE WIRING LENGTH between microcontroller board and first pixel. // - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR. // - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS // connect GROUND (-) first, then +, then data. // - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip, // a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED. // (Skipping these may work OK on your workbench but can fail in the field) #include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> // Required for 16 MHz Adafruit Trinket #endif // Which pin on the Arduino is connected to the NeoPixels? // On a Trinket or Gemma we suggest changing this to 1: #define LED_PIN 6 // How many NeoPixels are attached to the Arduino? #define LED_COUNT 60 // Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); // Argument 1 = Number of pixels in NeoPixel strip // Argument 2 = Arduino pin number (most are valid) // Argument 3 = Pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) // setup() function -- runs once at startup -------------------------------- void setup() { // These lines are specifically to support the Adafruit Trinket 5V 16 MHz. // Any other board, you can remove this part (but no harm leaving it): #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // END of Trinket-specific code. strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) strip.show(); // Turn OFF all pixels ASAP strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) } // loop() function -- runs repeatedly as long as board is on --------------- void loop() { // Fill along the length of the strip in various colors... colorWipe(strip.Color(255, 0, 0), 50); // Red colorWipe(strip.Color( 0, 255, 0), 50); // Green colorWipe(strip.Color( 0, 0, 255), 50); // Blue // Do a theater marquee effect in various colors... theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness theaterChase(strip.Color(127, 0, 0), 50); // Red, half brightness theaterChase(strip.Color( 0, 0, 127), 50); // Blue, half brightness rainbow(10); // Flowing rainbow cycle along the whole strip theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant } // Some functions of our own for creating animated effects ----------------- // Fill strip pixels one after another with a color. Strip is NOT cleared // first; anything there will be covered pixel by pixel. Pass in color // (as a single 'packed' 32-bit value, which you can get by calling // strip.Color(red, green, blue) as shown in the loop() function above), // and a delay time (in milliseconds) between pixels. void colorWipe(uint32_t color, int wait) { for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip... strip.setPixelColor(i, color); // Set pixel's color (in RAM) strip.show(); // Update strip to match delay(wait); // Pause for a moment } } // Theater-marquee-style chasing lights. Pass in a color (32-bit value, // a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms) // between frames. void theaterChase(uint32_t color, int wait) { for(int a=0; a<10; a++) { // Repeat 10 times... for(int b=0; b<3; b++) { // 'b' counts from 0 to 2... strip.clear(); // Set all pixels in RAM to 0 (off) // 'c' counts up from 'b' to end of strip in steps of 3... for(int c=b; c<strip.numPixels(); c += 3) { strip.setPixelColor(c, color); // Set pixel 'c' to value 'color' } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment } } } // Rainbow cycle along whole strip. Pass delay time (in ms) between frames. void rainbow(int wait) { // Hue of first pixel runs 5 complete loops through the color wheel. // Color wheel has a range of 65536 but it's OK if we roll over, so // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time // means we'll make 5*65536/256 = 1280 passes through this outer loop: for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) { for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip... // Offset pixel hue by an amount to make one full revolution of the // color wheel (range of 65536) along the length of the strip // (strip.numPixels() steps): int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels()); // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or // optionally add saturation and value (brightness) (each 0 to 255). // Here we're using just the single-argument hue variant. The result // is passed through strip.gamma32() to provide 'truer' colors // before assigning to each pixel: strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue))); } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment } } // Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames. void theaterChaseRainbow(int wait) { int firstPixelHue = 0; // First pixel starts at red (hue 0) for(int a=0; a<30; a++) { // Repeat 30 times... for(int b=0; b<3; b++) { // 'b' counts from 0 to 2... strip.clear(); // Set all pixels in RAM to 0 (off) // 'c' counts up from 'b' to end of strip in increments of 3... for(int c=b; c<strip.numPixels(); c += 3) { // hue of pixel 'c' is offset by an amount to make one full // revolution of the color wheel (range 65536) along the length // of the strip (strip.numPixels() steps): int hue = firstPixelHue + c * 65536L / strip.numPixels(); uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB strip.setPixelColor(c, color); // Set pixel 'c' to value 'color' } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames } } }
Und hier noch eine einfache Version: Regenbogen oder Aus :-)
#include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> // Required for 16 MHz Adafruit Trinket #endif #define BUTTON_PIN 2 #define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels. #define PIXEL_COUNT 25 // Number of NeoPixels Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); boolean buttonState = HIGH; boolean lastState = HIGH; boolean myState = false; void setup() { Serial.begin(115200); pinMode(BUTTON_PIN, INPUT_PULLUP); strip.begin(); // Initialize NeoPixel strip object (REQUIRED) strip.show(); // Initialize all pixels to 'off' } void loop() { rainbow(100); } void colorWipe(uint32_t color, int wait) { for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip... strip.setPixelColor(i, color); // Set pixel's color (in RAM) strip.show(); // Update strip to match delay(wait); // Pause for a moment } } void rainbow(int wait) { for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) { buttonState = digitalRead(BUTTON_PIN); if ((buttonState == LOW) && (lastState == HIGH)) { myState = !myState; Serial.println(myState); } if (myState == true) { for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip... int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels()); strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue))); } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment } else { colorWipe(strip.Color( 0, 0, 0), 0); } lastState = buttonState; } }
Und noch eine Version, in der das Herz nach dem Drücken des Tasters eine bestimmte Zeit leuchtet und dann ausgeht. Die Dauer lässt sich in der Variablen myTimeout einstellen.
#include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> // Required for 16 MHz Adafruit Trinket #endif #define BUTTON_PIN 4 #define PIXEL_PIN 2 // Digital IO pin connected to the NeoPixels. #define PIXEL_COUNT 50 // Number of NeoPixels #define BRIGHNESS 25 // Set BRIGHTNESS to about 1/5 (max = 255) long myTimeout = 10000; // Zeit, die das Herz nach dem Drücken des Tasters leuchten soll (in Sekunden) long myTimer; Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); boolean buttonState = HIGH; boolean lastState = HIGH; boolean myState = false; void setup() { Serial.begin(115200); pinMode(BUTTON_PIN, INPUT_PULLUP); strip.begin(); // Initialize NeoPixel strip object (REQUIRED) strip.show(); // Initialize all pixels to 'off' strip.setBrightness(BRIGHNESS); } void loop() { rainbow(100); } void colorWipe(uint32_t color, int wait) { for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip... strip.setPixelColor(i, color); // Set pixel's color (in RAM) strip.show(); // Update strip to match delay(wait); // Pause for a moment } } void rainbow(int wait) { for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) { buttonState = digitalRead(BUTTON_PIN); if ((buttonState == LOW) && (lastState == HIGH)) { myState = !myState; Serial.println(myState); if (myState == true) myTimer = millis(); } if ((myState == true) && (myTimer + myTimeout < millis())) { for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip... int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels()); strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue))); } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment } else { colorWipe(strip.Color( 0, 0, 0), 0); } lastState = buttonState; } }
Wenn dir das Projekt gefallen hat und du von weiteren interessanten Projekten inspiriert werden willst, sieh dir doch mal mein neues E-Book »Arduino Projekte Volume 1« an!
- Die beliebtesten Arduino-Projekte von StartHardware
- Inklusive Schaltplan, Beschreibung und Code
- Arduino-Schnellstart-Kapitel
- Kompakter Programmierkurs
Pingback: Arduino und WS2812 – Viele LEDs einzeln mit Arduino steuern
Vielen Dank, für diesen sehr guten Beitrag. Das ist alles super verständlich erklärt. Wenn ich 60 LED in zwei Metern verwenden will, muss ich dann weitere Kondensatoren oder einen mit mehr uF verwenden? Wie kann ich das berechnen? Und werden die dann auch alle jeweils parallel gelötet oder in Reihe geschaltet? Wie sieht es da mit dem Widerstand aus? Der bleibt doch gleich, oder? Ich hab es aus einem anderen Post von dir gelesen, dass ich pro Lichtquelle 60 mA einbeziehen soll. Dann habe ich einen Stromverbrauch von 3,6 A, die ich sicherlich nicht über den USB-Anschluss beziehen kann. Wie löse ich das mit dem Strom? Ich hab bisher nur verstanden, dass ich bei LED-Streifen spätestens ab 5 m Länge den Ground und +5V unterbrechen und neu verlöten soll, damit die letzten LED, nicht so wenig Spannung abbekommen. Aber das hat ja nichts mit der Stromstärke zu tun. Reicht es ein Netzteil an den Arduino anzuschließen, oder wird das nicht reichen, oder zu heiß?
Ich werde ein Bühnenbild bauen, in dem ein 2 Meterstreifen mit 30 LED pro Meter eingesetzt wird. Meine Sorge ist, dass etwas schief geht bei der Ausstellung, oder dass mir die Streifen oder der Arduino kaputt gehen, es im schlimmsten Fall zu einem Brand kommt.
Viele Grüße und danke für die Antwort
Hi Martin, also meiner Erfahrung nach (und ich bin kein Elektrotechniker) brauchst du immer nur den einen Kondensator und den einen Widerstand. Guck dir mal diesen Beitrag an: https://starthardware.org/viele-leds-mit-arduino-steuern-ws2812/ … Das Netzteil muss direkt mit den LEDs verbunden werden. Lies dir auch mal die Best Practices von Adafruit dazu durch: https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices
Durch die LED-Strips kann nur eine bestimmte Menge Strom fließen, deshalb muss man z.B. alle 5m (ja nach LED Anzahl) wieder Strom von außen hinzuführen. 2 Meter sollten aber unkritisch sein. Liebe Grüße Stefan
Hallo Stefan,
klingt cool. Werde ich auf alle Fälle nachbauen. Da kommt aber bei mir gleich die Frage auf, ob das auch mit kleineren LEDs geht, damit man H0 Kirmesmodelle damit verzieren und ansteuern kann?
Viele Grüße
Klaus
Hi Klaus, die WS2812-LEDs sind SMD-LEDs auf den Leuchtstreifen. Die gibt es einzeln oder man lötet sie von den LED-Strips mit Heißluft ab. Lichtleiter wären auch noch eine Option. Liebe Grüße Stefan
Hallo Stefan, tolles Projekt und ich habe mir mal den oberen Code angeschaut. Kann es sein das dort der BUTTON_PIN nicht definiert ist und das mit dem ein aus schalten nicht geht?
Kann man das auch abändern das es nur einen Loop macht und dann aus geht. Ihc habs gnadenlos versucht ber scheitere drann. Danke für deine Antwort
Hi Martin,
der Pin wird oben definiert mit: #define BUTTON_PIN 2
Sieht etwas kryptisch aus, ich gebe es zu :-) Ich hab einen Code hinzugefügt, in dem das Herz nach Tastendruck nur eine gewisse Zeit leuchtet. Probier das gern mal aus, ich konnte es nicht live testen.
Liebe Grüße
Stefan
Hallo
Ich habe es nachgebaut aber leider funktioniert die Taste nicht.
Können sie mir da helfen?
Mit freundlichen Grüßen
Hi Darek, hast du es schon hinbekommen? Liebe Grüße Stefan
Super Idee werds nachbauen.
Hallo, Danke für die gute Anleitung. Ich mache mir etwas Sorgen wegen der Stromversorgung.
Ich schätze die Anzahl der LEDs auf ca. 40. Das wäre bei einem maximalen Verbrauch von 60mA pro LED 2.4A die nötig wären.
Kann man das einfach so über den Arduino anschließen?
Hallo Henry,
sehr gute Frage. Vielen Dank dafür. Also das Arduino kann soviel ich weiß 1A über den 5V-Pin liefern. Die 60mA benötigt eine LED ja nur, wenn gleichzeitig bei voller Leuchtkraft alle drei Farbkanälen leuchten (RGB). Wenn man das will, müsste man tatsächlich lieber den Schaltplan ändern. Ich hab das mal hier beschrieben: WS2812 – Der einfachste Weg, viele LEDs mit Arduino steuern. Ich hab das Licht aber schon recht lange im Einsatz und betreibe es mit einem iPhone-Charger. Es liefert genau 1A. Weder der Charger, noch das Arduino werden heiß. Sollte also passen.
Liebe Grüße
Stefan
Hallo,
würde der Arduino Nano auch reichen?
Mfg
Hi Manuel, der Arduino Nano sollte auch funktionieren. Liebe Grüße