Am Anfang war das Feuer

Hallo da draussen,

ich bin Autodidakt und kürzlich auf dieses Projekt gestossen:
Mortal Kombat Wall Light

Und hab gedacht, das baust du mal nach. Für einen Freud weil wir immer mal wieder Mortal Kombat spielen. Wobei wir beide eigentlich zu alt dafür sind.

Ich hab das ziemlich genau so gemacht wie da beschrieben und es sieht dem auch relativ ähnlich. Und es leuchtet auch...allerdings nur weiß.
Ich hab vor viele Jahren mal programmieren gelernt, aber das ist schon lange her. C++ damals noch.
Ich bilde mir ein, dass ich den Code halbwegs lesen kann. Aber es stellen sich Fragen.

#define PIN 6               // Which pin are those Neopixels hook up to?
#define NUMBER_OF_FLAMES 8  // depends on number of neopixel triplets. 5 for 16 NeoPixel ring. 4 for 12 NeoPixel ring
#define FLAME_WIDTH 1       // How wide are the flames (in LEDs)
#define FLICKER_CHANCE 5    // increase this to increase the chances an individual flame will flicker

PIN ist bei mir die 6 wie im Link,
Number of Flames...das ist die Anzahl der LEDs oder?
Flame Width ist mir ein Rätsel :wink:
Flicker Chance ist klar.

Jetzt die spannende, vielleicht dumme Frage:
Warum ist mein Feuer kein Feuer sondern es leuchtet nur weiß?

Wie gesagt ist es mein allererstes Projekt und mir fehlt sicher auch ne Menge Basiswissen.
Zum Beispiel wonach ich suchen muss?

Hat jemand von euch ne Idee oder einen Schubser in die richtige Richtung?

Grüße aus dem Bergischen.
Boris

NUMBER_OF_FLAMES scheint die ganze Zahl der Anzahl der LEDs geteilt durch 3 zu sein, laut dem Kommentar.
FLAME_WIDTH ist vermutlich dafür da, um die Ausbreitung einer Flamme auf die benachbarten Pixel zu steuern. Hier wäre das 1 benachbarter Pixel (vielleicht auf beiden Seiten?).

Zu Ihrer Frage: Welchen LED-Streifen verwenden Sie und wie wird er mit Strom versorgt?

Den WS8212b und so auch so wie da per MicroUSB

Dann poste mal den ganzen Code.

Irgendwo muss da der Befehl sein, die LED auf die passende Farbe zu stellen.

In deinen Link ist ein Foto mit Code daneben. Die unteren Zeilen mit den Color sind z.T. dafür zuständig.

Gruß

Pucki

mit den gegebenen Angaben und den Kommentaren ist das nicht eindeutig klärbar.
Auch wirds darauf ankommen wie die Pixel verlegt sind, Matte mit ZickZack, links-rechts, ring?!?

edit... gut, es ist als Ring ausgeführt...

da dann

NUMBER_OF_FLAMES * FLAME_WIDTH

für die Pixel Anzahl verwendet wird - sollte das für dich entsprechend verwendbar sein.

#include <Adafruit_NeoPixel.h>

/*
 5 "flames" of 3 pixels each.
 Each flame can have a brightness of 0 to 254 (play with this scale)
 Eventually, light up center pixel of three first then the sides. This version will just distribute amongst the 3 pixels.

*/

#define PIN 6              // Which pin are those Neopixels hook up to?
#define NUMBER_OF_FLAMES 3  // depends on number of neopixel triplets. 5 for 16 NeoPixel ring. 4 for 12 NeoPixel ring
#define FLAME_WIDTH 1       // How wide are the flames (in LEDs)
#define FLICKER_CHANCE 5    // increase this to increase the chances an individual flame will flicker


// Parameter 1 = number of pixels in strip
// Parameter 2 = 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)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMBER_OF_FLAMES * FLAME_WIDTH, PIN, NEO_GRB + NEO_KHZ800);

uint32_t rez_range = 256 * 3;
#define D_ false

// console buttons:
struct flame_element {
  int brightness;
  int step;
  int max_brightness;
  long rgb[3];
  byte state;
} flames[NUMBER_OF_FLAMES];

int new_brightness = 0;
unsigned long rgb[3];  //reusable temporary array
uint8_t scaleD_rgb[3];
byte acc;

#define SCALERVAL 256 * 3
const int flamecolors[22][3] = {
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  { SCALERVAL, 0, 0 },
  {
    SCALERVAL,
    SCALERVAL * .4,
  },
  { SCALERVAL, SCALERVAL * .4, 0 },
  { SCALERVAL, SCALERVAL * .4, 0 },
  { SCALERVAL, SCALERVAL * .4, 0 },
  { SCALERVAL, SCALERVAL * .3, 0 },
  { SCALERVAL, SCALERVAL * .3, 0 },
  { SCALERVAL, SCALERVAL * .3, 0 },
  { SCALERVAL, SCALERVAL * .3, 0 },
  { SCALERVAL, SCALERVAL * .3, 0 },
  { SCALERVAL, SCALERVAL * .3, 0 },
  {
    SCALERVAL,
    SCALERVAL * .3,
  },
  { SCALERVAL, SCALERVAL * .3, SCALERVAL },  // white
  { 0, SCALERVAL * .2, SCALERVAL },          // that one blue flame
  { SCALERVAL, SCALERVAL * .3, SCALERVAL * .5 }
};



void setup() {
  // if (D_){
  Serial.begin(9600);
  Serial.println("STARTUP");
  //  }
  strip.begin();
  strip.show();  // Initialize all pixels to 'off'
  randomSeed(analogRead(4));
  InitFlames();
}

void loop() {

  for (byte flame_count = 0; flame_count < NUMBER_OF_FLAMES; flame_count++) {
    switch (flames[flame_count].state) {
      case 0:  // reset
        CreateNewFlame(flame_count);
        break;

      case 1:  //increasing
        new_brightness = flames[flame_count].brightness + flames[flame_count].step;
        if (new_brightness > flames[flame_count].max_brightness) {
          UpdateFlameColor(flame_count, flames[flame_count].max_brightness);
          flames[flame_count].brightness = flames[flame_count].max_brightness;
          flames[flame_count].step = GetStepSize();  // pick a different speed for flame going out
          flames[flame_count].state = 2;
        } else {
          UpdateFlameColor(flame_count, new_brightness);
          flames[flame_count].brightness = new_brightness;
        }

        break;


      case 2:  //decreasing
        new_brightness = flames[flame_count].brightness - flames[flame_count].step;
        // chance to flicker/rekindle:
        if (random(new_brightness) < FLICKER_CHANCE) {
          // rekindle:
          flames[flame_count].state = 1;  //increase again
          flames[flame_count].brightness = max(GetMaxBrightness(), flames[flame_count].brightness);
          flames[flame_count].step = GetStepSize();

        } else {
          if (new_brightness < 1) {
            flames[flame_count].state = 0;  // bottomed out - reset to next flame
            flames[flame_count].brightness = 0;
            UpdateFlameColor(flame_count, 0);
          } else {
            UpdateFlameColor(flame_count, new_brightness);
            flames[flame_count].brightness = new_brightness;
          }
        }
        break;
    }
  }
  strip.show();
  delay(22);

}  //loop()


void InitFlames() {
  // Sets initial states in flames array
  for (byte i = 0; i < NUMBER_OF_FLAMES; i++) {
    flames[i].state = 0;
  }
}


void UpdateFlameColor(byte flame_num, int new_brightness) {
  //
  uint32_t c = 0;
  uint32_t color_channel_value;
  byte rgb_channel;

  new_brightness = min(new_brightness, flames[flame_num].max_brightness);


  for (byte rgb_channel = 0; rgb_channel < 3; rgb_channel++) {
    color_channel_value = flames[flame_num].rgb[rgb_channel];
    color_channel_value = color_channel_value * (uint32_t)new_brightness;  // keep it long
    color_channel_value = color_channel_value / (uint32_t)rez_range;
    rgb[rgb_channel] = max(0L, color_channel_value);
  }  // step through R G B



  // spread possible values of 0 -768 across 3 pixels
  for (byte sub_pixel = 0; sub_pixel < FLAME_WIDTH; sub_pixel++) {
    for (byte i = 0; i < 3; i++) {  // rgb
      acc = rgb[i] / 3;
      byte d = rgb[i] % 3;
      if (sub_pixel < d) {
        acc++;
      }
      scaleD_rgb[i] = acc;
    }
    c = strip.Color(scaleD_rgb[0], scaleD_rgb[1], scaleD_rgb[2]);
    strip.setPixelColor(flame_num * FLAME_WIDTH + sub_pixel, c);
  }
}


void CreateNewFlame(byte flame_num) {
  flames[flame_num].step = GetStepSize();
  flames[flame_num].max_brightness = GetMaxBrightness();

  flames[flame_num].brightness = 0;
  flames[flame_num].state = 1;
  byte color_index = random(22);
  for (byte i = 0; i < 3; i++) {
    flames[flame_num].rgb[i] = flamecolors[color_index][i];
  }
}

int GetStepSize() {
  return random(70) + 1;
}
int GetMaxBrightness() {
  int retVal;
  //  retVal = random(rez_range/4) +  random(rez_range/4) + random(rez_range/4) + rez_range/4 +1; // bell curve
  //  retVal = random(rez_range*3/4) +  rez_range/4; // flat distribution
  retVal = random(rez_range / 2) + rez_range / 2;  // brighter flat distribution
  return retVal;
}
  1. Die setzen keinen Streifen ein sondern ein Ring.
    Amazon.de : neopixel ring
  2. Number of Flames <- Gibt der Anzahl der LED's auf den den Ring an
  3. Flicker Chance = gibt die "Blinkrate" an.
  4. Flame Width = Interpretiere ich als die Anzahl der Pixel die flackern sollen.

Gruß

Pucki

ps.: Sorry zu langsam war

Ok, dann mal für blöde wie mich :wink:
Der hat doch in den Bildchen in der Anleitung einen Streifen verbastelt.

Oder wo hab ich das die Wissenslücke bzw. den Denkfehler.

Nachtrag:

Mach dich einfach mal über die Ansteuerung von Neopixeln schlau.

Du brauchst dazu i.d.R. 3 Leitungen. Plus - MINUS - DATA. Data ist die Leitung über die die einzelnen Pixel angesteuert werden. Im Treiber sagst du dann nur welcher Pixel und gibst den Farb-Code als RGB Wert mit.

Das ist eigentlich alles.

Das deiner nur weiß leuchtet lässt mich vermuten das du die Data-Leitung nicht richtig angeschlossen hast, und deinen MC das mitgeteilt hast wo die ist.

Edit: Der DATA-Pin ist in dein Code übrigens PIN 6.

Gruß

Pucki

Hat er. Nur im Code redet er von einen Ring. :wink:

Ich persönlich hab aber 0 Ahnung wo der Unterschied ist, außer das bei den Ring die LED's so schön aufgeklebt sind.

Gruß

Pucki

Ich hab drei Leitungen und wenn ich die so anschließe wie in den Bildern ist es doch PIN6 oder stehe ich da auf dem Schlauch? Auf meinem LED Streifen ist es in der Mitte, die anderen beiden sind 5V und GND.

RICHTIG.

Was für ein MC benutzt du eigentlich. Ein Atiny wie im Link oder was anders. Andern MC = vermutlich anderen Pin du benutzen musst.

Davon abgesehen ist dieser Typ von LED's zickig. Was bedeutet, kurze uns sehr saubere Verbindung der Datenleitung zum MC.

Gruß

Pucki

Alles genau so wie in dem Link. Hab ja viel zu wenig Peilung davon um das zu experimentieren. Wobei ich auch schon viel gelernt habe.
Einen Attiny85.

Ja es ist doch PIN6 auf den Attiny wenn ich es so mache wie in der Beschreibung. Oder sehe ich das falsch?

Ja, sollte.

ABER, ich vermute da was.

Hast du den nackten Chip oder ein Board von z.b. Digiparks ??
Wenn nackten Chip wie hast du den Programmiert.

Anfänger rate ich i.d.R. von einen Chip wie den Atiny ab, da der selten mit einen USB-Board ausgeliefert wird. Ich rate immer zu einen Nano/UNO oder einen ESP32 mit fertigen Board. Das macht sowas viel einfacher.

Der ATiny ist nur gut, wenn man absolut kein Platz hat, und wenn man mit einen Programmer umgehen kann.

Ist aber nur meine Meinung.

Gruß

Pucki

Ja, beim ATtiny85 ist Pin 6 nicht der Pin 6 den du im Sketch angeben solltest.
Den (elektrischen) 6 gibt es beim ATtiny85 nicht.
Schau dir dazu das Pinout an.

Vermutlich nicht so wie man sollte:)
So wie es da beschrieben steht mit so einem USB Stick auf den nackten Chip.
Ich hab auch Arduino Nanos hier rum liegen, das sind ja meine ersten Gehversuche bei dem Thema

Danke :bulb:

Dann solltest du besser mit dem starten. Der ATtiny85 ist schon mal etwas komplizierter, aber mit entsprechender Erfahrung auch lösbar.

:joy: Im Ring sind die LED im Kreis aufgeklebt, die "letzte" LED klebt somit vor der "ersten" LED. Alternativ kannst Du einen Streifen mit dem Ende an den Anfang kleben und hast einen Ring mit "Außen"- oder "Innen"-LED, je nachdem wie herum Du in drehst. Oder verdreht geklebt ein Möbiusband.

cu