[gelöst] millis() sketch

Ich habe jetzt verstanden wie es mit millis() funktioniert, aber leider blicke ich nicht so richtig durch wie ich das mache, wenn ich mehrere LED habe, die dürfen aber nicht gleichzeitig leuchten. Heißt z.B. rote LED an, 3 Sekunden warten, aus. dann grün an 2 Sekunden warten und aus. der Spaß geht dann wieder von vorne los. Ich habe mal mein bisherigen sketch angehängt. Wo muss ich den Hebel ansetzen für die grüne wenn die rote aus geht?

int rot = 6;
int gruen = 10;
unsigned long letzte = 0;       //  letzte zeit
const long intervalrot = 3000;  //  interval
const long intervalgruen = 2000;

int my = 0;
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  unsigned long aktuelle = millis();
  if (aktuelle - letzte > intervalrot) {   // so lange aktuelle millis() - letzte groesser ist
    letzte = aktuelle;
    if (my == 0) {
      my = 255;
    }
    else {
      my = 0;
    }
    if (my == 0) {
      analogWrite(rot, 255);
    }
    else {
      analogWrite(rot, 0);
    }

  }
}

Eine Ablaufsteuerung bauen. Eine Schrittkette. Einen einfachen endlichen Automaten.

OK hilft mir leider nicht weiter

matze12: Wo muss ich den Hebel ansetzen für die grüne wenn die rote aus geht?

Wenn ich mir einen „endlichen Automaten“ baue, benutze ich so gut wie immer switch/state. Wenn unterschiedliche Dinge zu unterschiedlichen Zeitpunkten passieren sollen, ist das für mich der verständlichste und am besten wartbare Konstrukt. Irgendwie verknotete (verschränkte) if()-Orgien sind mir zu unübersichtlich. Wie ich vorgehe, habe ich hier zusammengetippt.

HTH

Gregor

Hallo die LEDs in einem array organisieren.

matze12: OK hilft mir leider nicht weiter

Was würde dir denn helfen?

@gregorss Ja das beispiel sieht schon mal vielversprechend aus. "case" bedeutet bestimmt eine Funktion, die nach und nach abgearbeitet werden.

“case” bedeutet bestimmt eine Funktion,

Nein, das ist ein Teil einer Anweisung.

Siehe: switch/case

Hallo hier kommt eine Sketch in dem die o.g. arrays eingefügt worden sind zum Testen.

int rot =  6;
int gruen = 10;
unsigned long letzte = 0;       //  letzte zeit
const long intervalrot = 3000;  //  interval
const long intervalgruen = 2000;
int my = 0;
// Zwei arrays für die LEDs und für die Wartezeit 
int led[] = {rot, gruen};
unsigned long interval[] = {intervalrot, intervalgruen};

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(rot, OUTPUT);
  pinMode(gruen, OUTPUT);
}
void loop() {
  static int farbe; //  und einen Zähler für die Farbe 
  unsigned long aktuelle = millis();
  if (aktuelle - letzte > interval[farbe]) {   // so lange aktuelle millis() - letzte groesser ist
    letzte = aktuelle;
    analogWrite(led[farbe], 255);
    farbe = (farbe + 1) % 2;
    analogWrite(led[farbe], 0);
  }
}

Wenn die LED´s unabhängig blinken sollem, dann muss ein zweiter Zeitgeber programmiert werden.

Ich habe eine Aufgabe: Sage mir, was Du in Deinem Sketch mit der OnBoard LED vorhast.

Und was findest in folgendem Sketch: (nicht raten)

const int rot = 6;
const int gruen = 10;
unsigned long lastmillis = 0;
const unsigned long intervalrot = 3000;  //  interval
const unsigned long intervalgruen = 2000;
const unsigned long pause = 1000;
int state;
enum {rotan, nachrotaus, gruenan, nachgruenaus};

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start..."));
  digitalWrite(rot, LOW);
  digitalWrite(gruen, LOW);
  digitalWrite(LED_BUILTIN, LOW);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(rot, OUTPUT);
  pinMode(gruen, OUTPUT);
  state = rotan;
}

void loop()
{
  switch (state)
  {
    case rotan:
      digitalWrite(rot, HIGH);
      if (millis() - lastmillis > intervalrot)
      {
        state = nachrotaus;
        lastmillis = millis();
        Serial.println(F("Next: rot aus"));
      }
      break;
    case nachrotaus:
      digitalWrite(rot, LOW);
      if (millis() - lastmillis > pause)
      {
        state = gruenan;
        lastmillis = millis();
        Serial.println(F("Next: gruen"));
      }
      break;
    case gruenan:
      digitalWrite(gruen, HIGH);
      if (millis() - lastmillis > intervalgruen)
      {
        state = nachgruenaus;
        lastmillis = millis();
        Serial.println(F("Next: gruen aus"));
      }
      break;
    case nachgruenaus:
      digitalWrite(gruen, LOW);
      if (millis() - lastmillis > pause)
      {
        state = rotan;
        lastmillis = millis();
        Serial.println(F("Next: rot"));
      }
      break;
  }

  // Blinklicht mit interner LED
  if (digitalRead(gruen) || digitalRead(rot)) // Variante 1 
  //  if (state == gruenan || state == rotan)    // Variante 2
  {
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else
  {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

matze12: @gregorss Ja das beispiel sieht schon mal vielversprechend aus. "case" bedeutet bestimmt eine Funktion, die nach und nach abgearbeitet werden.

Das ist eine Kontrollstruktur, die mit if() vergleichbar ist - eine Fallunterscheidung. Mir fällt eine Denke leichter, in der ich mir vorstelle, dass zu bestimmten Zeitpunkten etwas Bestimmtes passieren soll. Es gibt eine geniale „Nachtwächter-Erklärung“, die auf meiner Seite verlinkt ist. Guck mal irgendwo unten auf der Seite, da gibt's was zum Klicken.

Gruß

Gregor

Ihr machts euch ja dolle kompliziert!
:o :o :o :o :o

#include <TaskMacro.h>

const byte ledRot   = A0;
const byte ledGruen = A1;
const unsigned long intervalRot   = 3000;  
const unsigned long intervalGruen = 2000;

Task beispiel()
{
  taskBegin();
  pinMode(ledRot,OUTPUT);
  pinMode(ledGruen,OUTPUT);
  
  while(1)
  {
    digitalWrite(ledRot,1);
    taskPause(intervalRot);
    digitalWrite(ledRot,0);
    digitalWrite(ledGruen,1);
    taskPause(intervalGruen);
    digitalWrite(ledGruen,0);
  }
  taskEnd();
}

void setup(){}

void loop() 
{
  beispiel();
}

TaskMacro.zip (8.31 KB)

Vielen dank.
Aber wenn ich schleifen einbaue funktioniert das mit den millis() bestimmt nicht, weil es ja warten muss, bis die schleife durchlaufen ist oder?

matze12: Vielen dank. Aber wenn ich schleifen einbaue funktioniert das mit den millis() bestimmt nicht, weil es ja warten muss, bis die schleife durchlaufen ist oder?

Du meinst meine while(1) Schleife?

Dazu kann ich sagen: Die TaskMacro Lib hat als Vorbild die Protothreads des Herren Adam Dunkels. Und bei dem Verfahren werden die Schleifen sehr wohl unterbrochen.

Eigentlich wie bei allem, was sich Multitasking nennt. Denn alle diese Systeme basieren genau auf solchen Endlosschleifen. Auf dem Wege ist es kein Problem (bei der nötigen Sorgfalt) Dutzende solcher Schleifen im System zu haben. Alle diese laufen "nebeneinander".

OK vielen dank.

matze12:
OK vielen dank.

Und, wie sieht deine Lösung jetzt aus?

Ich komme mit dem Beispiel im Post #11 sehr gut zurecht.
Vielen dank.

Aber bei einer “for schleife” funktioniert das ganze noch nicht. Wenn ich folgenden Abschnitt einfüge tut sich nichts.

.
.
.
while(1)
  {
    for(int i=0; i<255; i++){
    analogWrite(rot, i);
    taskPause(300);
    }
    analogWrite(rot,0);
.
.
.

Aber bei einer "for schleife" funktioniert das ganze noch nicht.

Doch, bei einer zählenden Schleife tuts das auch! Dazu muss int i static gemacht werden und am schönsten vor taskBegin() definiert werden. In den Beispielen wird das auch gezeigt. z.B. der Piepser im Ampel Beispiel und Blink5Mal.

Einzig bei der "range based for loop" funktioniert das nicht, da dort die Schleife den Iterator verbirgt.

OK hat geklappt. Vielen dank.
Jetzt läuft es so wie es soll.

Fein!