HELP: Neopixel Ringe synchron bekommen

Hallo zusammen,

ich habe ein kleines Problem bei dem ich nicht weiter komme mit meinem Projekt.

Ich habe 5 Arduino Pro Mini 5V welche jeweils einen Neopixel LED Ring ansteuern und im TheatherMode laufen lassen.

Jetzt habe ich das Problem, dass ich die Mini's mit einem 433Mhz Funkempfänger ausgestattet habe welcher mit dem Empfangen eines vordefinierten Codes den Neopixel synchron starten soll.

Die ersten paar Runden klappt das auch doch dann werde allesamt asynchron. Mal ist einer schneller mal einer langsamer. Da alle allerdings zwingend für die "Show" synchron laufen sollen bin ich am Rätseln wie ich das am besten anstelle.

Da ich schon im Forum bisschen gestöbert habe bin ich auf ähnliche Probleme gestoßen die wohl auf die Delay Funktion oder die Abweichungen im Quarz zurückzuführen sind.

Wirklich schlau bin ich daraus aber nicht geworden.

Könntet ihr mir evtl. weiterhelfen oder hat jemand dieses Problem evtl. ebenfalls gehabt und gelöst?
Wäre wirklich dankbar weil das Projekt für ein Ehrenamt im Verein ist und ich wie der Ochse vorm Berg stehe im Moment.

Vielen vielen Dank

Sketch ist dieser hier - komplett Standard:

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

#define PIN 6

// 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(60, 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'
}

void loop() {
  // Some example procedures showing how to display to the pixels:
  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);
}

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

Erstmal willkommen im Forum!

Synchron bedeutet ja, dass was synchronisiert werden muss/sollte. Das passiert ja bei Dir nicht, und ob der vermeintlich synchrone Start das auch ist weiß niemand so genau.

Da jetzt (noch) keiner weiß, über welche Entfernungen und Laufzeiten wir sprechen, ist ein Tipp eher schwierig.
MEIN erster Ansatz wäre, dass 1 arduino den Master spielt und die anderen über einen Takt oder ähnliches eben synchronisiert.

Das Hauptproblem hastdu schon richtig erkannt.
Das sind die verbauten Resonatoren, diese sind nie so genau, dass du über längere Zeit in einheitliches Ablaufbild bekommst.

Wenn es besser laufen soll, musst du wie Klaus_ww schon schrieb, den Durchlauf zwischendurch synchronisieren.
Am einfachsten zwischendurch erneut einen Startimpuls senden.

Danke für eure Antworten :slight_smile:
Die Entfernung wäre unter 2 meter zu den einzelnen Ardus. Der "Dirigent" übernimmt den Start per Funksender. Erneut starten klingt gut. Daran hatte ich noch gar nicht gedacht.

Die Laufzeit wäre zwischen 45 und 90 Minuten.

Würde ein zusätzlicher Quarz oder Zeitgeber Abhilfe schaffen können?

hi,

die frage ist, was Du mit "runden" meinst.
sind das abschnitte?
wenn es abschnitte sind, wie lange dauern die?

ich "vermute" jetzt mal: es sind einzelne abschnitte, die selbst nicht allzu lange dauern. also wenn alle zugleich starten, laufen sie in einem abschnitt/einer runde nicht sichtbar auseinander.

dann solltest Du den langsamsten als referenz nehmen und (vorsichtshalber mit einer sicherheitsreserve von einer x-tel sekunde) nach dieser langsamsten zeit einen neuen impuls vom center senden, aufgrund dessen alle den nächsten abschnitt/die nächste runde angehen.

oder eben keine sicherheitsreserve, dann wird, wenns denn so ist, mancher arduino "nicht ganz fertigmachen", sondern beim neuen impuls gleich den nächsten abschnitt starten.

falls diese abschnitte nicht allzu lange dauern, wird das optisch nicht auffallen, falls die abschnitte zu lang sind, mußt Du sie aufteilen.

gruß stefan

Hallo Stefan,

ich meinte natürlich nicht TheaterMode sondern ColorWipe also dass die LEDs sich nach und nach bis der ganze Ring ausgefüllt ist mit der selben Farbe füllen. Wie ein Ladebalken sozusagen.

So machts auch mehr Sinn ^^ Sorry.

Mit Runden ist der Übergang zur nächsten Farbe also nach 60 LEDs gemeint. Sind die ersten 60 LEDs Blau fängt er von vorne an mit Grün usw

Eine Pause dazwischen könnte für Synchronität sorgen? Sprich er füllt die ersten 60 LEDs und wartet dann sagen wir 1 Sekunde bis er die nächste Runde beginnt mit einer anderen Farbe?

Aber falls ein Arduino dabei langsamer ist setzt sich doch der Delay fort oder?
EDIT: Ich verstehe glaube ich was du meinst. Ich setze die Länge eines Abschnitts einfach fest. Das würde auch super zum Takt passen 1/4 etc.

Welche Funktion kann ich dafür verwenden? Wait?

Hallo,
Am Pro1 einen 433 Sender verbauen, der vor jeder "Runde" an die anderen 4 Pros ein Startsignal
sendet ?

mfg Martin

hi,

so ganz hast Du's noch nicht heraus, was ich meine.

nemmen wer mal an, alle abschnitte/runden sind gleich lang und dauern 20 sekunden.

dann schickt der sender(pro1) alle 20,2 sekunden ein signal per funk.

alle anderen warten auf ein signal und fangen dann mir der runde an, bis zum ende der runde, und dann warten sie, bis wieder ein signal kommt, dann nächste runde, usw.

wenn's nicht mehr können muß, kannst Du das einfach mit delays erschlagen:

am pro1 einfach ein delay von 20,2 sekunden zwischen den sendungen.
bei den satelliten nach jeder runde eine schleife die auf ein signal lauscht, und bei empfang die schleife velassen und die nächste runde starten.

sind die runden verschieden lang, beim sender ein array hinterlegen, im dem die zeiten gespeichert sind, und das delay zwischen den sendungen bekommt einen wert nach dem anderen aus dem array.

gruß stefan