Feinschliff in den Schleifen beheben

Hallo zusammen

Ich habe ein Programm, welches über eine Fernbedienung 3 LED’s nach einer vorgegebenen Blinksequenz anwählen soll. Die habe ich im Array vorgegeben.
Taste 1 soll Muster 1 mit Blau, Rot und Gelber LED laufen lassen und
Taste 2 soll Muster 2 mit Blau, Rot und Gelber LED laufen lassen.
Das funktionier soweit ganz gut. Aber
wenn ich jetzt die Taste Blau drücke, sollen nur die Rote und die Gelbe LED weiter blinken, unabhängig ob ich das Muster 1 oder Muster 2 wähle.
Wenn ich jetzt noch die Taste Gelb drücke, sollen nur noch die Rote LED weiter blinken, unabhängig ob ich das Muster 1 oder Muster 2 wähle.
Wenn ich jetzt wieder die Taste Blau drücke, sollen nur noch die Rote LED und die Blaue LED weiter blinken, unabhängig ob ich das Muster 1 oder Muster 2 wähle.
Mein Problem besteht das umzusetzen. Wenn ich die Blaue Taste Taste im drücke verhält sich das Programm ganz anders als es soll. Auch wenn ich die Taste 1 drücke, wärend Muster 1 schon läuft soll das Programm darauf nicht reagieren, aber dann läuft es auch nicht richtig. Was muss ich machen das es funktioniert?

/* Dezimal codierung der Sky Fernbedienung.
    Jede Taste hat 2 Code's

    Taste 1 A = 2152244737
    Taste 1 B = 2152211969
    Taste 2 A = 2152244738
    Taste 2 B = 2152211970
    Taste Blau A = 2152212080
    Taste Blau B =2152244848
    Taste Rot A = 2152244845
    Taste Rot B = 2152212077
    Taste Gelb A= 2152212079
    Taste Gelb B = 2152244847


*/
#include <IRremote.h>

int Blau = 6;
int Rot = 9;
int Gelb = 11;
int IRpin = 3; // Pin fr den IR Empfaenger

int R = 255;
int B = 255;
int G = 255;

IRrecv irrecv(IRpin);
decode_results results;

byte OFF = 0;
byte Muster1_BlauLED[14]   =  {B, B, B, B, B, 0, 0, 0, B, 0, 0, 0, 0, 0};
byte Muster1_RotLED[14]    =  {0, 0, 0, 0, R, R, R, R, R, 0, 0, 0, R, 0};
byte Muster1_GelbLED[14]   =  {G, G, G, G, G, 0, 0, 0, G, 0, 0, 0, 0, 0};

byte Muster2_BlauLED[16]   =  {B, 0, B, 0, B, 0, B, B, B, B, B, 0, 0, 0, 0, 0};
byte Muster2_RotLED[16]    =  {R, R, R, R, R, 0, 0, 0, 0, 0, R, 0, R, 0, R, 0};
byte Muster2_GelbLED[16]   =  {G, 0, G, 0, G, 0, G, G, G, G, G, 0, 0, 0, 0, 0};

void setup()
{
  Serial.begin(9600);
  pinMode(Blau, OUTPUT);    // Setzt Pin für Linke Blaue LED als Ausgang
  pinMode(Rot, OUTPUT);    // Setzt Pin für Linke Rote LED als Ausgang
  pinMode(Gelb, OUTPUT);     // Setzt Pin für Gelbe  LED als Ausgang

  analogWrite(Blau, 0);
  analogWrite(Rot, 0);
  analogWrite(Gelb, 0);
  irrecv.enableIRIn();           // IR Empfaenger starten
}

void loop()
{

  if (irrecv.decode(&results))
  {
    irrecv.resume();
    Serial.println(results.value, DEC);
  }

  if ((results.value == 2152244737) || (results.value == 2152211969))      //  Wenn taste 1 gedrückt, Blau, Rot, Gelb LED nach Muster 1 blinken
  {
 //   Serial.println("If taste1");

    for (int i = 0; i < 14; i++)
    {
      Serial.println("for taste1");
      analogWrite(Blau, Muster1_BlauLED[i]);
      analogWrite(Rot, Muster1_RotLED[i]);
      analogWrite(Gelb, Muster1_GelbLED[i]);
      delay(100);
    }
  }
  if ((results.value == 2152244737) || (results.value == 2152211969) && (results.value == 2152212080) || (results.value == 2152244848)) //  Taste 1 & Taste Blau sollen NUR Rot und Gelb nach Muster 1 blinken
  { Serial.println("If taste1 + Blau");


    for (int i = 0; i < 14; i++)
    {
   //   Serial.println("for taste1 + Blau");
      analogWrite(Blau, OFF);
      analogWrite(Rot, Muster1_RotLED[i]);
      analogWrite(Gelb, Muster1_GelbLED[i]);
      delay(100);

    }
  }

  //********************************************************************************

  if ((results.value == 2152244738) || (results.value == 2152211970))                   //  Wenn taste 1 gedrückt sollen Blau, Rot, Gelb LED nach Muster 1 blinken

  {
    //    Serial.println("If taste2");
    for (int i = 0; i < 16; i++)
    {
      //    Serial.println("for taste2");
      analogWrite(Blau, Muster2_BlauLED[i]);
      analogWrite(Rot, Muster2_RotLED[i]);
      analogWrite(Gelb, Muster2_GelbLED[i]);
      delay(40);
    }
  }
  if ((results.value == 2152244738) || (results.value == 2152211970) && (results.value == 2152212080) || (results.value == 2152244848))//  Taste 2 & Taste Blau sollen NUR Rot und Gelb nach Muster 2 blinken
  {
    //    Serial.println("If taste2 + Blau");
    for (int i = 0; i < 16; i++)
    {
      //      Serial.println("for taste2 + Blau");

      analogWrite(Blau, OFF);
      analogWrite(Rot, Muster2_RotLED[i]);
      analogWrite(Gelb, Muster2_GelbLED[i]);
      delay(40);
    }
  }

  else
  {
    analogWrite(Blau, OFF);
    analogWrite(Rot, OFF);
    analogWrite(Gelb, OFF);

  }
}

Parax:
Was muss ich machen das es funktioniert?

Du musst es richtig programmieren. :wink:

Sorry, aber ich habe das nicht verstanden.

Kannst du das nicht nochmal in Form einer Tabelle aufschreiben ?
Das würde uns das sicher verdeutlichen.

Schleifen und Delay in Zusammenhang mit IR-Empfängern ist eine ganz schlechte Idee.
Du hast eine große Schleife und die heißt loop().
Deinen Ablauf habe ich auch nicht verstanden, ich vermute aber, dass Du Tasten einlesen willst, während Dein Programm in den for-Schleifen fest hängt.
Also suche nach BlinkWithoutDelay und die Nachtwächtererklärung (kein Witz) und wirf alle for und Delay raus.

Außerdem sieht es derzeit so aus, als würdest Du die LED nur auf 255 und 0 setzen wollen. Dazu brauchst Du kein analogWrite, da reicht digitalWrite.

Gruß Tommy

Hallo,
Sorry für die verspätete Antwort, war die ganze Woche auf Montage. Danke für die Info mit dem Nachtwächter, das ist ja echt super erklärt. Werde die Programmiermöglichkeit in meinen nächsten Projekten auf allenfall anwenden. Muss mir das jetzt erstmal einverleiben. Auch die Task- Macro Programmierung ist echt interessant. Ich frage mich nur warum es den Befehl delay dann überhaupt gibt, oder anders gefragt, hat " delay" denn auch Vorteile? Zurück zu meiner Hauptfrage, ich habe mal die Funktion aufgeschrieben. Im Prinzip möchte ich, unabhängig welches Muster gerade läuft, die Farben der einzelnen LED ein und abschalten.

Ich drücke : Taste 1

Muster 1 läuft durch Led Rot = ON
LED Blau = ON
LED Gelb = ON

Ich drücke : Taste 2

Muster 2 läuft durch Led Rot = ON
LED Blau = ON
LED Gelb = ON

Ich drücke : Taste Blau

Muster 2 läuft durch Led Rot = ON
LED Blau = OFF
LED Gelb = ON

Ich drücke : Taste 1

Muster 1 läuft durch Led Rot = ON
LED Blau = OFF
LED Gelb = ON

Ich drücke : Taste Rot

Muster 1 läuft durch Led Rot = OFF
LED Blau = OFF
LED Gelb = ON

Ich drücke : Taste 2

Muster 2 läuft durch LED Rot = OFF
LED Blau = OFF
LED Gelb = ON

Ich drücke : Taste Gelb

Muster 2 läuft durch Led Rot = OFF
LED Blau = OFF
LED Gelb = OFF

Ich drücke : Taste Rot

Muster 2 läuft durch LED Rot = ON
LED Blau = OFF
LED Gelb = OFF

Ich drücke : Taste Blau

Muster 2 läuft durch Led Rot = ON
LED Blau = ON
LED Gelb = OFF

Das erste Blinkmuster besteht aus 14 Zuständen der LED’ s mit einer dauer von (14*40 ms) 560 ms . Nach dieser Zeit beginnen die 14 Zustände von vorne abzulaufen. Beim zweiten Blinkmuster sind es
16 Zustände die mit einer Verweildauer von 40 ms abgearbeitet werden. Der Sketch funktioniert auch soweit einwandfrei, ich kann problemlos mit der Fernbedienung zwischen den beiden Mustern wählen. Habe den Sketch so wie er jetzt läuft nochmal bereitgestellt.

/* Dezimal codierung der Sky Fernbedienung.
    Jede Taste hat 2 Code's

    Taste 1 A = 2152244737
    Taste 1 B = 2152211969
    Taste 2 A = 2152244738
    Taste 2 B = 2152211970
    Taste Blau A = 2152212080
    Taste Blau B =2152244848
    Taste Rot A = 2152244845
    Taste Rot B = 2152212077
    Taste Gelb A= 2152212079
    Taste Gelb B = 2152244847

*/
#include <IRremote.h>

int Blau = 6;     // Blaue LED an Pin 6
int Rot = 9;      // Rote LED an Pin 9
int Gelb = 11;    // Gelbe LED an Pin 11
int IRpin = 3; // Pin fr den IR Empfaenger

IRrecv irrecv(IRpin);
decode_results results;

byte R = 255;                         
byte  B = 255;
byte  G = 255;

byte LED_OFF = 0;


byte Muster1_BlauLED[14]   =  {B, B, B, B, B, 0, 0, 0, B, 0, 0, 0, 0, 0};
byte Muster1_RotLED[14]    =  {0, 0, 0, 0, R, R, R, R, R, 0, 0, 0, R, 0};
byte Muster1_GelbLED[14]   =  {G, G, G, G, G, 0, 0, 0, G, 0, 0, 0, 0, 0};

byte Muster2_BlauLED[16]   =  {B, 0, B, 0, B, 0, B, B, B, B, B, 0, 0, 0, 0, 0};
byte Muster2_RotLED[16]    =  {R, R, R, R, R, 0, 0, 0, 0, 0, R, 0, R, 0, R, 0};
byte Muster2_GelbLED[16]   =  {G, 0, G, 0, G, 0, G, G, G, G, G, 0, 0, 0, 0, 0};

void setup()
{
  Serial.begin(9600);
  pinMode(Blau, OUTPUT);    // Setzt Pin für Linke Blaue LED als Ausgang
  pinMode(Rot, OUTPUT);    // Setzt Pin für Linke Rote LED als Ausgang
  pinMode(Gelb, OUTPUT);     // Setzt Pin für Gelbe  LED als Ausgang

  analogWrite(Blau, LED_OFF);       // erstmal alle LED aus
  analogWrite(Rot, LED_OFF);
  analogWrite(Gelb, LED_OFF);
  
  irrecv.enableIRIn();           // IR Empfaenger starten
}

void loop()
{

  if (irrecv.decode(&results))
  {
    irrecv.resume();
    Serial.println(results.value, DEC);
  }

  if ((results.value == 2152244737) || (results.value == 2152211969))      //  Wenn Taste 1 gedrückt sollen Blau, Rot, Gelb LED nach Muster 1 blinken
  {
     for (int i = 0; i < 14; i++)
    {
       analogWrite(Blau, Muster1_BlauLED[i]);
      analogWrite(Rot, Muster1_RotLED[i]);
      analogWrite(Gelb, Muster1_GelbLED[i]);
      delay(40);
    }
  }
 

 

  if ((results.value == 2152244738) || (results.value == 2152211970))                   //  Wenn Taste 2 gedrückt sollen Blau, Rot, Gelb LED nach Muster 2 blinken

  {
      for (int i = 0; i < 16; i++)
    {
      //    Serial.println("for taste2");
      analogWrite(Blau, Muster2_BlauLED[i]);
      analogWrite(Rot, Muster2_RotLED[i]);
      analogWrite(Gelb, Muster2_GelbLED[i]);
      delay(40);
    }
  }
 

  else
  {
    analogWrite(Blau, LED_OFF);
    analogWrite(Rot, LED_OFF);
    analogWrite(Gelb, LED_OFF);

  }
}

AnalogWrite / PWM nutze ich, weil mir die Power LEDs die ich ansteuern zum testen im Wohnzimmer zu Hell sind, desweiteren will ich die Helligkeit auch per Fernbedienung ändern. Aber ich muss erst mal das Problem mit der LED Auswahl in den Griff bekommen.

delay() ist ein Fluch, weil fast alle (kurzen) Beispielprogramme damit arbeiten, weil das schnell geht und es keinen Aufwand für die Schreiber bedeutet.
Dummerweise sind es gerade diese Beispiele, auf die der Anfänger zuerst stößt oder im Fall von Einsteigersets, gestoßen wird und damit natürlich erst mal denkt, das muss so sein.

Kurze delays (ein paar ms) können duchauus ihre Berechtigung haben (Entprellen von Tastern) ansonsten sollte man loop halt ungebremst laufen lassen.

Gruß Tommy

Hallo,

Deinen Themennamen “Feinschliff in den Schleifen beheben” verstehe ich nicht :confused:

Deinen Sketch würde ich in einen Logikteil und die Ausgabe aufteilen.

#include <IRremote.h>

const byte Blau = 6;     // Blaue LED an Pin 6
const byte Rot = 9;      // Rote LED an Pin 9
const byte Gelb = 11;    // Gelbe LED an Pin 11
const byte IRpin = 3; // Pin fr den IR Empfaenger

IRrecv irrecv(IRpin);
decode_results results;

const byte R = 255;
const byte  B = 255;
const byte  G = 255;

byte LED_OFF = 0;


const byte Muster1_BlauLED[14]   =  {B, B, B, B, B, 0, 0, 0, B, 0, 0, 0, 0, 0};
const byte Muster1_RotLED[14]    =  {0, 0, 0, 0, R, R, R, R, R, 0, 0, 0, R, 0};
const byte Muster1_GelbLED[14]   =  {G, G, G, G, G, 0, 0, 0, G, 0, 0, 0, 0, 0};
const byte laenge_Muster1 = sizeof(Muster1_BlauLED) / sizeof(Muster1_BlauLED[0]);

const byte Muster2_BlauLED[16]   =  {B, 0, B, 0, B, 0, B, B, B, B, B, 0, 0, 0, 0, 0};
const byte Muster2_RotLED[16]    =  {R, R, R, R, R, 0, 0, 0, 0, 0, R, 0, R, 0, R, 0};
const byte Muster2_GelbLED[16]   =  {G, 0, G, 0, G, 0, G, G, G, G, G, 0, 0, 0, 0, 0};
const byte laenge_Muster2 = sizeof(Muster2_BlauLED) / sizeof(Muster2_BlauLED[0]);

const uint32_t intervall = 40;
uint32_t aktMillis;
byte muster = 1;
bool blauEIN = true, rotEIN = true, gelbEIN = true;

void setup()
{
  Serial.begin(9600);
  pinMode(Blau, OUTPUT);    // Setzt Pin für Linke Blaue LED als Ausgang
  pinMode(Rot, OUTPUT);    // Setzt Pin für Linke Rote LED als Ausgang
  pinMode(Gelb, OUTPUT);     // Setzt Pin für Gelbe  LED als Ausgang

  analogWrite(Blau, LED_OFF);       // erstmal alle LED aus
  analogWrite(Rot, LED_OFF);
  analogWrite(Gelb, LED_OFF);

  irrecv.enableIRIn();           // IR Empfaenger starten
  Serial.println("Anfang");
  Serial.println();
}

void loop()
{
  aktMillis = millis();

  if (irrecv.decode(&results))
  {
    uint32_t taste = results.value;
    switch (taste) {    // Codes der Fernbedienung Carmp3
      case 0xFF30CF:		// Taste 1
        muster = 1;
        break;
      case 0xFF18E7:    // Taste 2
        muster = 2;
        break;
      case 0xFFA25D:    // Taste Blau
        blauEIN = !blauEIN;
        break;
      case 0xFF629D:    // Taste Rot
        rotEIN = !rotEIN;
        break;
      case 0xFFE21D:    // Taste Gelb
        gelbEIN = !gelbEIN;
        break;
    }
    Serial.print(taste, HEX);
    Serial.print("\t");
    Serial.println(muster);
    irrecv.resume();
  }
  ausgabe(muster, blauEIN, rotEIN, gelbEIN);
}

void ausgabe(byte ledmuster, bool blau, bool rot, bool gelb)
{
  static uint32_t ausgabeMillis = 0;
  static byte j = 255;
  if (aktMillis - ausgabeMillis >= intervall)
  {
    ausgabeMillis = aktMillis;
    j++;
    if (ledmuster == 1)
    {
      j = j % laenge_Muster1;
      blau ? analogWrite(Blau, Muster1_BlauLED[j]) : analogWrite(Blau, 0);
      rot ? analogWrite(Rot, Muster1_RotLED[j]) : analogWrite(Rot, 0);
      gelb ? analogWrite(Gelb, Muster1_GelbLED[j]) : analogWrite(Gelb, 0);
    }
    if (ledmuster == 2)
    {
      j = j % laenge_Muster2;
      blau ? analogWrite(Blau, Muster2_BlauLED[j]) : analogWrite(Blau, 0);
      rot ? analogWrite(Rot, Muster2_RotLED[j]) : analogWrite(Rot, 0);
      gelb ? analogWrite(Gelb, Muster2_GelbLED[j]) : analogWrite(Gelb, 0);
    }
  }
}

Wenige ms von loop Durchlauf sind in Ordnung, wenn der restliche Programmablauf nicht so schnell reagieren muss. Vorteile hat es ein paar schon. Jedoch meist falsch eingesetzt und nur zur Verdeutlichung vom Prinzip gedacht.

In einer LCD16x2 Libary ist es sinnvoll. Die Lib bleibt verhältnismäßig schlank

Ich dachte das die geschweiften Klammern an der falschen Stelle stehen und das Programm aus dem Grund nicht richtig läuft. So wie der Sketch jetzt umgeschrieben ist, da wäre ich so nie draufgekommen. Das ist schon eine ganz andere Liga da kann ich noch nicht mitspielen.
Aber vielen Dank, ich werde den gleich direkt mal ausprobieren.
Ich habe auch in den letzten Stunden meinen Sketch umgeschrieben. Mit der switch-case Variante und kein delay mehr drin. Allerdings stolpert und hängt das alles. Das erste Muster welches eigentlich alle 40 ms die Schaltzustände der LED verändern sollte, Da bleibt die LED manchmal für ca 100 ms lange dunkel . Im 2. Muster habe ich die Schaltwechsel mal auf 400 ms gesetzt aber dort auch ein nicht erhofftes Ergebnis. Mit delay(40) lief das viel kontinuierlicher ab. Woran könnte das liegen?

Hier mal der von mir umgemodelte Sketch

/* Dezimal codierung der Sky Fernbedienung.
    Jede Taste hat 2 Code's

    Taste 1 A = 2152244737
    Taste 1 B = 2152211969
    Taste 2 A = 2152244738
    Taste 2 B = 2152211970
    Taste Blau A = 2152212080
    Taste Blau B =2152244848
    Taste Rot A = 2152244845
    Taste Rot B = 2152212077
    Taste Gelb A= 2152212079
    Taste Gelb B = 2152244847
*/
#include <IRremote.h>

const byte Blau = 6;                 //Pinbelegung der LED's
const byte Rot = 10;
const byte Gelb = 11;

byte B = 255;
byte R = 255;
byte G = 255;

unsigned long previousMillis ;
const long interval = 40;               // 40 ms Verzögerung zw. den Sequenzen
int LEDStatus = 0;


int IRpin = 3; // Pin fr den IR Empfaenger

IRrecv irrecv(IRpin);
decode_results results;

void setup() {
  pinMode(Blau, OUTPUT);    // Setzt Pin für Linke Blaue LED als Ausgang
  pinMode(Rot, OUTPUT);    // Setzt Pin für Linke Rote LED als Ausgang
  pinMode(Gelb, OUTPUT);     // Setzt Pin für Gelbe  LED als Ausgang
  irrecv.enableIRIn();           // IR Empfaenger starten
}

byte LED_OFF = 0;
byte Muster1_BlauLED[14]   =  {B, 0, B, 0, B, 0, B, 0, B, 0, B, 0, B, 0};
byte Muster1_RotLED[14]    =  {R, 0, R, 0, R, 0, R, 0, R, 0, R, 0, R, 0};
byte Muster1_GelbLED[14]   =  {G, 0, G, 0, G, 0, 0, 0, G, 0, G, 0, G, 0};

byte Muster2_BlauLED[16]   =  {B, 0, B, 0, B, 0, B, 0, B, 0, B, 0, B, 0, B, 0};
byte Muster2_RotLED[16]    =  {R, 0, R, 0, R, 0, R, 0, R, 0, R, 0, R, 0, R, 0};
byte Muster2_GelbLED[16]   =  {G, 0, G, 0, G, 0, G, 0, G, 0, G, 0, G, 0, G, 0};
void loop()
{
  unsigned long currentMillis = millis();

  if (irrecv.decode(&results))
  {
    irrecv.resume(); // Das Signal empfangen
  }

  switch (results.value) // Abhaengig vom Signal in den richtigen Modus springen
  {

      void Muster1 ();

    case 2152244737:                      //Taste1
    case  2152211969:                     //Taste1

      for (int i = 0; i < 15; i++)
      {
        if (LEDStatus == LOW)
        {
          if (millis() - previousMillis >= 40) 
          {                                                 // Muster 1 wechselt alle 40 ms von LOW auf HIGH


            analogWrite(Blau, Muster1_BlauLED[i]);          // Bei allen 3 LED's
            analogWrite(Rot, Muster1_RotLED[i]);
            analogWrite(Gelb, Muster1_GelbLED[i]);
            previousMillis = millis();
          }
        }
      }
      break;


      void Muster2();

    case 2152244738:                      // Taste 2
    case 2152211970:                      // Taste 2

      for (int i = 0; i < 17; i++)
      {
        if (LEDStatus == 0)
        {
          if (millis() - previousMillis >= 400)
          {                                                // Muster 2 wechselt alle 400 ms von LOW auf HIGH
            

            analogWrite(Blau, Muster2_BlauLED[i]);         // Bei allen 3 LED's
            analogWrite(Rot, Muster2_RotLED[i]);
            analogWrite(Gelb, Muster2_GelbLED[i]);
            previousMillis = millis();
          }
        }
      }
      break;

    default:
      if (LEDStatus == 0) {           // Bei falscher oder unbekannter Taste, alle LED's aus
        if (millis() - previousMillis >= 400) {
          analogWrite(Blau, LED_OFF);                       // Bei allen 3 LED's
          analogWrite(Rot, LED_OFF);
          analogWrite(Gelb, LED_OFF);


        }
      }
  }
}

Hallo,
es hat zwar eine Zeit gedauert aber ich habe mir einmal die Mühe gemacht mein Projekt " LED Panel Sondersignalanlage" in einem kurzen You Tube Video zu präsentieren.

Besonderen Dank an "agmue "(Super!!) und die anderen Mitglieder (Tipp Nachtwächter :slight_smile:
die mir bei meinem Software Problemen geholfen haben.

Bitte gerne, danke für die Rückmeldung, ist ja toll was geworden 8)

Könntest Du bei Zeigt her eure geilen Projekte ! mit vorstellen.

Parax:
ARDUINO - Projekt "LED Panel Sondersignalanlage" im Eigenbau #Paradelix - YouTube

Das Video sieht richtig professionell aus. Eine sehr gute Projektpräsentation. Setze doch einen Link hier in den Thread, so dass Interessenten gleich den Sketch finden.

Als Tipp für weitere Projekte mit LEDs, könntest du dir Konstantstromquellen mit PWM-Eingang (z.B. MEANWELL LDD-350) anschauen. Du sparst dir dadurch den Aufbau mit Fets und Lastwiderständen. Die Helligkeitsregulierung müsstest du allerdings über den Arduino und nicht per externem PWM-Board machen.