Weihnachtliche Beleuchtung mit ATtiny85 und WS2811

Wenn man im Dezember zu Weihnachten durch die Straßen geht, sieht man an vielen Stellen Blitzenden und hektische Beleuchtung an Fenstern, Zäunen und Bäumen.
Weinachtleiche Beleuchtung ist schön. Nur könnte sie etwas ruhiger, aber trotzdem nicht langweilig sein. Sternen-funkeln wäre schön. Bunt wäre auch nicht schlecht. Eine Lichterkette, bei der die einzelnen Lichter zufällig anfangen in einer zufälligen Farbe ein und dann wieder auszublenden.
Und wie immer wenn es so etwas nicht gibt, muss man es halt selber bauen.

Testaufbau für Entwicklung

Komponenten

Für die Umsetzung findet verschiedene Angebote für Lichterketten mit WS281x und WS2801 Chip. Die beiden Chips unterschieden sich durch den Bus, über den sie angesteuert werden. WS2801 verwendet einen Zweidraht Bus. Eine Leitung für den Takt und eine andere für die Daten. Die WS281x Serie wird über einen Eindraht Bus. Der Takt ist fest mit 800 Kinoherz vorgegeben.
Ein Ring aus WS2812, wie im Video zu sehen, dient zum Testen.

Das kleinste was mir für die Steuerung eingefallen ist, war ein ATtiny85. Hier gibt es für die Arduino Umgebung eine fertige Bibliothek eine zur Ansteuerung der WS281x, die auch den ATtiny unterstützt. Man findet sich über die Suche unter „NeoPixel“.

Schaltung

Die Schaltung gestaltet sich als äußerst einfach, sowohl ATtiny85 als auch WS2812 werden an 5V Versorgungsspannung angeschlossen. Die Lichterkette soll später 0,3W pro Pixel haben. Bei 50 Pixel sind das 15 Wart, die das Netzteil liefern muss. Für den Testaufbau genügt der USB-Port. Ein 1000µF Kondensator soll spitzen vom Netzteil und Schwankungen durch Stromverbrauch der LED ausgleichen.
Der Daten-Pin der WS2812 wird an Arduino PIN 1 beziehungsweise Pin 6 des ATtiny85 Gehäuse angeschlossen. Die Pins werden nämlich unterschiedlich nummeriert.

Programmcode

Folgendes Programm steuert dann die Pixel.
TODO: Beschreibung des Programmcode 😉

// there is a 1 in IMPROBABILITY chance to activate a pixel
#define IMPROBABILITY   600

// there are COLORCOUNT colors to chose from
#define COLORCOUNT        8

const byte COLOURS[COLORCOUNT][3] = {
  {65,105,225},//royaleblue
  {255,140,0}, //darkorange
  {178,34,34}, //firebrick
  {99,235,50}, //yellowgreen
  {255,69,0},  //orange red
  {127,0,225}, //lila
  {255,203,5}, //green
  {255,10,10}  //red
};

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

// Pin connected to the NeoPixel Data pin
#define PIN            1

// How many NeoPixels are attached
#define NUMPIXELS      50

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  
  randomSeed(analogRead(0));
  pixels.begin();
}

void loop() {
  for(byte i=0;i<NUMPIXELS;i++){
    pixels.setPixelColor(i, fadein(i));
  }
  pixels.show();
  delay(50/NUMPIXELS);
}

uint32_t fadein(byte pixel) {
  static byte pcolor[NUMPIXELS] = { 0 };
  static byte pvalue[NUMPIXELS] = { 0 };

  if (pvalue[pixel] > 0) {
      pvalue[pixel]++;
  } else if (pvalue[pixel] == 0) {
    if (random(IMPROBABILITY) == 0) {
      pvalue[pixel] = 1;
      pcolor[pixel] = random(COLORCOUNT);
    }
  }
  
  float x = (float)(128-abs(pvalue[pixel]-128))/128;

  byte new_r = COLOURS[pcolor[pixel]][0] * x;
  byte new_g = COLOURS[pcolor[pixel]][1] * x;
  byte new_b = COLOURS[pcolor[pixel]][2] * x;

  return pixels.Color(new_r, new_g, new_b);
}

Schreibe einen Kommentar