Anfänger sucht Hilfe beim Programmieren (delay / millis() )

Hallo ForumLer,
zunächst Euch allen Frohes neues Jahr!
Ich bin Anfänger in der Welt des Arduinos und der Elektrotechnik bzw. Elektronik (und hoffe, dass nun nicht 99% aller Leser die Augen verdrehen).
Ein paar Monate befasse ich mich mit Allem und habe auch das ein oder andere kleinere Projekt erfolgreich umsetzen können.
Beim aktuellen Projekt komme ich etwas ins "Schleudern" mit der Programmierung hinsichtlich der delay bzw. millis - Funktion.
Folgendes soll nach dem Start des Arduinos erreicht werden:

  • Eine LED-Leiste soll dauerhaft aufleuchten (funktioniert einwandfrei)
  • ein Soundmodul soll dauerhaft in Schleife abgespielt werden (funktioniert einwandfrei)
  • ein Motor soll alle 30 Minuten für etwa 5 Sekunden angetrieben werden

...und genau beim Letzten habe ich ein Problem. Ich bekomme den Motor dazu nach der vorgegebenen Zeit zu starten und auch zu stoppen, aber der nächste Intervall ist dann einfach nicht gegeben. Entweder der Motor läuft nur ein einziges Mal für die 5 Sekunden oder nach dem ersten lauf vergehen nicht erneut die gewünschten 30 Minuten sondern nur wenige Sekunden.

Ich habe die delay und millis Anweisungen einfach nicht richtig verstanden bzw. kann sie nicht richtig wiedergeben - kann mir hier jemand helfen, so dass ich es auch verstehe?

Lieben Dank

Roger

Die "Nachtwächter Erklärung" schon gelesen?

Mal etwas Pseudocode als Denkanstoß:

const unsigned int warten30 = 1000UL * 60 * 30;
const unsigned int warten5 = 1000UL * 60 * 5;
unsigned int letzte = 0;  
bool isAn = false; 

....
// im loop
unsigned long aktuell = millis();
if (!isAn && aktuell - letzte >= warten30) {
  isAn = true;
  letzte = aktuell;
  // Motor anschalten
}
if (isAn && aktuell - letzte >= warten5) {
  isAn = false;
  letzte = aktuell;
  // Motor ausschalten
}

Ich habe die Teile bewußt nicht erklärt bzw. optimiert, aber die Variablennamen sollten Dir beim Verständnis helfen.

Gruß Tommy

combie:
Die "Nachtwächter Erklärung" schon gelesen?

Hallo Combie,
nein - hatte ich noch nicht, aber sie gerade aufgerufen und ich lese es mir nun durch und melde mich! Vielen Dank!

Hallo,

Du kannst Dir auch gerne mein Geschreibsel mal duchlesen.

von Delay zur Methode

oder auch hier :link

Heinz

Rentner:
Hallo,

Du kannst Dir auch gerne mein Geschreibsel mal duchlesen.

von Delay zur Methode

oder auch hier :link

Heinz

Nach dem Einführen des "Nachtwächter Codes" dreht der Motor nach dem EInschalten kontinuierlich.......

combie:
Die "Nachtwächter Erklärung" schon gelesen?

Hallo Combie, hab ich gelesen - nach dem Einfügen dieses Codes schaltet der Motor nach dem Boot dauerhaft an und nicht wieder ab.

Dann wirst Du wohl etwas falsch gemacht haben. Das können wir aber nicht sehen, da Du den Code geheim hälst.
Hast Du Dir meinen Vorschlag aus #2 schon angeschaut?

Gruß Tommy

Tommy56:
Dann wirst Du wohl etwas falsch gemacht haben. Das können wir aber nicht sehen, da Du den Code geheim hälst.
Hast Du Dir meinen Vorschlag aus #2 schon angeschaut?

Gruß Tommy

Hallo Tommy, ich wollte nicht mit langweiligem Code nerven, sorry. Hier ist er:

int led = 9; // LED 
int motor = 3; // Wischermotor 
int sound = 1; // Soundmodul 
unsigned long motor_timestore; 
int motorStatus = HIGH; 
 
void setup() { 
 
pinMode(led, OUTPUT); 
pinMode(sound, OUTPUT); 
pinMode(motor, OUTPUT); 
} 
 
 
void loop() 
{ 
digitalWrite(led, HIGH); 
digitalWrite(sound, HIGH); 
if(millis() <20000) 
delay(500); 
else 
delay(15000); 
digitalWrite(sound, LOW); 
delay(5000); 
 
 
if (motorStatus == LOW) { 
if (millis() - motor_timestore> 300000 ) { //5 Minuten 
digitalWrite(motor, HIGH); 
motor_timestore = millis(); 
motorStatus = HIGH; 
} 
} else { 
if (millis() - motor_timestore> 5000) { 
digitalWrite(motor, LOW); 
motorStatus = LOW; 
} 
}}
if (millis() - motor_timestore> 5000) {
digitalWrite(motor, LOW);
motorStatus = LOW;
}

Da fehlt was. Du speicherst die aktuellen millis nicht in motor_timestore. Oben hast Du es gemacht.

if(millis() <20000)
delay(500);
else
delay(15000);
digitalWrite(sound, LOW);
delay(5000);

Da fehlen mindestens Klammern { und }.

Gruß, Jürgen

demateraliz:
Hallo Tommy, ich wollte nicht mit langweiligem Code nerven, sorry. Hier ist er:

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter oder gehe in der IDE auf Bearbeiten - Für Forum kopieren und füge es hier ein).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Außerdem formatiere bitte den Code ordentlich (+T in der IDE hilft Dir dabei).

Gruß Tommy

Tommy56:
Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder

[code] davor und [/code]

dahinter oder gehe in der IDE auf Bearbeiten - Für Forum kopieren und füge es hier ein).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Außerdem formatiere bitte den Code ordentlich (+T in der IDE hilft Dir dabei).

Gruß Tommy

Hallo Tommy,
danke für die Hilfestellung zur Übertragung des Codes zur besseren Lesbarkeit - so habe ich das gleich noch mitgelernt. Ich habe es bereits geändert - ist es jetzt so besser?

Die Codetgs sind ok, die Formatierung / Einrückung noch nicht.

Gruß Tommy

Katsumi_S:

if (millis() - motor_timestore> 5000) {

digitalWrite(motor, LOW);
motorStatus = LOW;
}




Da fehlt was. Du speicherst die aktuellen millis nicht in motor_timestore. Oben hast Du es gemacht.



if(millis() <20000)
delay(500);
else
delay(15000);
digitalWrite(sound, LOW);
delay(5000);




Da fehlen mindestens Klammern { und }.

Gruß, Jürgen

Hallo Jürgen, danke für die Info - hab ich übersehen. Auch nach dem Einfügen startet der Motor direkt nach dem Einschalten und dreht kontinuierlich.....

Katsumi_S:

if (millis() - motor_timestore> 5000) {

digitalWrite(motor, LOW);
motorStatus = LOW;
}




Da fehlt was. Du speicherst die aktuellen millis nicht in motor_timestore. Oben hast Du es gemacht.



if(millis() <20000)
delay(500);
else
delay(15000);
digitalWrite(sound, LOW);
delay(5000);




Da fehlen mindestens Klammern { und }.

Gruß, Jürgen

Hallo Jürgen...... es funktioniert DOCH! Ich hatte nur die Werte (Zeiten) verändert. VIELEN VIELEN Dank für die Hilfe! Der Motor startet zwar für 5 Sekunden nach dem Arduino Start - aber das ist mir völlig egal! Nach mehrmaligem Durchlesen hab ich es jetzt auch verstanden.
Jetzt würde ich am Liebsten das Ganze um ein LCD-Display erweitern, welches mir in Form eines Countdowns anzeigt, wann der Motor das nächste Mal schalten wird. Ist das realisierbar?
Roger

Hallo demateraliz,

das lässt sich realizizen. Dann musste aber konsequent auf die Verwendung von millis() umsteigen
und alle delays() weglassen.

Das ist doch immer das gleiche mit ziemlich komplexem Code mit der Tür ins Haus fallen anstatt mit einem Alltags-Analogon einzusteigen

Dieser Text ist im Original english. Den habe ich ganz auf die Schnelle in google-translate reingeklatscht

als ganztägiges Beispiel mit leicht zu verfolgenden Zahlen
delay () blockiert. Solange die Verzögerung "verzögert", kann nichts anderes des Codes ausgeführt werden.

Jetzt gibt es eine Technik zum nicht blockierenden Timing.
Das Grundprinzip des nicht blockierenden Timings unterscheidet sich grundlegend von der Verwendung von delay ()
Sie müssen zuerst den Unterschied verstehen und dann in den Code schauen.
Andernfalls könnten Sie versuchen, ein "Delay-Analog-Ding" im millis () - Code zu "sehen", was es wirklich nicht ist

Der Versuch, ein "Delay-Analog-Ding" in millis () zu sehen, macht es schwierig, millis () zu verstehen.
Wenn Sie das Grundprinzip des nicht blockierenden Timings auf der Basis von millis () verstanden haben, ist es leicht zu verstehen.

Stellen Sie sich vor, Sie backen eine gefrostete Pizza
Auf dem Deckel steht für die Zubereitung der Ofen auf 200 ° C aufheizen
dann Pizza hineinlegen.
Backzeit 10 Minuten

Sie schätzen, dass das Aufheizen 3 Minuten dauert
Sie werfen einen Blick auf Ihre Uhr, es ist 13:02 Uhr (Momentaufnahme der Zeit)
Sie lesen die Zeitung und schauen von Zeit zu Zeit auf Ihre Uhr
schau 13:02 noch nicht aufgeheizt
schau 13:03 noch nicht aufgeheizt
Uhr 13:04 noch nicht Zeit 13:04 - 13:02 = 2 Minuten sind weniger als 3 Minuten
Uhr 13:05 Wann habe ich 13:02 angefangen? OK 13:05 - 13:02 = 3 Minuten Zeit, um Pizza in den Ofen zu geben

Neue Basiszeit 13:05 (die Momentaufnahme der Zeit)
schau 13:06 noch nicht fertig
schau 13:07 noch nicht fertig
Uhr 13:08 noch keine Zeit (13:08 - 13:05 = 3 Minuten sind weniger als 10 Minuten
schau 13:09 noch nicht fertig
Uhr 13:10 noch nicht Zeit
Uhr 13:11 noch nicht Zeit
Uhr 13:12 noch nicht fertig
Uhr 13:13 noch keine Zeit
Uhr 13:14 noch keine Zeit (13:14 - 13:05 = 9 Minuten sind weniger als 10 Minuten
schau 13:15 wann habe ich angefangen 13:05 OK 13:15 - 13:05 = 10 Minuten Zeit um Pizza zu essen (yum yum)

Sie haben wiederholt verglichen, wie viel Zeit vergangen ist
Dies ist, was nicht blockierendes Timing tut

Im Code wird nach "Wie viel Zeit ist vergangen" gesucht

currentTime - startTime> = Backzeit

Die Backzeit beträgt 10 Minuten

13:06 - 13:05 = 1 Minute> = Backzeit ergibt false
13:07 - 13:05 = 2 Minuten> = Backzeit ergibt false
...
13:14 - 13:05 = 9 Minuten> = Backzeit ergibt false
13:15 - 13:05 = 10 Minuten> = Backzeit ergibt true Zeit für zeitgesteuerte Aktionen !!

if (currentTime - previousTime> = period) {

es muss genau so codiert werden, weil es auf diese Weise den Rollover von Max zurück auf Null verwaltet
der Funktion millis () automatisch

hier das original auf English

as an allday example with easy to follow numbers 
delay() is blocking. As long as the delay is "delaying" nothing else of the code can be executed.
Now there is a technique of non-blocking timing.
The basic principle of non-blocking timing is fundamental different from using delay()
You have to understand the difference first and then look into the code.
otherwise you might try to "see" a "delay-analog-thing" in the millis()-code which it really isn't 
Trying to see a "delay-analog-thing" in millis() makes it hard to understand millis()
Having understood the basic principle of non-blocking timing based on millis() makes it easy to understand.

imagine baking a frosted pizza 
the cover says for preparation heat up oven to 200°C
then put pizza in. 
Baking time 10 minutes

You are estimating heating up needs 3 minutes
You take a look onto your watch it is 13:02  (snapshot of time)
You start reading the newspaper and from time to time looking onto your watch
watch 13:02  not yet time
watch 13:03  not yet time     
watch 13:04  not yet time    13:04 - 13:02 = 2 minutes is less than 3 minutes
watch 13:05   when did I start 13:02?  OK 13:05 - 13:02 = 3 minutes time to put pizza into the oven

New basetime 13:05 (the snapshot of time)
watch 13:06  not yet time
watch 13:07  not yet time
watch 13:08  not yet time     (13:08 - 13:05 = 3 minutes is less than 10 minutes
watch 13:09  not yet time
watch 13:10  not yet time
watch 13:11  not yet time
watch 13:12  not yet time
watch 13:13  not yet time 
watch 13:14  not yet time   (13:14 - 13:05 = 9 minutes is less than 10 minutes
watch 13:15  when did I start 13:05  OK 13:15 - 13:05 = 10 minutes time to eat pizza (yum yum)

You did a repeated comparing how much time has passed by
This is what non-blocking timing does

In the code looking at "How much time has passed by" is done

currentTime - startTime >= bakingTime

bakingTime is 10 minutes

13:06  - 13:05 = 1 minute     >= bakingTime      is false
13:07  - 13:05 = 2 minutes    >= bakingTime      is false
...
13:14  - 13:05 = 9 minutes    >= bakingTime      is false
13:15  - 13:05 = 10 minutes    >= bakingTime     is TRUE   time for timed action!!

if (currentTime - previousTime >= period) {

it has to be coded exactly this way because in this way it manages the rollover from Max back to zero 
of the function millis() automatically

vgs

Passt! Läuft jetzt alles - vielen Dank Euch allen!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.