Neopixel Brightnessfade

Hallo ich versuche einen WS2812 LED Streifen so anzusteuern, daß er nie ganz aus ist sich aber eine dunklere Welle von einem Ende zum anderen bewegt.

Ich habe einen Sketch im Netz gefunden und angepasst. Es funktioniert auch einigermaßen, läuft aber extrem langsam und ich verstehe nicht wieso.

Vielleicht gibt es ja eine bessere Lösung?

Vielen Dank im voraus für Eure Hilfe.

#include <Adafruit_NeoPixel.h>

#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:

Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit... if you must, connect GND first.

void setup() {
  strip.begin();
  strip.show(); // initialize all pixels to "off"
}

void loop() {
  colorFade(255, 0, 0, 0); // fade into red
  colorFade(50, 0, 0, 0); // and then into white
  delay(1);
}



void colorFade(uint8_t r, uint8_t g, uint8_t b, uint8_t wait) {
  for(uint16_t i = 0; i < strip.numPixels(); i++) {
      uint8_t curr_r, curr_g, curr_b;
      uint32_t curr_col = strip.getPixelColor(i); // get the current colour
      curr_b = curr_col & 0xFF; curr_g = (curr_col >> 8) & 0xFF; curr_r = (curr_col >> 16) & 0xFF;  // separate into RGB components

      while ((curr_r != r) || (curr_g != g) || (curr_b != b)){  // while the curr color is not yet the target color
        if (curr_r < r) curr_r++; else if (curr_r > r) curr_r--;  // increment or decrement the old color values
        if (curr_g < g) curr_g++; else if (curr_g > g) curr_g--;
        if (curr_b < b) curr_b++; else if (curr_b > b) curr_b--;
        strip.setPixelColor(i, curr_r, curr_g, curr_b);  // set the color
        strip.show();
        delay(wait);  // add a delay if its too fast
      }
      delay(1);
  }
}

petemanzel:
Es funktioniert auch einigermaßen, läuft aber extrem langsam und ich verstehe nicht wieso.

strip.show(); kann nicht schneller.

Ungefähr zehnmal schneller wären Streifen wie APA102 bei einem entsprechend schnellen Arduino.

Sonst kannst Du nur das Dimmen des sich ändernden Pixels in größeren Schritten durchführen oder weglassen, das bremst gewaltig.

Hallo,

Du könntest erst alle die werte für alle Pixel neu berechnen und dann einmal show. machen. Dann Sollte das schon viel schneller gehen. Du hast da noch ein delay(wait) drin , ich habe aber keinen Wert für wait gefunden.

Schau dir mal die fastLED lib ab , die har ein paar spezielle Funktionen.

Heinz

Rentner:
Du könntest erst alle die werte für alle Pixel neu berechnen und dann einmal show. machen.

Das würde aber dem Sinn des Programms widersprechen. strip.show außerhalb von while würde bedeuten, die while-Schleife wäre sinnlos.

Rentner:
... ich habe aber keinen Wert für wait gefunden.

Bei den Funktionsparametern uint8_t wait.

Rentner:
Schau dir mal die fastLED lib ab , die har ein paar spezielle Funktionen.

Das ist richtig, weshalb ich sie auch bevorzuge, macht die NeoPixel-Kommunikation aber auch nicht schneller.

Hallo,

@agmue ich denke wir reden aneinander vorbei. Das strip.show() sollte ausserhalb der for Schleife machen, damit es für den gesamten Streifen gilt und nicht für jeden einzelnen geänderten Pixel. Allerdings müsste man die Funktion dazu ändern.

In etwa sowas
Zustand von pixel 19 lesen und auf 20 schreiben , 18 auf 19 usw . neue Farbe für pixel 0 berechnen alles ausgeben.

damit würde der Streifen dann z.B von rechts nach links recht schnell geändert werden können. Das gäbe dann eine "fliessenden" Übergang von einer Seite zur anderen.

Heinz

Rentner:
@agmue ich denke wir reden aneinander vorbei.

Das kann ich leider nicht ausschließen.

Die while-Schleife ändert die Farbe des Übergangspunktes sanft von der alten zur neuen Farbe. Befindet sich strip.show außerhalb der Schleife, wird dieser sanfte Übergang zwar berechnet, nicht aber zum Streifen geschickt. Das macht keinen Sinn, weil in der Anzeige die Farbe des Übergangspunktes springt. Die while-Schleife kann man sich dann auch sparen. Die Animation wird dadurch zu einem Flackern beschleunigt, aber es ist nicht mehr die angestrebte Animation.

Da Du 24 Neopixel hast und die Übertragung der Daten an die Neopixel mit 800kHz erfolgt braucht ein Update ca:
50µS + 24 LED x 24 bit x 1,25µS = 770µS

Wie schnell ein Übergang von einer Farbe zu nächsten erfolgt hängt nun von der Anzahl der Zwischenschritte ab. Sollte der 2 Sekunden dauern sind irgendwas zwischen 1000 und 2500 Zwischenschritte möglich (Zeit für die Ausführung der Berechnung der Werte zwischen 1300µ und 0µS geschätzt).
Grüße Uwe

Hallo danke für Eure Tips.

Ich habe mir mal FastLed angesehen. Sieht vielversprechend aus. Muss ich mich mal mehr mit befassen.

Ich habe jetzt einen Sketch der so funktioniert wie ich es gerne hätte. Einzig eine Sache gelingt mir noch nicht. Ich habe zwei LED-Strips an zwei verschieden Pins. Die Animationen werden nacheinander wiedergegeben.

Wie kann ich beide Animationen parallel laufen lassen?

Danke!

#include <Adafruit_NeoPixel.h>

#define REDPIXEL_PIN 6
#define REDPIXEL_COUNT  27

#define BLUEPIXEL_PIN 5
#define BLUEPIXEL_COUNT  27

Adafruit_NeoPixel REDPIXELS = Adafruit_NeoPixel(REDPIXEL_COUNT, REDPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel BLUEPIXELS = Adafruit_NeoPixel(BLUEPIXEL_COUNT, BLUEPIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  //pinMode(REDPIXEL_PIN, OUTPUT);
  REDPIXELS.begin();
  REDPIXELS.show(); // initialize all REDPIXELS to "off"

  //pinMode(BLUEPIXEL_PIN, OUTPUT);
  BLUEPIXELS.begin();
  BLUEPIXELS.show(); // initialize all REDPIXELS to "off"
}


void loop() {
  RunningLights(50);
}

void RunningLights(int WaveDelay) {
  
  int BluePosition=0;
  int RedPosition=REDPIXEL_COUNT;
  
    for(int j=0; j<REDPIXEL_COUNT*2; j++)
    {
        RedPosition--; // = 0; //Position + Rate;
        for(int i=REDPIXEL_COUNT; i>0; i--) {
          REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 155)/255)*255, ((sin(i+RedPosition) * 127 + 128)/255)*0, ((sin(i+RedPosition) * 127 + 128)/255)*0); 
        }  
        REDPIXELS.show();
        delay(WaveDelay);  
    }
  
  
    for(int j=0; j<BLUEPIXEL_COUNT*2; j++)
    {
        BluePosition++; // = 0; //Position + Rate;
        for(int i=0; i<BLUEPIXEL_COUNT; i++) {
          BLUEPIXELS.setPixelColor(i,((sin(i+BluePosition) * 50 + 155)/255)* 0,((sin(i+BluePosition) * 127 + 128)/255)*0, ((sin(i+BluePosition) * 50 + 155)/255)*255);
          //setRedPixel(i,((sin(i+Position) * 50 + 155)/255)*255, ((sin(i+Position) * 127 + 128)/255)*0, ((sin(i+Position) * 127 + 128)/255)*0);
        }
        BLUEPIXELS.show();
        delay(WaveDelay);
    }
  
  }

Hallo,

Du musst das delay() rausbekommen und die Zeit durch millis() ersetzen , dann kannst Du während der Zeit was anderes machen, z.B den zweiten Strip bedienen.

FastLED hast solche Timer in der lib drin, must Du mal in der Doku nachsehen Doku

EVERY_N_MILLISECONDS( 20 )

siehe Beispiel aus der Lib DemoReel100

Heinz

Rentner:
Du musst das delay() rausbekommen und die Zeit durch millis() ersetzen...

Ja, das würde ich auch dringend empfehlen.

@Pete:
In diesem einen speziellen Fall kannst Du auch einfacher zu einem vorläufigen Erfolgserlebnis kommen.
Da die Anzahl roter und blauer Pixel ja gleich ist, muss Du ja "nur" die Bearbeitung beider Farben in einer gemeinsamen Schleife vornehmen. Zwei davon brauchst Du nicht.

for(int j=0; j<PIXEL_COUNT*2; j++)
{
   // mach was mit den roten Pixeln
   // mach was mit den blauen Pixeln
}

Wenn Du das zusammengefummelt hast, kannst Du Dich ja nochmal melden.

Hallo,

vielen Dank für Eure Tips.

Ich habe mich an BlinkWithoutDelay entlang gehangelt und bin jetzt hier angelangt.

Jetzt bewegen sich beide Zeitgleich aber "Interval" hat keinen Einfluss auf die Geschwindigkeit und es bewegt sich alles in Zeitlupe.

#include <Adafruit_NeoPixel.h>

#define REDPIXEL_PIN 6
#define REDPIXEL_COUNT  27

#define BLUEPIXEL_PIN 5
#define BLUEPIXEL_COUNT  27

Adafruit_NeoPixel REDPIXELS = Adafruit_NeoPixel(REDPIXEL_COUNT, REDPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel BLUEPIXELS = Adafruit_NeoPixel(BLUEPIXEL_COUNT, BLUEPIXEL_PIN, NEO_GRB + NEO_KHZ800);

unsigned long previousRedMillis = 0;        // will store last time x.show() was updated
unsigned long previousBlueMillis = 0;        // will store last time x.show() was updated

// constants won't change:
const long RedInterval = 50;           // interval at which to to refresh x.show();
const long BlueInterval = 50;           // interval at which to to refresh x.show();

int BluePosition=0;
int RedPosition=REDPIXEL_COUNT;
  


void setup() {
  //pinMode(REDPIXEL_PIN, OUTPUT);
  REDPIXELS.begin();
  REDPIXELS.show(); // initialize all REDPIXELS to "off"

  //pinMode(BLUEPIXEL_PIN, OUTPUT);
  BLUEPIXELS.begin();
  BLUEPIXELS.show(); // initialize all REDPIXELS to "off"
}


void loop() {
  RunningLights();
}

void RunningLights() {
  unsigned long currentRedMillis = millis();
  unsigned long currentBlueMillis = millis();
    
  if (currentRedMillis - previousRedMillis >= RedInterval) {
      previousRedMillis = currentRedMillis; 
    
    for(int j=0; j<REDPIXEL_COUNT*2; j++)
    {
        RedPosition--; // = 0; //Position + Rate;
        for(int i=0; i<REDPIXEL_COUNT; i++) {
          REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 155)/255)*255, ((sin(i+RedPosition) * 127 + 128)/255)*0, ((sin(i+RedPosition) * 127 + 128)/255)*0); 
        }
    }
   }
    
  if (currentBlueMillis - previousBlueMillis >= BlueInterval) {
      previousBlueMillis = currentBlueMillis;    
    
    for(int j=0; j<BLUEPIXEL_COUNT*2; j++)
    {
        BluePosition++; // = 0; //Position + Rate;
        for(int i=0; i<BLUEPIXEL_COUNT; i++) {
          BLUEPIXELS.setPixelColor(i,((sin(i+BluePosition) * 50 + 155)/255)* 0,((sin(i+BluePosition) * 127 + 128)/255)*0, ((sin(i+BluePosition) * 50 + 155)/255)*255);
        }
    }
   }
  
  BLUEPIXELS.show();
  REDPIXELS.show(); 
}

Das langsame wird daran liegen, dass Du in jedem Aufruf von RunningLights() und damit in jeder Loop für beide Streifen ein show() aufrufst. Das solltest Du nur tun, wenn sich etwas geändert hat - also die jeweilige Zeitbedingung erfüllt war.

Die Intervalle solltest Du auch unsigned long machen. Negativ sollten die nicht werden.

wno158:
Das langsame wird daran liegen, dass Du in jedem Aufruf von RunningLights() und damit in jeder Loop für beide Streifen ein show() aufrufst. Das solltest Du nur tun, wenn sich etwas geändert hat - also die jeweilige Zeitbedingung erfüllt war.

Die Intervalle solltest Du auch unsigned long machen. Negativ sollten die nicht werden.

Danke für deine Zeit!

Das Verhalten ist identisch oder ich übersehe etwas:

#include <Adafruit_NeoPixel.h>

#define REDPIXEL_PIN 6
#define REDPIXEL_COUNT  27

#define BLUEPIXEL_PIN 5
#define BLUEPIXEL_COUNT  27

Adafruit_NeoPixel REDPIXELS = Adafruit_NeoPixel(REDPIXEL_COUNT, REDPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel BLUEPIXELS = Adafruit_NeoPixel(BLUEPIXEL_COUNT, BLUEPIXEL_PIN, NEO_GRB + NEO_KHZ800);

unsigned long previousRedMillis = 0;        // will store last time x.show() was updated
unsigned long previousBlueMillis = 0;        // will store last time x.show() was updated

// constants won't change:
unsigned long RedInterval = 50;           // interval at which to to refresh x.show();
unsigned long BlueInterval = 50;           // interval at which to to refresh x.show();

int BluePosition=0;
int RedPosition=REDPIXEL_COUNT;
  


void setup() {
  //pinMode(REDPIXEL_PIN, OUTPUT);
  REDPIXELS.begin();
  REDPIXELS.show(); // initialize all REDPIXELS to "off"

  //pinMode(BLUEPIXEL_PIN, OUTPUT);
  BLUEPIXELS.begin();
  BLUEPIXELS.show(); // initialize all REDPIXELS to "off"
}


void loop() {
  RunningLights();
}

void RunningLights() {
  unsigned long currentRedMillis = millis();
  unsigned long currentBlueMillis = millis();
    
    for(int j=0; j<REDPIXEL_COUNT*2; j++)
    {
        RedPosition--; // = 0; //Position + Rate;
        for(int i=0; i<REDPIXEL_COUNT; i++) {
          REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 155)/255)*255, ((sin(i+RedPosition) * 127 + 128)/255)*0, ((sin(i+RedPosition) * 127 + 128)/255)*0); 
        }
    }
   
    for(int j=0; j<BLUEPIXEL_COUNT*2; j++)
    {
        BluePosition++; // = 0; //Position + Rate;
        for(int i=0; i<BLUEPIXEL_COUNT; i++) {
          BLUEPIXELS.setPixelColor(i,((sin(i+BluePosition) * 50 + 155)/255)* 0,((sin(i+BluePosition) * 127 + 128)/255)*0, ((sin(i+BluePosition) * 50 + 155)/255)*255);
        }
    }
 
  
  if (currentBlueMillis - previousBlueMillis >= BlueInterval) {
      previousBlueMillis = currentBlueMillis;    
  BLUEPIXELS.show();
  }

  if (currentRedMillis - previousRedMillis >= RedInterval) {
      previousRedMillis = currentRedMillis; 
  REDPIXELS.show();
  }
}

Bin gerade nur auf dem Telefon unterwegs, da ist das so eine Sache mit Code gucken.

Nimm nochmal die vorherige Version aus #10 und schiebe die show() jeweils in das if (zeitbedingung) hinter die for-Schleife.

Ansonsten schaue ich heute Abend nochmal nach.

wno158:
Bin gerade nur auf dem Telefon unterwegs, da ist das so eine Sache mit Code gucken.

Nimm nochmal die vorherige Version aus #10 und schiebe die show() jeweils in das if (zeitbedingung) hinter die for-Schleife.

Ansonsten schaue ich heute Abend nochmal nach.

Geanu das habe ich in #12 gemacht. Unverändert.

Danke für deine Hilfe!

Ich kann nicht erkennen, wozu j gut ist. Außerdem mußt Du die for-Schleife zu loop hin öffnen:

   for(int j=0; j<REDPIXEL_COUNT*2; j++)
    {
        RedPosition--; // = 0; //Position + Rate;
        for(int i=0; i<REDPIXEL_COUNT; i++) {
          REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 155)/255)*255, ((sin(i+RedPosition) * 127 + 128)/255)*0, ((sin(i+RedPosition) * 127 + 128)/255)*0);
        }
    }

Eine ausbaufähige Anregung:

#include <Adafruit_NeoPixel.h>

#define REDPIXEL_PIN 6
#define BLUEPIXEL_PIN 5
#define PIXEL_COUNT  27

Adafruit_NeoPixel REDPIXELS = Adafruit_NeoPixel(PIXEL_COUNT, REDPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel BLUEPIXELS = Adafruit_NeoPixel(PIXEL_COUNT, BLUEPIXEL_PIN, NEO_GRB + NEO_KHZ800);

const long INTERVALL = 50;          // interval at which to to refresh x.show();

void setup() {
  REDPIXELS.begin();
  REDPIXELS.show(); // initialize all REDPIXELS to "off"

  BLUEPIXELS.begin();
  BLUEPIXELS.show(); // initialize all BLUEPIXELS to "off"
}

void loop() {
  RunningLights();
}

void RunningLights() {
  unsigned long currentMillis = millis();
  static unsigned long previousMillis = 0;        // will store last time x.show() was updated
  static int RedPosition = PIXEL_COUNT;
  static int BluePosition = 0;

  if (currentMillis - previousMillis >= INTERVALL)
  {
    previousMillis = currentMillis;
    RedPosition--;
    BluePosition++;
    for (int i = 0; i < PIXEL_COUNT; i++)
    {
      REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 155)/255)*255, ((sin(i+RedPosition) * 127 + 128)/255)*0, ((sin(i+RedPosition) * 127 + 128)/255)*0);
      BLUEPIXELS.setPixelColor(i,((sin(i+BluePosition) * 50 + 155)/255)* 0,((sin(i+BluePosition) * 127 + 128)/255)*0, ((sin(i+BluePosition) * 50 + 155)/255)*255);
    }
    REDPIXELS.show();
    BLUEPIXELS.show();
  }
}

Die Sinusberechnungen, die Du mit 0 multiplizierst, sind wenig sinnvoll. Auch das Überlaufenlassen von RedPosition und BluePosition wäre zu überdenken.

Aber schnell ist es jetzt :slight_smile:

agmue:
Ich kann nicht erkennen, wozu j gut ist. Außerdem mußt Du die for-Schleife zu loop hin öffnen:

...

Die Sinusberechnungen, die Du mit 0 multiplizierst, sind wenig sinnvoll. Auch das Überlaufenlassen von RedPosition und BluePosition wäre zu überdenken.

Aber schnell ist es jetzt :slight_smile:

Danke! Es läuft jetzt!

j hatte ich angelegt um beide Ledstripes unabhängig voneinander beeinflussen zu können.

Die Sinusberechnungen, die ich mit 0 multipliziere hatte ich gelassen da ich vielleicht noch die Farben anpassen möchte.

REDPOSITION und BLUEPOSITION wird doch vor jedem Durchlauf von RunningLights neu definiert.

Das ist mein funktionierender Zwischenstand.
DANKE!

#include <Adafruit_NeoPixel.h>

#define REDPIXEL_PIN 6
#define BLUEPIXEL_PIN 5
#define PIXEL_COUNT  27

Adafruit_NeoPixel REDPIXELS = Adafruit_NeoPixel(PIXEL_COUNT, REDPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel BLUEPIXELS = Adafruit_NeoPixel(PIXEL_COUNT, BLUEPIXEL_PIN, NEO_GRB + NEO_KHZ800);

const long INTERVALL = 30;          // interval at which to to refresh x.show();

void setup() {
  REDPIXELS.begin();
  REDPIXELS.show(); // initialize all REDPIXELS to "off"

  BLUEPIXELS.begin();
  BLUEPIXELS.show(); // initialize all BLUEPIXELS to "off"
}

void loop() {
  RunningLights();
}

void RunningLights() {
  unsigned long currentMillis = millis();
  static unsigned long previousMillis = 0;        // will store last time x.show() was updated
  static int RedPosition = PIXEL_COUNT;
  static int BluePosition = 0;

  if (currentMillis - previousMillis >= INTERVALL)
  {
    previousMillis = currentMillis;
    RedPosition--;
    BluePosition++;
    for (int i = 0; i < PIXEL_COUNT; i++)
    {
      //REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 155)/255)*255, ((sin(i+RedPosition) * 127 + 128)/255)*0, ((sin(i+RedPosition) * 127 + 128)/255)*0);
      //BLUEPIXELS.setPixelColor(i,((sin(i+BluePosition) * 50 + 155)/255)* 0,((sin(i+BluePosition) * 127 + 128)/255)*0, ((sin(i+BluePosition) * 50 + 155)/255)*255);
      REDPIXELS.setPixelColor(i,((sin(i+RedPosition) * 50 + 205)/255)*255, 0, 0);
      BLUEPIXELS.setPixelColor(i, 0, 0, ((sin(i+BluePosition) * 50 + 205)/255)*255);
    }
    REDPIXELS.show();
    BLUEPIXELS.show();
  }
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.