blinkender Weihnachtsstern mit ATtiny85 und Neopixeln

So, hier kommt eine kleine Weihnachtsbastelei, ideal auch zum in
Kleinserie bauen und zum Verschenken :slight_smile:
Ich habe alles nochmal in ein ZIP Archiv gepackt. Code, Gerberdaten, die
Fotos, falls hier was soweit verkleinert wird, das die Anmerkungen zur
Best√ľckung in den Bildern nicht mehr lesbar sind usw.
Die Schaltung ist an sich kein Hexenwerk, die Herausforderung bestand
eher darin, das Ganze auf die geometrische Form einer Schneeflocke zu
stopfen :smiley:
Kern des Ganzen sind ein ATiny85, denn ein ATmega wäre hier etwas
oversized, auch platzmäßig. Dazu 18 Stck. Neopixel WS2812. Ausgelöst
wird das Ganze optional duch ein kleines PIR Bewegungsmeldermodul vom
Typ AM312. Versorgt wird das Ganze aus einem kleinen LiPo Akku. Wenn man
noch einen Wechselakku von einem Smartphone rumfliegen hat, ist der
perfekt. Komplettiert wird das dann durch einen LiPo-Lade IC TP4056, wie
man ihn von den kleinen, briefmarkengroßen Ladeplatinchen her kennt und
einem MT3608 StepUp IC, das die 3-4V vom LiPo wieder auf 5V f√ľr den ¬ĶC
und die WS2812 bringt.
Der Code ist im wesentlichen die Demo der Adafruit Neopixel-Lib.
Wer will, kann sich da noch austoben.
Eigener Code ist hier ausdr√ľcklich erw√ľnscht. Ich habe die Helligkeit
mit 50 ziemlich reduziert, um zum einen die Batterie und zum anderen das
StepUp IC zu schonen. trotzdem sind die Pixel immer noch beeindruckend
hell.
Am besten, man beschr√§nkt sich zun√§chst auf die Best√ľckung der
Schaltungsteile Laderegler und StepUp. Sollte man da Best√ľckungsfehler
machen und die Spannung läuft höher, als die geforderten 5V, an können
sich anderenfalls die WS2812, der ¬ĶC und auch der MT3608 in Schrott
verwandeln!
Ich fange zunächst mit dem MT3608, dem TP4056, der 2-Farb LED und der
USB.Ladebuchse an, mit best√ľcken. Danach folgen die Widerst√§nde und
Kondendatoren, wie auf dem nächten Bild zusehen ist.
Danach folgt der 22¬Ķ KerKo auf der R√ľckseite der Platine.
Jetzt ist es an der Zeit, f√ľr einen ersten Test, nachdem man noch einmal
gr√ľndlich alles auf L√∂tbr√ľcken und korrekte Best√ľckung kontrolliert hat.
Zunächst einmal schließt man das USB Kabel an die Ladebuchse und
kontrolliert ohne angeschlossenen Akku. Die gr√ľne LED sollte leuchten,
eventuell glimmt die Rote leicht mit. Jetzt schließt man den Akku an,
jetzt sollte die LED auf rot - Laden umschlagen. Noch ein Wort zu den
beiden Archiven Star_V2 und Star_V3 mit den Gerber Daten f√ľr die
Leiterplattenfertigung. Bei V2 ist die LED auf der selben Seite, wie der
Hauptteil der Elektronik. Da ich dort aber den Akku mit doppelseitigem
Klebeband fixiert habe, verdeckt dieser die Ladezustands-LED. Darum habe
ich V3 erstellt und die LED auf die andere Boardseite, zu den Neopixeln
gepiegelt.
Die 10 oder 22¬ĶH Induktivit√§t sollte mindestens 2A S√§ttigungsstrom
haben, da die Spitzenströme aus dem Akku ja noch höher sind, als was auf
5V Seite flie√üt. W√ľrde man die Neopixel ungedrosselt volle Pulle, alle
weiß leuchten lassen, dann sind das 18 x 3 x 0,02A = 1,08 Ampere! um die
Best√ľckungsseite sch√∂n flach zu halten, damit dort der Akku noch
huckepack drauf kann, habe ich mich f√ľr die 4 mm flache 10¬Ķ Ferrocore
HPI0530‚Äď100 entschieden.
Nun testet man mit angeschlossenem Akku und auf position des Enschalters
aufgel√∂teter Drahtbr√ľcke, die korrekte Funktion des StepUp Wandlers.
Dazu kann man einfach auf 2 Pads f√ľr einen Puffer-KerKo der WS2812
gehen. Genug Pads sind ja davon da. Hier sollten ca. 5,1V messbar sein.
Wenn das passt, dann trennt man den Akku und best√ľckt den Rest der
Bauelemente.
Den 6 pol. Pfostenstecker zum Programmieren des ¬ĶC habe ich aus
√§sthischen Gr√ľnden nicht best√ľckt. Ein Nadeladapter langt zum
Programmieren völlig. Man steckt in in die Durchkontaktierungen und
dr√ľckt seitlich gegen den Stecker, so das er verkantet und so sicher
kontakt gibt. Mit der anderen Hand bedient man die Maus und startet das
Flashen.
Bei mir hat sich die Kombination aus USBasp (Chinaclone) und eXtreme
Burner AVR bewährt. Zuerst setzt man die Fuses. Lower C1, Upper D4,
danach √ľbertr√§gt man die HEX Datei. Den Jumper gleich neben der USB
Buchse, zur Drosselung des Programmiertempos sollte man setzen, sonst
wird der ¬ĶC vor dem Setzen der Fuses nicht erkannt, da er ab Werk einen
langsameren Systemtakt hat.
Danach entfernt man die Br√ľcken f√ľr den Schalter und den PIR und
best√ľckt beides auf Seiten der LEDs. Beim PIR habe ich die
Steckkontaktleiste ausgel√∂tet und ihn direkt im 90¬į Winkel auf die
Lötpads gelötet. Dazu muß die Seite mit dem kleinen schwarzen Dreibeiner
Richtung Ladebuchse zeigen. Nun verkabelt man den Akku und wäscht die
Platine ausgiebig in einem Bad aus Isopropanol, um die Flussmittelreste
der Optik wegen, zu entfernen. Nun klebt man den Akku auf, läd ihn
nochmal und fertig ist der Weihnachtsstern :thumbup:
Das ganze Projekt stelle ich unter Open Source und Open Hardware, auch
noch auf anderen Plattformen. Falls Bedarf an unbest√ľckten Leiterplatten
oder Kits aus Leiterplatte und Bauelementen als Bausatz besteht, dann
tut das kund, dann kann ich ggf. immer noch was einstellen.

Star_all_Docs.zip (894 KB)

Irgendwie gängelt mich die Upload-Funktion :fearful:
Durch den Code war alles zu lang, die Bilder hat er mir auch eingek√ľrzt‚Ķ So what, es ist alles im ZIP Archiv, auch wenn es so direkt √ľbersichtlicher und bequemer w√§re‚Ķ

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 4
int PirPin = 3;
int PirStatus;


// 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(18, 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() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  // End of trinket special code


  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  pinMode(PirPin, INPUT);
}

void loop() {

  strip.setBrightness(50);

  // Some example procedures showing how to display to the pixels:

  PirStatus = digitalRead(PirPin);
  if (PirStatus == LOW) {
    strip.show();
  }
  else {

    colorWipe(strip.Color(255, 0, 0), 50); // Red
    colorWipe(strip.Color(0, 255, 0), 50); // Green
    colorWipe(strip.Color(0, 0, 255), 50); // Blue
    //colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
    // Send a theater pixel chase in...
    theaterChase(strip.Color(127, 127, 127), 50); // White
    theaterChase(strip.Color(127, 0, 0), 50); // Red
    theaterChase(strip.Color(0, 0, 127), 50); // Blue

    rainbow(20);
    rainbowCycle(20);
    theaterChaseRainbow(50);
  }
} // das muss zusaetzlich!

// 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);
  }
}

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);
}
// } Das muß weg!