Arduino Millis

Gast #5318616
Lesenswert?

Hallo Leute, hab nicht viel Erfahrung mit uC's, fang gerade klein an mit 
einem Arduino Uno.

Arbeite mir die Funktionen nach der Reihe durch und lasse eigentlich 
immer nur ne LED blinken. Hier bei der Millis Funktion will aber meine 
LED nie aufleuchten, was ist an dem Code falsch?

Ich hoffe es kann mir wer einen Denkstoss geben.

Lg
Angehängte Dateien:
Gast #5318624
Lesenswert?

Schau zunächst mal nach ob die LED überhaupt angeht, d.h. setze den 
einaus ganz oben mal auf HIGH anstatt LOW. Wenn immer noch nicht geht, 
versuch mal den Pin 13 mit der internen LED.
Und setze millis()-startwert in der if()-Abfrage zur Sicherheit mal in 
Klammern...
Gast #5318643
Lesenswert?

loop() wird immer wieder aufgerufen. Dort setzt du jedesmal den 
startwert auf millis(). Die nachfolgende if() Bedingung kann daher 
niemals erfüllt sein.

Wenn du den Quelltext gepostet hättest, hätte ich ihn für Dich 
korrigiert. Aber alles von deinem Foto abzuschreiben, dazu bin ich zu 
Faul.
#5318645
Lesenswert?

Bei jedem Durchlauf wird Start auf den aktuellen millis Wert gesetzt.

Deine Bedingung wird nur war wenn zwischen dem setzten von Start und der 
If Abfrage mehr als 6000 ms vergehen, und so langsam ist der Arduino 
nicht.

Das kopieren des neuen Wertes darf nur innerhalb der If Bedinung 
erfolgen.

Gruß JackFrost
(Firma: @home) #5318648
Lesenswert?

... hier mal was zum nachdenken und benutzen!

// toggling led, 500ms on/off
PERIODIC(500) //{
   digitalWrite(LEDPIN, !digitalRead(LEDPIN))
};


#ifndef PERIODIC_H
#define PERIODIC_H

//TODO:
// - excluded "{"
// - variant: repeat parameter
// - variant: timed window
// - for (; (millis() - UNIQUE(timer)) >= ms; ) {  \

//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
Gast #5318667
Lesenswert?

Apollo Mond schrieb:

>... hier mal was zum nachdenken und benutzen!

So einfach kann es also sein -und so übersichtlich. Ich dachte wirklich 
nicht, daß es mit so geringem Aufwand möglich ist, eine LED blinken zu 
lassen. Erstaunlich.
Gast #5318682
Lesenswert?

Hallo Mike,

wie meine Vorposter bereits geschrieben haben setzt du mit jedem 
Durchlauf des Hauptprogramms den Startwert mit den aktuellen millis().

dadurch wird aber die Bedingung nie wahr, dass mehr als die nanos() 
(gibt es auch am Arduino) vergehen, die ein Programmdurchlauf braucht.

Versuche dir das ganze als Code aber selber herzuleiten!

- Initiere eine Variable millisAktuell und millisVorher mit "0" im 
Setup.
- Im Hauptprogramm setzt du nun die millisAktuell mit den millis()
- vergleiche den Wert von millisAktuell mit den millisVorher per 
arithmetischer Operation auf Differenz von deinem gewünschten 
Blinkinterval
- sind die millisAktuell und millisVorher soweit wie dein gewünschter 
Interval auseinander, soll deine Bedingung als wahr gelten und dein If 
ausgeführt werden.
- setze im If deinen Ausgang (togglen mit einaus!=einaus), hiernach die 
millisVorher mit den millis() setzen.
- If abgeschlossen, Hauptschleife durchlaufen bis Bedingung 
(millisAktuell-millisVorher >= Intervall) wieder wahr.

Vorsicht, die Funktion millis() kann auch wieder bei lang genuger 
Betriebsdauer des Arduinos von vorne anfangen. Daher immer die millis() 
in einer eigenen Variable zwischenspeichern. Zusätzlich ist es von 
Vorteil die Differenz zwischen aktuellen und vorherigen millis() als 
Betrag zu rechnen, also ohne Vorzeichen.

MfG, EGS
Gast #5318696
Lesenswert?

Stefan U. schrieb:
> aber das ist weit weg vom Arduino Style.

Was ist schon "Arduino Style" ?



Blink mit Pulsator
1
// Wieder eine Variation des BlinkWithoutDelay
2

3
#include <CombieTimer.h>
4

5
Combie::Timer::Pulsator puls(1000); // liefert alle 1000 ms einmal true sonst false
6

7
void setup()
8
{
9
  pinMode(LED_BUILTIN,OUTPUT);
10
  puls.start(); // dank des start(), beginnt puls mit Pause
11
}
12

13
void loop()
14
{
15
  if(puls) digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
16
}

//----------------------

Blink mit SimpleTimer:
1
// Wieder eine Variation des BlinkWithoutDelay
2

3
#include <CombieTimer.h>
4

5
Combie::Timer::SimpleTimer timer; // timer Instanz anlegen
6

7
void setup()
8
{
9
  pinMode(LED_BUILTIN,OUTPUT);
10
}
11

12
void loop()
13
{
14
  if(timer(1000)) // wenn abgelaufen
15
  { 
16
    digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
17
    timer.start();
18
  }
19
}
Angehängte Dateien:
Gast #5320113
Lesenswert?

Erstaunter
>So einfach kann es also sein -und so übersichtlich. Ich dachte wirklich
>nicht, daß es mit so geringem Aufwand möglich ist, eine LED blinken zu
>lassen. Erstaunlich.

Ja, mit dem Programmierstiel hätte gute Chancen, beim IOCCC mitmachen zu 
dürfen:

https://de.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest

Mittlerweile gibt es aber gute Bücher, wie man seinen Stiel verbessern 
kann:

https://www.oreilly.de/buecher/120174/9783897215672-weniger-schlecht-programmieren.html

( das Buch ist übrigens wirklich gut )
Gast #5325901
Lesenswert?

Apollo M. schrieb:
> if (millis()-startwert >= interval) {
>
>   ... //to do something
>   startwert = millis(); //reset startwert und los gehts wieder ...
>
> }

Damit wirst du keine vernünftig definierten Intervalle produzieren 
können.


Mit dem Code sammelst du dir bei jedem Durchlauf zusätzlich zu der durch 
interval festgelegten Periode eine Zeitverschiebung in Höhe der 
Laufzeit von "... //to do something" auf. Wenigstens sollte man den 
neuen Startwert, so man ihn unbeding aus dem aktuellen Wert von millis() 
ableiten will, direkt als erstes nach dem "if"-Statement festlegen.

Besser wäre, zumindest solange "to do something" sicher kürzer als 
"interval" ist, ihn aus dem alten zu berechnen:
1
   startwert = startwert + interval;
Gast #5325931
Lesenswert?

Wolfgang schrieb:
> Mit dem Code sammelst du dir bei jedem Durchlauf zusätzlich zu der durch
> interval festgelegten Periode eine Zeitverschiebung in Höhe der
> Laufzeit von "... //to do something" auf.
Und?
Wen kümmerts?


Naja...
In Fällen wo es keinen "Schlupf" geben darf, ist dein Einwand schon ok.
Aber andersrum gibt es auch Fälle, wo eine Zeit nicht unterschritten 
werden darf.
Und dann fällt dir dein Verfahren auf die Füße.

Also, wie immer:
Ohne konkrete Anforderungsliste, kann man diesen, oder jenen, Weg nicht 
als die "richtige" oder "falsche" Lösung bezeichnen.

Noch nicht mal ein "Besser" ist zu benennen.
Gast #5325940
Lesenswert?

Arduino F. schrieb:
> Aber andersrum gibt es auch Fälle, wo eine Zeit nicht unterschritten
> werden darf.
> Und dann fällt dir dein Verfahren auf die Füße.

Das Intervall ist genau das spezifizierte Vielfache vom 
millis()-Timerinterruptintervall. Da wird nichts unterschritten, 
jedenfalls wenn man von der Zeit zwischen zwei Aufrufen von "... //to do 
something" spricht.
Gast #5325948
Lesenswert?

Wolfgang schrieb:
> Da wird nichts unterschritten,
Das ist gelogen!
Oder du kannst einfach nur nicht rechnen.
Oder du denkst dir einfach nur Dinge aus, bist aber zu faul diese zu 
prüfen.

Aber die Unwahrheit, die lasse ich dir nicht durch gehen.

Beweis:
Angenommen 5 ms Verspätung
>   startwert = startwert + interval;

Dann
> if (millis()-startwert >= interval)
Wird der Zyklus 5 ms kürzer sein, als von interval vorgegeben.

Denn millis() ist schon 5ms weiter.

Und damit bist du widerlegt.
Gast #5325962
Lesenswert?

Arduino F. schrieb:
> Und damit bist du widerlegt.

Wenn du die Aufgabe nicht in der zur Verfügung stehenden Zeit erledigt 
kriegst, hast du natürlich ein Problem.
Dann hast du nur die Wahl, unkontrollierte Verschiebungen in Kauf zu 
nehmen, (deine Methode) oder Aufrufe von "... //to do something" 
ausfallen zu lassen, indem man z.B. prüft, wie es am Ende von "... //to 
do something" mit der Restzeit aussieht. Es kommt drauf an, was 
wichtiger ist - festes Intervall oder Mindest-Idle-Zeit.

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