Hallo
Ich würde gerne die LEDs einer WS2811 LEDKette mit einer Infrarotfernbedienung (Empfang über einfachen TSOP3811) steuern. In meinem Sketch benutze ich zum Decodieren der IR Signale die Library IRRemote. Zum Steuern der LEDs benutze ich die Library FastLib2.
Ich weiss nicht genau wie die IRRemote-Lib funktioniert aber anscheinend kommt sie bei der Dekodierung der IRSignale durcheinander wenn ich die LED-Kette ansteuere. Die Ausgabe der Hexwerte gleicht eher Zufallszahlen als einem vernünftig dekodierten Wert. Wenn die LEDs nicht angesteuert werden dekodiert die IRRemote-Lib die Signale der Fernbedienung korrekt. Das Ansteuern der LEDs (Zeile: FastLED.show() ) dauert ja einige Millisekunden und ich vermute in der Zeit kann die IRRemote-Lib dann die Puls/Pausenlängen der Infrarotsignale nicht mehr richtig messen. (Zum Überprüfen ob die LEDs nicht den Empfang stören habe ich die RGB Werte sicherheitshalber mal auf 0 gesetzt)
Weiß jemand wie man das Problem am einfachsten softwaretechnisch lösen kann? Ich weiss nicht 100% ob es wirklich an der Zeit liegt in der die LEDs beschrieben werden oder ob es an etwas internem liegt (zB. die FastSPI2 Lib schaltet irgendwas mit den Interrupts um die von IRRemote benötigt werden oder sowas)
Bin für alle Lösungsvorschläge dankbar.
Anbei noch mein Sketch mit dem ich das Ganze getestet habe:
#include <FastSPI_LED2.h>
#include <IRremote.h>
#define LEDSTRIPE_DATA_PIN 6 // Datapin
#define NUM_LEDS 30
#define IR_RECV_PIN 11 // IRReceiver TSOP1738
// ir
IRrecv irrecv(IR_RECV_PIN);
decode_results irresults;
// led
CRGB leds[NUM_LEDS];
float time = 0;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // IR Empfang starten
FastLED.addLeds<WS2811, LEDSTRIPE_DATA_PIN, RGB>(leds, NUM_LEDS);
Serial.println("Setup done");
}
void loop()
{
bool irreceived = irrecv.decode(&irresults);
if (irreceived)
{
Serial.println(irresults.value, HEX);
irrecv.resume(); // Receive the next value
}
// Farbberechnung
time += 0.0025;
float hr = (sin (time*0.1) + 1.0) * .5;
float hg = (sin (time*0.4) + 1.0) * .5;
float hb = (sin (time*0.7) + 1.0) * .5;
for( int i = 0; i < NUM_LEDS; i++)
{
// nur zum Test auf 0 setzen. Später kommen echte RGB Werte rein
leds[i].r = 0;
leds[i].g = 0;
leds[i].b = 0;
}
FastLED.show();
}
Gruß
Jarny
PS: Ja, ich möchte das Ansteuern der LEDs wirklich zyklisch in der Loop haben weil dort später dynamische Farbeffekte berechnet werden sollen. Also keine statische Ansteuerung der LEDs.
Diese Funktion blockiert bei Ansteuerung von WS2811 Controllern die Interrupts auf dem Atmega, so lange wie sie läuft.
Wenn Du diese Funktion ständig aufrufst, werden damit die Interrupts ständig blockiert und ALLE Funktionen werden auf dem Atmega unbrauchbar, die auf laufende Interrupts angewiesen sind.
Der Empfang Deiner IR-Sequenzen ist dagegen auf funktionierende Interrupts angewiesen.
Mit ständig blockierten Interrupts geht das nicht zusammen.
Jarny:
Bin für alle Lösungsvorschläge dankbar.
Wenn Du nicht auf andere, teurere LEDs wechseln möchtest, die Du auch ohne Blockierung des Interrupt-Systems ansteuern kannst, wirst Du wohl Deine beiden Aufgaben auf zwei Controller verteilen müssen, die Du dann synchronisierst. Der eine empfängt die IR-Signale und stellt sie auf Anforderung bereit, der andere blockiert fast ständig seine Interrupts während er die LEDs ansteuert und fordert ggf. zwischendurch erhaltene IR-Befehle an. So dass der anfordernde Controller es selbst steuern kann, wann er zeitlich bereit ist, einen neuen Befehl entgegenzunehmen, nämlich immer genau zwischendurch, wenn FastLED.show() gerade nicht läuft.
Hmm, ok. Das mit den Interrupts hatte ich fast befürchtet. Schade!
Gibt es vielleicht fertige billige ICs die die IR-Decodierung übernehmen und nur noch über ein Pin an den Arduino angebunden werden? Über den Pin kann man dann seriell den empfangenen dekodierten Wert abholen.
Hallo,
nehme das "irrecv.resume(); // Receive the next value" mal aus der
ifSchleife raus
und dann z.B. so:
irrecv.resume(); // Receive the next value
FastLED.show();
Gruß und Spaß
Andreas
Dann geht gar nichts mehr. Ich sehe keine empfangenen Werte auf der Konsole. Das resume() darf man wohl nur aufrufen wenn etwas empfangen wurde.
Ich hab auch noch andere Varianten ausprobiert indem ich abhängig von dem boolean irreceived nach dem FastLED.show() das irrecv.resume() aufrufe. Aber das bringt nichts. Ihm fehlt die Zeit zum Dekodieren per Interrupt.
Jarny:
Gibt es vielleicht fertige billige ICs die die IR-Decodierung übernehmen und nur noch über ein Pin an den Arduino angebunden werden? Über den Pin kann man dann seriell den empfangenen dekodierten Wert abholen.
Ja, einen zweiten Controller.
Der ATtiny ist hier nicht so geeignet, da man da mehrere Klimmzüge mit dem IR Empfang, Serial oder I2C machen muss. Es geht zwar, aber ist viel Arbeit. Aber ein blanker Atmega328 + Quarz ist auch billig zu haben.