Probleme mit FASTLED und RCSwitch

Hallo,
hoffe ihr könnt mir hier weiter helfen. Stehe gerade auf dem Schlauch .... :confused:

Ich möchte diverse Szenarien über RCSwitch library auf einen LED Strip mit WS2812B und 2x20 LED´s gegenläufig aufbauen.

Mein Problem liegt aktuell bei dem realisieren von Feuer.... aktuell ist es so, dass nur solange das Signal gesendet wird der Code ausgeführt wird. Im Regelfall ist dieser ja im LOOP, bei mir allerdings in einem VOID.

Ich finde keine Möglichkeit hier eine Schleife einzubinden....

Der Code ist da gerade erst im Aufbau nicht gut gegliedert und nicht vollständig. Geht aktuell also nur darum, warum ich hier ein dauerndes Funksignal benötige. Gehe davon aus das es an dem Interrupt liegt den ich ja für RCSwitch benötige.

Hoffe ihr habt den entscheidenden Tipp für mich ....

//#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <FastLED.h>


#define NUM_LEDS 40
//#define NUM_LEDS_STICK NUM_LEDS/20
#define DATA_PIN 6
#define BRIGHTNESS  200
#define FRAMES_PER_SECOND 60

bool gReverseDirection = false;
CRGB leds[NUM_LEDS];

#include <RCSwitch.h>

int j = 40;
int i = 0;
int value = 0;
RCSwitch mySwitch = RCSwitch();
CRGBPalette16 gPal;
void setup()
{
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Empfänger ist an Interrupt-Pin "D2"
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  i = 0; j = 39;
   FastLED.setBrightness( BRIGHTNESS );
   gPal = HeatColors_p;
  for (i = 0; i <= 39; i++) {

    leds[i] = CRGB::Black;

    FastLED.show();
  }
}
void loop() {
if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
    int value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
    Serial.println(value);
    if (value == -10816 || value == 14144960) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {


      one();
    }
    if (value == -10960|| value == 14144816) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      two();
    }

    if (value == -10768|| value == 14145008) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      three();
    }
    if (value == -10996|| value == 14144780) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      four();
    }
    if (value == -10804|| value == 14144972) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      five();
    }
    if (value == -10948|| value == 14144828) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      six();
    }
    if (value == -10756|| value == 141450209) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      seven();
    }
    if (value == -11005|| value == 14144771) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      eight();
    }


    mySwitch.resetAvailable();  // Hier wird der Empfänger "resettet"
  } }





void one() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Red;
    leds[i] = CRGB::Red;

    FastLED.show();
    delay(20);
    j--;
    Serial.println(i);
  }

}

void two() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Olive;
    leds[i] = CRGB::Olive;
    Serial.print(i);Serial.print(" ");Serial.println(j); 
    FastLED.show();
    delay(20);
    j--;
  }


}


void three() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Green;
    leds[i] = CRGB::Green;
    FastLED.show();
    delay(20);
    j--;
  }


}
void four() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Lime;
    leds[i] = CRGB::Lime;
    FastLED.show();
    delay(20);
    j--;
  }


}
void five() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Yellow;
    leds[i] = CRGB::Yellow;
    FastLED.show();
    
    j--;
  }


}
void six() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Blue;
    leds[i] = CRGB::Blue;
    FastLED.show();
    delay(20);
    j--;
  }


}
void seven() {
  i = 0; j = 39;
  for (i = 0; i <= 19; i++) {
    leds[j] = CRGB::Purple;
    leds[i] = CRGB::Purple;
    FastLED.show();
    delay(20);
    j--;
  }


}
void eight() {

random16_add_entropy( random());
Fire2012WithPalette(); // run simulation frame, using palette colors
  
  FastLED.show(); // display this frame
  FastLED.delay(1000 / FRAMES_PER_SECOND);
}

#define COOLING  100
#define SPARKING 40

void Fire2012WithPalette()
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];

  // Step 1.  Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }
  
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
    
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      // Scale the heat value from 0-255 down to 0-240
      // for best results with color palettes.
      byte colorindex = scale8( heat[j], 240);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        pixelnumber = (NUM_LEDS-1) - j;
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}

Das hat mit dem Interrupt nix zu tun.
Du musst nur deine Anforderung n einer Variable zwischen speichern und diese auslesen.

Dachte das ich das mit dem "VALUE" eigentlich doch mache...

ediciustsaf:
Dachte das ich das mit dem "VALUE" eigentlich doch mache...

In Value hast du ja nur den RC-Switch-Code.
Du musst zusätzlich eine Variable nehmen, die wenn der RC-Switch-Code ausgewertet wurde, auf 1 gesetzt wird.
Diese fragst du in der Loop vor deiner Funktion ab. Solange die Funktion aktiv ist bleibt die auf 1. Ist die Funktion durch, setzt du die auf 0.

ediciustsaf:
hoffe ihr könnt mir hier weiter helfen.

Auf die Schnelle nur mit einem video.

Der Macher war auch hier zeitweise aktiv - ich weiß nur nicht mehr, wie er sich hier genannt hat.

Gruß

Gregor

@HotSystems

Ich habe das Ganze nun geändert, nochmal danke für den tipp, aber jetzt ist das problem, dass die funktion unendlich weiterlaufen soll, bis er über funk eine neue nachricht empfängt, und dann eine andere funktion ausführen soll. Mit dem was ich programmiert habe, läuft die funktion nun unendlich weiter, aber es wird nichts neues empfangen...

Ok, wenn deine Led-Funktionen kein Ende haben, musst du an geeigneter Stelle eine Funk-Code-Abfrage für das Ende einfügen.

Hab da jetzt ein paar unterschiedliche Sachen probiert aber komm hier nicht mehr aus dem Unterprogramm raus ODER im Loop wird der Empfang blockiert warum auch immer...

EDIT: Habe gerade vor der Abfrage mySwitch available einen Zähler gesetzt und den am SerialMonitor angeschaut. Scheint also als würde er die Abfrage mySwitchavailable einfach nicht machen weil er eben das Funksignal nicht mehr erkennt... Wo wir wieder beim Interrupt wären. Deshalb hängt der doch eigentlich auf D2 damit genau das nicht passieren soll ???

Tante Edith hat noch was ...:
Ich bin mal interessehalber LAAAAAAANG auf senden geblieben und siehe da es schaltet irgendwann mal um... Also kommt wohl doch irgendwie nichts bis zum interrupt an dem der receiver angeschlossen ist durch...

#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <FastLED.h>


#define NUM_LEDS 40
//#define NUM_LEDS_STICK NUM_LEDS/20
#define DATA_PIN 6
#define BRIGHTNESS  200
#define FRAMES_PER_SECOND 60
uint8_t gHue1 = 0;
uint8_t gHue2 = 255;
uint8_t gHueDelta = 3;

bool gReverseDirection = false;
CRGB leds[NUM_LEDS];

#include <RCSwitch.h>

int j = 40;
int Prog = 0;
int i = 0;
int value = 0;
RCSwitch mySwitch = RCSwitch();
CRGBPalette16 gPal;
void setup()
{
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Empfänger ist an Interrupt-Pin "D2"
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  i = 0; j = 39;
  FastLED.setBrightness( BRIGHTNESS );
  gPal = HeatColors_p;
  for (i = 0; i <= 39; i++) {
    leds[i] = CRGB::Black;
    FastLED.show();
  }
}
void loop() {

  if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  { Prog = 0;
    int value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
    Serial.print(mySwitch.available()); Serial.print("  "); Serial.println(value);
    if (value == -10816 || value == 14144960)
    {
      Prog = 1;
    }
    if (value == -10960 || value == 14144816)
    {
      Prog = 2;
    }

    if (value == -10768 || value == 14145008)
    {
      Prog = 3;
    }
    if (value == -10996 || value == 14144780)
    {
      Prog = 4;
    }
    if (value == -10804 || value == 14144972)
    {
      Prog = 5;
    }
    if (value == -10948 || value == 14144828)
    {
      Prog = 6;
    }
    if (value == -10756 || value == 141450209)
    {
      Prog = 7;
    }
    if (value == -11005 || value == 14144771)
    {
      Prog = 8;
    }
    mySwitch.resetAvailable();  // Hier wird der Empfänger "resettet"
  }
  if (Prog == 1) {

    one();
  }

  if (Prog == 2) {

    two();

  }
  if (Prog == 3) {


    three();

  }
  if (Prog == 4) {

    four();
  }

  if (Prog == 5) {
    five();
  }

  if (Prog == 6) {

    six();
  }
  if (Prog == 7) {
    seven();
  }
  if (Prog == 8) {

    eight();

  }
  EVERY_N_MILLISECONDS( 20 ) {
    gHue1++;
  }

}


void one() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {

    i = 0; j = 39;
    for (i = 0; i <= 19; i++) {
      leds[j] = CRGB::Red;
      leds[i] = CRGB::Red;
      FastLED.show();
      j--;
    }

  }
}

void two() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    i = 0; j = 39;
    for (i = 0; i <= 19; i++) {
      leds[j] = CRGB::Olive;
      leds[i] = CRGB::Olive;
      FastLED.show();
      j--;
    }
  }
}


void three() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    i = 0; j = 39;
    for (i = 0; i <= 19; i++) {
      leds[j] = CRGB::Green;
      leds[i] = CRGB::Green;
      FastLED.show();
      j--;
    }
  }
}

void four() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    fill_rainbow( leds, NUM_LEDS / 2, gHue1, 3);
    FastLED.show();
  }
}


void five() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    i = 0; j = 39;
    for (i = 0; i <= 19; i++) {
      leds[j] = CRGB::Yellow;
      leds[i] = CRGB::Yellow;
      FastLED.show();
      j--;
    }
  }
}
void six() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    i = 0; j = 39;
    for (i = 0; i <= 19; i++) {
      leds[j] = CRGB::Blue;
      leds[i] = CRGB::Blue;
      FastLED.show();
      j--;
    }
  }
}
void seven() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    i = 0; j = 39;
    for (i = 0; i <= 19; i++) {
      leds[j] = CRGB::Purple;
      leds[i] = CRGB::Purple;
      FastLED.show();
      j--;
    }
  }
}
void eight() {
  if (mySwitch.getReceivedValue() == 1)

  { Prog = 0;
  } else {
    random16_add_entropy( random());
    Fire2012WithPalette(); // run simulation frame, using palette colors

    FastLED.show(); // display this frame
    FastLED.delay(1000 / FRAMES_PER_SECOND);
  }
}

#define COOLING  130
#define SPARKING 80

void Fire2012WithPalette()
{
  // Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];

  // Step 1.  Cool down every cell a little
  for ( int i = 0; i < NUM_LEDS; i++) {
    heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
  }

  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for ( int k = NUM_LEDS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
  }

  // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
  if ( random8() < SPARKING ) {
    int y = random8(7);
    heat[y] = qadd8( heat[y], random8(160, 255) );
  }

  // Step 4.  Map from heat cells to LED colors
  for ( int j = 0; j < NUM_LEDS; j++) {
    // Scale the heat value from 0-255 down to 0-240
    // for best results with color palettes.
    byte colorindex = scale8( heat[j], 240);
    CRGB color = ColorFromPalette( gPal, colorindex);
    int pixelnumber;
    if ( gReverseDirection ) {
      pixelnumber = (NUM_LEDS - 1) - j;
    } else {
      pixelnumber = j;
    }
    leds[pixelnumber] = color;
  }
}

Habe jetzt in jedem Unterprogramm ein Delay(40); gesetzt. Das Feuer wird dadurch leider unbrauchbar, aber nun scheint es zum umschalten zu klappen. Somit ist wohl doch ein Problem mit dem Interrupt und FastLED das Problem. Hab nur leider keine 4 Adrigen LED Streifen da. Wäre interessant ob es dann besser ist....

@Gregor: unser LED Künstler ist Helmuth
https://forum.arduino.cc/index.php?topic=575419.0

ediciustsaf:
Habe jetzt in jedem Unterprogramm ein Delay(40); gesetzt. Das Feuer wird dadurch leider unbrauchbar, aber nun scheint es zum umschalten zu klappen. Somit ist wohl doch ein Problem mit dem Interrupt und FastLED das Problem. Hab nur leider keine 4 Adrigen LED Streifen da. Wäre interessant ob es dann besser ist....

Stimmt, hier an dieser Stelle ist das Problem der Interrupt.
Der wird soweit mir bekannt ist, durch die FastLed abgeschaltet.

Es gibt da auch eine Lösung mit einem externen Controller, der hier eingreifen kann.
Ich glaube agmue hat da eine Lösung schon mal gebaut.
Mir fehlen da leider die Erfahrungen mit den Stripes.

Ok danke

HotSystems:
Ich glaube agmue hat da eine Lösung schon mal gebaut.

Eher nicht, denn mit RCSwitch habe ich keine praktische Erfahrungen. Möglicherweise verwechselst Du das mit NeoPixel zusammen mit IR-Fernbedienung. Da sehe ich tatsächlich eine Analogie, mein Beitrag also theoretisch und ausdrücklich ohne Gewähr!

Wegen des Timings der NeoPixel müssen bei Datenübertragungen während FastLED.show() die Interrupts ausgeschaltet werden. Da RCSwitch mittels Interrupts Daten erkennt, ist der µC bei abgeschalteten Interrupts taub. Abhilfe:

  • Anstelle NeoPixeln den Typ DotStar (APA102) verwenden, da bei diesem Typ die Interrupts nicht abgeschaltet werden müssen.
  • Zwei mittels I2C verbundene µCs, einer für NeoPixel, einer für RCSwitch.

Beide Lösungen habe ich im Einsatz zusammen mit IR-Fernbedienungen. Eine dritte Variante ist mir unbekannt.

agmue:
Eher nicht, denn mit RCSwitch habe ich keine praktische Erfahrungen. Möglicherweise verwechselst Du das mit NeoPixel zusammen mit IR-Fernbedienung. Da sehe ich tatsächlich eine Analogie, mein Beitrag also theoretisch und ausdrücklich ohne Gewähr!

Ok, das hatte ich tatsächlich verwechselt.

Einen weiteren Controller habe ich ja schon erwähnt und wäre hier sicher auch möglich.
Auch ein ATtiny85 sollte ist da auch möglich sein.
Evtl. sogar mein Beispiel aus "zeigt her eure geilen Projekte" hier nur abgewandelt mit einem 433 MHz Empfänger.

HotSystems:
Auch ein ATtiny85 sollte da möglich sein.

Sieht nicht so gut aus:

// At least for the ATTiny X4/X5, receiving has to be disabled due to
// missing libm depencies (udivmodhi4)

agmue:
Sieht nicht so gut aus:

// At least for the ATTiny X4/X5, receiving has to be disabled due to
// missing libm depencies (udivmodhi4)

Nein, kein Problem.
Man kann die Library anpassen, dann funktioniert das auch mit dem ATtiny85.
Ich habe damit selbst Projekte (RCSwitch mit 433 MHz-Receiver und ATtiny85) aufgebaut.

Also das funktioniert wirklich.

HotSystems:
Also das funktioniert wirklich.

Gut zu wissen! Dann kann ich meine Bedenken, ob RCSwitch mit I2C harmoniert, auch zur Seite legen.

Mit einem Standard-Arduino wie dem Nano kommt ein Anfänger aber womöglich besser zurecht.

agmue:
Gut zu wissen! Dann kann ich meine Bedenken, ob RCSwitch mit I2C harmoniert, auch zur Seite legen.

Mit einem Standard-Arduino wie dem Nano kommt ein Anfänger aber womöglich besser zurecht.

Na das hätte ich dir auch schon sagen können.
RCSwitch und I2C ist kein Problem, auch auf dem ATtiny85 nicht.
Und ja, Nano oder Pro Mini sind da einfacher zu handhaben.

Edit:
Bei Empfang gibt es leider das Problem, die Empfängerdaten landen auf Pin PB2, der auch für I2C verwendet wird.
Da muss der IRQ-Eingang verschoben werden.
Das wurde im Web auch schon mal beschrieben aber von mir noch nicht getestet.
Alternative ist die Verwendung dann der UART mit SoftwareSerial.

HotSystems:
Na das hätte ich dir auch schon sagen können.

Daher wollte ich mich zu diesem Thema eigentlich auch nicht äußern. Da Du mich aber erwähnt hattest, wurde ich persönlich angeschrieben, weshalb ich dann doch meinen Senf in Form einer Analogie dazu gegeben habe. Natürlich verwende ich dann ein paar Konjunktive mehr.

Da wir uns ja einig sind, kann der TO nun aus seiner Ohnmacht - er erwähnte Zeitdruck - erwachen und sich für eine der Möglichkeiten entscheiden. Die erste ist einfach aber teuer, die zweite schwieriger zu programmieren.

Ich bin gespannt :slight_smile:

agmue:
.....
Da wir uns ja einig sind, .....

Ich bin gespannt :slight_smile:

So sehe ich das auch.

Ja und Hilfe wird er hier sicher weiterhin erhalten.