Suche timer ohne millis()

Hallo,
ich suche einen timer der ohne die millis() Methode funktioniert.
Es geht darum ich habe ein Projekt dort will ich eine Zeit auf einem Segmentdisplay ausgeben. Die Zeit wird mit einem Button bei gedrückt halten gestartet und beim loslassen angehalten. Nun ist es auch so dass diese Zeit über einen längeren Zeitraum gespeichert werden soll.

Mit der millis() würde ich ja immer nur die Zeit seit dem Boardstart haben, und ich wüsste auch nicht wie ich das realisieren sollte.

Hier ist mal mein momentaner Sketch:

#include "SevSeg.h"
SevSeg sevseg;

  int button = 2;     //Button pull up
  
  int buttonSig = 0;  //Button pull up
  long myTimer = 0;
  long myTimeout = 1000;
  int min=0;

void setup() {
  
  byte digitPins[]={3,4,5};
  byte segmentPins[]={6,7,8,9,10,11,12,13};
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool disableDecPoint = true;

  sevseg.begin(COMMON_ANODE,2,digitPins,segmentPins,updateWithDelays,disableDecPoint);
  sevseg.setBrightness(90);
  pinMode(button, INPUT);       //Button pull up
  digitalWrite(button, HIGH);   //Button pull up

  Serial.begin(9600);
  
}

void loop() {

    buttonSig = digitalRead(button);
              
     if (millis() > myTimeout + myTimer && buttonSig == LOW) {       
        myTimer = millis();
        min+=1;
        sevseg.setNumber(min);

        Serial.print("Botton: ");             
        Serial.println(buttonSig);
        Serial.print("Minuten: ");
        Serial.println(min);
      }
      
     sevseg.refreshDisplay();    
}

Mit der millis() würde ich ja immer nur die Zeit seit dem Boardstart haben, und ich wüsste auch nicht wie ich das realisieren sollte.

dann merk die die aktuellen millis() in einer Variable wenn du deine Taste drückst, dann kannst du immer wieder deine Variable befragen, wann du die Taste gedrückt hast.
auch wenn millis() schon weiter ist.

Das beste Beispiel ist, um dich von deinem Irrtum zu überzeugen, sieh dir das Beispel "BlinkWithoutDelay" an.

HotSystems:
Das beste Beispiel ist, um dich von deinem Irrtum zu überzeugen, sieh dir das Beispel "BlinkWithoutDelay" an.

Ja!

Dann lernst du auch solche Fehler zu vermeiden:

millis() > myTimeout + myTimer

Wie kannst Du feststellen, wie lange Du zum Brötchenholen die Wohnung verläßt? Deine Armbanduhr kannst Du vergessen, denn die zeigt ja nur die Zeit seit Mitternacht an, also unbrauchbar.

Oder?

Genauso wie mit Deiner Armbanduhr (Zeit Ankunft - Zeit Weggehen) machst Du das auch mit millis().

Deine analoge Armbanduhr läuft nach 12 Stunden "über", millis() nach ca. 49 Tagen, da muß man dann nochmal genauer überlegen.

Hallo,
danke für eure Tipps. Ich habe das Ganze jetzt mal wie bei BlinkWithoutDelay umgeschrieben.

Aber ich muss sagen ich komme nicht drauf. Nehmen wir mal an ich speichere den Wert in einer Variablen und er beträgt beim loslassen des Buttons 50.000 und beim erneuten drücken sind die millis() auf 100.000 weitergelaufen.
So wie bringe ich nun wieder in den richtigen "Rhythmus", ohne dass mir was verloren geht? Intervall = 60.000.

#include "SevSeg.h"
SevSeg sevseg;

  int button = 2;     //Button pull up
  
  int buttonSig = 0;  //Button pull up
  unsigned long previousMillis = 0;
  const long interval = 60000;
  int min=0;

void setup() {
  
  byte digitPins[]={3,4};
  byte segmentPins[]={6,7,8,9,10,11,12,13};
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool disableDecPoint = true;

  

  sevseg.begin(COMMON_ANODE,2,digitPins,segmentPins,updateWithDelays,disableDecPoint);
  sevseg.setBrightness(90);
  pinMode(button, INPUT);       //Button pull up
  digitalWrite(button, HIGH);   //Button pull up

  Serial.begin(9600);
  
}

void loop() {

    buttonSig = digitalRead(button);
    unsigned long currentMillis = millis();
                 
     if (currentMillis - previousMillis >= interval  && buttonSig == LOW) {
          
        previousMillis = currentMillis;
        min+=1;
        sevseg.setNumber(min);

        Serial.print("Botton: ");             
        Serial.println(buttonSig);
        Serial.print("Minuten: ");
        Serial.println(min);
      }
      
     sevseg.refreshDisplay();    
}

Hallo,
ich habe versucht Deinen Eingangstext zuverstehen:
Du suchst eine Stoppuhr, die beim drücken des Tasters die Zeitmessung startet, beim losLassen stoppt und die Zeitdifferenz zur Anzeige auf dem 7-Segement bringt?

Die Zeit wird mit einem Button bei gedrückt halten gestartet

actualButtonState = digitalRead(42);

WENN previousButtonState==losgelassen UND actualButtonState == gedruckt DANN startzeit=millis();

und beim loslassen angehalten.

WENN previousButtonState == gedruckt UND actualButtonState == losgelassen DANN endzeit = millis();

previousButtonState = actualButtonState;
gesamtzeit=endzeit-startzeit;

also das Prinzip ist nicht so ein Mirakel. Aufpassen halt wegen Debounce und stateChangeDetection. Aber dafür gibt es auch schöne Beispiele in der IDE.

Könnte dieser Ansatz etwas sein?

void loop() {

    buttonSig = digitalRead(button);
    unsigned long currentMillis = millis();
    long diff = currentMillis - previousMillis;
    peviousMillis = diff + previousMillis;
                 
     if (currentMillis - previousMillis >= interval  && buttonSig == LOW) {
          
        previousMillis = currentMillis;
        min+=1;
        sevseg.setNumber(min);

Du suchst eine Stoppuhr, die beim drücken des Tasters die Zeitmessung startet, beim losLassen stoppt und die Zeitdifferenz zur Anzeige auf dem 7-Segement bringt?

Ja so könnte man es auch sagen. Also die Differenz zwischen drücken und loslassen. ALSO es soll sich wären dessen ändern. Wie ein counter

mastershredder:
ich suche einen timer der ohne die millis() Methode funktioniert.

Ich denke eher nicht.

Eigentlich schöne Schrittkette - warten - auslösen - zählen - stoppen
Geht aber auch mit Schachteln.
Zusammengebastelt, also ungetestet und nur mal zum probieren, ob es das ist, was Du meinst.
Deine loop() damit ersetzen ...
[edit] noch ne Variable vergessenn..[/edit]

void loop() {
  static bool laststate = HIGH;
  static unsigned long startmillis = 0;
  static int lastmin = min;

  buttonSig = LOW;
  if (buttonSig == LOW) // Taste gedrückt?
  {
    if (laststate == HIGH) // Vorher nicht gedrückt?
    {
      laststate = LOW;    // Setze Startzustand
      startmillis = millis();
      min = 0;
    }
    if ((millis() - startmillis) % 1000 == 0) // Zeit läuft?
    {
      if (lastmin != min) {
        min += 1;
        lastmin = min;
        sevseg.setNumber(min);
      }
      Serial.print("Botton: ");
      Serial.println(buttonSig);
      Serial.print("Minuten: ");
      Serial.println(min);
    }
    else
    {
      lastmin = -1;
    }
  }
  else  // Taste nicht gedrückt?
  {
    laststate = HIGH;    // Beende Startzustand
  }
  sevseg.refreshDisplay();
}

ich suche einen timer der ohne die millis() Methode funktioniert.

Das ist nicht dein Problem.
Ganz im Gegenteil.

Es geht darum ich habe ein Projekt dort will ich eine Zeit auf einem Segmentdisplay ausgeben. Die Zeit wird mit einem Button bei gedrückt halten gestartet und beim loslassen angehalten. Nun ist es auch so dass diese Zeit über einen längeren Zeitraum gespeichert werden soll.

Das hört sich doch nach einer klassischen Stoppuhr an…

Eine Stoppuhr aus meiner Wühlkiste:
(leicht für diese Anforderungen angepasst)

Taster an 2 losgelassen, die Uhr steht
Taste an 2 gedrückt, die Uhr läuft weiter.
Die Uhr zählt also nur die ms, wie lange der Knopf gedrückt wurde.
Maximaler Zeitraum: 49,x Tage.

#include <Streaming.h>

class StoppUhr: public Printable 
{
  private:
  unsigned long startzeit;
  unsigned long abgelaufenezeit; 
  bool isrunning;

  public:
  void reset()
  {
    isrunning = false;
    startzeit = 0;
    abgelaufenezeit = 0;
  }
  
  StoppUhr()
  {
    reset();
  }
  
  void start()
  {
    if(!isrunning)
    {
      isrunning = true;
      startzeit = millis();
    }
  }
  
  void halt()
  {
    if(isrunning)
    {
      isrunning = false;
      abgelaufenezeit += millis()-startzeit;
    }  
  }
 
  virtual size_t printTo(Print &printer) const
  {
    return printer.print(isrunning?millis()-startzeit+abgelaufenezeit:abgelaufenezeit);
  }
} stoppuhr;


const byte button = 2;     //Button with pull up



void yield()
{
  if(digitalRead(button)) stoppuhr.halt(); else  stoppuhr.start();
}

void setup() 
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;
  pinMode(button,INPUT_PULLUP);
}

void loop() 
{
  Serial << "Vergangene Zeit: "<< stoppuhr << endl;
  delay(1000);
}

Mantra:

Es gibt ein Leben neben delay()

Wirklich interessante Vorschläge.
my_xy_projekt: Deiner geht noch nicht so ganz.

und

combie: Bei dir muss ich mich noch durchkämpfen.

Aber jetzt erst mal erkläre ich mal mein ganzes Projekt dass man versteht was ich will:

Also ich habe einen Staubsauger der einen ziemlich kleinen Akku hat, und keinerlei Anzeige dafür. Ich weiß das er ca. 25min hält aber jach. Es gibt so ein Phänomen dass immer wenn ich was größeres saugen will das Ding nur noch 5min Saft hat >:( sehr ärgerlich. Ich habe mir jetzt gedacht wenn ich hingehe und immer wenn ich den Staubsauger anmache, einen Button mit drücke und dann die Zeit(in Minuten) wie ich sauge hoch zählt und ich sie auf einem Segmentdisplay angezeigt bekomme wäre das doch schon eine coole Sache.

Dann habe ich wenigstens eine kleine Orientierung :smiley:

Wenn der Akku dann leer ist und wieder vollgeladen, einfach reset und fertig.

Dass heißt dann auch das der Microcontroller an einer Batterie hängt. Display kann man noch sehen dass man dies noch abschalten kann.

Ja das ist der Plan :wink: 8)

combie: Bei dir muss ich mich noch durchkämpfen.

Das tu du mal....

Als Anregung ist das sicherlich zu gebrauchen.


Kannst/darfst du den Staubsauger öffnen?

mastershredder:
Wirklich interessante Vorschläge.
my_xy_projekt: Deiner geht noch nicht so ganz.

Dochdoch, der geht. ganz.
Jede Sekunde zählt der min++ - Das war Absicht!
Wenn Du jetzt nicht sekunde sondern min haben willst, musst Du da *60 nehmen.

Dann hier mal die Variante in kurz

void loop() {
  static bool laststate = HIGH;
  const unsigned long intervall = 10; // Zeit in ms
  static unsigned long startmillis = 0; // Merker
  static unsigned long tik = 0; // yo...


  buttonSig = digitalRead(button);
  if (buttonSig == LOW) // Taste gedrückt?
  {
    if (laststate == HIGH) // Vorher nicht gedrückt?
    {
      laststate = LOW;    // Setze Startzustand
      startmillis = millis();
      min = 0;
    }
    if (millis() - startmillis > tik) // Zeit läuft?
    { tik += intervall;
      min++;
    }
    Serial.print("Botton: ");
    Serial.println(buttonSig);
    Serial.print("Minuten: ");
    Serial.println(min);
  }
  else  // Taste nicht gedrückt?
  {
    laststate = HIGH;    // Beende Startzustand
  }
}

Hinter intervall steht der passende Kommentar...

my_xy_projekt:
Wenn Du jetzt nicht sekunde sondern min haben willst, musst Du da *60 nehmen.

Nicht eher /60?

Gruß Tommy

Tommy56:
Nicht eher /60?

Ich hatte im Ersten auf modulo 1000 ms abgeglichen.
Habs jetzt - auch aus Gründen - mit intervall gemacht. :wink:

mastershredder:
Deiner geht noch nicht so ganz.

Aaah... Moment...
Deine Ansage war:

Die Zeit wird mit einem Button bei gedrückt halten gestartet und beim loslassen angehalten. Nun ist es auch so dass diese Zeit über einen längeren Zeitraum gespeichert werden soll.

Hm. Hab ich doch den zweiten Satz überlesen...
Na nichts leichter als das:
Lösche doch einfach das rücksetzen der min!

min = 0;

Zeile gelöscht und schon aufaddiert.

[edit]

mastershredder:
Wenn der Akku dann leer ist und wieder vollgeladen, einfach reset und fertig.

Ich frag mich grad, ob es nicht besser wäre einfach den Akku abzufragen.
Angezeigt wird dann mit einer RGB-LED whatever und das nur, solange button == pressed....

Aber Vorsicht - das ginge wohlmöglich ohne ARDUINO; da fehlt dann das schöpferische... :wink:

Na dann...
[/edit]

Hallo :slight_smile:
ich habe auch noch eine Stoppuhr in der Sketch Restekiste gefunden, den du ganz einfach an deine 7-Segment Ausgabe anpassen kannst. Dieser Sketch arbeitet allerdings mit der millis() Funktion, wenn es dich nicht stört :slight_smile: .

t // Forum: Suche timer ohne millis()
// Autor: paulpaulson
// Sketch aus der Restekiste 
struct ENTPRELLEN {
  unsigned long zeitStempel;
  unsigned long zeitDauer = 20;
};
ENTPRELLEN entprellen;
struct TASTER {
  int pin = 2;
  bool status = HIGH;
};
TASTER taste;
void setup()
{
  pinMode(taste.pin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  Serial.print(F("und los geht´s mit Taster an Pin ")), Serial.println(taste.pin); 
}
void loop()
{
  static unsigned long jetztZeit;
  static unsigned long startZeit;
  static bool anzeige;
  jetztZeit = millis();
  digitalWrite(LED_BUILTIN,jetztZeit/500%2);
  bool buttonGelesen = digitalRead(taste.pin);
  if (jetztZeit - entprellen.zeitStempel >= entprellen.zeitDauer) {
    entprellen.zeitStempel = jetztZeit;
    if (taste.status != buttonGelesen) taste.status = buttonGelesen;
    if (!taste.status) {
      if (!anzeige) anzeige = true, startZeit = jetztZeit;
    }  else {
      if (anzeige) anzeige = false, Serial.print((jetztZeit - startZeit)/60000), Serial.println(" min");
    }
  }
}

Ich frag mich grad, ob es nicht besser wäre einfach den Akku abzufragen.
Aber Vorsicht - das ginge wohlmöglich ohne ARDUINO; da fehlt dann das schöpferisch

Also ich bleibe lieber jetzt mal bei der Methode. Habe auch noch nicht so viel Ahnung davon.

Aber jach also my_xy_projekt deine Methode hab ich nun mal rein kopiert. Die könnte fast funktionieren.

Da ist nur eine Sache: Ich drücke den Button es zählt hoch, wunderbar. Dann beim zweiten Mal sind es unterschiedliche ZEITEN wo NICHTS passiert bis es weiter läuft. Also es hängt mal kurz mal lang. Ich habe auch noch was als Kommentar in den Sketch geschrieben.

#include "SevSeg.h"
SevSeg sevseg;

  int button = 2;     //Button pull up  
  int buttonSig = 0;  //Button pull up
  
  //unsigned long previousMillis = 0;
  //const long interval = 1000;
  int min=0;
  //int startmillis;
  
void setup() {
  
  byte digitPins[]={3,4};
  byte segmentPins[]={6,7,8,9,10,11,12,13};
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool disableDecPoint = true;

  

  sevseg.begin(COMMON_ANODE,2,digitPins,segmentPins,updateWithDelays,disableDecPoint);
  sevseg.setBrightness(90);
  pinMode(button, INPUT);       //Button pull up
  digitalWrite(button, HIGH);   //Button pull up

  Serial.begin(9600);
  
}



void loop() {
  static bool laststate = HIGH;
  const unsigned long intervall = 1000; // Zeit in ms
  static unsigned long startmillis = 0; // Merker
  static unsigned long tik = 0; // yo...


  buttonSig = digitalRead(button);
  
  if (buttonSig == LOW) // Taste gedrückt?
  {
    if (laststate == HIGH) // Vorher nicht gedrückt?
    {
      laststate = LOW;    // Setze Startzustand
      startmillis = millis();      
    } // Haben diese beiden millis bzw startmilis und millis() nicht den genau gleichen Wert, und heben sich so gegenseitig wieder auf?
    if (millis() - startmillis > tik) // Zeit läuft?
    { tik += intervall;
      min++;
      sevseg.setNumber(min);
    }    
    Serial.print("Botton: ");
    Serial.println(buttonSig);
    Serial.print("Minuten: ");
    Serial.println(min);
  }
  else  // Taste nicht gedrückt?
  {
    laststate = HIGH;    // Beende Startzustand
  }

  sevseg.refreshDisplay();
}

paulpaulson Der Sketch aus deiner Restekiste sieht auch interessant aus. Aber da hätte ich ein paar Fragen. Habe sie als Kommentar in den Sketch geschrieben.

t // Forum: Suche timer ohne millis()
// Autor: paulpaulson
// Sketch aus der Restekiste

struct ENTPRELLEN {
  unsigned long zeitStempel;
  unsigned long zeitDauer = 20;
};

ENTPRELLEN entprellen;


struct TASTER {
  int pin = 2;
  bool status = HIGH;
};

TASTER taste;


void setup() {

  pinMode(taste.pin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  Serial.print(F("und los geht´s mit Taster an Pin ")), Serial.println(taste.pin);
}


void loop() {

  static unsigned long jetztZeit;
  static unsigned long startZeit;
  static bool anzeige;
  
  jetztZeit = millis();

  // Was übergiebst du da für einen Wert du Teilst doch da durch 0 oder nicht?
  digitalWrite(LED_BUILTIN,jetztZeit/500%2);
  
  bool buttonGelesen = digitalRead(taste.pin);

  
  if (jetztZeit - entprellen.zeitStempel >= entprellen.zeitDauer) {
      entprellen.zeitStempel = jetztZeit;
    
    if (taste.status != buttonGelesen) taste.status = buttonGelesen;
    
    if (!taste.status) {
      
      if (!anzeige) anzeige = true, startZeit = jetztZeit; }
      
   // Zu welchem if Block gehört dieses else, zum obersten?  
  else {
      if (anzeige) anzeige = false, Serial.print((jetztZeit - startZeit)/60000), Serial.println(" min");
    }
  }
}