Forum: Mikrocontroller und Digitale Elektronik Arduino Millis


von Mike1996 (Gast)


Angehängte Dateien:

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

von Stefan S. (chiefeinherjar)


Lesenswert?

Ein erster Anstoß wäre es ganz einfach den Code zu kopieren und hier - 
korrekt formatiert - im Forum zu posten. Ich kann da kaum etwas 
erkennen...

von Marct (Gast)


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...

von Mike1996 (Gast)


Lesenswert?

Wenn ich den Code ändere so wie du es mir geschrieben hast dann leuchtet 
die LED nur noch :/
@stefan schmid: sry ich poste hier vom handy aus.

von Marc H. (marchorby)


Lesenswert?

Mike1996 schrieb:
> Wenn ich den Code ändere so wie du es mir geschrieben hast dann leuchtet
> die LED nur noch

Stefan S. schrieb:
> Ein erster Anstoß wäre es ganz einfach den Code zu kopieren und hier -
> korrekt formatiert - im Forum zu posten

Poste doch erst mal den Code! Und mach ein Foto lieber vom Aufbau der 
Schaltung als vom Bildschirm

von Mike1996 (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch einmal der Code und die "Supergroße" Schaltung.

von Mike1996 (Gast)


Angehängte Dateien:

Lesenswert?

Hier die Schaltung.

von Stefan F. (Gast)


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.

von Bastian W. (jackfrost)


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

von Apollo M. (Firma: @home) (majortom)


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

von Stefan F. (Gast)


Lesenswert?

Sorry, aber das ist weit weg vom Arduino Style. Damit verwirrst du den 
TO nur.

von Erstaunter (Gast)


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.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

ok!

also

static unsigned long startwert = millis();

UND

if (millis()-startwert >= interval) {

  ... //to do something
  startwert = millis(); //reset startwert und los gehts wieder ...

}

von czxfhz (Gast)


Lesenswert?

Stefan U. schrieb:
> Damit verwirrst du den
> TO nur.

Stimmt. Der muss erstmal lernen, Code hier als Text in den Beitrag zu 
kopieren.

czxfhz

von EGS (Gast)


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

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Erstaunter schrieb:
> 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.

... das sind doch nur ein paar geniale makros für ... äh - junge 
nachdenker :/)

von Einer K. (Gast)


Angehängte Dateien:

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
}

von Mike1996 (Gast)


Lesenswert?

Hallo Leute, Danke euch, ihr habt mir einen Denkstoss verpasst und ich 
habe es jetzt ? Lg und schönes WE

von Harry (Gast)


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 )

von Huh (Gast)


Lesenswert?

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

Den Besenstiel? ;-)

von Marc H. (marchorby)


Lesenswert?

Mike1996 schrieb:
> Hier noch einmal der Code und die "Supergroße" Schaltung.

Mike, das du ein Foto von deinem Code machst, anstatt die mit Copy&Past 
hier zu posten ist schon eine Frechheit für sich!

von Stefan S. (chiefeinherjar)


Lesenswert?

Huh schrieb:
> Harry schrieb:
>> Mittlerweile gibt es aber gute Bücher, wie man seinen Stiel verbessern
>> kann:
>
> Den Besenstiel? ;-)

Männer sind Frauen mit Stiel ;)

von Forist (Gast)


Lesenswert?

Mike1996 schrieb:
> @stefan schmid: sry ich poste hier vom handy aus.

Selbst so ein "smartes" Handy wird doch copy&paste irgendwie hin kriegen 
...

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Forist schrieb:
> Selbst so ein "smartes" Handy wird doch copy&paste irgendwie hin kriegen

Hmm: Per RDP auf den Windows-Rechner (alternativ SSH auf Linux) gehen, 
dort den Bereich markieren, ausscheiden und anschließend im 
(Handy-)Browser einfügen und versenden.

Ja, das sollte gehen.

von Wolfgang (Gast)


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;

von Einer K. (Gast)


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.

von Wolfgang (Gast)


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.

von Einer K. (Gast)


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.

von Wolfgang (Gast)


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.

von Einer K. (Gast)


Lesenswert?

Wolfgang schrieb:
> Es kommt drauf an, was
> wichtiger ist - festes Intervall oder Mindest-Idle-Zeit.

Damit hast du jetzt zugegeben, dass dein Verfahren die wirksame Interval 
Zeit verkürzen kann!

Richtig?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.