Autarkes Neopixel Modul

Hallo zusammen,

ich zerbreche mir schon seit einer weil den Kopf, wie ich ein Neopixelmodul integriere und gleichzeitig auch einen IR Empfänger an der AiO betreiben kann.
Ohne die Möglichkeit des noch kommenden BT Moduls zu nehmen.

Heute kam ich drauf.

Der Neopixel könnte doch einen eigenen Kontroller bekommen und seinen Input von einem Microphon nehmen.

Hier hab ich nach sehr kurzem googeln ein Beispiel gefunden. Sehr klein und auf das nötigste. reduziert, das mag ich!

Ich bin noch nicht so weit das um zu setzen.
Aber ich wollte unbedingt @Jens2305 seine
Glow in the Dark box in Transparent drucken und von innen mit einer Tongesteuerten Partybeleuchtung versehen.

Jetzt wollte ich auch mal in die Runde fragen ob ihr das Prinzip schon mal umgesetzt habt und ob ihr eure Erfahrungen oder Meinung dazu teilen wollt.

1 Like

Gute Idee, ich schau mir das einmal an. Ich denke das hätte einige Vorteile :thinking:

Ich habe noch etwas recherchiert und ein paar möglichst kleine Komponenten heraus gesucht:

AZDelivery 3 x Digispark Rev.3 Kickstarter mit ATTiny85 und USB kompatibel mit Arduino inklusive E-Book!: Amazon.de: Gewerbe, Industrie & Wissenschaft

Mikrofon Sensor Audiosensor Geräuschsensor Max4466 für Arduino Raspberry Pi: Amazon.de: Gewerbe, Industrie & Wissenschaft

AZDelivery 5V RGB LED Ring WS2812B 12-Bit 37mm kompatibel mit Arduino inklusive E-Book!: Amazon.de: Gewerbe, Industrie & Wissenschaft

Und noch ein Projektbeispiel für den ATTiny:

Code | Trinket Sound-Reactive LED Color Organ | Adafruit Learning System

Ich habe vor das ganz wie eine Art Münze auf zu bauen.
Also einen runden, gedruckten Träger für alle Komponenten. Der Kontroller und das Micro sollten so klein sein, das sie in die Mitte des Neopixelrings passen.
Das wäre dann auch gut nach zu rüsten und eventuell auch separat vom Arduino zu betreiben.

Kennt jemand eine gute Libary für NeoPixel Animationen?
Habe auf Anhibe diese gefunden:

Ich dachte nur an Pulsierende oder Blinkende Bilder mit Farbwechsel.

Ich weiß noch nicht wie viel Varianz ich auf den kleinen ATTiny bekomme.

Ich hab das vor einiger Zeit mal gebaut.
Sogar 2 Mal.
EInmal Micro gesteuert und sonst verschiedene Animationen umschaltbar per Knopfdruck.
Basierend natürlich auf einem Nano
Muss mal ein Bild suchen…

Gefunden.
Ansicht von hinten. Das lilane ist das Micro.
Taster für statische Animationen kam später


Hier in Action

Und ja, das ist natürlich der Ikea Übertopf, der hier als Basis des Konstrukts dient :wink:

Also kein klassicher runder NeoPixel Ring sondern mit WS2812B LEDs umgesetzt.
Das Prinzip ist ja dasselbe.

Bei der anderen Version, ist noch ein Display mit drin, das die aktuelle Animation anzeigt.

4 Like

Sehr schön.
Hast du auch einen Code dazu den du vlt. Teilen kannst?

Das selbe Micro hab ich auch bestellt.
Problem könnte der ATTiny und sein Speicher werden.

Ich suchs später raus und lads bei Github hoch.

Ist halt eher auf ein oder zwei Längsstreifen optimiert.
Die Idee bei mir war ein LED VU Meter.
Video kann ich leider nicht hochladen.

2 Like

Ein Ring ist auch nur ein gebogener Streifen :sweat_smile:

Die Beleuchtung soll in ein transparentes Gehäuse. Man soll ein pulsieren im Takt sehen das die Farbe ändert.

Alle Teile sind gekommen, mal sehen ob ich es heute nich schaffe das zusammen zu löten, sind ja nur ein paar Kabel.

Hatte aber mit einem kleineren Kontroller gerrechnet, naja.

3 Like

Ein erster Test ist ganz vielversprechend.
Nicht Perfekt, das zappelt mir zu sehr und die Farben sind noch zu statisch.

Aber meine Idee scheint für mich auf zu gehen

2 Like

Ich hab einen bessern Code gefunden, der mir sehr gut gefällt.
Mehr Farben, bessere übergänge, schönere Animation.
Der Attiny lässt leider nicht all zu viel zu.

https://learn.sparkfun.com/tutorials/interactive-led-music-visualizer/all

Hier unter dem Punkt: „Simple Visualizer Program“ ist ein Testcode. Dieser passt fast genau auf den tiny.
Ein paar Anpassungen müssen aber vorgenommen werden. Der komplette Code dort enthält auch weiter Animationen und Farbsets. Eventuell lassen sich dies im Testcode Ersatzweise einfügen. Hier der Code mit meinen Anpassungen:

//language:c
//Program by Michael Bartlett
//https://learn.sparkfun.com/tutorials/interactive-led-music-visualizer/all
//Libraries
#include <Adafruit_NeoPixel.h>  //Library to simplify interacting with the LED strand
#ifdef __AVR__
#include <avr/power.h>   //Includes the library for power reduction registers if your chip supports them. 
#endif                   //More info: http://www.nongnu.org/avr-libc/user-manual/group__avr__power.htlm

//Constants (change these as necessary)
#define LED_PIN   0  //Pin for the pixel strand. Does not have to be analog.
#define LED_TOTAL 12  //Change this to the number of LEDs in your strand.
#define LED_HALF  LED_TOTAL/2
#define AUDIO_PIN A1  //Pin for the envelope of the sound detector
//#define KNOB_PIN  A1  //Pin for the trimpot 10K
#define INTERNAL2V56_NO_CAP (6)

//////////<Globals>
//  These values either need to be remembered from the last pass of loop() or 
//  need to be accessed by several functions in one pass, so they need to be global.

Adafruit_NeoPixel strand = Adafruit_NeoPixel(LED_TOTAL, LED_PIN, NEO_GRB + NEO_KHZ800);  //LED strand objetc

uint16_t gradient = 0; //Used to iterate and loop through each color palette gradually

uint8_t volume = 0;    //Holds the volume level read from the sound detector.
uint8_t last = 0;      //Holds the value of volume from the previous loop() pass.

float maxVol = 15;     //Holds the largest volume recorded thus far to proportionally adjust the visual's responsiveness.
float knob = 1023.0;   //Holds the percentage of how twisted the trimpot is. Used for adjusting the max brightness.
float avgVol = 0;      //Holds the "average" volume-level to proportionally adjust the visual experience.
float avgBump = 0;     //Holds the "average" volume-change to trigger a "bump."

bool bump = false;     //Used to pass if there was a "bump" in volume

//////////</Globals>


//////////<Standard Functions>

void setup() {    //Like it's named, this gets ran before any other function.

  //Serial.begin(9600); //Sets data rate for serial data transmission.

  strand.begin(); //Initialize the LED strand object.
  strand.show();  //Show a blank strand, just to get the LED's ready for use.  
}


void loop() {  //This is where the magic happens. This loop produces each frame of the visual.


  analogReference( INTERNAL2V56_NO_CAP );
  volume = analogRead(AUDIO_PIN);       //Record the volume level from the sound detector
  //knob = 0.8; //Record how far the trimpot is twisted
  avgVol = (avgVol + volume) / 2.0;     //Take our "average" of volumes.

  //Sets a threshold for volume.
  //  In practice I've found noise can get up to 15, so if it's lower, the visual thinks it's silent.
  //  Also if the volume is less than average volume / 2 (essentially an average with 0), it's considered silent.
  if (volume < avgVol / 2.0 || volume < 15) volume = 0;

  //If the current volume is larger than the loudest value recorded, overwrite
  if (volume > maxVol) maxVol = volume;

  //This is where "gradient" is reset to prevent overflow.
  if (gradient > 1529) {

    gradient %= 1530;

    //Everytime a palette gets completed is a good time to readjust "maxVol," just in case
    //  the song gets quieter; we also don't want to lose brightness intensity permanently 
    //  because of one stray loud sound.
    maxVol = (maxVol + volume) / 2.0;
  }

  //If there is a decent change in volume since the last pass, average it into "avgBump"
  if (volume - last > avgVol - last && avgVol - last > 0) avgBump = (avgBump + (volume - last)) / 2.0;

  //if there is a notable change in volume, trigger a "bump"
  bump = (volume - last) > avgBump;

  Pulse();   //Calls the visual to be displayed with the globals as they are.

  gradient++;    //Increments gradient

  last = volume; //Records current volume for next pass

  delay(50);   //Paces visuals so they aren't too fast to be enjoyable
}

//////////</Standard Functions>

//////////<Helper Functions>


//PULSE
//Pulse from center of the strand
void Pulse() {

  fade(0.75);   //Listed below, this function simply dims the colors a little bit each pass of loop()

  //Advances the gradient to the next noticeable color if there is a "bump"
  if (bump) gradient += 64;

  //If it's silent, we want the fade effect to take over, hence this if-statement
  if (volume > 0) {
    uint32_t col = Rainbow(gradient); //Our retrieved 32-bit color

    //These variables determine where to start and end the pulse since it starts from the middle of the strand.
    //  The quantities are stored in variables so they only have to be computed once.
    int start = LED_HALF - (LED_HALF * (volume / maxVol));
    int finish = LED_HALF + (LED_HALF * (volume / maxVol)) + strand.numPixels() % 2;
    //Listed above, LED_HALF is simply half the number of LEDs on your strand. ↑ this part adjusts for an odd quantity.

    for (int i = start; i < finish; i++) {

      //"damp" creates the fade effect of being dimmer the farther the pixel is from the center of the strand.
      //  It returns a value between 0 and 1 that peaks at 1 at the center of the strand and 0 at the ends.
      float damp = float(
                     ((finish - start) / 2.0) -
                     abs((i - start) - ((finish - start) / 2.0))
                   )
                   / float((finish - start) / 2.0);

      //Sets the each pixel on the strand to the appropriate color and intensity
      //  strand.Color() takes 3 values between 0 & 255, and returns a 32-bit integer.
      //  Notice "knob" affecting the brightness, as in the rest of the visuals.
      //  Also notice split() being used to get the red, green, and blue values.
      strand.setPixelColor(i, strand.Color(
                             split(col, 0) * pow(damp, 2.0) * knob,
                             split(col, 1) * pow(damp, 2.0) * knob,
                             split(col, 2) * pow(damp, 2.0) * knob
                           ));
    }
    //Sets the max brightness of all LEDs. If it's loud, it's brighter.
    //  "knob" was not used here because it occasionally caused minor errors in color display.
    strand.setBrightness(255.0 * pow(volume / maxVol, 2));
  }

  //This command actually shows the lights. If you make a new visualization, don't forget this!
  strand.show();
}



//Fades lights by multiplying them by a value between 0 and 1 each pass of loop().
void fade(float damper) {

  //"damper" must be between 0 and 1, or else you'll end up brightening the lights or doing nothing.
  if (damper >= 1) damper = 0.99;

  for (int i = 0; i < strand.numPixels(); i++) {

    //Retrieve the color at the current position.
    uint32_t col = (strand.getPixelColor(i)) ? strand.getPixelColor(i) : strand.Color(0, 0, 0);

    //If it's black, you can't fade that any further.
    if (col == 0) continue;

    float colors[3]; //Array of the three RGB values

    //Multiply each value by "damper"
    for (int j = 0; j < 3; j++) colors[j] = split(col, j) * damper;

    //Set the dampened colors back to their spot.
    strand.setPixelColor(i, strand.Color(colors[0] , colors[1], colors[2]));
  }
}


uint8_t split(uint32_t color, uint8_t i ) {

  //0 = Red, 1 = Green, 2 = Blue

  if (i == 0) return color >> 16;
  if (i == 1) return color >> 8;
  if (i == 2) return color >> 0;
  return -1;
}


//This function simply take a value and returns a gradient color
//  in the form of an unsigned 32-bit integer

//The gradient returns a different, changing color for each multiple of 255
//  This is because the max value of any of the 3 LEDs is 255, so it's
//  an intuitive cutoff for the next color to start appearing.
//  Gradients should also loop back to their starting color so there's no jumps in color.

uint32_t Rainbow(unsigned int i) {
  if (i > 1529) return Rainbow(i % 1530);
  if (i > 1274) return strand.Color(255, 0, 255 - (i % 255));   //violet -> red
  if (i > 1019) return strand.Color((i % 255), 0, 255);         //blue -> violet
  if (i > 764) return strand.Color(0, 255 - (i % 255), 255);    //aqua -> blue
  if (i > 509) return strand.Color(0, 255, (i % 255));          //green -> aqua
  if (i > 255) return strand.Color(255 - (i % 255), 255, 0);    //yellow -> green
  return strand.Color(255, i, 0);                               //red -> yellow
}

//////////</Helper Functions>

Ich habe auch eine erste Aufnahme für alle Komponenten „konstruiert“. Mal sehen ob das klappt

2 Like

Na also. Das ging aber schnell jetzt.
Bin auf das Endergebnis gespannt

Hier steckt ja keine Arbeit von mir drin.
Das ist ja alles zusammenkopiert und hier und da etwas angepasst.

Das Verkabeln hat 10min gedauert.
Das schwierige war den richtigen sketch zu finden.

Die Komponenten harmonieren sehr gut.
Der Tiny schafft die Aufgabe, ist aber auf Abschlag im Speicher.
Ich hätte nur gleich das oben verlinkte Micro kaufen sollen das kann 5 V Versorgung ab. Das was ich bestellt habe sollte mit 3.3V versorgt werden (mach ich jetzt natürlich nicht :upside_down_face:).

Jetzt fehlt nur noch die Halterung und ein Schalter/Taster um das Ding Ein/Aus zu schalten.

Das ist auf jeden Fall eine gute Möglichkeit etwas Licht und Frabe in eine TonUINO zu bringen ohne was an der TonUINO SW zu ädern, was oft schwer ist.
Und wer den TonUINO löten konmte, schafft das hier auch.

3 Like

So die Aufnahme ist auch fertig.

Die Teile sind aber nich nicht verkabelt.

Update:
Das Modul ist fertig. Etwas fummelig zum löten…

Schaltplan und Druckdaten folgen.
Ich lade alles auf Thingiverse hoch.

4 Like

2 Like

Wo genau hast Du das in der Box „montiert“? Oder ist das im Grunde egal weil deine Box das Licht so gut weiter gibt?

Die Box ist schon gut Lichtdurchlässig
Ich hab das Modul einfach unten an den RFID Reader gekelbt.

2 Like

Cool.
Lässt du das nur rein mit dem micro laufen, oder baust du auch einen statischen, relaxteren Effekt ein?

Rein übers Micro.
Für statische Effekte fehlt die Kommunikation zwischen den beiden Controllern.

Einen IO Pin am Leuchtmodul werde ich noch fürs Ein- und Ausschalten einbauen, mehr nicht.