Mein Projekt für ein "Lichtschwert" fing etwas holprig an. Es ist kein Lichtschwert alá StarWars, sondern eher eine 1m lange Schiene mit 60 RGB-LEDs. Diese LEDs sind in einem Silikonschlauch verbaut, so ist ein gestreuteres Licht möglich. Das setze ich für mein Hobby, Lightpainting, ein. Für die, die nicht wissen was Lightpainting ist: Man animiert Lichtquellen oder Licht reflektierende Objekte, wie z.B. Wunderkerzen, abbrennende Stahlwolle, Taschenlampen oder eben solch selbstgebaute Leuchtelemente während einer Langzeitbelichtung der Kamera (BULB) im Dunkeln durchs Bild. Die "Schlieren" die dabei entstehen machen das Werk aus.
Das die Bäume grün leuchten, liegt am Licht, welches in 30s aus den Wohnungen und Hauseingängen abgestrahlt wird und die Kamera einfängt.
Ich hatte mich das erste Mal mit den RGBs WS2812B beschäftigt. Was am Ende rauskam, stellte mich zufrieden.
Ich habe einen Joyit Nano-Clone (Old Bootloader, ca. 7,90€) verbaut. 8 Taster sind für 8 Farben zuständig, rot, grün, blau, weiß, lila, türkis, orange und gelb. Ein neunter schaltet die jeweilige Farbe aus. Ein Schalter kann die gewählte Farbe blinken lassen, ein Poti legt die Blinkfrequenz fest. Und ein weiterer Schalter lässt die LEDs als Regebogenverlauf erstrahlen.
Der mechanische Aufbau ist einem Gehäuse geschuldet, welches ich nutzen wollte.
Der Nano ist so verbaut, dass ich ihn weiterhin programmieren kann, falls ich etwas ändern möchte.
Das folgende Foto zeigt, wie der LED-Silikonschlauch in einem U-Profil aus Alu steckt. Das Gehäuse und eine 10Ah-Powerbank sind einfach mit schwarzem Isolierband mit dran befestigt. Beim Lightpainting kommt es nicht auf Schönheit an, es ist eh immer dunkel. Die Powerbank versorgt den Nano und die WS-LEDs mit 5V, hält mehrere Stunden Dauerlicht aus. Weiß frisst mit 1,8A am meisten.
Nun kommt es drauf an, was man damit anstellt. Ich bin in dem Foto einfach 2x durchs Bild gelaufen. Einmal ist der Regenbogeneffekt an und 1x blinkt die Leiste in Türkis.
Wer Lust hat mit sowas zu experimentieren, hier mein Sketch. Der ist noch mit delays fürs blinken. Kann jeder für sich übernehmen oder abändern. Nicht schön aber funktioniert.
[code]
#include <Adafruit_NeoPixel.h>
#define PIN 3 // Hier wird angegeben, an welchem digitalen Pin die WS2812 LEDs bzw. NeoPixel angeschlossen sind
#define NUMPIXELS 60 // Hier wird die Anzahl der angeschlossenen WS2812 LEDs bzw. NeoPixel angegeben
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
const byte rainb = 2; // Rainbow gesteuert über D2
const byte rot = 4; // Rot gesteuert über D4
const byte gruen = 5; // Grün gesteuert über D5
const byte blau = 6; // Blau gesteuert über D6
const byte lila = 7; // Lila gesteuert über D7
const byte tuerkis = 8; // Türkis gesteuert über D8
const byte orange = 9; // Orange gesteuert über D9
const byte gelb = 10; // Gelb gesteuert über D10
const byte weiss = 11; // Weiß gesteuert über D11
const byte aus = 12; // LEDs aus gesteuert über D12
const byte blk = A1; // schnelles blinken gesteuert über A1, genutzt als Digitalpin
const byte poti = A0; // Blinkfrequenz
const byte pause = 250; // 250ms Pause
byte R = 0; // Rot auf Null
byte G = 0; // Grün auf Null
byte B = 0; // Blau auf Null
void setup()
{
pinMode(rainb, INPUT_PULLUP); // alle Pins auf Digital-Input mit Pullup-Rs
pinMode(rot, INPUT_PULLUP);
pinMode(gruen, INPUT_PULLUP);
pinMode(blau, INPUT_PULLUP);
pinMode(lila, INPUT_PULLUP);
pinMode(tuerkis, INPUT_PULLUP);
pinMode(orange, INPUT_PULLUP);
pinMode(gelb, INPUT_PULLUP);
pinMode(weiss, INPUT_PULLUP);
pinMode(aus, INPUT_PULLUP);
pinMode(blk, INPUT_PULLUP);
pixels.begin(); // Initialisierung der NeoPixel
pixels.setBrightness(255); // NeoPixel auf volle Helligkeit
}
void loop()
{
bool rainbStatus = digitalRead(rainb); // alle Eingänge einlesen
bool rotStatus = digitalRead(rot);
bool gruenStatus = digitalRead(gruen);
bool blauStatus = digitalRead(blau);
bool lilaStatus = digitalRead(lila);
bool tuerkisStatus = digitalRead(tuerkis);
bool orangeStatus = digitalRead(orange);
bool gelbStatus = digitalRead(gelb);
bool weissStatus = digitalRead(weiss);
bool ausStatus = digitalRead(aus);
bool blinkStatus = digitalRead(blk);
uint16_t frequenz = analogRead(poti);
frequenz = map(frequenz, 0, 1023, 1000, 100);
// Funktionen behandeln
// Rainbow hat Priorität vor allen anderen
if (rainbStatus == HIGH) {
R = 0, G = 0, B = 0;
rainbow(20);
} else {
// dann kommen die anderen Funktionen
if (blinkStatus == HIGH) { // blinken mit Poti
for (int i = 0; i <= NUMPIXELS; ++i) {
pixels.setPixelColor(i, pixels.Color(R, G, B));
}
pixels.show();
delay(frequenz);
ledaus();
delay(frequenz);
}
if (rotStatus == LOW) { // Farbe Rot definieren
R = 255, G = 0, B = 0;
}
if (gruenStatus == LOW) { // Farbe Grün definieren
R = 0, G = 255, B = 0;
}
if (blauStatus == LOW) { // Farbe Blau definieren
R = 0, G = 0, B = 255;
}
if (lilaStatus == LOW) { // Farbe Lila definieren
R = 255, G = 0, B = 255;
}
if (tuerkisStatus == LOW) { // Farbe Türkis definieren
R = 0, G = 255, B = 200;
}
if (orangeStatus == LOW) { // Farbe Orange definieren
R = 255, G = 100, B = 0;
}
if (gelbStatus == LOW) { // Farbe Gelb definieren
R = 255, G = 255, B = 0;
}
if (weissStatus == LOW) { // Farbe Weiß definieren
R = 255, G = 255, B = 150;
}
if (ausStatus == LOW) { // LEDs ausschalten
R = 0, G = 0, B = 0;
ledaus();
}
}
for (int i = 0; i <= NUMPIXELS; ++i) { // definierte Farbe an Neopixel senden...
pixels.setPixelColor(i, pixels.Color(R, G, B));
}
pixels.show(); // ... und einschalten
}
void ledaus() { // LEDs ausschalten
for (int i = 0; i <= 60; ++i) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // Farbe definiern, also schwarz/dunkel...
}
pixels.show(); // ... und einschalten/ausschalten
}
void rainbow(uint8_t wait) { // Routine für Farbverlauf
uint16_t i, j;
for (j = 0; j < 256; j++) {
for (i = 0; i < pixels.numPixels(); i++) {
pixels.setPixelColor(i, Wheel((i + j) & 255));
}
pixels.show();
delay(wait);
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
WheelPos -= 85;
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
[/code]
Ich danke allen für Unterstützung hier im Forum, allen voran möchte ich agmue für seine Geduld danken.
Der Link zur eigentlichen Diskussion, hier gehts lang: Steuerung für Lichtschwert
Nachtrag: Ich habe noch weiter experimentiert. Die Hardware ist die gleiche geblieben, allein die Software hatte mir nicht gefallen, habe sie geändert.
Zur Beschreibung des Sketches:
- Die 60 LEDs habe ich in drei Gruppen á 20 aufgeteilt. Es sind also drei Abschnitte. Diese kann ich gesondert in der Farbe über das Poti einstellen.
- Ich kann die Helligkeit über alle Modi über das Poti einstellen
- Ich kann die Blinkfrequenz über das Poti einstellen, jetzt übrigens nicht mehr mit delay, sondern mit millis
Für diese fünf Funktionen ist nur ein Poti nötig, werden dann nur per Taster aktiviert. Nun mein neuer Sketch:
#include <FastLED.h>
FASTLED_USING_NAMESPACE
#define DATA_PIN 3
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB // Farbreihenfolge variiert je nach Hersteller
#define NUMPIXELS 60 // Hier wird die Anzahl der angeschlossenen WS2812 LEDs bzw. NeoPixel angegeben
CRGB leds[NUMPIXELS];
const byte rainb = 2; // Rainbow gesteuert über D2
const byte ein = 4; // LEDs ein gesteuert über D4
const byte aus = 7; // LEDs aus gesteuert über D7
const byte hell = 5; // Helligkeit gesteuert über D5
const byte blinkt = 12; // blinken solange gedrückt, über D12
const byte orange = 8; // Spitze Farbe festlegen, mit Poti, über D8
const byte gelb = 9; // Mittelteil Farbe festlegen, mit Poti, über D9
const byte weiss = 10; // unteren Teil, Farbe festlegen, mit Pot, über D10
const byte poti = A0; // Farbeinstellung
byte unten = 0; // Anzahl LEDs unten
byte mitte = 21; // Anzahl LEDs in der Mitte
byte spitze = 41; // Anzahl LEDs an der Spitze
byte farbe1 = 127; // Farbe 1, unten, Startfarbe türkis
byte farbe2 = 213; // Farbe 2, Mitte, Startfarbe lila
byte farbe3 = 96 ; // Farbe 3, Spitze, Startfarbe grün
byte color; // Zwischenvariable
byte merker;
byte helligkeit = 100; // Starthelligkeit
void setup()
{
pinMode(rainb, INPUT_PULLUP); // alle Pins auf Digital-Input mit Pullup-Rs
pinMode(ein, INPUT_PULLUP);
pinMode(hell, INPUT_PULLUP);
pinMode(aus, INPUT_PULLUP);
pinMode(blinkt, INPUT_PULLUP);
pinMode(orange, INPUT_PULLUP);
pinMode(gelb, INPUT_PULLUP);
pinMode(weiss, INPUT_PULLUP);
Serial.begin (9600);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUMPIXELS);
FastLED.show(); // send the 'leds' array out to the actual LED strip
}
void loop()
{
bool rainbStatus = digitalRead(rainb); // alle Eingänge einlesen
bool einStatus = digitalRead(ein);
bool hellStatus = digitalRead(hell);
bool ausStatus = digitalRead(aus);
bool blinktStatus = digitalRead(blinkt);
bool orangeStatus = digitalRead(orange);
bool gelbStatus = digitalRead(gelb);
bool weissStatus = digitalRead(weiss);
// Funktionen bearbeiten
// Vorrang hat Rainbow mit Helligkeit
if (rainbStatus == HIGH) {
int merker = analogRead(poti);
helligkeit = map(merker, 0, 1023, 30, 255);
rainbow(20, helligkeit);
}
else {
// dann kommen die anderen Funktionen
if (ausStatus == LOW) { // LEDs ausschalten
faerbeLeds(0, 0, 0);
}
if (einStatus == LOW) { // LEDs einschalten
faerbeLeds(color, 255, helligkeit);
}
if (blinktStatus == LOW) { // Blinken solange gedrückt
blinken(color, helligkeit);
}
if (hellStatus == LOW) { // Helligkeit einstellen
int merker = analogRead(poti);
helligkeit = map(merker, 0, 1023, 30, 255);
faerbeLeds(color, 255, helligkeit);
}
if (weissStatus == LOW) { // Farbe unten einstellen
farbe1 = analogRead(poti) / 4;
faerbeLeds(farbe1, 255, helligkeit);
}
if (gelbStatus == LOW) { // Farbe Mitte einstellen
farbe2 = analogRead(poti) / 4;
faerbeLeds(farbe2, 255, helligkeit);
}
if (orangeStatus == LOW) { // Farbe Spitze einstellen
farbe3 = analogRead(poti) / 4;
faerbeLeds(farbe3, 255, helligkeit);
}
}
}
void faerbeLeds(const uint8_t color, const uint8_t saettigung, const uint8_t helligkeit) {
for (uint8_t led = 0; led <= 20; led++)
{
leds[led] = CHSV(farbe1, 255, helligkeit);
}
for (uint8_t led = 21; led <= 40; led++)
{
leds[led] = CHSV(farbe2, 255, helligkeit);
}
for (uint8_t led = 41; led < NUMPIXELS; led++)
{
leds[led] = CHSV(farbe3, 255, helligkeit);
}
FastLED.show();
}
void rainbow(const uint8_t wait, const uint8_t helligkeit) { // Routine für Farbverlauf
uint32_t jetzt = millis();
static uint32_t vorhin = 0;
static uint8_t rbfarbe = 0;
if (jetzt - vorhin >= wait) {
vorhin = jetzt;
for (uint8_t led = 0; led < NUMPIXELS; led++)
{
leds[led] = CHSV(rbfarbe, 255, helligkeit);
}
FastLED.show();
rbfarbe++;
}
}
void blinken(const uint8_t color, const uint8_t helligkeit) {
uint32_t jetzt = millis();
uint16_t intervall = analogRead(poti);
intervall = map(intervall, 0, 1023, 1000, 100);
Serial.print("Intervall = ");
Serial.print(intervall);
Serial.println(" ms");
static uint32_t vorhin = jetzt;
static byte schritt = 0;
if (jetzt - vorhin >= intervall) {
vorhin = jetzt;
switch (schritt) {
case 0:
faerbeLeds(color, 255, helligkeit);
schritt = 1;
break;
case 1:
faerbeLeds(0, 0, 0);
schritt = 0;
break;
}
FastLED.show();
}
}