WS2812B leuchte LED-Pixelanzahl begrenzen, 'Ich habe Feuer gemacht', abgekupfert

Hi

Hatte mich Heute (ok, Gestern) an dem Sketch ‘Ich habe Feuer gemacht…’ probiert - nutze aber WS2812B-Stripes.
Lange Rede, kaum ein Sinn: Bekam den Sketch mit meinen WS2812B nicht ans Laufen.
In der FastLED-Lib gibt’s ein Beispiel Fire2012, Welches ich, der Name klang ‘artverwandt’, etwas angepasst habe.
In meinem Fall soll die Flamme eine Kerze darstellen - die Sankt-Martins-Umzüge stehen vor der Tür und im Moment ermittle ich die Laufzeit der ganzen Mimik bei Versorgung mittels PowerBank.
Mein Aufbau umfasst 31 LED-Pixel auf einem Stripe mit 30 LED/Meter (also die billigsten Streifen), Welcher Sich 7x um eine KloPapierRolle wickeln lässt.
Damit der Arduino, Welcher den Stripe am 5V-Pin versorgen soll (und selbst via USB versorgt wird) nicht dahin schmilzt, sorge ich dafür, daß maximal ‘x’ LED gleichzeitig leuchten.
Das aber in schneller Abfolge, bei jedem loop()-Durchlauf werden die nächsten ‘x’ LEDs angezeigt.
Trotzdem wird nur alle zig Millisekunden der Effekt weiter geschaltet.
Ab einer Anzeige von 5 LEDs zur gleichen Zeit zeigt die KloRollenKerze kaum noch Flackern - mit einem Drucker-Papier als Diffusor schaut’s schon ganz nett aus - in der Fledermaus-Laterne der Nichte sollte das Teil eine recht gute Figur machen :slight_smile:

Ok, in dem Beispiel-Sketch ‘Fire2012’ wird in der Funktion Fire2012() das Array leds[ x ] mit den Farbwerten gefüllt.
Diese Zuweisung lasse ich auf ein separates Array set_led[ x ] erfolgen, um dann in der loop() in jedem Durchlauf ‘die nächsten x Pixel’ in das Array leds zu kopieren, was eine separate Funktion übernimmt.
Statt dem Delay, um auf die ‘Frames_per_second’ zu kommen, nutze ich INTERVAL (ebenfalls hier aus dem Forum)
Der Farbwert für WEISS wird wohl als 0xFF000000 (RGBW) oder 0x00FFFFFF (RGB) reichen, schicke in diesem Code aber der Zeit 0xFFFFFFFF (alle Bits gesetzt - ergibt weiß) - möge man, dem Strom Sparen Willen, anpassen.

#include <INTERVAL.h>
//Ein WS2812B-LED-Streifen mit 30 LED/Meter wird um eine Klopapier-Rolle
//drum herum geklebt. Bei meinem Streifen komme ich auf 'knapp über 4 LED
//pro 'Runde' - die 5.te LED sitzt leicht hinter der Ersten.
//Insgesamt bekomme ich 31 LED auf die Rolle.
//Zusätzlich zu 'Fire2012' wurde eine Begrenzung der gleichzeitig
//leuchtenden LED einprogrammiert - ab 5 lässt das Flackern nach -> 300mA max
// ... soll die 5V-Leiterbahnen des verwendeten Arduino schonen, versorgt
//wird Er per PowerBank und USB-Kabel.

//Alle x Frames (im Sketch einstellbar) blitzen (10ms zu 40ms) die LED weiß auf

//Als Diffusor ist ein Blatt Drucker-Papier angedacht

//Leuchtdauertest steht noch aus

#include <FastLED.h>

const uint8_t maxpunkte = 5;    //maximal x gleichzeitig leuchtende LED-Pixel
uint8_t lastpixel = 0;          //der zuletzt eingeschaltete Pixel

const uint8_t LED_PIN = 10;
#define  COLOR_ORDER   GRB
#define CHIPSET    WS2811
const uint8_t NUM_LEDS  =  31;
const uint16_t leuchtcount_normal=600;    //Wert : Frames_per_second = Sekunden Laufzeit
const uint16_t leuchtcount_blitz=30;


const uint8_t BRIGHTNESS = 255;
const uint8_t FRAMES_PER_SECOND = 60;

bool gReverseDirection = false;

CRGB leds[NUM_LEDS];
CRGB set_leds[NUM_LEDS]; //hier werden die Farbei eingetragen, um von
//der Begrenzungsfunktion (maximal gleichzeitig
//leuchtender LED) in leds[] kopiert zu werden

void setup() {
  delay(3000); // sanity delay
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( BRIGHTNESS );
}

void loop()
{
  static uint16_t framecounter = 0;
  // Add entropy to random number generator; we use a lot of it.
  // random16_add_entropy( random());
  INTERVAL(1000UL / FRAMES_PER_SECOND) {
    Fire2012(); // run simulation frame
    framecounter++;
  }
  if (framecounter > leuchtcount_normal) {
    CRGB wert = 0;
    if (millis() % 50 > 40) {   //10ms Blitz
      wert = 0xFFFFFFFF;
    }
    for (byte u = 0; u < NUM_LEDS; u++) {
      set_leds[u] = wert;
    }
    if (framecounter >= leuchtcount_normal+leuchtcount_blitz) {
      framecounter = 0;
    }
  }
  //Begrenzen der gleichzeitig leuchtenden Pixel
  kopiere_leds();

  FastLED.show(); // display this frame
}


void kopiere_leds(void) {
  for (byte u = 0; u < NUM_LEDS; u++) { //Pixel löschen
    leds[u] = 0;
  }

  byte pixelanzahl = 0;
  for (byte u = NUM_LEDS; u > 0; u--) { //maximal 'maxpunkte' Pixel anschalten
    lastpixel++;
    if (lastpixel >= NUM_LEDS) {
      lastpixel = 0;
    }
    if (isPixelOn(lastpixel)) {
      //      debugPrint("Setze Pixel ");
      //      debugPrintln(lastpixel);
      leds[lastpixel] = set_leds[lastpixel];
      pixelanzahl++;
      if (pixelanzahl >= maxpunkte) { //wenn bereits die maximale Anzahl an Pixel leuchten, FOR abbrechen
        break;
      }
    }
  }
}

boolean isPixelOn(uint8_t pixelnr) {
  return set_leds[pixelnr];
}

// Fire2012 by Mark Kriegsman, July 2012
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
////
// This basic one-dimensional 'fire' simulation works roughly as follows:
// There's a underlying array of 'heat' cells, that model the temperature
// at each point along the line.  Every cycle through the simulation,
// four steps are performed:
//  1) All cells cool down a little bit, losing heat to the air
//  2) The heat from each cell drifts 'up' and diffuses a little
//  3) Sometimes randomly new 'sparks' of heat are added at the bottom
//  4) The heat from each cell is rendered as a color into the leds array
//     The heat-to-color mapping uses a black-body radiation approximation.
//
// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
//
// This simulation scales it self a bit depending on NUM_LEDS; it should look
// "OK" on anywhere from 20 to 100 LEDs without too much tweaking.
//
// I recommend running this simulation at anywhere from 30-100 frames per second,
// meaning an interframe delay of about 10-35 milliseconds.
//
// Looks best on a high-density LED setup (60+ pixels/meter).
//
//
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames.  More cooling = shorter flames.
// Default 50, suggested range 20-100
#define COOLING  35

// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire.  Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 120


void Fire2012()
{
  // Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];

  // Step 1.  Cool down every cell a little
  for ( int i = 0; i < NUM_LEDS; i++) {
    heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
  }

  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for ( int k = NUM_LEDS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
  }

  // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
  if ( random8() < SPARKING ) {
    int y = random8(7);
    heat[y] = qadd8( heat[y], random8(160, 255) );
  }

  // Step 4.  Map from heat cells to LED colors
  for ( int j = 0; j < NUM_LEDS; j++) {
    CRGB color = HeatColor( heat[j]);
    int pixelnumber;
    if ( gReverseDirection ) {
      pixelnumber = (NUM_LEDS - 1) - j;
    } else {
      pixelnumber = j;
    }
    set_leds[pixelnumber] = color;
  }
}

Vll. kann ja Wer was mit meinem Versuch anfangen :slight_smile:

MfG

Hallo,

postmaster-ino:
Hatte mich Heute (ok, Gestern) an dem Sketch ‘Ich habe Feuer gemacht…’ probiert - nutze aber WS2812B-Stripes.
Lange Rede, kaum ein Sinn: Bekam den Sketch mit meinen WS2812B nicht ans Laufen.

Was hattest Du für Probleme mit den WS2812B und auf welchem “Arduino”? Mit

#define LED_PIN 3
...
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);

lief es hier dann problemlos. LED_PIN habe ich nur oben definiert weil ich nicht gern Pin-Nummern irgendwo im Code suchen gehe.

Wenn mehr WS2812B-LEDs im Spiel sind wird bei mir immer extern versorgt, die LEDs an ein Netzteil, bei den 31 eben an einen 2A USB-Ladeadapter, Stripe vorerst nur GND und DIN (über 390 Ohm Schutzwiderstand) verbunden. Wenn alles dann geht kommt der Arduino mit an die 5V der LEDs, diese Verbindung dann meist steckbar, so daß ich bei Anschluß an den PC den Arduino nur vom USB und die LEDs weiter von ihrem Netzteil versorge.
Ist hier im Moment auch noch so mit der 16x16 Matrix.

Gruß aus Berlin
Michael

Gruß aus Berlin
Michael

Hi

Zum Probieren ist's ein Uno, in die Laterne kommt ein Nano.

Kaum macht man's richtig, zeigt sich Funktion. Hatte mich auch in den Tiefen der Library umgesehen, fand aber weder 'WS2812B', noch wie der Aufruf 'alternativ' erfolgen kann - dafür ist die FastLED-Library wohl etwas groß und mir zu unübersichtlich. Leider bekomme ich meine LED-Begrenzung nicht in den 2018er Sketch implementiert, ohne, daß Das ein Dauer-Blitzlich wird. Die Berechnungen selber, Die den Feuer-Effekt ausmachen, sind in dem 2018-er Sketch wohl wesentlich umfangreicher, als im 2012er (das Beispiel der FastLED-Library) - zumindest muß ich mindestens die Hälfte der LEDs anzeigen, um eine halbwegs flackerfreie blitzfreie Kerze darzustellen.

Klar sollte der Stripe eine eigenständige Versorgung bekommen, in diesem Fall ist's aber eh so, daß der ganze Aufbau in der Laterne versenkt wird. Einzig während der Bootloader-Zeit können mehr Pixel als 'erlaubt' leuchten (weshalb auch das delay(3000); im Fire2012-Code in setup() schnell verschwunden ist). 'Können' - solange der Arduino mir nicht abstürzt.

Als Widerstand nutze ich derzeit 390Ω - nachdem mir auf einem 90°-15 LED-Segment (eBay, 4 Stück ergeben eine Uhr) die erste LED verstorben ist und meine SMD-Löt-'Skills' gefordert wurden, ist dieser Widerstand hoch im Kurs ;).

MfG

Hallo, ich weiß, das ich mich jetzt, teilweise für mich auch verständlich, etwas unbeliebt mache: ich nehme für Sachen, die etwas mehr Rechenleistung, Ram oder Flash erfordern, nur noch Wemos D1 ESP8266, selbst dann, wenn ich den in der endgültigen Nutzung mit komplett abgeschaltetem WLAN betreibe. Das geht per Software mit einem Trick, dann verbraucht der ESP noch ca. 15mA.

Ohne die ArduinoIDE und das Umfeld "Arduino" mit diveren Modulboards usw. hätte ich mich vermutlich nie so tief in die ESPs vergraben. Nano, Mini und Micro geistern hier für Sachen rum, wo Rechenleistung, Speicherbedarf usw. gut ausreichen. LoRa-Modul + GPS an einem Micro, meine PanaPlex-Uhr hat einen Pro Mini als Beipiele.

Will damit sagen: seit Arduino bin ich bequemer geworden als früher, aber inzwischen als Rentner darf ich das schon.

Ja, der Reihenwiderstand ist spätestens dann lebensrettend für die erste LED wenn die Versorgung des Stripes aus ist und Daten anliegen...

Gruß aus Berlin Michael

Hi

Keine Angst - bei mir ist Deine Beliebtheit nicht gesunken :slight_smile:
Mein ‘Tick’ ist eher in die Richtung, daß ich gerne ‘Alles, was der Chip bietet, benutze’ - seit Arduino ist Das ebenfalls nicht mehr so ausgeprägt, vorher waren zig unbenutzte Pins ein ‘no-go’, da ich dann ja auch mit einem kleineren Chip zurecht kommen sollte.
Das Konzept Arduino macht Einem das Kontroller Verbauen aber recht einfach und für den aufgerufenen Preis (besonders bei den Klonen) sind nackte µC nebst Außenbeschaltung teurer und/oder weit außerhalb des Arduino-Zeit-Rahmen.

Hier erfassen einige Nano Temperaturen und spucken Diese alle 10 Sekunden in einen CAN-Bus - Das sollte auch mit einem ATtiny möglich sein - aber eben nicht in der kurzen Entwicklungs Zeit.

MfG