Problem mit IR Fernbedienung, Denkblockade oder unmöglicher Wunsch?gelöst!!

Unten stehender Loop läuft im Prinzip einwandfrei.

Man kann Ein- und ausschalten.
Mit den Tasten 1-7 werden jeweils statische Zustände ( von RGB LED ) geschaltet.
(Hier im Loop von Taste 3 bis 7 rausgeschmissen, das sich das eigentlich immer wiederholt)
Durch die Variable "Verlauf" wird sichergestellt, das die Helligkeitsregelung ankommt, ohne das man die Taste 1-7 nochmal drücken muss.
War etwas Tüftelei, aber klappt.

Ich würde gerne eine weitere Taste( z.B: 8 ) dazu nutzen, einen Verlauf durch die Regenbogenfarben ablaufen zu lassen.
Schrittweise per Tastendruck funktionierte das auch. >:(

Haken an der Sache ist, das der Sketch an der Stelle "if (irrecv.decode(&results)) {"xxxx;}
brav stehenbleibt und auf eine neue Eingabe wartet.

Damit wird der Teil"Regenbogen zeigen" natürlich unterbrochen. Im Grunde läuft er zwar, aber dann wird eben der IR Empfänger nie wieder abgefragt, macht also keinen Sinn.

Fazit:
Ich möchte per IR etwas einschalten, was sich wiederholt, bis ich per IR etwas anderes auswähle.
Da ich das nun schon recht lange möchte, aber funktionabel keinen Schritt weiter komme, frage ich mal in die Runde, ob jemand mir damit konkret helfen kann.
Den Regenbogenverlauf bekomme ich über einen PWMtable (array) problemlos hin, hier geht es um das Abfragen des IR-Empfängers.

void loop() {

  //Serial.println(an);
  digitalWrite (13, an);
  //Serial.println(brightness);
  //Serial.println(lastCode);
  if (an == 0) {
    analogWrite(R, 0);
    analogWrite(G, 0);
    analogWrite(B, 0);
  }

if (irrecv.decode(&results)) {
   // Serial.print(results.value); Serial.print("  "); Serial.println(lastCode);
    if (results.value == 4294967295)
    {
      results.value = lastCode;
    }
    // Wiederholcode ist 4294967295




 
    if ((results.value == 16724175 || Verlauf==1) && (an == 1)) // 1, weiß
    {
      Serial.println(" Es wurde taste 1 gedrückt");
      lastCode = results.value;
      Verlauf=1;
      analogWrite(R, 255-brightness);
      analogWrite(G, 255-brightness);
      analogWrite(B, 255-brightness);
      delay(10);

      //irrecv.resume();
    }

    if ((results.value == 16718055 || Verlauf==2) && (an == 1)) // 2, blau
    {
      Serial.println(" Es wurde taste 2 gedrückt");
      lastCode = results.value;
      Verlauf=2;
      analogWrite(R, 0);
      analogWrite(G, 0);
      analogWrite(B, 255-brightness);
      delay(10);
    }

   if ((results.value == 16754775)  && (an == 1))  //+, heller
    {
        lastCode = results.value;
        brightness -=5;
        if (brightness<=0)brightness=0;
    }

    if ((results.value == 16769055)  && (an == 1))  //-, dunkler
{
        lastCode = results.value;
        brightness +=5;
        if (brightness>=255)brightness=255;
    }

if (results.value == 16769565)  // ch+, an/aus
    {
      an = !an;
      delay(100);

      irrecv.resume();
 }

Da fehlen wieder die wichtigsten Infos.
An welchen PWM-Pins? Welcher Prozessor?

Das könnte ein Timerkonflikt mit der IRRecive sein.

Gruß Tommy

skyfox60:
Fazit:
Ich möchte per IR etwas einschalten, was sich wiederholt, bis ich per IR etwas anderes auswähle.

Sowas ist auf jeden Fall machbar.
Du musst aber den Empfang und die Ausführung trennen.
Mit einem Code-Fragment kann man nichts anfangen. Zeige bitte einen kompilierbaren kompletten Sketch, wie Du das bisher versucht hast.

Hallo Franz Peter,

hier mal der Sketch, den ich probehalber gemacht hatte, und der eben nur schrittweise funktionierte.

#include <IRremote.h>



int RECV_PIN = A1;
IRrecv irrecv(RECV_PIN);
decode_results results;

int velocity;
int brightness = 1;
int R = 10;
int G = 9;
int B = 6;
int angle=1;
int var=1;
bool an = 0;
int Verlauf = 0;
unsigned long lastCode;
unsigned char pwmtable[40] = {0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 16, 19, 23, 27, 31, 36, 41, 47, 52, 59, 65, 72, 80, 88, 96, 105, 114, 123, 133, 143, 154, 165, 177, 189, 201, 214, 227, 241, 255};
void setup()

{
  pinMode (R, OUTPUT);    // R
  pinMode (G, OUTPUT);    // G
  pinMode (B, OUTPUT);    // B
  pinMode (A1, INPUT);    //IR-in
  pinMode (13, OUTPUT);   //not necessary, just for Test purposes



  irrecv.enableIRIn();

  Serial.begin(9600);

}



void loop() {

  //Serial.println(an);
  digitalWrite (13, an);
  Serial.println(brightness);
  //Serial.println(lastCode);
  if (an == 0) {
    analogWrite(R, 0);
    analogWrite(G, 0);
    analogWrite(B, 0);
  }

  if (irrecv.decode(&results)) {
    Serial.print(results.value); Serial.print("  "); Serial.println(lastCode);
    if (results.value == 4294967295)
    {
      results.value = lastCode;
    }
    // Wiederholcode ist 4294967295




 
    if ((results.value == 16724175 || lastCode == 16724175 || Verlauf==1) && (an == 1)) // 1, weiß
    {
      Serial.println(" Es wurde taste 1 gedrückt");
      lastCode = results.value;
      Verlauf=1;
      analogWrite(R, 255-brightness);
      analogWrite(G, 255-brightness);
      analogWrite(B, 255-brightness);

      irrecv.resume();
    }

    if ((results.value == 16718055) && (an == 1)) // 2, blau
    {
      lastCode = results.value;
      analogWrite(R, 0);
      analogWrite(G, 0);
      analogWrite(B, 255-brightness);
    }
    if ((results.value == 16743045) && (an == 1)) // 3, Cyan
    {
      lastCode = results.value;
      analogWrite(R, 0);
      analogWrite(G, 255-brightness);
      analogWrite(B, 255-brightness);
    }
    if ((results.value == 16716015)  && (an == 1)) // 4, gelb
    {
      lastCode = results.value;
      analogWrite(R, 255-brightness);
      analogWrite(G, 255-brightness);
      analogWrite(B, 0);
    }
    if ((results.value == 16726215)  && (an == 1)) // 5, grün
    {
      lastCode = results.value;
      analogWrite(R, 0);
      analogWrite(G, 255-brightness);
      analogWrite(B, 0);
    }
    if ((results.value == 16734885)  && (an == 1)) // 6, rot
    {
      lastCode = results.value;
      analogWrite(R, 255-brightness);
      analogWrite(G, 0);
      analogWrite(B, 0);
    }
    if ((results.value == 16728765)  && (an == 1)) // 7, magenta
    {
      lastCode = results.value;
      analogWrite(R, 255-brightness);
      analogWrite(G, 0);
      analogWrite(B, 255-brightness);
    }
    //if (results.value == 16730805)  // 8, Regenbogenschleife
   
    if ((results.value == 16754775)  && (an == 1))  //+, heller
    {
        lastCode = results.value;
        brightness -=5;
        if (brightness<=0)brightness=0;
    }
    if ((results.value == 16769055)  && (an == 1))  //-, dunkler
{
        lastCode = results.value;
        brightness +=5;
        if (brightness>=255)brightness=255;
    }


    //if (results.value == 16712445)  // >>|, schneller // hiermit soll später der Verlauf des Regenbogens schneller oder langsamer gemacht werden.



    //if (results.value == 16720605)  // |<<, langsamer



    if (results.value == 16769565)  // ch+, an/aus
    {
      an = !an;

      irrecv.resume();
 }

    //if (results.value == 16736925)

    //if (results.value == 16736925)


    //if ((results.value == 16730805) && (an == 1)) {      //das war nur zum Test
     // lastCode = results.value;
      //for (int i = 0; i < 6;) {
      //  digitalWrite (13, HIGH); delay(100); digitalWrite(13, LOW); delay(100);
      //  i++; irrecv.resume();
    //  }
    

    irrecv.resume();                // Warte auf nächsten Wert



  }}

So, hier der Sketch mit dem Regenbogen.
Bei Taste 8 beginnts.

#include <IRremote.h>



int RECV_PIN = A1;
IRrecv irrecv(RECV_PIN);
decode_results results;

int velocity;
int brightness = 1;
int R = 10;
int G = 9;
int B = 6;
int angle=1;
int var=1;
bool an = 0;
int Verlauf = 0;
unsigned long lastCode;
unsigned char pwmtable[40] = {0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 16, 19, 23, 27, 31, 36, 41, 47, 52, 59, 65, 72, 80, 88, 96, 105, 114, 123, 133, 143, 154, 165, 177, 189, 201, 214, 227, 241, 255};
void setup()

{
  pinMode (R, OUTPUT);    // R
  pinMode (G, OUTPUT);    // G
  pinMode (B, OUTPUT);    // B
  pinMode (A1, INPUT);    //IR-in
  pinMode (13, OUTPUT);   //not necessary, just for Test purposes



  irrecv.enableIRIn();

  Serial.begin(9600);

}



void loop() {

  //Serial.println(an);
  digitalWrite (13, an);
  Serial.println(brightness);
  //Serial.println(lastCode);
  if (an == 0) {
    analogWrite(R, 0);
    analogWrite(G, 0);
    analogWrite(B, 0);
  }

  if (irrecv.decode(&results)) {
    Serial.print(results.value); Serial.print("  "); Serial.println(lastCode);
    if (results.value == 4294967295)
    {
      results.value = lastCode;
    }
    // Wiederholcode ist 4294967295




 
    if ((results.value == 16724175 || lastCode == 16724175 || Verlauf==1) && (an == 1)) // 1, weiß
    {
      Serial.println(" Es wurde taste 1 gedrückt");
      lastCode = results.value;
      Verlauf=1;
      analogWrite(R, 255-brightness);
      analogWrite(G, 255-brightness);
      analogWrite(B, 255-brightness);

      irrecv.resume();
    }

    if ((results.value == 16718055) && (an == 1)) // 2, blau
    {
      lastCode = results.value;
      analogWrite(R, 0);
      analogWrite(G, 0);
      analogWrite(B, 255-brightness);
    }
    if ((results.value == 16743045) && (an == 1)) // 3, Cyan
    {
      lastCode = results.value;
      analogWrite(R, 0);
      analogWrite(G, 255-brightness);
      analogWrite(B, 255-brightness);
    }
    if ((results.value == 16716015)  && (an == 1)) // 4, gelb
    {
      lastCode = results.value;
      analogWrite(R, 255-brightness);
      analogWrite(G, 255-brightness);
      analogWrite(B, 0);
    }
    if ((results.value == 16726215)  && (an == 1)) // 5, grün
    {
      lastCode = results.value;
      analogWrite(R, 0);
      analogWrite(G, 255-brightness);
      analogWrite(B, 0);
    }
    if ((results.value == 16734885)  && (an == 1)) // 6, rot
    {
      lastCode = results.value;
      analogWrite(R, 255-brightness);
      analogWrite(G, 0);
      analogWrite(B, 0);
    }
    if ((results.value == 16728765)  && (an == 1)) // 7, magenta
    {
      lastCode = results.value;
      analogWrite(R, 255-brightness);
      analogWrite(G, 0);
      analogWrite(B, 255-brightness);
    }
    if (results.value == 16730805)  // 8, Regenbogenschleife

     int Z = angle;
     Z = Z+var
     if (Z>240){Z=240;var=!var;}
     if (Z<0){Z=0);var=!var;}
  if(angle<40)
        {
            R=0;
            G=pwmtable[angle];
            B=255;
        }
        else if(angle<80)
        {
            angle-=40;
            R=0;
            G=255;
            B=pwmtable[39-angle];
        }
        else if(angle<120)
        {
            angle-=80;
            R=pwmtable[angle];
            G=255;
            B=0;
        }
        else if(angle<160)
        {
            angle-=120;
            R=255;
            G=pwmtable[39-angle];
            B=pwmtable[angle];
        }
        else if(angle<200)
        {
             angle-=160;
            R=255;
            G=0;
            B=pwmtable[39-angle];
        }
        else if(angle<240)
        {
            
            angle-=200;
            R=255;
            G=pwmtable[angle];
            B=pwmtable[angle];                 
        }           
                     


    analogWrite(R, brightness);
    analogWrite(G, brightness);
    analogWrite(B, brightness); 
    delay(50);
 }
    if ((results.value == 16754775)  && (an == 1))  //+, heller
    {
        lastCode = results.value;
        brightness -=5;
        if (brightness<=0)brightness=0;
    }
    if ((results.value == 16769055)  && (an == 1))  //-, dunkler
{
        lastCode = results.value;
        brightness +=5;
        if (brightness>=255)brightness=255;
    }


    //if (results.value == 16712445)  // >>|, schneller // hiermit soll später der Verlauf des Regenbogens schneller oder langsamer gemacht werden.



    //if (results.value == 16720605)  // |<<, langsamer



    if (results.value == 16769565)  // ch+, an/aus
    {
      an = !an;

      irrecv.resume();
 }

    //if (results.value == 16736925)

    //if (results.value == 16736925)


    //if ((results.value == 16730805) && (an == 1)) {      //das war nur zum Test
     // lastCode = results.value;
      //for (int i = 0; i < 6;) {
      //  digitalWrite (13, HIGH); delay(100); digitalWrite(13, LOW); delay(100);
      //  i++; irrecv.resume();
    //  }
    

    irrecv.resume();                // Warte auf nächsten Wert



  }}

Die erste Idee war das mit dem lastCode. Der Taugt aber ben nur für dauergedrückte Taste.
Ich dachte, er würde immer wieder die IF Bedingung erfüllen.
Daher auch das teilweise eingesetzte IF(results = xx || lastCode....
Aber er kommt ja bei der IF Abfrage nicht wieder an.
Erst, wenn ich z.B: auf "werde Heller drücke, dann fragt er danach alle ifs wieder einmal ab, oder auch dauern, wenn ich "heller" gedrückt halte.

Aber immer wenn der Receiver auf ein Einganssignal wartet, steht ja alles erst mal still, bis es ein neues Eingangssignal gibt.
Und da ist der stop.

Das Problem ist, dass Du den Empfang und die Ausführung der jeweiligen Tastenbefehle nicht trennst. In den if-Block springt er ja nur rein, wenn eine Taste gedrückt wurde. Dort darfst Du dir also nur merken, welche Taste gedrückt wurde.
Das Auswerten der Tastendrücke muss dann im loop ausserhalb des if (irrecv.decode(&results)) { .. } Blocks gemacht werden.

Du musst das anders aufbauen.

Durch den IR-Empfänger werden nur Statisvariablen gesetzt (Helligkeit, Geschwindigleit, Farbe, ...)
Damit hast Du im Loop immer die nötigen Informationen und weißt, was Du tun musst.
Dann stoppt auch nichts mehr, wenn keine Taste gedrückt wird.

Gruß Tommy

skyfox60:
Aber immer wenn der Receiver auf ein Einganssignal wartet, steht ja alles erst mal still, bis es ein neues Eingangssignal gibt.
Und da ist der stop.

Dann solltest du eine Statemachine bauen und die IR-Abfrage in einer Funktion durchführen, die nur in der loop aufgerufen wird.

Mit Funktionen arbeiten macht es auch übersichtlicher.

Hallo Franz Peter, Hallo Tommy,

im Prinzip versteh ich das, aber eben nicht so richtig.

Wo hakts bei mir?

Wer Loop läuft immer durch, ok, das versteh ich natürlich.

Außerhalb des Loops empfange ich das IR Signal, nur wie komm ich dahin, wenn der Loop immer "loopt"?

Franz Peter,

irgendwann kommt doch "if (irrecv.decode(&results)) { .. }"
da bleibt er doch solange stehen, bis irgendein "result kommt.
Wenn der Loop mehrere Sekunden dauert, weil beispielsweise der Regenbogen gemütlich durchfährt, wie erwische ich die o. g. if abrage nach den results.

Ich schau gerade wahrscheinlich vor eine Wand.

if (irrecv.decode(&results)) { .. } blockiert doch nicht.
Wenn nichts da ist, geht es nach der } weiter.
Du darfst nur Deine Auswertungen nicht in diesem if machen.

Wenn Dein Regenbogen mehrere Sekunden den loop blockiert, dann machst Du was falsch.

Gruß Tommy

Tommy,

ich bin Anfänger, sorry.
Wenn du mir sagst, da blockiert nichts, der läuft weiter, dann denke ich, das der erneute "andere" Tastendruck nur dann erkannt wird, wenn er ganz genau dann kommt, wenn grad die IF Abfrage dafür dran ist.

Im Prinzip blockiert ja mein Regenbogen nicht, der Loop ist durchlaufend.

Nur, wenn der Arduino gerade 3 Werte setzt, und dann drei Ausgänge beschreibt, und während dieser Zeit ein Signal am IR ankommt, dann kann er das doch gar nicht mitbekommen, und wenns ungünstig kommt, nur fragmentös mitbekommen.

Von daher weiß ich nicht, wie ich den da so implementiere, dass das funktioniert.

@Franz Peter:

Du schreibst: "Das Problem ist, dass Du den Empfang und die Ausführung der jeweiligen Tastenbefehle nicht trennst. In den if-Block springt er ja nur rein, wenn eine Taste gedrückt wurde. Dort darfst Du dir also nur merken, welche Taste gedrückt wurde.
Das Auswerten der Tastendrücke muss dann im loop ausserhalb des if (irrecv.decode(&results)) { .. } Blocks gemacht werden."

Frage:
Was etwa steht denn dann in den {...}?Und stehtr dann die if(irrecv.decode...
vor oder hinter dem Loop

Merkst du was? Ich komm grad grad echt nicht hinterher.

Im Prinzip ist das doch auch nicht anders wie ein Empfang von der seriellen Schnittstelle.
Natürlich steht der Empfang auch im loop. Wie Tommy schon schrieb, blockiert die if (irrecv.decode(&results)) { .. } ja nicht. Wenn Du da eine Taste empfangen hast, schreibst Du dir das in eine Variable. Und hinter dem Empfangsblock ( immer noch im loop ) wertest Du diese Variable dann aus. Da kann dann auch dein Regenbogen starten :wink: .

Hi

Momentan horchst Du nur auf neue Befehle, wenn Du mit Abarbeiten fertig bist - Deine Befehls-Annahme blockiert.
Du musst Dir in dem Bereich, wo Du die Befehle erkennst NUR merken, welcher Befehl aktiv ist.
(Flag setzen)

In loop() prüfst Du dieses Flag - wenn Das gesetzt ist, machst Du hier was - sonst eben nicht.
WENN das Flag gesetzt ist (also innerhalb der Flag-IF) schaust Du, ob JETZT was zu tun ist - wenn JA, mach was und merke Dir die Zeit, wenn NICHT, machst Du Nichts.

So kommt die Abfrage, ob ein Befehl vorliegt IMMER dran, wie auch die Abarbeitung des Befehl - zwar in kleinen Einzelschritten, aber dafür IMMER (sogar viel öfter, als ein Einzelschritt nötig ist).
Wenn die Sache 'abgearbeitet' ist, lösche Du dieses Flag als letzte Aktion - nun wird dieser Bereich nicht mehr ausgeführt, weil wir hier ja fertig sind.

Nachtwächter, Blink_without_delay, combie hat eine schöne Liste zum endlichen Automaten.

MfG

skyfox60:
Merkst du was? Ich komm grad grad echt nicht hinterher.

Dann solltest du einfach mal genau lesen, was wir dir schreiben.

Hallo Dieter,

du kannst dir sicher sein, das tue ich.

Aber:
Lesen, auch genau lesen, und verstehen, das sind schon 2 paar Schuhe.

Ja, es fällt mir halt nicht in den Schoß.

Hab mir jetzt einen ganz kleinen reduzierten Sketch geschrieben, um am serial Monitor beobachten zu können, was wann wie passiert, wenn ich was wo ändere.

Auch dadurch kommen neue Erkenntnisse, die dem Verständnis hilfreich sind.

Aber vom Durchbruch ist das noch ein Stück entfernt.

So, ein wenig Erkenntniss gewonnen.

Irgendwie war es weder noch.

Unten der "Testsketch". Dazu im Anhang ein Screenshot vom Serial Monitor.

Meine gewonnene Erkenntnis daraus ist:

bei if(irrecv..... geht es, wenn keine Taste gedrückt ist, nicht weiter, sondern wie man am Monitor sieht, zurück zum Angfang des Loops.
Das Serial.print dort wird ständig wiederholt.

Beim Drücken der Taste 1 oder 2 wird dann gemäß der if Abfrage oberhalb der Serial.print angepasst und auch ständig wiederholt.

Der Teil oberhalb der Abfrage läuft also ständig, der unterhalb nur, wenn eine Taste aktiv ist.

Das ist ja schonmal was.

Auf der anderen Seite, und damit frage ich gern noch mal in die Runde, könnte ich die results.value, also 167...irgendwas ja für die IF abfrage benutzen, und müsste sie nicht zwingend vorher in die Variable X geben.
Denn entweder bräuchte ich mehrere zus. Variablen, oder ich sage oben direkt anstelle von
if X=1, tue was, dann if Y = 1 tue was anderes,
das kann doch auch lauten
if res.val == 167123, tue A,
if res.val == 167456, tue B

Liege ich in dem Punkt richtig oder falsch.

hier der kleine Testsketch:

#include <IRremote.h>



int RECV_PIN = A1;
IRrecv irrecv(RECV_PIN);
decode_results results;




int lastCode;

int X;

void setup()

{
  



  irrecv.enableIRIn();

  Serial.begin(9600);

}



void loop() {

  
  Serial.print("Hier fangen wir an.    ");  Serial.print(results.value);
  if(X==1){Serial.print("   eingeschaltet  "); Serial.println(X);}
  if(X==0){Serial.print("   ausgeschaltet  "); Serial.println(X);}
  

  if (irrecv.decode(&results)) {
    //Serial.print(results.value); Serial.print("  "); Serial.println(lastCode);
    //if (results.value == 4294967295)
    {
     // results.value = lastCode;
    }
    // Wiederholcode ist 4294967295
    Serial.print("ich habe was empfangen");
    if(results.value==16724175)X=1;
    if(results.value==16718055)X=0;
irrecv.resume();
}}

IMG_5213.JPG

IMG_5213.JPG

Das täuscht, weil Du nach dem If nichts mehr ausgibst.
Mach mal:

irrecv.resume();
}
Serial.println("Am Ende vom Loop");
}

Außerdem lasse die vielen unnötigen Leerzeilen weg und formatiere ordentlich. (Y+T in der IDE hilft Dir dabei.

Gruß Tommy

Yep, da hast du recht, Tommy.

Also ist es doch ein durchlaufender Posten.

Damit müsste es theoretisch ja sogar total egal sein, wo if(IRrecv..... steht.

Das macht es jetzt nicht einfacher.
Oder besser gesagt, es wirft mich an den Anfang zurück.

Wobei, mir kommt gerade ein Gedanke.

Ich experimentier das noch mal durch und melde mich wieder.
Kann sein, das gerade ein wenig Erleuchtung kam.

Ich werde berichten.