Arduino ohne delay und millis

Gast #5238200
Lesenswert?

Hallo

um Timerfunktionen z.b für ein Blinken, in der Arduino Umgebung 
(Software) zu nutzen gibt es die delay Funktion, mit allen ihren 
Problemen wenn das Programm ein wenig mehr machen soll.
Das ist selbst den Arduinoentwicklern klar und deshalb gibt es auch eine 
Funktion millis, auf die ich aber auch gerne verzichten würde.
Wieso, weshalb, warum steht nicht zu Diskussion, und zwar bezüglich 
meines Wunsch auf Verzicht als auch (!) warum ich die Arduino 
Entwicklungsumgebung nutze obwohl ich teilweise Hardware nah arbeiten 
möchte - Glaubenskrieger und Missionare können sich woanders austoben 
-Danke.

Jetzt findet Google zwar 1001 Tutorials zu "Arduino without delay" aber 
bei "Arduino without delay and millis" und Ähnliches erhalte ich keine 
brauchbaren Treffer sondern letztendlich die gleichen Tutorials, Fragen, 
Hinweise... wie bei der reinen "... without delay..." Suche.
Deutschsprachige Suche bringt eher noch weniger.

Ich möchte aber in der Arduinoumgebung (und nicht in reinen C, 
Assembler...)  Hardwarenah den ATMega328 bezüglich den Timer (sowohl 
"Timer" in der Bedeutung beim µC als auch wie sie im Allgemeinen 
Sprachgebrauch verwendet wird)verstehen und nutzen.

Dafür gibt es doch mit hoher Wahrscheinlichkeit schon Tutorials - nur 
ich finde diese nicht da die gefühlt Millionen Tutorials zum Ersatz der 
Delay Funktion das Auffinden unmöglich machen.

Wer kann helfen (Link, genialer Suchbegriff, eigene Worte...)?

Ardu Ino
Gast #5238207
Lesenswert?

Wie ist denn die Blink-Frequenz?

Im Idealfall gibt es in der Loop() kein einzigen Aufruf der eine 
Wartezeit verursacht.

Sodas die Loop() mit einer sehr hohen Frequenz durchlaufen ist.

Um ein Blinken ohne Nutzung einer Delay-Funktion zu erzeugen, muss du in 
der Loop die vergangene Zeit messen.
Ist die gewünschte Zeit (z.B. 0,5 Sekunden) abgelaufen, schaltest du den 
Ausgang um und startest eine neue Zeitmessung, so bekommst du eine 
Blinkfrequenz von z.B. 1Hz
Gast #5238212
Lesenswert?

> Wer kann helfen (Link, genialer Suchbegriff, eigene Worte...)?

Suchbegriff: "pferd von hinten aufzäumen". Verabschiede Dich von der 
Arduinolaufzeitarchitektur oder von genauen Timings. In ersterem Falle: 
Herzlichen Glückwunsch, als nächstes bitte das Datenplatt zum 
Mikrocontroller lesen und verstehen.
Gast #5238215
Lesenswert?

Ardu Ino schrieb:
> ... obwohl ich teilweise Hardware nah arbeiten möchte

Es hindert dich keiner daran, eigene Funktionen für hardwarenahen 
Anwendungen zu verwenden.

> ... und deshalb gibt es auch eine Funktion millis, auf die ich
> aber auch gerne verzichten würde.

Selber schuld - warum?

> -Danke.

Bitte

Ardu Ino schrieb:
> Wer kann helfen (Link, genialer Suchbegriff, eigene Worte...)?

Geniale Suchbegriffe wären z.B. "Timer" und "Interrupt".
Wenn du dem Timer-Interrupt, der hinter millis() steht, nicht traust, 
setze doch einen eigenen Timer auf. Die Registerbezeichnungen stehen im 
Datenblatt und sind auch in der Arduino IDE verfügbar.

Wenn du das nicht kannst/möchtest nutze die Arduino Umgebnung oder lese 
dir   Grundlagen an, z.B.
https://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts

Wasch mir den Pelz, aber mach mich nicht nass funktioniert hier nicht, 
wenn Copy&Paste schon an elementaren Suchbegriffen scheitert
Gast #5238221
Lesenswert?

Ardu Ino schrieb:
> Ich möchte aber in der Arduinoumgebung (und nicht in reinen C,
> Assembler...)  Hardwarenah den ATMega328 bezüglich den Timer (sowohl
> "Timer" in der Bedeutung beim µC als auch wie sie im Allgemeinen
> Sprachgebrauch verwendet wird)verstehen und nutzen.

Schreibe deine Funktion

int main (void)
{
.....
}

in deiner Arduino IDE und vermeide die Implementierungen

Setup();

und

Loop();

Damit bist du Herr über alles ohne auch nur eine Mikrosekunde
deines Controllers hergeschenkt zu haben. Und alle Hardware,
auch die Timer, ist/sind frei verfügbar.
Gast #5238230
Lesenswert?

Ardu Ino schrieb:
> Ich möchte aber in der Arduinoumgebung (und nicht in reinen C,
> Assembler...)  Hardwarenah den ATMega328 bezüglich den Timer (sowohl
> "Timer" in der Bedeutung beim µC als auch wie sie im Allgemeinen
> Sprachgebrauch verwendet wird)verstehen und nutzen.

Schon mal drüber nachgedacht, das Datenblatt zu studieren? Da steht 
alles drin, was man so wissen muss.
#5238258
Lesenswert?

Hallo,

auch in der Arduino-IDE niemand hindert Dich niemand eigene 
Timerinterrups einzubauen.

https://github.com/esp8266/Arduino/blob/master/libraries/Ticker/Ticker.h
ist möglicher Weg.

Das stammt aus einer Scrollroutine eines meiner Displays:
1
#include <Ticker.h>       // Bibliothek einbinden
2

3
Ticker scroll_display;    // Instanz anmelden 
4

5
int scrollpos = 0;        // aktuelle Scrollposition
6
int scrolltime  = 250;    // Zeit in ms zwischen den Scrollschritten
7

8

9
void scrollen()           // Scrollroutine die vom Ticker-Interrupt aufgerufen wird 
10
{
11
  scrollpos++;
12
  if (disp_buf[scrollpos] == 0)                    // Stringende   
13
  {
14
    scrollpos = 0;
15
  }
16

17
  int aktpos = scrollpos;
18
  
19
  for (int i = 0; i < 16; i++)
20
  {
21
    if (disp_buf[aktpos] == 0)                    // Stringende   
22
    {
23
      aktpos = 0;                                 // von vorne      
24
    }
25
    displayWriteChar(i, disp_buf[aktpos]);
26
    aktpos++;
27
  }
28
}

Im loop dann eben mit
  scroll_display.attach_ms(scrolltime, scrollen);

und mit
  scroll_display.detach();
ausschalten.

Gruß aus Berlin
Michael
Gast #5238271
Lesenswert?

Ich verstehe das Problem nicht. Warum sollte auf millis() verzichtet 
werden? Das ist doch einfach zu benutzen und man kann überprüfen ob eine 
Zeit schon abgelaufen ist.

Was ist das Problem mit millis() ?
Gast #5238273
Lesenswert?

> Was ist das Problem mit millis() ?

Verstehe ich auch nicht. Jedes PC Betriebssystem hat das, jedes 
Smartphone und ARM Kerne haben dazu sogar einen extra Timer integriert.

Wie willst du sonst Zeiten messen? Etwa mit Kondensatoren?
#5238274
Lesenswert?

@Ardu Ino (Gast)

>Jetzt findet Google zwar 1001 Tutorials zu "Arduino without delay" aber
>bei "Arduino without delay and millis" und Ähnliches erhalte ich keine
>brauchbaren Treffer sondern letztendlich die gleichen Tutorials, Fragen,
>Hinweise... wie bei der reinen "... without delay..." Suche.
>Deutschsprachige Suche bringt eher noch weniger.

Dann suchst du falsch.

>Ich möchte aber in der Arduinoumgebung (und nicht in reinen C,
>Assembler...)  Hardwarenah den ATMega328 bezüglich den Timer (sowohl
>"Timer" in der Bedeutung beim µC als auch wie sie im Allgemeinen
>Sprachgebrauch verwendet wird)verstehen und nutzen.

Das ist leicht, denn Arduino ist nicht sooo isoliert wie manche meinen. 
Es ist "nur" eine Sammlung von Bibliotheken, die man nutzen KANNN (und 
meist auch sollte), der Rest des AVRs ist aber genauso verfügbar und 
zugreifbar wie in reinem C ohne Arduino.

>Dafür gibt es doch mit hoher Wahrscheinlichkeit schon Tutorials

Jaja, die ganze Welt als Tutorial. Nerd 2.0

>ich finde diese nicht da die gefühlt Millionen Tutorials zum Ersatz der
>Delay Funktion das Auffinden unmöglich machen.

Ich schon. Siehe Multitasking.

Einen Interrupt kann man beim Arduino genauso leicht nutzen wie ohne.

Beitrag "Re: Arduino Nano, SD Card, PCM"
Moderator (Firma: Titel) Persönliche Seite #5238283
Lesenswert?

millis() ist genau das, was der TO braucht, unabhängig davon, was er 
will. Den millis() arbeitet ja mit einem Timer und dessen Interrupt.
Ich vermute sehr, der TO weiß nur nicht, wie man diese Funktion am 
besten einsetzt und zyklisch mit Zustandsautomaten programmiert 
(Stichwort Mainloop).
Und deshalb versucht er, seinen Schopf über ein Programm, das direkt im 
Timerinterrupt läuft, aus der Schlinge zu ziehen.
Dass er sich damit ganz andere Probleme an die Backe klebt, weiß er 
allerdings auch nicht (Stichworte Semaphorenproblem und Racecondition).
#5238285
Lesenswert?

Ardu Ino schrieb:
> Ich möchte aber in der Arduinoumgebung (und nicht in reinen C,
> Assembler...)  Hardwarenah den ATMega328 bezüglich den Timer (sowohl
> "Timer" in der Bedeutung beim µC als auch wie sie im Allgemeinen
> Sprachgebrauch verwendet wird)verstehen und nutzen.

tue es doch

ich kam vom nackten Atmel AVR mit AVR Studio 4.18 zum Arduino, nutze 
eigene C-Module die ich einbinde als *.ino als auch LIBs der Arduinio 
wahlweise nach Bedarf.

Mich stört weder setup(), noch loop() auch nicht millis() oder eigene 
Timerinterrupts, alles kooperiert nach meinen Wunsch und wenn mal nicht 
schaue ich wo ich ändern muss, z.B. mal einen anderen Timer wählen.
Gast #5238295
Lesenswert?

zur erhellung ohne delay ...

#ifndef PERIODIC_H
#define PERIODIC_H

//usage:
//  PERIODIC(100) //{
//    digitalWrite(PIN, HIGH/LOW)
//  }

//create an unique name from given parameter and line number
#define UNIQUE(name) __CONCAT(name,__LINE__)

//creates an unique timer for each instance, ms period in milli-seconds
#define WAITBLOCK(ms)                                     \
  static uint32_t UNIQUE(timer) = millis();               \
  if (millis() - UNIQUE(timer) >= ms) {

//creates an unique timer for each instance, ms period in milli-seconds
#define PERIODIC(ms)                                      \
  static uint32_t UNIQUE(timer) = millis();                \
  if (millis() - UNIQUE(timer) >= ms) {                   \
    UNIQUE(timer) = millis();

//XPERIODIC(ms,1) = WAITBLOCK but takes more program code space!
//XPERIODIC(ms,0) = PERIODIC
//creates an unique timer for each instance, x: repeats 0-255, 0=endless
#define XPERIODIC(ms, x)                                  \
  static uint32_t UNIQUE(timer) = millis();               \
  static uint8_t UNIQUE(xRepeats) = x;                    \
  static uint8_t UNIQUE(lock);                            \
  if (millis() - UNIQUE(timer) >= ms) {                   \
    if (!UNIQUE(lock)) {                                  \
      if ((UNIQUE(xRepeats)==0) || (--UNIQUE(xRepeats)))  \
        UNIQUE(timer) = millis();                         \
      else UNIQUE(lock)=1;                                \
    }

#endif //PERIODIC_H
#5238296
Lesenswert?

@Lothar Miller (lkmiller) (Moderator) Benutzerseite

>millis() ist genau das, was der TO braucht,

Nein, denn diese Funktion liefert nur einen Timerwert, welche in einem 
1ms Timer-Interrupt hochgezählt wird. Die nützt rein gar nichts, wenn 
andere Funktionen, warum auch immer, den Programmablauf längere Zeit 
"blockieren".

> unabhängig davon, was er
>will. Den millis() arbeitet ja mit einem Timer und dessen Interrupt.

Dort kommt man aber so direkt nicht ran, sprich, man kann sich NICHT in 
den 1ms Timer einklinken! Dazu müßte es eine Funktion geben, die der 
Anwender erstellen kann, welche dann vom Arduino-Framework im 1ms 
Interrupt aufgerufen wird. So etwas gibt es nicht, u.a. weil es dem 
Konzept der Vereinfachung deutlich widerspricht.

>Ich vermute sehr, der TO weiß nur nicht, wie man diese Funktion am
>besten einsetzt und zyklisch mit Zustandsautomaten programmiert
>(Stichwort Mainloop).

Das ist nur ein Würg-Around mit begrenzter Leistung. Siehe oben.

>Und deshalb versucht er, seinen Schopf über ein Programm, das direkt im
>Timerinterrupt läuft, aus der Schlinge zu ziehen.

Genau DAS ist aber die Lösung der allermeisten Probleme dieser Art!
Außerdem hat der OP ganz sicher sehr wenig Plan von AVRs und Interrupts, 
denn ich wette 1 Kasten Bier, daß er für seine Drehgeberauswertung die 
rudimentäre Interrupt-Funktionalität des Arduinos nutzt.

https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

>Dass er sich damit ganz andere Probleme an die Backe klebt, weiß er
>allerdings auch nicht (Stichworte Semaphorenproblem und Racecondition).

Jaja, und schon wieder sind am Sonntag Morgen die Reichsbdenkenträger 
voll dabei, die Welt zur retten. ODer zumindest viel Staub aufzuwirblen! 
:-(

Siehe Anhang!!!
Angehängte Dateien:
Gast #5238317
Lesenswert?

>> millis() ist genau das, was der TO braucht,

> Nein, denn diese Funktion liefert nur einen Timerwert, welche in einem
> 1ms Timer-Interrupt hochgezählt wird. Die nützt rein gar nichts, wenn
> andere Funktionen, warum auch immer, den Programmablauf längere Zeit
> "blockieren".


Die millis() Funktion ist ideal, um innerhalb eines Zustandsautomaten 
Aktionen zu einem bestimmten Zeitpunkt auszuführen. Das Abwarten einer 
Zeitspanne zählt auch dazu.

> wenn andere Funktionen... den Programmablauf längere Zeit "blockieren".

Das ist in vernünftigen Multi-Task fähigen Anwendungen ohnehin nicht 
zulässig. Größere Aktionen müssen ggf. in kleinere zerlegt werden.

Zustandsautomaten ist das Stichwort zum lernen, sobald man die Grenzen 
von delay() und anderen blockierenden Aktionen erkannt hat.
#5238523
Lesenswert?

@Stefan Us (stefanus)

>>> millis() ist genau das, was der TO braucht,

>> Nein, denn diese Funktion liefert nur einen Timerwert, welche in einem
>> 1ms Timer-Interrupt hochgezählt wird. Die nützt rein gar nichts, wenn
>> andere Funktionen, warum auch immer, den Programmablauf längere Zeit
>> "blockieren".


>Die millis() Funktion ist ideal, um innerhalb eines Zustandsautomaten
>Aktionen zu einem bestimmten Zeitpunkt auszuführen. Das Abwarten einer
>Zeitspanne zählt auch dazu.

FALSCH! Auch du hast das Problem NICHT verstanden!

>> wenn andere Funktionen... den Programmablauf längere Zeit "blockieren".

>Das ist in vernünftigen Multi-Task fähigen Anwendungen ohnehin nicht
>zulässig. Größere Aktionen müssen ggf. in kleinere zerlegt werden.

Jaja, soweit die Theorie. Dumm nur, daß das selbt für Profis bisweilen 
nicht möglich ist, weil bestimmte Funktionen bzw. Bibliotheksfunktionen 
schlicht länger dauern und nicht teilbar sind.

Hier geht es um das gleiche Problem. Und besonders dort ist millis() 
fehl am Platz. Der schelle, zeitkritische Kram gehört in die Timer-ISR, 
der langsame LCD-Kram in die Hauptschleife.

Beitrag ""Interrupt" durch Vergleich von Variablen möglich? Timingprobleme durch zu lange Programmlaufzeit"

>Zustandsautomaten ist das Stichwort zum lernen, sobald man die Grenzen
>von delay() und anderen blockierenden Aktionen erkannt hat.

Eben dafür braucht es KEINE gottverdammte millis() Funktion, die nur ein 
Arduino-Würg-Around ist! Denn in den allermeisten Fällen will man 
diverse State Machines mit einer definierten, konstanten Frequenz 
aufrufen, damit ergibt sich das Timing von allein und diverse 
Verzögerungen werden in den FSMs per Zustand und Zähler gemacht. Un komm 
mir jetzt nicht mit der 101 Ausnahme, welche die Regel bestätigt!
Gast #5238531
Lesenswert?

> millis() Funktion, die nur ein Arduino-Würg-Around ist!

Dann schau Dir mal Java an, oder Windows, oder Linux, oder Android, oder 
ARM Kerne. Die haben alle einen Millisekunden-Zähler mit mehr oder 
weniger ähnlichem Namen.

> weil bestimmte Funktionen bzw. Bibliotheksfunktionen
> schlicht länger dauern und nicht teilbar sind

Diese Funktionen würde ich als Designfehler bezeichnen. Mit einem OS das 
aktiv Threads unterbricht könnte man sie verwenden, aber auf µC wären 
sie fehl am Platz.

Blockierende Warteschleifen dürfen meiner Meinung nach nur wenige Nano-
 bis Mikrosekunden dauern.
#5238537
Lesenswert?

@ Stefan Us (stefanus)

>> millis() Funktion, die nur ein Arduino-Würg-Around ist!

>Dann schau Dir mal Java an, oder Windows, oder Linux, oder Android, oder
>ARM Kerne. Die haben alle einen Millisekunden-Zähler mit mehr oder
>weniger ähnlichem Namen.

Du Nase! Wer hat denn die Existenz dieser Sache abgestritten?
Es ging um die Frage, wie man sinnvoller, bzw. optimalerweise ein 
minimales Multitasking auf einem uC gestaltet. Und schau dir mal 
diverse Java-Anwendungen an, dann weißt du, warum die Mist sind 
(Performance, was ist das?) Ob das an den schlechten Konzepten der 
mittelmäßigen Programmierer und dernen millis() Funktion liegt?
#5238540
Lesenswert?

@Stefan Us (stefanus)

>
>> weil bestimmte Funktionen bzw. Bibliotheksfunktionen
>> schlicht länger dauern und nicht teilbar sind

>Diese Funktionen würde ich als Designfehler bezeichnen. Mit einem OS das
>aktiv Threads unterbricht könnte man sie verwenden, aber auf µC wären
>sie fehl am Platz.

Schon wieder Unsinn. Heute nicht dein Tag, oder?

Beispiel. Das VORZÜGLICHE FATfs vom Meister Elm Chan aus dem fernen 
Osten hat diverse Funktion, die halt mal länger und mal kürzer dauern. 
Willst du daraus schließen, daß dFATfs Mist ist? NEIN! Denn wenn man 
damit was performantes auf die Beine stellen will, muss man halt "nur" 
wissen wie das geht. Mein schon mehrfach zitierter DMX Rekorder macht 
das mit 22kB/s. Totz daß diverse FATfs Funktionen eher Millisekunden 
brauchen.
Gast #5238541
Lesenswert?

Wie kann denn etwas ein Arduino-Würg-Around sein, was in praktisch allen 
anderen Programmiersprachen und Betriebssystemen ebenso vorhanden ist?

> in den allermeisten Fällen will man diverse State Machines
> mit einer definierten, konstanten Frequenz aufrufen

Ich kenne das als eine mögliche Lösung.

Ich habe aber schon wesentlich mehr State Machines gesehen, deren 
hauptschleife einfach nur schnellstmöglich ausgeführt wird. Unter 
anderem in Arduino, µC Projekte die auf LwIp und µIP basieren (somit 
auch ESP8266), fast alle meine eigenen µC Projekte, zahlreiche Windows 
Programme, die Event-Loop vom QT Framework, ...

Vielleicht beginnst du mal zu akzeptieren, dass viele Wege zum Ziel 
führen und deiner nicht der einzig richtige ist.
Gast #5238574
Lesenswert?

In Sachen millis() und delay(), bin ich schon fast eine Fachkraft.
Zumindest eine eingewiesene Person, mit fundiertem Halbwissen.


Die Hierarchie des ArduinoZeitHändlings:

Einfache Dinge ruhig mit delay().
Solange, bis es einem auf die Füße fällt....

Dann das BlinkWithoutDelay Konzept anwenden.
Damit kann man eigentlich alles erschlagen.
Ja, wenn es einen nicht stört, dass dauernd millis() aufgerufen und 
verglichen wird.


Wird dann schlußendlich ein exaktes Timing gebraucht, kann man  ja noch 
immer die HardwareTimer zur Hilfe nehmen. Ein UNO hat 3 davon, wobei 
Timer0 vom Core belegt wird.
Da ist man dann an dem Punkt, wo es ohne Datenblatt nicht weiter geht.


----

Auch gibt es die Chance den Arduino Core abzuändern.
In dessen Timer0 ISR eine Weak Funktion rein zu klemmen ist eine 
Kleinigkeit von 3 oder 4 Zeilen.
Dieser Interrupt kommt alle, ca. 1ms. Er ist nicht ganz exakt. Damit 
millis() korrekt läuft wird da im Core noch rumkorrigiert.
Gast #5238632
Lesenswert?

Ich kopier's mal raus:
1
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
2
// the overflow handler is called every 256 ticks.
3
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
4

5
// the whole number of milliseconds per timer0 overflow
6
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
7

8
// the fractional number of milliseconds per timer0 overflow. we shift right
9
// by three to fit these numbers into a byte. (for the clock speeds we care
10
// about - 8 and 16 MHz - this doesn't lose precision.)
11
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
12
#define FRACT_MAX (1000 >> 3)
13

14
volatile unsigned long timer0_overflow_count = 0;
15
volatile unsigned long timer0_millis = 0;
16
static unsigned char timer0_fract = 0;
17

18
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
19
ISR(TIM0_OVF_vect)
20
#else
21
ISR(TIMER0_OVF_vect)
22
#endif
23
{
24
  // copy these to local variables so they can be stored in registers
25
  // (volatile variables must be read from memory on every access)
26
  unsigned long m = timer0_millis;
27
  unsigned char f = timer0_fract;
28

29
  m += MILLIS_INC;
30
  f += FRACT_INC;
31
  if (f >= FRACT_MAX) {
32
    f -= FRACT_MAX;
33
    m += 1;
34
  }
35

36
  timer0_fract = f;
37
  timer0_millis = m;
38
  timer0_overflow_count++;
39
}
40

41
unsigned long millis()
42
{
43
  unsigned long m;
44
  uint8_t oldSREG = SREG;
45

46
  // disable interrupts while we read timer0_millis or we might get an
47
  // inconsistent value (e.g. in the middle of a write to timer0_millis)
48
  cli();
49
  m = timer0_millis;
50
  SREG = oldSREG;
51

52
  return m;
53
}
Beitrag #5238637 wurde von einem Moderator gelöscht.
Moderator (Firma: Titel) Persönliche Seite #5238669
Lesenswert?

Falk B. schrieb:
> @Lothar Miller (lkmiller) (Moderator) Benutzerseite
>> millis() ist genau das, was der TO braucht,
> Nein, denn diese Funktion liefert nur einen Timerwert, welche in einem
> 1ms Timer-Interrupt hochgezählt wird.
Das reicht für übliche zeitliche Abläufe völlig aus.

> Die nützt rein gar nichts, wenn andere Funktionen, warum auch immer,
> den Programmablauf längere Zeit "blockieren".
Dann haben wir das Problem ja schon erkannt: der Programmablauf der 
Hauptschleife darf schlicht und einfach nicht blockiert werden. Das 
wars. Wenn man sich daran hält, dann kann man ganz einfach wartbare und 
erweiterbare und vor allem portierbare Programme schreiben.

Die wichtigste (Überwachungs-)Funktion meiner Hauptschleife ist der 
Abschnitt, wo die minimale, maximale und durchschnittliche Zykluszeit 
berechnet wird. Und wenn ein durch die Anwendung bestimmter Grenzwert 
der maximalen Zykluszeit überschritten wird, dann habe ich gerade eben 
einen Fehler reinprogrammiert.

Merke: der am einfachsten erkennbare Programmierfehler ist ein 
delay_ms().

Falk B. schrieb:
> Das VORZÜGLICHE FATfs vom Meister Elm Chan aus dem fernen Osten hat
> diverse Funktion, die halt mal länger und mal kürzer dauern. Willst du
> daraus schließen, daß dFATfs Mist ist?
Doch. Genau das ist es: wenn es mir wegen irgendwelcher Warterei auf 
irgendwelche Hardware das Timing verhagelt, dann ist das Murks.
Und ich muss dann auf die eine oder andere Art einen Workaroud drumrum 
basteln.

Falk B. schrieb:
>> Dass er sich damit ganz andere Probleme an die Backe klebt, weiß er
>>>allerdings auch nicht (Stichworte Semaphorenproblem und Racecondition).
> Jaja, und schon wieder sind am Sonntag Morgen die Reichsbdenkenträger
> voll dabei, die Welt zur retten. ODer zumindest viel Staub aufzuwirblen!
Falk, du lenkst ab. Hier schlagen doch laufend Anfänger auf, die sich 
wundern, warum ihre volatile Variable, die im Interrupt und im 
Huptprogramm verwendet wird, ab&zu "spinnt".
Und ich kenne einige Fälle, wo Anfänger um genau solche Fälle dann mit 
"Dreifach-Abfragen mit anschließendem Vergleich" übel um genau dieses 
Semaphoren-Problem herumflicken.
Denn das ist nichts, was einem Angst machen soll, sondern man muss es 
einfach wissen um daraus entstehende Probleme zu vermeiden. So wie du es 
weißt und auf diese Art Probleme vermeidest.

Falk B. schrieb:
> Du Nase!
Falk, könntest du bitte die Antworten OHNE solche absolut vollkommen 
unnötigen persönlichen Angriffe und Beleidigungen schreiben? Den Rest 
meiner Antwort spare ich mir!
#5239214
Lesenswert?

@Stefan Us (stefanus)

>Wie kann denn etwas ein Arduino-Würg-Around sein, was in praktisch allen
>anderen Programmiersprachen und Betriebssystemen ebenso vorhanden ist?

Falsch! Du verwechselst die Verfügbarkeit einer Methode mit deren 
optimalem Einsatz.

>> in den allermeisten Fällen will man diverse State Machines
>> mit einer definierten, konstanten Frequenz aufrufen

>Ich kenne das als eine mögliche Lösung.

Na immerhin.

>Ich habe aber schon wesentlich mehr State Machines gesehen, deren
>hauptschleife einfach nur schnellstmöglich ausgeführt wird. Unter
>anderem in Arduino,

WOW! Was für eine Referenz! Vor allem was die Performance angeht!

> µC Projekte die auf LwIp und µIP basieren (somit
>auch ESP8266),

Hmm.

>fast alle meine eigenen µC Projekte,

Naja.

> zahlreiche Windows
>Programme, die Event-Loop vom QT Framework, ...

Sinngemäßes Zitat von Bertrand Russel

"Nur weil eine Meinung von der Mehrheit vertreten wird, ist kein Beweis, 
daß es nicht vollkommener Unsinn ist."

Mein letztes Plädoyer zum Thema.

Man KANN mit einer Funktion ala millis() diverse Statemachine betreiben, 
die ggf. auch nur so schnell wie möglich oder auch langsamer aufgerufen 
werden. Für einige Anwendungen ist das ausreichend.

Manchmal MUSS man es machen, weil es nicht besser geht und ggf. mit den 
daraus folgenden Einschränkungen leben.

ABER!!!!!

Wenn möglich, versucht man bei einer Problemlösung von vorn herein 
erstmal KEINE Kompromisse zu schließen und eine schnelle, 
leistungsfähige Lösung anzustreben. Das bedeutet hier, eine Statemachine 
mittels Timer oder gar ISR im festen Zeitraster aufzurufen, ohne 
sonstige Kompromisse. Und genau DAS will und braucht der OP!!! OK, es 
war der andere Thread, die Diskussion ist aber praktisch die Gleiche, 
weil das grundlegende Problem das Gleiche ist!

Beitrag ""Interrupt" durch Vergleich von Variablen möglich? Timingprobleme durch zu lange Programmlaufzeit"

>Vielleicht beginnst du mal zu akzeptieren, dass viele Wege zum Ziel
>führen und deiner nicht der einzig richtige ist.

Das habe ich nie behauptet. Siehe oben.
#5239228
Lesenswert?

@ Lothar Miller (lkmiller) (Moderator)

>>> millis() ist genau das, was der TO braucht,
>> Nein, denn diese Funktion liefert nur einen Timerwert, welche in einem
>> 1ms Timer-Interrupt hochgezählt wird.
>Das reicht für übliche zeitliche Abläufe völlig aus.

Nö. Definiere mal "übliche zeitliche Abläufe".

>> Die nützt rein gar nichts, wenn andere Funktionen, warum auch immer,
>> den Programmablauf längere Zeit "blockieren".

>Dann haben wir das Problem ja schon erkannt: der Programmablauf der
>Hauptschleife darf schlicht und einfach nicht blockiert werden. Das
>wars. Wenn man sich daran hält, dann kann man ganz einfach wartbare und
>erweiterbare und vor allem portierbare Programme schreiben.

Bla! Auch das ist, wie bereits geschrieben, in einigen Fällen nicht 
möglich, vor allem bei Einsatz von Fremdsoftware oder Bibliotheken.

>> Das VORZÜGLICHE FATfs vom Meister Elm Chan aus dem fernen Osten hat
>> diverse Funktion, die halt mal länger und mal kürzer dauern. Willst du
>> daraus schließen, daß dFATfs Mist ist?

>Doch. Genau das ist es: wenn es mir wegen irgendwelcher Warterei auf
>irgendwelche Hardware das Timing verhagelt, dann ist das Murks.

Pure Arroganz und Ignoranz! Beschäftige dich mal mit der Software, dann 
kannst du ggf. einen fundierten Kommentar abgeben!

>Und ich muss dann auf die eine oder andere Art einen Workaroud drumrum
>basteln.

Jain. Eine vergleichbare Software, die beliebig multitaskingfähig ist, 
braucht entweder ein echtes, prääemtives Multitasking oder einen 
deutlich anderen Softwareansatz. Beides ist ziemlich aufwändig. Der 
Kompromiss der bestehenden Lösung ist IMO optimal.

Natürlich muss man des Öfteren Kompromisse und manchmal auch Workarounds 
machen. Die Frage ist aber, ob man ohne Not gleich damit anfängt. Und 
meine Antwort darauf ist: NEIN!

Falk B. schrieb:
>> Dass er sich damit ganz andere Probleme an die Backe klebt, weiß er
>>>allerdings auch nicht (Stichworte Semaphorenproblem und Racecondition).
> Jaja, und schon wieder sind am Sonntag Morgen die Reichsbdenkenträger
> voll dabei, die Welt zur retten. ODer zumindest viel Staub aufzuwirblen!

>Falk, du lenkst ab. Hier schlagen doch laufend Anfänger auf, die sich
>wundern, warum ihre volatile Variable, die im Interrupt und im
>Huptprogramm verwendet wird, ab&zu "spinnt".

Ja und? Das Problem ist mit einem volatile lösbar. Und die Grundlagen 
dazu sind im Artikel Interrupt zu finden.

>Und ich kenne einige Fälle, wo Anfänger um genau solche Fälle dann mit
>"Dreifach-Abfragen mit anschließendem Vergleich" übel um genau dieses
>Semaphoren-Problem herumflicken.

Auch das ist ein lösbares Problem. millis() macht es nicht wirklich 
besser. Du willst nicht die Stützräder am Fahrrad abschrauben sondern 
bunt anmalen. Das klingt sehr fürsorglich, entmündigt aber nur.

>> Du Nase!
>Falk, könntest du bitte die Antworten OHNE solche absolut vollkommen
>unnötigen persönlichen Angriffe und Beleidigungen schreiben?

Nö, manchmal geht es einfach nicht anders.

> Den Rest meiner Antwort spare ich mir!

Ist auch besser so, moralinsaure Gardinenpredigten sind sowieso sinnlos, 
in meinem Alter erst recht ;-)
Gast #5239230
Lesenswert?

Hallo

danke für die diversen Links und auch für die sich entwickelnde 
Diskussion die meist interessant und teilweise sogar hilfreich für mich 
ist.

Aber bitte: Es handelt sich um ein Technisches Thema - da sollte eine 
vernünftige Diskussionskultur doch möglich sein?
Das sich hier einige Leute herumtreiben die erkennbar richtig viel 
Wissen und Erfahrung in anspruchsvollen Technischen Bereichen haben, 
aber gleichzeitig wie ein Holligan oder ein 18 jähriger besoffener am 
Samstagmorgen um 4:00Uhr in der Partymeile einer Großstadt 
"argumentieren" ist nur noch als beschämend zu bezeichnen.

Mensch Leute, seid Nett zueinander, akzeptiert andere Meinungen, 
Vorgehensweisen und das nicht alle genauso viel fachlich Wissen wie man 
selbst.

Ardu Ino
#5239320
Lesenswert?

Ardu Ino schrieb:
> deshalb gibt es auch eine
> Funktion millis, auf die ich aber auch gerne verzichten würde.
> Wieso, weshalb, warum steht nicht zu Diskussion

Sollte es aber.
"millis" gibt Dir nur einen Zeitstempel zurück, ist also überhaupt nicht 
böse. Es gibt daher keinen Grund darauf verzichten zu wollen. Der 
Unterschied, ob man CPU-Leistung verschwendet oder nicht, liegt allein 
an Dir, wie Du "millis" anwendest.

Eine bequeme Lösung für parallele Tasks mit verschiedenen Verzögerungen 
kann dann ein Scheduler sein, der z.B. in 1ms oder 10ms Schritten 
aufgerufen wird:
Beitrag "Wartezeiten effektiv (Scheduler)"
#5239370
Lesenswert?

@Matthias Melcher (Firma: privat) (quadraturencoder)

>Ich verstehe den Aufruhr nicht. Hat doch bei Heise alles schon mal
>gestanden. Man nimmt einen Timer Interrupt und gut:

Na wenn das bei heise steht, MUSS es ja die reine Wahrheit sein ;-)

Naja, die Begründung, warum ein delay() schlecht ist, ist aber auch eher 
schlecht 8-0

Daß dabei die CPU steht und zum Nichtstun verdonnert wird, kommt dort 
nicht wirklich rüber! Außerdem ist die Ungenauigkeit der Funktion das 
kleinste der Probleme, mal ganz davon abgesehen, daß sie gar nicht so 
ungenau ist, sondern mit einer Auflösung und Genauigkeit von wenigen 
CPU-Takten arbeitet. Naja, das übliche IT-Fastfood von heute . . .
Gast #5239387
Lesenswert?

Falk B. schrieb:
> @Matthias Melcher (Firma: privat) (quadraturencoder)
>
>>Ich verstehe den Aufruhr nicht. Hat doch bei Heise alles schon mal
>>gestanden. Man nimmt einen Timer Interrupt und gut:
>
> Na wenn das bei heise steht, MUSS es ja die reine Wahrheit sein ;-)

Auch wenn das gleiche bei Falk B. steht? ;-)

Falk B. schrieb:
> Das bedeutet hier, eine Statemachine
> mittels Timer oder gar ISR im festen Zeitraster aufzurufen, ohne
> sonstige Kompromisse. Und genau DAS will und braucht der OP!!!

Warum machst du dich jetzt über heise lustig, obwohl dort die gleiche 
Meinung vertreten wird, wie du sie vertrittst?
Gast #5239437
Lesenswert?

Falk B. schrieb:
> mal ganz davon abgesehen, daß sie gar nicht so
> ungenau ist, sondern mit einer Auflösung und Genauigkeit von wenigen
> CPU-Takten arbeitet. Naja, das übliche IT-Fastfood von heute . . .

...aber (fast) jedes µC-Programm arbeitet auch mit Interrupts. Und diese 
Interrupts unterbrechen logischerweise auch ein delay(). Damit (und das 
ist eigentlich der Normalfall) wird das delay() auf jeden Fall nicht 
mit der Genauigkeit von wenigen CPU-Takten arbeiten!
#5239446
Lesenswert?

@Krull (Gast)

>> mal ganz davon abgesehen, daß sie gar nicht so
>> ungenau ist, sondern mit einer Auflösung und Genauigkeit von wenigen
>> CPU-Takten arbeitet. Naja, das übliche IT-Fastfood von heute . . .

>...aber (fast) jedes µC-Programm arbeitet auch mit Interrupts.

Viele. Die Arduino-Welt nahezu ohne, vom "unsichtbaren" 1ms Timer mal 
abgesehen.

>Und diese
>Interrupts unterbrechen logischerweise auch ein delay(). Damit (und das
>ist eigentlich der Normalfall) wird das delay() auf jeden Fall nicht
>mit der Genauigkeit von wenigen CPU-Takten arbeiten!

Nö, du konstruierst schon wieder eine Sachlage, die so gar nicht 
existiert. So nach dem Motto, wenn ich ein 10m Maßband nur zu Hälft 
ausrolle, kann ich keine 10m messen. ;-)

Wer des Lesens und vor allem des sinnerfassenden Lesens mächtig ist, 
wird in der Doku davor gewarnt. Und dann kann man mit delay() recht 
genaue Zeiten erreichen, z.B. einfache Pulsgeneratoren. Für einige 
Anwendungen ist das OK, wenn die CPU so oder so nix besseres zu tun hat. 
In vielen Fällen hat sie das aber.
Gast #5239626
Lesenswert?

Falk B. schrieb:
> Nö, du konstruierst schon wieder eine Sachlage, die so gar nicht
> existiert. So nach dem Motto, wenn ich ein 10m Maßband nur zu Hälft
> ausrolle, kann ich keine 10m messen. ;-)

Und wenn ich mein Maßband in 1µm kleine Teile schneide, kann ich sogar 
sehr genau messen ;-)
Ich frage mich, wer hier etwas konstruiert, nur damit er recht behält.

Willst du allen ernstes behaupten, daß ein delay(), wenn es tausendmal 
durch einen Interrupt unterbrochen wird, der selbst ja logischerweise 
auch Zeit braucht, dann genauso lang ist wie ein delay(), was ganz 
allein und ungestört läuft? Ein delay() weiß doch nicht, wie lange ein 
Interrupt dauert, oder? Vor allem, weil ja innerhalb der isr noch 
Verzweigungen auftreten können, die auch von externen Ereignissen 
bestimmt werden können...
#5239642
Lesenswert?

@Krull (Gast)

>Willst du allen ernstes behaupten, daß ein delay(), wenn es tausendmal
>durch einen Interrupt unterbrochen wird, der selbst ja logischerweise
>auch Zeit braucht, dann genauso lang ist wie ein delay(), was ganz
>allein und ungestört läuft?

Keine Sekunde, nicht mal delay(1) ;-)

Mein Gott, willst du mich nicht verstehen oder kannst du mich nicht 
verstehen oder willst du nur schwätzen um des Schwätzens willen?

>Ein delay() weiß doch nicht, wie lange ein
>Interrupt dauert, oder?

Jaja, also doch nur Schwätzen!

>Vor allem, weil ja innerhalb der isr noch
>Verzweigungen auftreten können, die auch von externen Ereignissen
>bestimmt werden können...

BlaBlaBla!
#5239648
Lesenswert?

Krull schrieb:
> Ein delay() weiß doch nicht, wie lange ein
> Interrupt dauert, oder? Vor allem, weil ja innerhalb der isr noch
> Verzweigungen auftreten können, die auch von externen Ereignissen
> bestimmt werden können...
Bitte "Non-blocking Virtual Delay" anschauen - es wird ein Vergleich mit 
dem internen 1ms-Timer gemacht  --  der Fehler der dabei entsteht ist .. 
1ms  --  was häufig ausreichen sollte. Wie lang andere Abläufe dauern 
ist dabei nicht wichtig.
#5239663
Lesenswert?

@ Jens Grabner (jensg)

>Bitte "Non-blocking Virtual Delay" anschauen

Hab ich gemacht.

>- es wird ein Vergleich mit
>dem internen 1ms-Timer gemacht

Stimmt.

>  --  der Fehler der dabei entsteht ist ..
>1ms

Stimmt nicht!

> --  was häufig ausreichen sollte.

Dito!

> Wie lang andere Abläufe dauern ist dabei nicht wichtig.

Falsch! Es wird nur festgestellt, ob die vorgegebene Wartezeit erreicht 
wurde oder nicht. Ob die um 1, 10, oder 1.000.000 ms überschritten wurde 
wird weder geprüft, noch gemeldet noch könnte man was dagegen tun! 
Zumindest nicht direkt. Denn wenn die anderen Abläufe zu lange brauchen, 
erfolgt die Prüfung und damit ggf. die Reaktion auch zu spät. Und wenn 
man dann periodisch den virtuellen Timer wieder starten will, 
akkumuliert sich der Fehler! Ganz toll!

Mal ganz abgesehen davon, daß auch die Beispiele dort Mist sind. So 
lernt niemand eine gescheite Programmierung und Struktur von Programmen, 
sondern nur den allgegenwärtigen Arduino-Murks.

Ergo. Gute Tutorials fallen nicht vom Himmel und sind eher rar.
Gast #5239698
Lesenswert?

Falk B. schrieb:
> @ Jens Grabner (jensg)
>
>>Bitte "Non-blocking Virtual Delay" anschauen
>
> Hab ich gemacht.

Ich auch....

Selbst wenn ich ähnliche Verfahren anwende, muss ich sagen, dass das 
Tutorial/Code nicht schön ist.

z.B. static in Makros.
Darauf reagiere ich mittlerweile recht allergisch.
Das kann die Wiederverwendung von Funktionen und Klassen/Objekten derbe 
einschränken.
Gast #5239706
Lesenswert?

Könntest du bitte mal meine Fragen beantworten?
Deine drei letzten "Antworten" sind dafür nicht geeignet.

Ich frage dich, ob ein delay, das durch Interrupts ständig unterbrochen 
wird, genauso lang ist ist, wie ein "ungestörtes" delay?
Und du antwortest darauf:
> "keine Sekunde" ---???

Ich frage dich, ob ein delay weiß, wie lange Interrupts brauchen?
Deine Antwort:
> Jaja, also doch nur Schwätzen! --???

Ich stelle fest, daß innerhalb der isr noch Verzweigungen auftreten 
können und damit die Ausführungsdauer einer isr nicht bestimmbar ist.
Deine Antwort:
> BlaBlaBla!

Also bitte gib mir jetzt die richtigen Antworten, ja?
#5239712
Lesenswert?

Falk Brunner -- Besten dank für die genaue Beschreibung -- ein 
RealTimeOS oder auch nur ein Sytem zur Zeitsteuerung ist für viele 
"Anfänger" einfach schon eine Hürde  --  Arduino ist auf der anderen 
Seite auch nie für professionelle Dinge gedacht gewesen -- weshalb hier 
sehr heftig unterschiedliche Denkmuster zusammenlaufen.

aber gut -- delay() und die Beispiele dazu hätten "nie" Standard werden 
dürfen -- ohne delay() vermeidet man viele Probleme.
#5239723
Lesenswert?

@Jens Grabner (jensg)

>RealTimeOS oder auch nur ein Sytem zur Zeitsteuerung ist für viele
>"Anfänger" einfach schon eine Hürde

Sicher.

>--  Arduino ist auf der anderen
>Seite auch nie für professionelle Dinge gedacht gewesen -- weshalb hier
>sehr heftig unterschiedliche Denkmuster zusammenlaufen.

Mag sein.

>aber gut -- delay() und die Beispiele dazu hätten "nie" Standard werden
>dürfen -- ohne delay() vermeidet man viele Probleme.

Mag auch sein. delay() hat schon seine Berechtigung, sei es für 
einfach(ste) Arduino-Sachen oder wo es halt unkritisch ist. Ebenso die 
Funktion millis() und deren Anwendung. Man sollte aber dennoch in einer 
vernünftigen, anschaulichen Art und Weise zeigen, wie man es besser 
machen kann, wenn es denn nötig ist. Nicht mehr und nicht weniger wollte 
ich sagen.
Gast #5239724
Lesenswert?

Jens G. schrieb:
> delay() und die Beispiele dazu hätten "nie" Standard werden
> dürfen

Schwachsinn!

Ein delay() ist leicht zu verstehen, und tut genau das, wofür es 
vorgesehen ist.

Außerdem kan man während eines delay() noch tausend andere feine Dinge 
tun, nur nicht das delay() vorzeitig abbrechen.
Gast #5239736
Lesenswert?

Vielleicht habe ich ja auch Aussagen oder Anforderungen überlesen:

Aus Prinzip alles in eine isr zu packen ist sicher kurzsichtig und blöd. 
Falk B. sprach vom Drehgeber. Klar Stich gemacht, aber man weiß doch gar 
nicht, WAS der TO eigentlich machen will. Ein Dogma erarbeiten ist da 
nun auch nicht zielführend.

Eine Statemachine die millis() benutzt hat von mir auch quasi jedes 
Programm. Zugegebenermaßen neben härteren Echtzeit-Geschichten. Wenn ich 
alle 10s einen Feuchtigkeitswert angucken will, mache ich da keinen 
Timer für, sondern vergleiche mit der Systemzeit.

Mit delay_ms() operieren zu wollen ist an sich (fast) immer unklug. ich 
sage fast, weil man damit auch ein Programm schreiben kann, welches gut 
damit funktionieren kann wenn man das im Vorfeld weiß.

Werkzeug zum Problem wählen.
Gast #5239830
Lesenswert?

@Falk:
Könntest du bitte mal meine Fragen beantworten?
Deine drei letzten "Antworten" sind dafür nicht geeignet.

Ich frage dich, ob ein delay, das durch Interrupts ständig unterbrochen
wird, genauso lang ist ist, wie ein "ungestörtes" delay?
Und du antwortest darauf:
> "keine Sekunde" ---???

Ich frage dich, ob ein delay weiß, wie lange Interrupts brauchen?
Deine Antwort:
> Jaja, also doch nur Schwätzen! --???

Ich stelle fest, daß innerhalb der isr noch Verzweigungen auftreten
können und damit die Ausführungsdauer einer isr nicht bestimmbar ist.
Deine Antwort:
> BlaBlaBla! ---???

Also bitte gib mir jetzt die richtigen Antworten, ja?
Gast #5239853
Lesenswert?

Arduino F. schrieb:
> Krull schrieb:
>> Ich frage dich, ob ein delay, das durch Interrupts ständig unterbrochen
>> wird, genauso lang ist ist, wie ein "ungestörtes" delay?
>> Und du antwortest darauf:
>
> Ein bisschen verspannt heute?
>
> Weißt du es wirklich nicht, oder willst du nur Streit?

Ich suche absolut keinen Streit. Ich habe dem Falk ein paar Fragen 
gestellt. Seine "Antworten" kannst du selbst lesen.

Aber vielleicht kannst du mir die Fragen beantworten? Falk will es 
offensichtlich nicht.
#5239855
Lesenswert?

Wichtig ist zu erkennen ob Delay das Projekt nun "zerstört" oder 
hinreichend ist. Im ersteren Falle muss man einen einfachen Workaround 
schaffen, da brauch man nicht diskutieren und lange Sinnlos Schwafeln.

Wenn Du alles unbedingt mit einem Timer umsetzen möchtest, geht das 
auch..

Die Frage ist nur, reichen Deine Fähigkeiten dazu aus das ohne 
Delay/Millis zu machen oder nicht.

Millis ist schonmal ein guter Ansatz das Delay zu umgehen.. das ist 
mehrschichtig auch nicht "Super einfach" und verlangt auch schon Grips. 
(Bei einem siehts einafch aus.. mach mal nen BlinkWithoutDelay mit 3 
LEDS, und 3 IF/FOR)

Wenn man das mit Millis kann braucht es nur noch eine 
Timerinitialisierung und ein "Suchen/ersetzen" um es auf einen Timer 
umzumünzen.
Gast #5239862
Lesenswert?

Krull schrieb:
> Aber vielleicht kannst du mir die Fragen beantworten?

Sicher!

Es liegt ganz an der Implementierung!

1: Das AVR Lib (util/delay.h) Delay wird von jedem ISR Ereignis 
verlängert.


2: Bein Arduino delay() verlängert, schlimmstenfalls, die letzte ISR die 
Pause.

Jetzt alle Klarheiten beseitigt?
Gast #5239880
Lesenswert?

Arduino F. schrieb:
> Krull schrieb:
>> Aber vielleicht kannst du mir die Fragen beantworten?
>
> Sicher!
>
> Es liegt ganz an der Implementierung!
>
> 1: Das AVR Lib (util/delay.h) Delay wird von jedem ISR Ereignis
> verlängert.
>
> 2: Bein Arduino delay() verlängert, schlimmstenfalls, die letzte ISR die
> Pause.
>
> Jetzt alle Klarheiten beseitigt?

Alle noch nicht, aber damit kann ich auf jeden Fall wesentlich mehr 
anfangen als mit der "Gesprächskultur" von Falk.
Danke dir dafür.
Der erste Punkt (AVR-Delay) war mir bekannt, deshalb habe ich dem Falk 
die Fragen gestellt.
Der zweite Punkt ist mir neu. Da werde ich mich mal damit 
auseinandersetzen und versuchen den Grund herauszufinden, warum nur die 
letzte ISR das Delay verlängert. Allein daß das so ist, wußte ich nicht.
Das ist aber (meiner Meinung nach) kein Grund für Falk, mir nur mit 
"blabla" zu antworten. Ist er so abgehoben, daß er sich nicht vorstellen 
kann, daß es noch Leute gibt, die weniger wissen als er? Ich für meinen 
Teil finde das einfach arrogant. Sorry :-(

Auf jeden Fall danke ich dir für deine Antworten :-)
Gast #5239901
Lesenswert?

Krull schrieb:
> arrogant

Ich halte es für recht schwierig, Arroganz und Kompetenz auseinander zu 
halten, wenn ich die Person nicht kenne.

Auch kommen soziale und fachliche Kompetenz nicht immer in Personalunion 
vor.

PS:
Auch du zeigst hier ein irritierendes Verhalten.
(ein mich irritierendes)
Gast #5239911
Lesenswert?

Arduino F. schrieb:
> Krull schrieb:
>> arrogant
>
> Ich halte es für recht schwierig, Arroganz und Kompetenz auseinander zu
> halten, wenn ich die Person nicht kenne.
>
> Auch kommen soziale und fachliche Kompetenz nicht immer in Personalunion
> vor.

Das mag ja sein, aber wenn ich kompetent bin, gibt mir das nicht das 
Recht, jemandes Frage einfach mit "blabla" zu beantworten. Das ist dann 
der Punkt, wo sich die fachliche Kompetenz von der sozialen Kompetenz 
gründlich verabschiedet hat. Tut mir auch leid für Falk. Ich hoffe, er 
hatte nur einen "schlechten Tag" und ist nicht immer so :-)
Gast #5239914
Lesenswert?

BlaBla schrieb:
> Liegt wohl heute am Wetter. Ich hoffe es sind keine Psychopathen
> oder/und Soziopathen unter uns.

Da mache dir mal keine zu großen Hoffnungen.

Meiner Schätzung nach tragen ca 2% der Weltbevölkerung eine neurotische 
Fehlanpassung mit sich rum.

Ob die sich hier rudeln, ka, manchmal kommt es mir so vor.
Gast #5239942
Lesenswert?

Krull schrieb:
> Kommt es nicht so häufig vor, daß man Antworten einfordert, wenn man
> Fragen gestellt hat?

Z.B.:
Wenn in Fragen schon die gewünschte Antwort vorgegeben wird, empfinde 
ich das als provokant.
Als unangenehm.

Oft wird sowas (unbewusst?) als subtile Methode genutzt, um eine 
Eskalationsspirale zu starten, oder zu fördern.

Und das ist etwas, woran ich nur selten Spaß habe.
Gast #5239994
Lesenswert?

Arduino F. schrieb:
> 2: Bein Arduino delay() verlängert, schlimmstenfalls, die letzte ISR die
> Pause.

Das würde ich etwas relativieren.

Das Arduino-Delay (ms) basiert auf den "Standard-Millis". Wenn da 
mehrere Interrupts hintereinander kommen (incl. der Millis ...) dann 
wartet das Arduino-Delay diese alle ab (soweit mein Verständnis). Wenn 
ein Spassvogel die "Millis" deaktiviert, dann gibt es gar ein St. 
Nimmerlein-delay.

Das (Arduino-Delay (µs) ) arbeitet mit "NOP" und kann gleichfalls 
beliebig durch ISR unterbrochen und verzögert werden.
Gast #5240005
Lesenswert?

Das halte ich für einen konstruierten Sonderfall.

Wenn die ISR so dicht aufeinander folgen, dass noch nicht mal ein 
delay() sein Ende (recht pünktlich) findet, dann ist was ganz anderes 
faul.


Mindestens ein Maschinenbefehl, des Hauptprogramms, wird zwischen 2 ISR 
ausgeführt!?!

Also findet das delay() sein Ende.
Gast #5240017
Lesenswert?

Arduino F. schrieb:
> Das halte ich für einen konstruierten Sonderfall.

Das ist Dein gutes Recht:-) - aber der "schlimmste Fall"

Arduino F. schrieb:
> 2: Bein Arduino delay() verlängert, schlimmstenfalls, die letzte ISR die
> Pause.

ist nunmal oft ein Sonderfall.


Arduino F. schrieb:
> Mindestens ein Maschinenbefehl, des Hauptprogramms, wird zwischen 2 ISR
> ausgeführt!?!

So sei es. Die "Arduino-Delay (ms)"-Routine besteht aus einigen 
"Maschinenbefehlen" - oder?
1
void delay( uint32_t ms )
2
{
3
  if ( ms == 0 )
4
  {
5
    return ;
6
  }
7

8
  uint32_t start = _ulTickCount ;
9

10
  do
11
  {
12
    yield() ;
13
  } while ( _ulTickCount - start < ms ) ;
14
}
Gast #5240129
Lesenswert?

Arduino F. schrieb:
> Außerdem kan man während eines delay() noch tausend andere feine Dinge
> tun, nur nicht das delay() vorzeitig abbrechen.

Das würde ich gerne erklärt bekommen. Nach meinem Verständnis ist delay 
blockierend, während dieser Zeit kann kein weiterer Code ausgeführt 
werden.
Gast #5240138
Lesenswert?

>Wessen - von wann? Wir schreiben das Jahr 2017 ...
Genau so ist es. Im Jahr 2017 gibt es GitHub. Und dort befindet sich das 
aktuelle Arduino Repository. Und darauf habe ich verlinkt. Sogar auf's 
richtige File mit Angabe der Zeilennummer.

Zu schwer?
Gast #5240140
Lesenswert?

> Das würde ich gerne erklärt bekommen. Nach meinem Verständnis ist delay
> blockierend, während dieser Zeit kann kein weiterer Code ausgeführt
> werden.

Interrupts können delay() unterbrechen.

Ich schätze, du hast den Thread nicht mitverfolgt, oder?
Gast #5240142
Lesenswert?

Manfred schrieb:
> Das würde ich gerne erklärt bekommen. Nach meinem Verständnis ist delay
> blockierend, während dieser Zeit kann kein weiterer Code ausgeführt
> werden.

Testprogramm:
1
unsigned long counter;
2

3
void yield(void) 
4
{
5
  counter++;
6
}
7

8

9
void setup(void) 
10
{
11
  Serial.begin(9600);
12
}
13

14
void loop(void) 
15
{
16
   delay(1000);
17
   Serial.print("Counter: ");  Serial.println(counter);
18
}

Ausgabe:
1
Counter: 185875
2
Counter: 371726
3
Counter: 557577
4
Counter: 743427
5
Counter: 929278
6
Counter: 1115129
7
Counter: 1300979
8
Counter: 1486828
9
Counter: 1672677
10
Counter: 1858528
11
Counter: 2044379
12
Counter: 2230230
13
Counter: 2416081
14
Counter: 2601932
15
Counter: 2787783
16
Counter: 2973634
17
Counter: 3159485
18
Counter: 3345336
19
Counter: 3531186
Gast #5240149
Lesenswert?

chris schrieb:
> Genau so ist es. Im Jahr 2017 gibt es GitHub. Und dort befindet sich das
> aktuelle Arduino Repository. Und darauf habe ich verlinkt. Sogar auf's
> richtige File mit Angabe der Zeilennummer.
>
> Zu schwer?

Scheinbar ... 2005 - 2006 war einmal (von wem auch immer ...)
1
/*
2
  wiring.c - Partial implementation of the Wiring API for the ATmega8.
3
  Part of Arduino - http://www.arduino.cc/
4
  Copyright (c) 2005-2006 David A. Mellis

Neu ist
1
/*
2
  Copyright (c) 2015 Arduino LLC.  All right reserved. 
3

4
..
5

6

7
void delay( uint32_t ms )
8
{
9
  if ( ms == 0 )
10
  {
11
    return ;
12
  }
13

14
  uint32_t start = _ulTickCount ;
15

16
  do
17
  {
18
    yield() ;
19
  }
Gast #5240188
Lesenswert?

Das paradoxe an Frameworks ist: Sie sollen die Arbeit erleichtern. Doch 
früher oder später kommen Detailfragen auf, zu deren Beantwortung man in 
den Quelltext schauen muss. Spätestens, wenn das Framework darüber 
hinaus nicht genau das tut, was man braucht, muss man sich fragen, warum 
man überhaupt ein Framework verwendet hat.

Ich wollte diese Erkenntnis als Java Enterprise Entwickler viele Jahre 
lang nicht akzeptieren, doch mittlerweile wurde ich mehrfach auf die 
harte Tour (durch negative Erfahrung) eines besseren belehrt.
Gast #5240201
Lesenswert?

>Das paradoxe an Frameworks ist: Sie sollen die Arbeit erleichtern...

Ja, heutzutage kämpft man eigentlich nur noch mit den Frameworks.
Ich neige dazu, alles selber schreiben zu wollen. Aber am Ende bleibt 
einem halt doch nur, Frameworks nutzen zu müssen.
Bei den Arduinosachen hat man zumindest die Möglichkeit bis auf die 
unterste Ebene rein zu schauen und notfalls kann man da was ändern.
Bei den STM-HAL Sachen kann das aber richtig übel werden und eigentlich 
helfen da nur Workarrounds.
#5240202
Lesenswert?

Arduino F. schrieb:
> ööhmmmm...
> Ein kleines Jain, auf die Frage, weil sie in sich einen logischen Fehler
> hat.

wo?

ich habe void serialEvent(void) erst spät entdeckt ist ja eine 
Interruptnutzung

somit müsste

void serialEvent(void)
{ while (Serial.available())
  { char incomingByte = (char)Serial.read();

auch delay_ms unterbrechen

wo soll der logische Fehler sein?
Gast #5240207
Lesenswert?

Autor: Dieter F. (jim_quakenbush)
>Scheinbar ... 2005 - 2006 war einmal (von wem auch immer ...)
Oha, ich dachte mein Link sei das Main-Arduino-Repository.
Falls jemand das von 2015 findet, würde mich ein Link stark 
interessieren.
Gast #5240213
Lesenswert?

Rolf M. schrieb:
> Stefan U. schrieb:
>> Interrupts können delay() unterbrechen.
>
> Allerdings würde ich in einer ISR nicht
>
> Arduino F. schrieb:
>> noch tausend andere feine Dinge
>
> tun.

Ein drohendes Darama bei dem yield() ist, dass rekursive Aufrufe 
stattfinden könnten.
Das wird man (durch Disziplin?) unterbinden müssen.
Gast #5240217
Lesenswert?

Stefan U. schrieb:
> Nach meinem Verständnis ist delay
>> blockierend, während dieser Zeit kann kein weiterer Code ausgeführt
>> werden.
>
> Interrupts können delay() unterbrechen.

Das ist mir klar, aber ich sehe diese eher als Sonderform zeitkritischer 
Anwendungen denn im Tagesgeschäft.

> Ich schätze, du hast den Thread nicht mitverfolgt, oder?

Aber doch! Bei solchen Themen schaue ich immer, ob ich ein paar 
Informationen oder Anregungen für mich mitnehmen kann.
Gast #5240240
Lesenswert?

Arduino F. schrieb:
>> Das würde ich gerne erklärt bekommen. Nach meinem Verständnis ist delay
>> blockierend, während dieser Zeit kann kein weiterer Code ausgeführt
>> werden.
> Testprogramm:

Oops, da hast Du etwas gemacht, was mir vollkommen unbekannt ist. Mit 
einer Internetsuche lande ich auf einer Bachelorarbeit an der Uni 
Hamburg und finde "yield" als Scheduler beschrieben.

Heisst also, mit "void setup(void) und void loop(void)"
springst Du jedesmal durch void yield(void)?

Das muß ich erstmal sacken lassen :-)

Danke Dir!
Gast #5240266
Lesenswert?

Manfred schrieb:
> und finde "yield" als Scheduler beschrieben.
Über die Geschichte weiß ich nichts...

Aber irgendwo in den Tiefen der Arduino Doku findet sich ein Spruch 
dazu:
> yield() ist für Entwickler von Libraries bestimmt,
> um Kooperative Scheduler zu implementieren.
(möglichst sinngemäß wiedergegebeben)

Manfred schrieb:
> Heisst also, mit "void setup(void) und void loop(void)"
> springst Du jedesmal durch void yield(void)?

yield() wird in delay() aufgerufen.
Halt um die Wartezeit sinnvoll nutzen zu können.
Gast #5240271
Lesenswert?

Thomas E. schrieb:
> Und wo wachsen die Blätter? Arduino.org hört sich für mich nach oberster
> Instanz an. Oder ist das jetzt Alduino.cn?

Der Arduino.cc Trupp hat sich in die Wolle bekommen.

Arduino.org hat sich abgespalten.

Kürzlich war die Wiedervereinigung.

Damit ist Arduino.org weg vom Fenster.

Das war ein Prozess über ca. 2 Jahre.
Gast #5240290
Lesenswert?

Dieter F. schrieb:
>> Das ist mir klar, aber ich sehe diese eher als Sonderform zeitkritischer
>> Anwendungen denn im Tagesgeschäft.
> Was hast Du denn für ein Tagesgeschäft mit AVR-Mikrocontrollern?

Mein Tagesgeschäft im beruflichen Erwerbsleben hat leider keine Hardware 
mehr, früher war ich dort mal mit 2MHz-Taktfrequenz und Assembler 
unterwegs.

Arduino setze ich im Hobbybereich ein, für überschaubare Steuerungs- / 
Meßaufgaben. Meist renne ich da in einer Schleife herum und vergleiche 
diverse Millisekunden, um dann in einer Unterroutine etwas zu tun. Diese 
Unterroutine kann auch mal blockierend sein oder einige Dutzend 
Millisekunden dauern.

Interrupt habe ich eingesetzt, um auf eine Eingabe in akzeptabler Zeit 
zu reagieren.

Als nächstes will ich Entladekurven von Akkus auf eine SD-Karte 
schreiben, das wird aus Sicht des Prozessors im Prinzip unendlich 
langsam ablaufen.
Gast #5240293
Lesenswert?

>  Copyright (c) 2005-2006 David A. Mellis
>lol - aber vergiss es, ich lasse euch jetzt in Ruhe :-)

Die letzte Änderung im File ist aber vom Dez.2015:
https://github.com/arduino/Arduino/commit/b1231c39e9fa6d8602ac24305b07f074c1145633

Es sieht so aus, als wenn sie das Datum im Header nicht aktualisiert 
haben.
Das ist aber auch lästig, wenn man wegen jeder kleinen Änderung im File 
den Copyright Header ändern muss.
Gast #5240297
Lesenswert?

Joachim B. schrieb:
> sitzt definitiv ausserhalb der loop

Außerhalb von loop(), ja.
Aber innerhalb der Schleife, welche sich typischer weise in main() 
befindet.
Und damit eben nicht in einem Interrupt.
Es verlängert nicht das delay_ms()

Das Gegenteil ist der Fall:
Ein delay_ms() verzögert den serialEvent() Aufruf.


Siehe:
https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/main.cpp

Dort wird serialEventRun() aufgerufen, welches wiederum dann die 
diversen  serialEvent() aufruft.
Beitrag #5240298 wurde von einem Moderator gelöscht.
#5240325
Lesenswert?

Arduino F. schrieb:
> Außerhalb von loop(), ja.
> Aber innerhalb der Schleife, welche sich typischer weise in main()
> befindet.
> Und damit eben nicht in einem Interrupt.
> Es verlängert nicht das delay_ms()

das wiederum hatte ich nirgens behauptet, es wurde behauptet das während 
delay_ms nichts abgearbeitet wird, das war meine Frage, aber egal ich 
nutze mein eigenes my_delay_ms() und da wird nebenbei anderes 
abgearbeitet.

D.h. während my_delay wartet wird dort weitergearbeitet.

Arduino F. schrieb:
> Ist es nicht.
> serialEvent() wird in der main() Loop aufgerufen.

hört sich nach Ausrede an, in der Arduinowelt gibts nur loop()

klar liegt noch eine main loop drüber, dann schreibe das doch 
deutlicher, wenn in Arduino von loop gesprochen wird dann ist doch 
loop() gemeint und nicht while(1);
Gast #5240338
Lesenswert?

Dabei habe ich doch extra  "main() Loop" geschrieben!
Die Klammern mit Bedacht gesetzt.

Merksatz:
> Ich bin für das verantwortlich, was ich sage.
> Nicht für das, was du verstehst.

Und von deinem_delay() weiß ich natürlich nichts...
Aber das könntest du gerne mal zeigen.

Joachim B. schrieb:
> in der Arduinowelt gibts nur loop()
Das ist übrigens auch nicht richtig.

Ein korrektes Arduino Programm kann auch so aussehen:
1
int main()
2
{
3
  for(;;);
4
  return 0;
5
}
Man wird dann aber auch auf die ganzen Arduino Features verzichten 
müssen.
#5240362
Lesenswert?

Arduino F. schrieb:
> Ein korrektes Arduino Programm kann

stimmt, nur dann brauchts auch nicht mehr die IDE

Arduino F. schrieb:
> Merksatz:
>> Ich bin für das verantwortlich, was ich sage.
>> Nicht für das, was du verstehst.

kenne ich schon, ist aber auch nur platt

Arduino F. schrieb:
> Aber das könntest du gerne mal zeigen.

dazu bin ich ein zu schlechter progger, das hilft niemanden hier und 
Häme gibts ja genug, das brauche ich nicht, für mich reichts eben :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren