Millis() Timer pausieren und wieder starten

einfach mal so runtergeschrieben:

// Schachuhr
// https://forum.arduino.cc/t/millis-timer-pausieren-und-wieder-starten/855936
// by noiasca
// 2021-05-01 

int8_t activeTimer = -1;               // which timer is currently active

struct Timer {
  const byte buttonPin;                // pin to GND starts timer
  uint32_t previousMillis;             // last active millis of this timer
  uint32_t millis;                     // millis
};

Timer timer[] {
  {A0, 0, 0},                          // buttonPin, previousMillis, millis
  {A1, 0, 0},
};

const byte noOfTimer = sizeof(timer) / sizeof(timer[0]); // calculate number of timers

void setup() {
  Serial.begin(115200);
  Serial.println(F("Schachuhr"));
  for (auto &i : timer)
    pinMode(i.buttonPin, INPUT_PULLUP);
}

void loop() {
  // read button
  for (size_t i = 0; i < noOfTimer; i++)
  {
    if (digitalRead(timer[i].buttonPin) == LOW && activeTimer != (int8_t)i) activateTimer(i); // if different button, activate timer
  }
  // output
  updateSerial();
}

void activateTimer(byte i)                                          // sets timer i to active
{
  timer[i].previousMillis = millis();
  Serial.print(F("Button pressed ")); Serial.println(i);
  activeTimer = i;
}

uint32_t getMillis(byte i)                                          // returns the accumulated millis of one timer
{
  if (activeTimer == i)                                             // update millis before return
  {
    uint32_t currentMillis = millis();
    timer[i].millis += currentMillis - timer[i].previousMillis;     // add passed time to old millis
    timer[i].previousMillis = currentMillis;                        // remember the timestamp of the last millis update
  }
  return timer[i].millis;
}

void updateSerial()                                                 // demo output to serial
{
  static uint32_t previousMillis = 0;
  uint32_t currentMillis = millis();
  if (millis() - previousMillis > 500)
  {
    for (size_t i = 0; i < noOfTimer; i++)
    {
      Serial.print(F("Timer")); Serial.print(i); Serial.print(" "); Serial.print(getMillis(i)); Serial.print("\t");
    }
    Serial.print(F(" active=")); Serial.println(activeTimer);
    previousMillis = currentMillis;
  }
}

mit getMillis(i) bekommt man die jeweiligen millis retour.

ergibt:

10:44:15.334 -> Timer0 0	Timer1 0	 active=-1
10:44:15.836 -> Timer0 0	Timer1 0	 active=-1
10:44:16.338 -> Timer0 0	Timer1 0	 active=-1
10:44:16.825 -> Timer0 0	Timer1 0	 active=-1
10:44:17.142 -> Button pressed 0
10:44:17.342 -> Timer0 200	Timer1 0	 active=0
10:44:17.844 -> Timer0 701	Timer1 0	 active=0
10:44:18.300 -> Timer0 1202	Timer1 0	 active=0
10:44:18.802 -> Timer0 1703	Timer1 0	 active=0
10:44:19.304 -> Timer0 2204	Timer1 0	 active=0
10:44:19.806 -> Timer0 2705	Timer1 0	 active=0
10:44:20.308 -> Timer0 3206	Timer1 0	 active=0
10:44:20.826 -> Timer0 3707	Timer1 0	 active=0
10:44:21.312 -> Timer0 4208	Timer1 0	 active=0
10:44:21.761 -> Button pressed 1
10:44:21.815 -> Timer0 4208	Timer1 46	 active=1
10:44:22.317 -> Timer0 4208	Timer1 547	 active=1
10:44:22.834 -> Timer0 4208	Timer1 1048	 active=1
10:44:23.321 -> Timer0 4208	Timer1 1549	 active=1
10:44:23.824 -> Timer0 4208	Timer1 2050	 active=1
10:44:24.327 -> Timer0 4208	Timer1 2551	 active=1
10:44:24.829 -> Timer0 4208	Timer1 3052	 active=1
10:44:25.331 -> Timer0 4208	Timer1 3553	 active=1
10:44:25.833 -> Timer0 4208	Timer1 4054	 active=1
10:44:26.334 -> Timer0 4208	Timer1 4555	 active=1
10:44:26.784 -> Button pressed 0
10:44:26.837 -> Timer0 4244	Timer1 4555	 active=0
10:44:27.339 -> Timer0 4745	Timer1 4555	 active=0
10:44:27.852 -> Timer0 5246	Timer1 4555	 active=0

edit:
damit man nicht in Versuchung gerät, die Variablen direkt anzusprechen, mal die Timer als Objekte:

// Schachuhr OOP
// https://forum.arduino.cc/t/millis-timer-pausieren-und-wieder-starten/855936
// by noiasca
// 2021-05-01

int8_t activeTimer = -1;                     // stores the active Timer ID

class Timer {
  protected:
    const byte buttonPin;                    // pin to GND starts timer
    uint32_t previousMillis = 0;             // last active millis of this timer
    uint32_t _millis = 0;                    // millis
    const byte id;                           // give each object an ID
    static byte total;                       // keep track of the number of timer objects
    
  public:
    Timer (byte buttonPin): buttonPin(buttonPin), id (total++)
    {}

    void begin()
    {
      pinMode(buttonPin, INPUT_PULLUP);
    }

    void read()  // read button and if different button, activate timer
    {
      if (digitalRead(buttonPin) == LOW && activeTimer != id) activateTimer();
    }

    void activateTimer()                                          // sets timer i to active
    {
      previousMillis = millis();
      Serial.print(F("Button pressed ")); Serial.println(id);
      activeTimer = id;
    }

    uint32_t getMillis()                                          // returns the accumulated millis of one timer
    {
      if (activeTimer == id)                                      // update millis before return
      {
        uint32_t currentMillis = millis();
        _millis += currentMillis - previousMillis;                // add passed time to old millis
        previousMillis = currentMillis;                           // remember the timestamp of the last millis update
      }
      return _millis;
    }

    byte getId()
    {
      return id;
    }
};

byte Timer::total=0;             // declare inside class, but define outside = 0 (leave it 0!)

Timer timer[] {
  {A0},                          // buttonPin
  {A1}
};

void setup() {
  Serial.begin(115200);
  Serial.println(F("Schachuhr"));
  for (auto &i : timer) i.begin();
}

void loop() {
  // read button
  for (auto &i : timer) 
    i.read(); 
  // output
  updateSerial();
}

void updateSerial()                                                 // demo output to serial
{
  static uint32_t previousMillis = 0;
  uint32_t currentMillis = millis();
  if (millis() - previousMillis > 500)
  {
    for (auto &i : timer)
    {
      Serial.print(F("Timer")); Serial.print(i.getId()); Serial.print(" "); Serial.print(i.getMillis()); Serial.print("\t");
    }
    Serial.print(F(" active=")); Serial.println(activeTimer);
    previousMillis = currentMillis;
  }
}
1 Like