Neopixel-Ring zwei LEDs mit verschiedenen Geschwindigkeiten kreisen lassen

Hi Forum,

ich bin aktuell dabei ein kleines Spiel mit einem Neopixel-Ring und einem Taster zu programmieren.
Bei dem Spiel gibt es verschiedene Modis. Modus 1 hat eine feste rote LED und eine blaue die umherkreist. Man muss genau den Punkt abwarten, wo die blaue LED auf der roten ist und den Taster betätigen. Bei Modi 2 ist es wie bei 1 nur mit 3 statt 1 roten LED.

Jetzt möchte ich noch zwei Modis haben. Bei Modi 3 soll der eigentlich rote feste Punkt langsam mitkreisen. Bei Modi 4 sollen die 3 roten LEDs mitkreisen.

Jetzt bekomme ich das irgendwie nicht hin, dass die roten LEDs und die eine blaue gleichmäßig mit verschiedenen Geschwindigkeiten herumkreisen. Wenn die blaue bei der roten LED ist (oder den 3 roten LEDs bei Modi 4) stottert es immer etwas. Auch wenn die 3 roten LEDs am ende des Rings sind und eigentlich ohne "stolpern" weiter kreisen sollten hapert es auch. Entweder werden einige Punkte übersprungen, oder wenn die blaue LED bei der (den) roten ist, bleibt da teilweise ein roter Punkt stehen.

Ich bekomms einfach nicht hin. Kann mir da villeicht weiter helfen ? Hoffe das war halbwegs verständlich ausgedrückt, wo das Problem ist. Sonst könnte ich ein kleines Video aufnehmen.

Ich hab den Code unten eingefügt. Habe nur Modis 3 und 4 eingefügt, wo es gerade hapert, damit es nicht zu unübersichtlich wird.

Vielen Dank schon mal für die Hilfe!

Mfg

#define FASTLED_ALLOW_INTERRUPTS 0
#include <FastLED.h>

CRGB RING[45];

unsigned long millis_alt; // millis für Lauflicht

void setup()
{
  FastLED.addLeds<WS2812B, 2, GRB>(RING, 45).setCorrection(TypicalLEDStrip);
  FastLED.setMaxPowerInVoltsAndMilliamps( 5, 500);

  FastLED.setBrightness(10);
}

void loop()
{
  // Modi_3();
  Modi_4();
}

void Modi_3()
{
  /*
     Blaue LED kreist umher und die rote langsam mit . Taster muss gedrückt werden, wenn die blaue LED genau auf eine der drei roten ist
  */

  static unsigned long millis_a; // millis für roten Punkt

  static uint8_t i  = 0;
  static uint8_t i1 = 0;

  if (Tasterstatus()) // Wenn Taster gedrückt
  {
    if (i == i1) // Wenn Lauflicht bei der Roten LED, gilt das als win
      ; // win

    else
      ; // lose

    i  = 0; // Von vorne starten
    i1 = 0;
  }

  if (i <= 44)
  {
    if ((unsigned long)millis() - millis_alt >= 500)
    {
      millis_alt = millis();

      RING[i - 1] = CRGB::Black;
      RING[i] = CRGB::Navy;

      FastLED.show();

      i++;
    }
  }
  else
    i = 0;

  if (i1 <= 44)
  {
    if ((unsigned long)millis() - millis_a >= 2000)
    {
      millis_a = millis();

      RING[i1 - 1] = CRGB::Black;
      RING[i1] = CRGB::Red;

      FastLED.show();

      i1++;
    }
  }
  else
    i1 = 0;

}

void Modi_4()
{
  static unsigned long millis_a; // millis für rote Punkte
  /*
     Blaue LED kreist umher und die roten langsam mit . Taster muss gedrückt werden, wenn die blaue LED genau auf eine der drei roten ist
  */

  static uint8_t i  = 0;
  static uint8_t i1 = 0;
  static uint8_t i2 = 1;
  static uint8_t i3 = 2;

  if (Tasterstatus()) // Wenn Taster gedrückt
  {
    if ((i == i1) || (i == i2) || (i == i3)) // Wenn Lauflicht bei der Roten LED und eine davor und dannach ist, gilt das als win
      ; // win

    else
      ; // lose

    i  = 0; // Von vorne starten
    i1 = 0;
    i2 = 1;
    i3 = 2;
  }

  if (i3 <= 44)
  {


    if ((unsigned long)millis() - millis_a >= 2000)
    {
      millis_a = millis();

      RING[i1 - 1] = CRGB::Black;

      RING[i1] = CRGB::Red;
      RING[i2]  = CRGB::Red;
      RING[i3]  = CRGB::Red;
      FastLED.show();

      i1++;
      i2++;
      i3++;
    }
  }
  else
  {
    i1 = 0;
    i2 = 1;
    i3 = 2;

    RING[i1] = CRGB::Black;
    RING[i2]  = CRGB::Black;
    RING[i3]  = CRGB::Black;
  }

  if (i <= 44)
  {
    if ((unsigned long)millis() - millis_alt >= 500)
    {
      millis_alt = millis();

      RING[i - 1] = CRGB::Black;
      RING[i] = CRGB::Navy;
      FastLED.show();

      i++;
    }
  }
  else
    i = 0;

}

bool Tasterstatus() //== Taster ==
{
  static bool Taster_status;      // Flankenerkennung: true = gedrückt

  bool Taster_gedrueckt = !digitalRead(3); 

  if ((Taster_gedrueckt) && (!Taster_status))   // Taster wurde gedrückt
  {
    Taster_status = true;    // Taster staus true, da gedrückt
    delay(5);                // entprellen
    return true;             // Rückgabeweet für Sollwert
  }

  if ((!Taster_gedrueckt && Taster_status)) // Taster wurde losgelassen
  {
    Taster_status = false;   // Taster staus false, da losgelassen
    delay(5);                // entprellen
    return false;            // Rückgabewert für Sollwert
  }
  return false;              // Falls kein Taster gedrückt wurde
}

Ich nehme an der Ring hat 45 LED.

Ich würde nicht 3 Variablen nehmen sondern nur eine und 1 bzw 2 summieren. So hast Du nur eine Variable die Du incrementieren mußt.

Du schaltest zuerst die LED ein und incrementierst dann die Position. So wird die Position des andersfarbigen LED mit der falschen Position verglichen.

Falscher Übergang bei Ende des Rings.

Wenn i3 an der letzten Position des Rings ist ist i2 und i1 bereits draußen. Darum werden zeitweise nicht alle 3 LED eingeschaltet.

Du mußt beim Einschalten jeder LED immer kontrollieren ob die Position größer als 44 ist. Wenn sie größer ist dann einfach 44 subtrahieren. Gleiches bei ausschalten ob kleiner als null.

positionLED = position-1;
  if (position <0) positionLED = position+45;
  RING[positionLED1] = CRGB::Black; 
for (byte j = 0; j<3;j++)
  {
  positionLED = position+j;
  if (position+j >44) positionLED = position%45;
  RING[positionLED1] = CRGB::Red;

}
position ++;
if( position >44) position = position %45;

Grüße Uwe