Auf Kriegsfuss mit den millis

Ich will (muß :grin: ) mich jetzt endlich mal näher mit den millis beschäftigen.

Den sketch "Blink without Delay" hab ich ja nun halbwegs kapiert - denke ich jedenfalls... :smiley:

/* Blinken ohne "delay()"
 *
 * Schaltet eine LED, welche an einem digitalen Pin liegt ein- und aus 
 * ohne die "delay()" Funktion zu verwenden. Das heisst anderer Code 
 * kann zur gleichen Zeit ausgeführt werden ohne blockiert zu werden.
 *
 * http://playground.arduino.cc/Learning/BlinkWithoutDelay_de
 */

byte ledPin = 13;                  // LED liegt am (digitalen) Pin 13
boolean value = LOW;                  // Startwert der LED
unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 5000;    // Interval zwischen zwei Änderungen

void setup()
{
  pinMode(ledPin, OUTPUT);      // Setzt den ledPin (Pin 13) als Ausgang
}

void loop()
{
  // Code der immer laufen soll kommt hier hin.

 /* es wird kontrolliert, ob die Zeit für das Blink-Intervall schon abgelaufen ist
  * Wenn die Zeitdifferenz zwischen dem Letzten Abspeichern und der aktuellen Zeit größer 
  * als das Intervall ist, so wird die nachfolgende Funktion ausgeführt. 
  */
  if (millis() - previousMillis > interval) {
    previousMillis = millis();   // aktuelle Zeit abspeichern

    // LED Zustand wecheln.
    value = !value;

    // Wert auf den Ausgang schreiben
    digitalWrite(ledPin, value);
  }
}

Ich kann die millis aber noch nicht so recht anwenden.

Wie kann ich denn z.B. mit Frau Milli eine Schleife 5s lang immer wieder durchlaufen lassen?

Hallo,

du möchtest eine Schleifen nicht aller 5s aufrufen, sondern die Schleife soll 5s laufen bevor es weiter geht?
Dafür kannste ein while Schleife nehmen und läßt die Bedingung überprüfen.

Genau!

In dieser Zeit soll geprüft werden ob ein Ereignis mehrfach auftritt.

Hallo,

gut. Du hast das folgende schon verstanden, richtig?

if (millis() - previousMillis > interval) {
    previousMillis = millis();   // aktuelle Zeit abspeichern

dann mußte mit while() rum probieren. while(1) ist immer gültig, dass als Hinweis. Praktisch Endlosschleife.

Jetzt mußt die while Bedingung in der Klammer entsprechend ändern für dich. Also eine Variablenprüfung auf kleiner Zeit zum Bsp. Solange wäre dann die while gültig.

Also was muß grob passieren. Vor Eintritt der while mußte die aktuelle Zeit millis kennen. In der while mußte die aktuelle Zeit abfragen und mit der vor Eintritt vergleichen. Alles klar?

So?

.
.
.
  delay(5000);
  zaehler = 0;
  previousMillis = millis();   // aktuelle Zeit abspeichern
  while(millis() - previousMillis < interval)
    {
      Serial.println("im milli");
      ++zaehler;
      Serial.println(zaehler);
      delay(10);
    }
.
.
.

Die bösen delay's hab ich nur zum sichtbar machen (ser.Monitor) drin. :grin:

Scheint so als ob die millis machen was ich will...

Das kannste dann auch mit delay lösen in einer for-schleife. Das ist genauso blockierend und somit am Ziel vorbei!

void loop()
{
static bool var= false;

if(var== false)
{
lastMillis = millis();
var== true;
}

if(millis() - lastMillis < 5000)
{
tu was
}

if(blub == true) var = false;

}

Die bösen delays fliegen eh raus. Wollte nur im ser. Monitor "beobachten" was meine millis so machen. Geht sonst zu schnell.

Eine blockierende Schleife ist aber auch nicht besser als ein delay() :slight_smile:

Damit meine ich das!

 while(millis() - previousMillis < interval)
    {
      Serial.println("im milli");
      ++zaehler;
      Serial.println(zaehler);
      delay(10);
    }

Das Teil blockiert den Rest deines Programmes!

"Die bösen delay's hab ich nur zum sichtbar machen (ser.Monitor) drin."
Bau dir eine Funktion mit millis, die dir die Anzeige z,B. 1 mal je Sekunde aktualisiert

Hallo,

ich habe seine Frage so verstanden das er innerhalb 5s permanent etwas prüfen möchte. Danach soll es weitergehen.

Du hast in Deinem Code vergessen die Prüfbedingung in der while auch zu aktualisieren. Sonst wird das wieder eine Endlosschleife.

Testsketch zum rumspielen

unsigned long zaehler;
unsigned int interval = 5000;
unsigned long previousMillis;


void setup() {
  Serial.begin(9600);
  
  previousMillis = millis();   // aktuelle Zeit abspeichern
  
  while(millis() - previousMillis < interval)
    {
      zaehler++;
      Serial.print("Zähler "); Serial.print(zaehler); Serial.print('\t');
      Serial.println( (millis() - previousMillis)/1000 );  // Sekunden
      delay(10);
    }
}

void loop() {
  // put your main code here, to run repeatedly:

}

stoni99:
Wie kann ich denn z.B. mit Frau Milli eine Schleife 5s lang immer wieder durchlaufen lassen?

"Eine Schleife" ist bei mir loop und es soll fünf Sekunden etwas gemacht, beispielsweise ein Zähler incrementiert werden:

const byte ledPin = 13;
unsigned long aktMillis, altMillis, printMillis, blinkMillis, zaehler;
const unsigned int zeit = 5000;
const unsigned int printZeit = 200;
bool aktiv = true;

void setup () {
  Serial.begin(9600);
  Serial.println("Programmanfang");
  pinMode(ledPin, OUTPUT);
  aktMillis = millis();
  altMillis = aktMillis;
  Serial.print("zaehler: "); Serial.println(zaehler);
}

void loop () {
  aktMillis = millis();
  if (aktiv) {
    if (aktMillis - altMillis >= zeit) {
      aktiv = false;
    }
    zaehler++;  // Tue was für eine bestimmte Zeit
  }
  if (aktMillis - printMillis >= printZeit) {
    Serial.print("zaehler: "); Serial.println(zaehler);
    printMillis = aktMillis;
  }
  if (aktMillis - blinkMillis >= printZeit) {
    digitalWrite(ledPin, !digitalRead(ledPin));
    blinkMillis = aktMillis;
  }
}

Der Sketch ist nicht blockierend, was man an der blinkenden LED sehen kann.

Oha, erst mal danke für eure Antworten.

Bitte nicht gleich so bombardieren, ich muss mich Schritt für Schritt vortasten.

Um die millis zu verstehen und gleich anzuwenden möchte ich mir damit einen Klopfschalter zum Einschalten einer Pollerlampe bauen.
Damit es nicht zu einfach wird und ich die millis so richtig ausreizen will, soll die Pollerlampe je nach "Anzahl der Klopfzeichen in einer bestimmten Zeit" an bleiben. So der momentane Plan...

Step by step - erste Frage:

Wo blockiere ich mit dem Code? (wenn "delay(10);" raus ist)

while(millis() - previousMillis < interval)
    {
      Serial.println("im milli");
      ++zaehler;
      Serial.println(zaehler);
      delay(10);
    }

Wo blockiere ich mit dem Code?

^
Die Schleife wird nicht verlassen.
Der Rest des Codes im Loop() kommt nicht dran.

Deine Schleife blockiert den Rest des Codes.

Stimmt, ist ja 'ne Schleife die nicht verlassen wird solange Bedingung nicht erfüllt.

Es war sozusagen eine "böse milli-Schleife". :grin:

Also doch mit If. Muss ich mal mit sschultewolter's code spielen...

void loop()
{
static bool var= false;

if(var== false)
{
lastMillis = millis();
var== true;
}

if(millis() - lastMillis < 5000)
{
tu was
}

if(blub == true) var = false;

}

Aber wer ist "blub"?

stoni99:
Aber wer ist "blub"?

Der Bruder von "bla"!

Ich kenne diese Geschwister nicht... :smiley:

Hmm, Leute. Bin gefangen im milli-Sumpf. (Dort, wo ich nie hin wollte :fearful: )

"millis() - previousMillis" bleibt immer bei 0 oder 1

Die millis spinnen wohl... :grin:

Ich mach bestimmt irgend etwas blödes falsch - ich komm nicht drauf...

..
bool var = false;
.
.
.
void loop()
{

  if(var == false)
    {
      previousMillis = millis();
      var == true;
      zaehler = 0;
    }

  if(millis() - previousMillis < 5000)
    {
      value = analogRead(PIN_ANALOG_IN);
      if(value >= 100)
        {
          ++zaehler;
          Serial.print("++zaehler ");
          Serial.println(zaehler);
          if(zaehler = 5)
            {
              Serial.println("zaehler = 5");
            }
        }
      Serial.println("im milli");
      Serial.println(millis() - previousMillis);
    }
  else
    {
      var == false;
      Serial.println("5s vorbei");
      delay(2000);
    }
    delay(200);

}

Eins verstehe ich nicht...

   if(zaehler = 5)

Warum möchtest du Zähler immer wieder auf 5 setzen?
Und wofür das IF, wenn doch klar ist, dass der Ausdruck immer true wird?

Vielleicht hilft dir ja sowas beim Denken:

// nach einem Reset leuchtet die Pin 13 LED
// exakt 5 Sekunden, und geht dann aus.


class TimerAbfallVerzoegert
{
    private:
    unsigned long triggerzeit = 0;
    unsigned long intervall   = 0;
    bool activ                = false;

    public:
    void trigger(unsigned long _intervall)
    {
      intervall   =_intervall;
      triggerzeit = millis();
      activ       = true;
    }

    bool handle()
    {
      if(activ && (millis() - triggerzeit > intervall))  activ  = false;
      return activ;
    }
};

TimerAbfallVerzoegert LedTimer;


void setup() 
{
  pinMode(13,OUTPUT);
  LedTimer.trigger(5000);
}

void loop() 
{
  digitalWrite(13,LedTimer.handle());
}

Hallöle,
ich tat mich am Anfang auch mit diesen Dingen schwer. Irgendwann machte es "Klick" und heute bediene ich mehrere "Kanäle" vollkommen asynchron. Egal ob Ein- oder Ausgaben - alles mehr oder weniger "parallel und unabhängig". Versuche mal nachfolgenden Code durchzuarbeiten. Vielleicht kommt dein "Kick" mit anderen Variablen-Bezeichnungen...
Rudi

unsigned long aktuell_1; // Aktueller Millis-Wert (1) für einen Durchlauf
unsigned long zuletzt_1; // Letzter Wert für LED 1
boolean led_1;           // Status 1

unsigned long aktuell_2; // Aktueller Millis-Wert (2) für einen Durchlauf
unsigned long zuletzt_2; // Letzter Wert für LED 2
boolean led_2;           // Status 2

void setup() 
{
  pinMode( 13, OUTPUT ); // LED an Pin 13
  pinMode(  2, OUTPUT ); // LED an Pin 2
}

void loop() 
{  
  // Einmalig je Durchlauf speichern  
  // -------------------------------
  aktuell_1 = millis();
  aktuell_2 = aktuell_1;   //   Kopie für 2. "Kanal"

  // Verarbeitung 1: Blinken alle 250 mS
  // -----------------------------------
  if( aktuell_1 - zuletzt_1 > 250 )
    { 
      digitalWrite( 13, led_1 = ! led_1 );
      zuletzt_1 = aktuell_1;  //  Für nächste "Schleife 1" merken
    }
    
  // Verarbeitung 2: (z.B.) Blinken alle 5000 mS
  // -------------------------------------------
  if( aktuell_2 - zuletzt_2 > 5000 )
    {
      digitalWrite( 2, led_2 = ! led_2 );
      zuletzt_2 = aktuell_2;  //  Für nächste "Schleife 2" merken
 
      // Je nach "Status 2" andere Vorgänge bearbeiten           
      if( led_2 == true  ) { /* Starte z.B. Messvorgang              */ }
      if( led_2 == false ) { /* Beende Messvorgang (nach 5 Sekunden) */ }
    }
}