Projekt WS2812b

Habe den code an ein Arduino Mega hochgeladen, wenn ich den Taster drücke geht das Leuchtprogramm los. Wenn ich den Taster wieder drücke passiert nichts.
Habe WS2811 mit 300 led's an 12 V 30 A angeschlossen. Und genau so nach Chema wie auf dem Bild angeschlossen.

#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
#include <math.h>
#include <SoftwareSerial.h>


#define N_PIXELS  100  // Number of pixels in strand
#define MIC_PIN   A0  // Microphone is attached to this analog pin
#define LED_PIN    6  // NeoPixel LED strand is connected to this pin
#define SAMPLE_WINDOW   10  // Sample window for average level
#define PEAK_HANG 24 //Time of pause before peak dot falls
#define PEAK_FALL 4 //Rate of falling peak dot
#define INPUT_FLOOR 10 //Lower range of analogRead input
#define INPUT_CEILING 300 //Max range of analogRead input, the lower the value the more sensitive (1023 = max)
const int debounce = 150; // Taster entprellen mit 150ms
volatile unsigned long nowMillis;
volatile unsigned long prevMillis;
byte peak = 16;      // Peak level of column; used for falling dots
unsigned int sample;

byte dotCount = 0;  //Frame counter for peak dot
byte dotHangCount = 0; //Frame counter for holding peak dot

// #include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

int x;
int y;
int z;
const int tasterPin = 2;     // Taster an Pin 2 angeschlossen
volatile int lichtmodus = 0;          // Variable für die verschiedenen festgelegten Farben
int tasterStatus = HIGH;      // Variable zu speichern des Tasterstatus

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 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)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(100, 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()
{
  pinMode(tasterPin, INPUT_PULLUP);      // Setzt den TasterPin als Eingang
  strip.begin();
  strip.setBrightness(200);
  strip.show(); // Initialize all pixels to 'off'
  attachInterrupt(digitalPinToInterrupt(tasterPin), ChangeMode, RISING);
}
void ChangeMode() {
    nowMillis = millis();
    if (nowMillis - prevMillis > debounce) {
        lichtmodus ++;
        prevMillis = nowMillis;
    }
}
void loop() {
  
  // Abfrage ob der Taster gedrückt ist
  tasterStatus = digitalRead(tasterPin);
  
  // Wenn Taster gedrückt ist...
  if (tasterStatus == LOW)
  {
    lichtmodus++;     // Lichtmodus +1
    delay(300);       // 300ms warten
  }
  
  
//+++++++++++++++ LEUCHTPROGRAMME +++++++++++++++++
  
// Modus 0 = Licht aus
  if (lichtmodus == 0)
    {
     for (int t=1;t<15;t++)
     {
       x=random(1,255);
       y=random(1,255);
       z=random(1,255);
       colorWipe(strip.Color(x, y, z), 10);
      
       x=random(1,255);
       y=random(1,255);
       z=random(1,255);
       colorWipe2(strip.Color(x, y, z), 10);
     }
    rainbow(115);
    rainbowCycle(115);
    theaterChaseRainbow(300);    
    }
    
  // Modus 1 = Blau
  else if (lichtmodus == 1)
    {
        unsigned long startMillis= millis();  // Start of sample window
        float peakToPeak = 0;   // peak-to-peak level

        unsigned int signalMax = 0;
        unsigned int signalMin = 1023;
        unsigned int c, y;


        // collect data for length of sample window (in mS)
        while (millis() - startMillis < SAMPLE_WINDOW)
        {
          sample = analogRead(MIC_PIN);
          if (sample < 1024)  // toss out spurious readings
          {
           if (sample > signalMax)
          {
            signalMax = sample;  // save just the max levels
          }
          else if (sample < signalMin)
          {
            signalMin = sample;  // save just the min levels
          }
        }  
      }
  
      peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude

  // Serial.println(peakToPeak);


  //Fill the strip with rainbow gradient
      for (int i=0;i<=strip.numPixels()-1;i++){
       strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
      }


  //Scale the input logarithmically instead of linearly
      c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);

  


      if(c < peak) {
         peak = c;        // Keep dot on top
         dotHangCount = 0;    // make the dot hang before falling
      }
      if (c <= strip.numPixels()) { // Fill partial column with off pixels
        drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
      }

// Set the peak dot to match the rainbow gradient
      y = strip.numPixels() - peak;
  
      strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));

      strip.show();

// Frame based peak dot animation
      if(dotHangCount > PEAK_HANG) { //Peak pause length
        if(++dotCount >= PEAK_FALL) { //Fall rate
          peak++;
          dotCount = 0;
        }
      }    
      else {
        dotHangCount++;
      }
     }    
  


// Anzahl der Leutmodi auf 2 begrenzen. (0 bis 1)
      else
{
      lichtmodus = 0;
}
}


// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

// Fill the dots one after the other with a color
void colorWipe2(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(100-i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}





// 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 strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

//Used to draw a line between two points of a given color
void drawLine(uint8_t from, uint8_t to, uint32_t c) {
  uint8_t fromTemp;
  if (from > to) {
    fromTemp = from;
    from = to;
    to = fromTemp;
  }
  for(int i=from; i<=to; i++){
    strip.setPixelColor(i, c);
  }
}


float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;


  // condition curve parameter
  // limit range

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
  curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function

  /*
   Serial.println(curve * 100, DEC);   // multply by 100 to preserve resolution  
   Serial.println();
   */

  // Check for out of range inputValues
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  // Zero Refference the values
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd;
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;   // normalize to 0 - 1 float

  // Check for originalMin > originalMax  - the math for all other cases i.e. negative numbers seems to work out fine
  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else     // invert the ranges
  {  
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange);
  }

  return rangedValue;

}



Gruß ledlutz

Wo sind denn die LEDs angeschlossen, die finde ich nicht?

Hallo agmue,der Streifen ist an digitalen pin 6 angeschlossen.

Eventuell habe ich die falsche Brille auf, aber ich sehe keine Leds.

Laß Dir mal die Variable lichtmodus auf dem seriellen Monitor ausgeben. Du änderst diese Variable an zwei Stellen, warum?


Wie bekomme ich das hin ? Ich habe den Code nur runtergeladen. Der serielle Monitor zeigt nichts an.
Da steht Nachricht senden , Baudrate 9600.?

Ich schaue immer auch noch außerhalb Deines Problems und da fehlt mir der Widerstand zwischen Arduino-Pin und erstem Pixel, da Du zwei Stromversorgungen nutzt. Ohne Widerstand kann der erste Pixel zerstört werden.

Siehe dazu Adafruit NeoPixel Überguide

Schau mal in das IDE-Beispiel ASCIITable, da siehst Du, wie es geht.

Widerstand ist unter dem roten Schrumpfschlauch.
Werde mich mal an's Werk machen.
Danke erstmal für die schnelle Info.

Das blaue Kabel hat einen roten Schlauch, das sollte GND sein. Da ist ein Widerstand drin?

Widerstand in schwarzer Schrumpfschlauch über grünem Kabel wäre OK.

Moin @ledlutz,

schau mal hier:

https://wokwi.com/projects/403653802259706881

Ich habe Dein Projekt in Wokwi eingestellt und getestet. Mir sind dabei mehrere Dinge aufgefallen:

  • Der Taster wird an zwei Stellen im Programm ausgewertet:
    • Zum einem per Interrupt (attachInterrupt(digitalPinToInterrupt(tasterPin), ChangeMode, RISING)
    • zum anderen in der Loop() (tasterStatus = digitalRead(tasterPin); if (tasterStatus == LOW))

Die Interruptroutine funktioniert, die Variable lichtmodus wird hochgezählt (siehe die serielle Ausgabe, das ist nicht die feine Art, aber fürs Debuggen ...)

Die beiden Tastenroutinen haben aber keine unmittelbare Auswirkung auf das Programm, weil der lichtmodus 0 extrem lange benötigt (insbesondere rainbowCycle(), da hat mich die Geduld verlassen ... :wink: )

Entweder musst Du dafür sorgen, dass die Routinen kürzer laufen, bei Änderung des lichtmodus abgebrochen werden, oder ausreichend Geduld aufbringen ...

Gruß
ec2021

Zum Taster eine ISR.
Was ist mit prellen?

Guckst Du hier:

const int debounce = 150; // Taster entprellen mit 150ms

void ChangeMode() {
    nowMillis = millis();
    if (nowMillis - prevMillis > debounce) {
        lichtmodus ++;
        prevMillis = nowMillis;
    }
}

P.S.: Will auch nicht das Programm überarbeiten, sondern nur darauf hinweisen, warum eine Tastenbetätigung sich nicht in angemessener Zeit auswirkt ...

Ok, ich hab das nicht ganz gelesen - Handy sei Dank.
Aber debounce in ISR :man_facepalming:
Ich bin dann wieder raus...
Gruß an Dich :slight_smile:

2 Likes

Nur etwas Geduld, nach ein paar Minuten ...

Stimmt... :wink:

Man muss halt Geduld haben ...

SInd das nun WS2812 oder WS2811?

Ws2811, immer in 3 led in einer Guppe.

Nur zu meinem Verständnis:

Möchtest Du, dass die lichtmodi ggf. einige Minuten durchlaufen und danach auf den Tastendruck reagieren, oder erwartest Du eine schnelle Umschaltung der Modi nach Tastendruck?

Im zweiten Fall sind die vielen for-loops (inklusive der darin befindlichen delays) hinderlich! Die for-loops verhindern eine unmittelbare Reaktion auf einen veränderten Wert von "lichtmodus".

Um das zu ändern, müsstest Du

  • in jede for-loop() eine Abbruchbedingung einbauen (das ist aufwendig, fehlerträchtig und "unelegant") oder
  • den Code auf eine State Machine umstellen. Dies wäre die software-technisch wohl sauberste und am besten zu pflegende Lösung.

ec2021

Ich hatte den selben Code voriges Jahr schon mal auf ein Arduino Uno hochgeladen das hat das super funktioniert. Nach dam hochgeladen war der Streifen dunkel nach dem man den Taster gedrückt hat ging sofort das VU Meter los und dann konnte das Programm durchschalten. Warum das jetzt nicht mehr geht ist mir ein Rätsel.
Mit dem Programmieren bin ich nicht so versiert.

Eine schnelle Umschaltung der Modi wäre super.

Danke nochmals für deine Bemühungen. Wenn es für dich keine große Arbeit ist kannst du mir das im Programm so umstellen das es gleich beim ersten Tastendruck das vu- meter
startet?