Benutzer-Werkzeuge

Webseiten-Werkzeuge


silentbase_neopixel:programmversion_0.9

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
silentbase_neopixel:programmversion_0.9 [20.11.2016 21:45] Frickelpietsilentbase_neopixel:programmversion_0.9 [18.05.2023 12:16] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
-Der Glitzereffekt in [[silentbase_neopixel:programmversion_0.7|Programmversion 0.7]] war für mich bereits eine Herausforderung. Den [[http://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/|hier]] beschriebenen Effekt "FireMultitaskingfähig zu machen dürfte interessant werden+====== NeoPixel-Beleuchtung für SilentBase 800 Programmversion 0.9 ====== 
 +Der Glitzereffekt in [[silentbase_neopixel:programmversion_0.7|Programmversion 0.7]] war für mich bereits eine Herausforderung. (Der Feuereffekt Nr. 2 (Programmmodus 5) aus [[silentbase_neopixel:programmversion_0.8|Programmversion 0.8]] ist ein Kind des Zufalls.) Den bekannten Fire 2012-Effekt aus der FastLED-Bibliothek nachzubauen war eine Herausforderung für mich. Sehr hilfreich war der Code von [[http://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/|Tweaking4all]], der allerdings fehlerbehaftet ist. Aber letzendlich habe ich es geschafft. 
 + 
 +Eine gute Beschreibung der Auswirkung der Parameter "Coolingund "Sparkling" (inklusive Videos) gibt es [[https://github.com/krzychb/EspFire2012/blob/master/readme.md|hier]].
  
 Hilfreiche Links: Hilfreiche Links:
Zeile 5: Zeile 8:
   * https://blog.kriegsman.org/2014/04/04/fire2012-an-open-source-fire-simulation-for-arduino-and-leds/   * https://blog.kriegsman.org/2014/04/04/fire2012-an-open-source-fire-simulation-for-arduino-and-leds/
   * https://github.com/FastLED/FastLED/blob/master/examples/Fire2012/Fire2012.ino   * https://github.com/FastLED/FastLED/blob/master/examples/Fire2012/Fire2012.ino
 +  * https://github.com/krzychb/EspFire2012
 +  * Sehr gute Beschreibung des Codes: https://github.com/krzychb/EspFire2012/blob/master/readme.md
   * Simulation Fire-Effekt: http://dougalcampbell.github.io/LEDStrip/   * Simulation Fire-Effekt: http://dougalcampbell.github.io/LEDStrip/
   * Fire-Effekt in JS: https://github.com/dougalcampbell/LEDStrip/blob/master/fire.js   * Fire-Effekt in JS: https://github.com/dougalcampbell/LEDStrip/blob/master/fire.js
 +
 +ToDos:
 +  * Bei dem Fire2012-Effekt müsste die Temperatur eines Pixels die Bewegungsgeschwindigkeit beeinflussen. 
 +  * Die Variable  "buttonpressed" könnte auch als boolean definiert werden.
 +  * Das array "byte invert" könnte man sich mit dem Befehl map sparen.
 +
 +Der Sketch enthält Code von [[https://www.baldengineer.com/millis-cookbook.html|Baldengineer]], [[http://www.scynd.de/tutorials/arduino-tutorials/1-taster/1-2-taster-entprellt.html|Scynd]], [[http://www.walltech.cc]] und [[http://www.tweaking4all.com]].
 +<code>
 +// Dieser Sketch enthält Code von
 +// Baldengineer (https://www.baldengineer.com),
 +// Scynd (http://www.scynd.de) und
 +// Hans Luijten (http://www.tweaking4all.com).
 +
 +
 +// Bibliotheken einbinden
 +#include <EEPROM.h>
 +#include <ResponsiveAnalogRead.h>
 +#include <Adafruit_NeoPixel.h>
 +
 +
 +// Definiert die Pins
 +#define buttonPin 7           // Taster
 +#define loadPin A0            // analoge Spannungsmessung
 +#define neoPin1 11            // Neopixel-Strip rechte Seite
 +#define neoPin2 12            // Neopixel-Strip linke Seite
 +
 +
 +// Definiert eine Adresse im EEPROM
 +int addr = 0;                 // An dieser Adresse wird später der ausgewählte Programmmodus gespeichert
 +
 +
 +// Definiert ein ResponsiveAnalogRead Objekt
 +ResponsiveAnalogRead rload(loadPin, true);
 +
 +
 +// Definiert die Variablen
 +int numPixels = 64;           // Anzahl der NeoPixel
 +int load;                     // Variable repäsentiert später die Differenz zwischen minimaler und maximaler Netzteillast in Prozent
 +
 +int buttonstate = HIGH;       // aktuelles Signal vom Tasterpin
 +int buttonpressed = 0;        // abfragen ob Taster gedrückt war
 +int debouncetime = 50;        // Zeit für Entprellung ggf. anpassen
 +
 +float rloadmin = 350;         // Messwert am loadPin bei minimaler Netzteillast (muss abgelesen werden)
 +float rloadmax = 650;         // Messwert am loadPin bei maximaler Netzteillast (muss abgelesen werden)
 +
 +float x = 0;                  // Zählwert für verschiedene Beleuchtungseffekte 
 +boolean sw1 = true;           // Schaltvariable für verschiedene Beleuchtungseffekte
 +boolean sw2 = true;           // Schaltvariable für verschiedene Beleuchtungseffekte
 +int i;                        // Zählwert für verschiedene Beleuchtungseffekte
 +int j;                        // Zählwert für verschiedene Beleuchtungseffekte
 +int k;                        // Zählwert für verschiedene Beleuchtungseffekte
 +int l;                        // Zählwert für verschiedene Beleuchtungseffekte
 +
 +int cooling;                  // Variable für Beleuchtungseffekt Flammen
 +int sparkling;                // Variable für Beleuchtungseffekt Flammen
 +int cooldown;
 +static byte heat[64];         // Ein Array für die Temperaturwerte
 +
 +byte invert[] = {63, 62, 61, 60, 59, 58, 57, 56, 55, 54,  // Ein Array zur Umrechnung
 +  53, 52, 51, 50, 49, 48, 47, 46, 45, 44,
 +  43, 42, 41, 40, 39, 38, 37, 36, 35, 34,
 +  33, 32, 31, 30, 29, 28, 27, 26, 25, 24,
 +  23, 22, 21, 20, 19, 18, 17, 16, 15, 14,
 +  13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
 +  };
 +
 +byte programmode = 0;         // Programmmodus
 +
 +
 +// Definiert die NeoPixel-Strips
 +Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(numPixels, neoPin1, NEO_GRBW + NEO_KHZ800);
 +Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(numPixels, neoPin2, NEO_GRBW + NEO_KHZ800);
 +
 +
 +// Definiert die globalen RGBW-Werte
 +byte r = 0;
 +byte g = 0;
 +byte b = 0;
 +byte w = 0;
 +
 +
 +// Definiert die Tracking-Variablen für die IF-Abfragen
 +unsigned long previousMillisCalcLoad = 0;
 +unsigned long previousMillisFPS20 = 0;
 +unsigned long previousMillisFPS60 = 0;
 +unsigned long previousMillisSerialPrint = 0;
 +unsigned long buttontime = 0;
 +unsigned long sparkle1on = 0;
 +unsigned long sparkle1off = 0;
 +unsigned long sparkle1ondelay = 100;
 +unsigned long sparkle1offdelay = 500;
 +unsigned long sparkle2on = 0;
 +unsigned long sparkle2off = 0;
 +unsigned long sparkle2ondelay = 100;
 +unsigned long sparkle2offdelay = 500;
 +
 +
 +// Definiert die Intervalle für die IF-Abfragen
 +int intervalCalcLoad = 500;      // Delay für Berechnung der Last
 +int intervalFPS20 = 50;          // Delay für Effekte mit 20 FPS
 +int intervalFPS60 = 16;          // Delay für Effekte mit 60 FPS
 +int intervalSerialPrint = 1000;  // Delay für serielle Ausgabe
 +
 +
 +void setup() {
 +  // Initialisiere den Button-Pin
 +  pinMode(buttonPin, INPUT_PULLUP);
 +
 +  // Initialisiere die NeoPixel-Pins
 +  pinMode(neoPin1, OUTPUT);
 +  pinMode(neoPin2, OUTPUT);
 +
 +  // Initialisiere den analogen Pin 
 +  pinMode(loadPin, INPUT);
 +
 +  // Initialisiere die NeoPixel-Strips
 +  strip1.begin(); // Initialisiert das Neopixel
 +  strip1.show();  // Macht das NeoPixel sichtbar
 +  //strip1.clear(); // Macht das NeoPixel aus
 +  
 +  strip2.begin(); // Initialisiert das Neopixel
 +  strip2.show();  // Macht das NeoPixel sichtbar
 +  //strip2.clear(); // Macht das NeoPixel aus
 +
 +  // Lese den abgespeicherten Wert für den Programmmodus aus dem EEPROM
 +  programmode = EEPROM.read(addr);
 +
 +  // Initialisiere die serialle Schnittstelle
 +  Serial.begin(57600);
 +
 +delay (2000);
 +}
 +
 +
 +
 +void loop() {
 +// Lesen und entprellen des Tasters
 +  buttonstate = digitalRead(buttonPin);
 + 
 +  // Wenn der Taster gedrückt ist...
 +  if (buttonstate == LOW)
 +  {
 +    buttontime = millis();                      // aktualisiere tasterZeit
 +    buttonpressed = 1;                          // speichert, dass Taster gedrückt wurde
 +  }
 + 
 +  // Wenn die gewählte entprellZeit vergangen ist und der Taster gedrückt war...
 +  if ((millis() - buttontime > debouncetime) && buttonpressed == 1)
 +    {
 +      buttonpressed = 0;                        // setzt gedrückten Taster zurück
 +      programmode++;                            // Programmmodus wird um +1 erhöht
 +      EEPROM.write(addr, programmode);          // Schreibt den Programmmodus ins EEPROM
 +      r = 0;                                    // setzt den globalen Farbwert zurück
 +      g = 0;                                    // setzt den globalen Farbwert zurück
 +      b = 0;                                    // setzt den globalen Farbwert zurück
 +      w = 0;                                    // setzt den globalen Farbwert zurück
 +      strip1.clear();                           // setzt die NeoPixel zurück
 +      strip2.clear();                           // setzt die NeoPixel zurück
 +    }
 +
 +
 +// Aktuelle Zeit abfragen
 +  unsigned long currentMillis = millis();
 +
 +
 +// Messen der Spannung am analogen Eingangspin loadPin (A0) und Berechnen einiger Variablen zur Beeinflussung verschiedener Effekte
 +  if ((unsigned long)(currentMillis - previousMillisCalcLoad) >= intervalCalcLoad) {
 +  
 +     // Auslesen des analogen Eingangs (Last Netzteil)
 +     rload.update();
 +
 +     // Berechnung der Netzteillast in Prozent: Bei ruhendem Desktop soll der Wert 0 sein, bei maximaler Auslastung 100
 +     load = 100 - ((rloadmax - rload.getValue()) / (rloadmax - rloadmin)) * 100;
 +
 +     // Berechnung von Cooling für den Effekt Fire 2012: Legt fest, wie stark die aufsteigenden Flammen abkühlen
 +     // Werte zwischen 20 und 100 sollen am hübschesten sein, ein guter Standard ist 50
 +     cooling = 100 - (load / 0.8);
 +
 +     // Berechnung von Sparkling für den Effekt Fire2012: Legt fest, wie oft ein Funke auflohdert
 +     //Werte zwischen 50 und 200 sollen am hübschesten sein, ein guter Standard ist 120
 +     sparkling = 50 + (load * 1.5);
 +    
 +  //Speichere die aktuelle Zeit in die zughörige Variable
 +  previousMillisCalcLoad = currentMillis;
 +  }
 +
 +
 +// Steuerung der NeoPixel-Strips
 +  // Beleuchtungseffekt für Programmmodus 0 (Atmen rot)
 +  if (programmode == 0) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS20) >= intervalFPS20) {
 +
 +     if(load < 10) {       // Variable soll für diesen Effekt nicht kleiner als 10 werden
 +        load = 10;
 +        }
 +        
 +      // Ansteuerung der NeoPixel-Strips
 +      x = x + (0.05 * (load/10));
 +      if (x >= 6.28) {
 +        x = 0;
 +      }
 +        // fade led mit x
 +        r = ((exp(sin(x)) - 0.36787944) * 108.492061351);
 +        
 +      for (int i = 0; i < numPixels; i++) {
 +        strip1.setPixelColor(i, r, g, b, w);
 +        strip2.setPixelColor(i, r, g, b, w);
 +      }
 +      strip1.show();
 +      strip2.show();
 +   
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS20 = currentMillis;
 +    }
 +  }
 +
 +  //Beleuchtungseffekt für Programmmodus 1 (Atmen weiß)
 +  else if (programmode == 1) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS20) >= intervalFPS20) {
 +
 +     if(load < 10) {       // Variable soll für diesen Effekt nicht kleiner als 10 werden
 +        load = 10;
 +        }
 +        
 +      // Ansteuerung der NeoPixel-Strips
 +      x = x + (0.05 * (load/10));
 +      if (x >= 6.28) {
 +        x = 0;
 +      }
 +        // fade led mit x
 +        w = ((exp(sin(x)) - 0.36787944) * 108.492061351);
 +        
 +      for (int i = 0; i < numPixels; i++) {
 +        strip1.setPixelColor(i, r, g, b, w);
 +        strip2.setPixelColor(i, r, g, b, w);
 +      }
 +      strip1.show();
 +      strip2.show();
 +   
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS20 = currentMillis;
 +    }
 +  }
 +
 +
 +  //Beleuchtungseffekt für Programmmodus 2 (Stabthermometer)
 +  else if (programmode == 2) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS20) >= intervalFPS20) {
 +
 +      if(load >= numPixels) {       // Variable soll für diesen Effekt nicht größer als NeoPixel vorhanden
 +        load = 63;
 +        }
 +      // Weißer Bereich
 +      for (int i = 0; i < numPixels; i++) {
 +      strip1.setPixelColor(i, r, g, b, 127);
 +      strip2.setPixelColor(i, r, g, b, 127);
 +      }
 +      // Roter Bereich      
 +      for (int i = 63; i > (63 - load); i--) {
 +        strip1.setPixelColor(i, 127, g, b, w);
 +        strip2.setPixelColor(i, 127, g, b, w);
 +      }
 +      strip1.show();
 +      strip2.show();
 +   
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS20 = currentMillis;
 +    }
 +  }
 +
 +
 +  //Beleuchtungseffekt für Programmmodus 3 (Stabthermometer mit Glitzer)
 +  else if (programmode == 3) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS20) >= intervalFPS20) {
 +
 +      if(load >= numPixels) {       // Variable soll für diesen Effekt nicht größer als NeoPixel vorhanden
 +        load = 63;
 +        }
 +      // Blauer Bereich
 +      for (int i = 0; i < numPixels; i++) {
 +      strip1.setPixelColor(i, r, g, 127, w);
 +      strip2.setPixelColor(i, r, g, 127, w);
 +      }
 +      // Roter Bereich     
 +      for (int i = 63; i > (63 - load); i--) {
 +        strip1.setPixelColor(i, 127, g, b, w);
 +        strip2.setPixelColor(i, 127, g, b, w);
 +      }
 +
 +      // Sparkle NeoPixel-Strip 1
 +      if(sw1)
 +        {
 +          strip1.setPixelColor(j, r, g, b, 255);
 +          if(millis() - sparkle1on >= sparkle1ondelay)
 +          {
 +          sparkle1offdelay = random (100, 1000);
 +          sparkle1off = millis();
 +          sw1 = !sw1;
 +          }
 +        }
 +        if(!sw1)
 +          {
 +          if(millis() - sparkle1off >= sparkle1offdelay)
 +              {
 +                j = random(0, (numPixels -1));
 +                sparkle1on = millis();
 +                sw1 = !sw1;       
 +              }
 +        } 
 +      // Sparkle NeoPixel-Strip 2
 +      if(sw2)
 +        {
 +          strip2.setPixelColor(k, r, g, b, 255);
 +          if(millis() - sparkle2on >= sparkle2ondelay)
 +          {
 +          sparkle2offdelay = random (100, 1000);
 +          sparkle2off = millis();
 +          sw2 = !sw2;
 +          }
 +        }
 +        if(!sw2)
 +          {
 +          if(millis() - sparkle2off >= sparkle2offdelay)
 +              {
 +                k = random(0, (numPixels - 1));
 +                sparkle2on = millis();
 +                sw2 = !sw2;       
 +              }
 +        } 
 +      // Sende die Daten an die Neopixel
 +      strip1.show();
 +      strip2.show();
 +   
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS20 = currentMillis;
 +    }
 +  }
 +
 +
 +    //Beleuchtungseffekt für Programmmodus 4 (Feuer 1)
 +  else if (programmode == 4) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS20) >= intervalFPS20) {
 +
 +      for (int i = 0; i < numPixels; i++) {
 +        int flicker = random (0, 150);
 +        int r = 255;
 +        int g = r-100;
 +        int b = 30;
 +        
 +        r = r - flicker;
 +        g = g - flicker;
 +        b = b - flicker;
 +
 +        if(r < 0) r = 0;
 +        if(g < 0) g = 0;
 +        if(b < 0) b = 0;
 +        
 +      strip1.setPixelColor(i, r, g, b, 0);
 +      strip2.setPixelColor(i, r, g, b, 0);
 +      }
 +      // Sende die Daten an die Neopixel
 +      strip1.show();
 +      strip2.show();
 +   
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS20 = currentMillis;
 +    }
 +  }
 +
 +
 +    //Beleuchtungseffekt für Programmmodus 5 (Feuer 2)
 +  else if (programmode == 5) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS20) >= intervalFPS20) {
 +
 +      if(load >= numPixels) {       // Variable soll für diesen Effekt nicht größer als NeiPoxel vorhanden
 +        load = 63;
 +        }
 +        int r = 255;
 +        int g = 130;
 +        int b = 30;
 +        int w = 63;
 +
 +      for (int i = (numPixels -1); i > 0; i--) {
 +        int flicker = random (0, (42 - (load/2)));
 +
 +        r = r - flicker;
 +        g = g - flicker;
 +        b = b - flicker;
 +        w = w - (flicker * 3);
 +        
 +        if(r < 0) r = 0;
 +        if(g < 0) g = 0;
 +        if(b < 0) b = 0;
 +        if(w < 0) w = 0;
 +        
 +      strip1.setPixelColor(i, r, g, b, w);
 +      strip2.setPixelColor(i, r, g, b, w);
 +      }
 +      // Sende die Daten an die Neopixel
 +      strip1.show();
 +      strip2.show();
 +   
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS20 = currentMillis;
 +    }
 +  }
 +
 +
 +    //Beleuchtungseffekt für Programmmodus 6 (Fire2012))
 +  else if (programmode == 6) {
 +    if ((unsigned long)(currentMillis - previousMillisFPS60) >= intervalFPS60) {
 +
 +      // Step 1.  Cool down every cell a little
 +      for(int i = 0; i < numPixels; i++) {    
 +        cooldown = random(0, ((cooling * 10) / numPixels) + 2);
 +    
 +        if(cooldown > heat[i]) {
 +          heat[i] = 0;
 +            } else {
 +            heat[i] = heat[i] - cooldown;
 +            }
 +          }
 +
 +      // Step 2.  Heat from each cell drifts 'up' and diffuses a little
 +      for(int k = numPixels - 1; k >= 2; k--) {
 +        heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
 +        }
 +    
 +    // Step 3.  Randomly ignite new 'sparks' near the bottom
 +      if(random(255) < sparkling) {
 +        l = random(7);
 +        heat[l] = heat[l] + random(160,255);
 +        //heat[l] = random(160,255);
 +        }
 +
 +    // Step 4.  Convert heat to LED colors
 +      for(int j = numPixels -1; j >= 0; j--) {        
 +        // Scale 'heat' down from 0-255 to 0-191
 +        byte t192 = round((heat[j]  /255.0) * 191);
 + 
 +        // calculate ramp up from
 +        byte heatramp = t192 & 0x3F; // 0..63
 +        heatramp <<= 2; // scale up to 0..252
 +
 +        // figure out which third of the spectrum we're in:
 +        if( t192 > 0x80) {                       // hottest
 +          strip1.setPixelColor(invert[j], 255, 255, heatramp, 0);
 +          strip2.setPixelColor(invert[j], 255, 255, heatramp, 0);
 +          } else if( t192 > 0x40 ) {             // middle
 +          strip1.setPixelColor(invert[j], 255, heatramp, 0, 0);
 +          strip2.setPixelColor(invert[j], 255, heatramp, 0, 0);
 +          } else {                               // coolest
 +          strip1.setPixelColor(invert[j], heatramp, 0, 0, 0);
 +          strip2.setPixelColor(invert[j], heatramp, 0, 0, 0);  
 +          }
 +        }
 +      strip1.show();
 +      strip2.show();
 +      
 +    //Speichere die aktuelle Zeit in die zughörige Variable
 +    previousMillisFPS60 = currentMillis;
 +    }
 +  }
 +
 +
 +  // Wenn der Programmodus auf einen höheren Wert sprngt, wird er zurück auf 0 gesetzt und beginnt von vorne
 +  else {
 +    programmode = 0;
 +  }
 +
 +
 +// Ausgabe an die serielle Schnittstelle
 +  if ((unsigned long)(currentMillis - previousMillisSerialPrint) >= intervalSerialPrint) {
 +
 +     //Ausgabe der berechneten Netzteillast an die sereille Schnittstelle
 +     Serial.print("Last (berechnet): "); Serial.print(load); Serial.println(" %");
 +     Serial.print("Cooling: "); Serial.println(cooling);
 +     Serial.print("Sparkling: "); Serial.println(sparkling);
 +     //Ausgabe der Werte von ResponsiveAnalogRead
 +     Serial.print("Last (geglaettet): "); Serial.println(rload.getValue());
 +  
 +     // if the repsonsive value has change, print out 'changed'
 +     if(rload.hasChanged()) {
 +     Serial.println("\tchanged");
 +     }
 +
 +     // Ausgabe Programmzähler
 +     Serial.print("Programm Nr.: "); Serial.println(programmode);
 +
 +   //Speichere die aktuelle Zeit in die zughörige Variable
 +   previousMillisSerialPrint = currentMillis;
 +   }
 +
 +}
 +</code>
 +Der Sketch verwendet 10.912 Bytes (33%) des Programmspeicherplatzes. Das Maximum sind 32.256 Bytes.
 +Globale Variablen verwenden 567 Bytes (27%) des dynamischen Speichers, 1.481 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
 +
 +Tags: #Arduino #NeoPixel
silentbase_neopixel/programmversion_0.9.1479674734.txt.gz · Zuletzt geändert: 18.05.2023 09:09 (Externe Bearbeitung)