INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Multi-Timer-Class
02.12.2019, 19:34
Beitrag #1
Multi-Timer-Class
Die Multi-Timer-Class kann einen oder mehrere Ausgänge schalten, anhand einer Zeiten-Tabelle (Stunden, Minuten). Für jeden Ausgang kann eine extra Tabelle erstellt werden. Es werden immer Einschalt- und Ausschaltzeit eingetragen. Bis zu 20 Zeiten (voreingestellt, lässt sich aber auch erweitern) lassen sich festlegen pro Ausgang/Timer.
Außerdem habe ich das Beispiel so geschrieben, dass Millis() zum berechnen von Stunden/Minuten benutzt wird und man die Zeit auch schneller laufen lassen kann (Modellbahnbetrieb). Ich habe diverse Kommentare hinzugefügt, damit das Prinzip verständlich wird.

Hier mal das Beispiel:
Code:
#include "MultiTimer.h"

const uint16_t MULTIPLY = 30; // 60 Minuten Realzeit sind 2 Minuten Modellbahnzeit, also mal 30.
const uint32_t HOUR_MILLIS = 60 * 60 * 1000L;
const uint32_t MINUTE_MILLIS = 60 * 1000L;
char buf[32];

// Die Schaltzeiten fuer Timer1 jeweils: Einschaltzeit, Ausschaltzeit {h, m, h, m}
const int8_t timearr1[][4] = {
  {0, 3, 0, 7},     // 00:03 - 00:07
  {0, 10, 0, 15},   // 00:10 - 00:15
  {0, 30, 0, 40},   // 00:30 - 00:40
  {1, 10, 1, 25},   // 01:10 - 01:25
  {13, 5, 13, 17},  // 13:05 - 13:17
  {23, 42, 0, 17},  // 23:42 - 00:17
  { -1, -1, -1, -1} // Ende-Markierung
};

// Die Schaltzeiten fuer Timer2 jeweils: Einschaltzeit, Ausschaltzeit {h, m, h, m}
const int8_t timearr2[][4] = {
  {0, 2, 0, 8},     // 00:02 - 00:08
  {0, 9, 0, 25},    // 00:09 - 00:25
  {0, 33, 0, 45},   // 00:33 - 00:45
  {1, 10, 1, 25},   // 01:10 - 01:25
  {8, 0, 12, 0},    // 08:00 - 12:00
  {13, 20, 13, 33}, // 13:20 - 13:33
  {18, 5, 18, 37},  // 18:05 - 18:37
  {23, 42, 0, 17},  // 23:42 - 00:17
  { -1, -1, -1, -1} // Ende-Markierung
};

// Die Schaltzeiten fuer Timer3 jeweils: Einschaltzeit, Ausschaltzeit {h, m, h, m}
const int8_t timearr3[][4] = {
  {0, 1, 0, 9},     // 00:01 - 00:09
  {0, 10, 0, 15},   // 00:10 - 00:15
  {0, 35, 0, 50},   // 00:35 - 00:50
  {1, 10, 1, 25},   // 01:10 - 01:25
  { -1, -1, -1, -1} // Ende-Markierung
};

// Drei Timer-Objekte erstellen. Uebergabe: (Pin, Start-Zustand, Schaltzeiten-Array, Arraygroesse)
MULTI_TIMER timer1(13, 0, timearr1, sizeof(timearr1));
MULTI_TIMER timer2(A2, 0, timearr2, sizeof(timearr2));
MULTI_TIMER timer3(5, 0, timearr3, sizeof(timearr3));

void setup() {
  Serial.begin(115200);
}

void loop() {
  static uint32_t lastMillis;
  uint32_t nowMillis = millis();
  if (nowMillis - lastMillis > 1000) { // die serielle Ausgabe nur einmal pro Sekunde
    lastMillis = nowMillis;
    nowMillis = (nowMillis * MULTIPLY) % (24 * HOUR_MILLIS); // die Millis von den letzten 24 Stunden berechnen (Modulo)
    uint8_t hour = int(nowMillis / HOUR_MILLIS); // Stunden und Minuten werden davon berechnet
    uint8_t minute = int((nowMillis % HOUR_MILLIS) / MINUTE_MILLIS);
    sprintf(buf, "Uhrzeit (hh:mm) = %02i:%02i\n\0", hour, minute);
    Serial.print(buf);
    // Fuer jeden Timer muss regelmaessig das entsprechende Handle aufgerufen werden,
    // damit die Schaltzeiten ueberprueft werden koennen.
    timer1.handle(hour, minute);
    timer2.handle(hour, minute);
    timer3.handle(hour, minute);
  }
}

Und hier die MultiTimer.h:
Code:
#ifndef MULTI_TIMER_H_INCLUDED
#define MULTI_TIMER_H_INCLUDED

#include <Arduino.h>

const uint8_t MAX_SWITCH_TIMES = 20;

class MULTI_TIMER {
  public:
    MULTI_TIMER(const uint8_t, const bool, const int8_t (*)[4], const uint8_t);
    void handle(const uint8_t, const uint8_t);
    bool getState(void) {return _state;}
  private:
    int8_t _switchTimes[MAX_SWITCH_TIMES][4];
    uint8_t _pin;
    bool _state, _newState;
};

#endif // MULTI_TIMER_H_INCLUDED

Und die MultiTimer.cpp:
Code:
#include "MultiTimer.h"

MULTI_TIMER::MULTI_TIMER(const uint8_t pin, const bool state, const int8_t timeArray[][4], const uint8_t size):
  _pin(pin), _state(state), _newState(state) {
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, _state);
  memcpy(_switchTimes, timeArray, size);
}

void MULTI_TIMER::handle(const uint8_t hour, const uint8_t minute) {
  for (uint8_t i = 0; i < MAX_SWITCH_TIMES; i++) {
    if (_switchTimes[i][0] == -1) break;
    if (hour == _switchTimes[i][0] && minute == _switchTimes[i][1]) _newState = 1;
    if (hour == _switchTimes[i][2] && minute == _switchTimes[i][3]) _newState = 0;
  }
  if (_newState == _state) return;
  _state = _newState;
  digitalWrite(_pin, _state);
}

Im ZIP-Archiv (Anhang) gibt's das Ganze nochmal zusammengepackt.


Angehängte Datei(en)
.zip  MultiTimer.zip (Größe: 2 KB / Downloads: 6)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.12.2019, 19:52 (Dieser Beitrag wurde zuletzt bearbeitet: 02.12.2019 19:52 von Tommy56.)
Beitrag #2
RE: Multi-Timer-Class
Ich würde evtl. nur den Pointer auf das sowieso vorhandene Array in der Instanz speichern. Da sparst Du die Kopie der Daten (RAM). Ist dann zwar nicht exakt gekapselt, aber auf unseren kleinen MC halte ich RAM-Ersparnis für wichtiger, als Designregeln.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.12.2019, 20:59
Beitrag #3
RE: Multi-Timer-Class
Eine sehr interessante Sache. Danke dafür!

Wenn ich es richtig verstehe sind alle Zeiten relativ und es bewirkt:
Code:
{1, 10, 1, 25}
eine Aktion von 1 Stunde 10 Minuten bis 1 Stunde 25 Minuten nach einschalten des Controllers.
Nicht von 1:10 Uhr bis 1:25 Uhr. (es sei denn man schaltet den Controller um 00:00 Uhr ein)

Gruß Arne
Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.12.2019, 21:07
Beitrag #4
RE: Multi-Timer-Class
Da das meist für Modellanlagen benutzt wird, ist der Einschaltzeitpunkt wohl als 00:00 definiert

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
03.12.2019, 05:10
Beitrag #5
RE: Multi-Timer-Class
(02.12.2019 20:59)ardu_arne schrieb:  Wenn ich es richtig verstehe sind alle Zeiten relativ und es bewirkt:
Code:
{1, 10, 1, 25}
eine Aktion von 1 Stunde 10 Minuten bis 1 Stunde 25 Minuten nach einschalten des Controllers.
Nicht von 1:10 Uhr bis 1:25 Uhr. (es sei denn man schaltet den Controller um 00:00 Uhr ein)
Das ist nur in dem Beispiel so, weil ich dort Millis() für die Uhrzeit verwende. Du kannst aber auch eine Echtzeituhr anschließen und "Hour, Minute" von dort übergeben, dann sind das echte Uhrzeiten.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
03.12.2019, 11:05
Beitrag #6
RE: Multi-Timer-Class
(02.12.2019 19:52)Tommy56 schrieb:  Ich würde evtl. nur den Pointer auf das sowieso vorhandene Array in der Instanz speichern. Da sparst Du die Kopie der Daten (RAM). Ist dann zwar nicht exakt gekapselt, aber auf unseren kleinen MC halte ich RAM-Ersparnis für wichtiger, als Designregeln.
Ok, ich hab's jetzt doch noch geschafft Deinen Vorschlag umzusetzen. Vielleicht magst Du nochmal drüberschauen (Pointer und Co sind nicht gerade meine Stärke).

MultiTimer.h:
Code:
#ifndef MULTI_TIMER_H_INCLUDED
#define MULTI_TIMER_H_INCLUDED

#include <Arduino.h>

const uint8_t MAX_SWITCH_TIMES = 20;

class MULTI_TIMER {
  public:
    MULTI_TIMER(const uint8_t, const bool, int8_t*);
    void handle(const uint8_t, const uint8_t);
    bool getState(void) {return _state;}
  private:
    int8_t *_switchTimes;
    uint8_t _pin;
    bool _state, _newState;
};

#endif // MULTI_TIMER_H_INCLUDED
MultiTimer.cpp:
Code:
#include "MultiTimer.h"

MULTI_TIMER::MULTI_TIMER(const uint8_t pin, const bool state, int8_t *timeArray):
  _pin(pin), _state(state), _newState(state) {
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, _state);
  _switchTimes = timeArray;
}

void MULTI_TIMER::handle(const uint8_t hour, const uint8_t minute) {
  for (uint8_t i = 0; i < MAX_SWITCH_TIMES; i++) {
    if (_switchTimes[i * 4] == -1) break;
    if (hour == _switchTimes[i * 4] && minute == _switchTimes[i * 4 + 1]) _newState = 1;
    if (hour == _switchTimes[i * 4 + 2] && minute == _switchTimes[i * 4 + 3]) _newState = 0;
  }
  if (_newState == _state) return;
  _state = _newState;
  digitalWrite(_pin, _state);
}

Und das Beispiel:
Code:
#include "MultiTimer.h"

const uint16_t MULTIPLY = 30; // 60 Minuten Realzeit sind 2 Minuten Modellbahnzeit, also mal 30.
const uint32_t HOUR_MILLIS = 60 * 60 * 1000L;
const uint32_t MINUTE_MILLIS = 60 * 1000L;
char buf[32];

// Die Schaltzeiten fuer Timer1 jeweils: Einschaltzeit, Ausschaltzeit {h, m, h, m}
int8_t timearr1[][4] = {
  {0, 3, 0, 7},     // 00:03 - 00:07
  {0, 10, 0, 15},   // 00:10 - 00:15
  {0, 30, 0, 40},   // 00:30 - 00:40
  {1, 10, 1, 25},   // 01:10 - 01:25
  {13, 5, 13, 17},  // 13:05 - 13:17
  {23, 42, 0, 17},  // 23:42 - 00:17
  { -1, -1, -1, -1} // Ende-Markierung
};

// Die Schaltzeiten fuer Timer2 jeweils: Einschaltzeit, Ausschaltzeit {h, m, h, m}
int8_t timearr2[][4] = {
  {0, 2, 0, 8},     // 00:02 - 00:08
  {0, 9, 0, 25},    // 00:09 - 00:25
  {0, 33, 0, 45},   // 00:33 - 00:45
  {1, 10, 1, 25},   // 01:10 - 01:25
  {8, 0, 12, 0},    // 08:00 - 12:00
  {13, 20, 13, 33}, // 13:20 - 13:33
  {18, 5, 18, 37},  // 18:05 - 18:37
  {23, 42, 0, 17},  // 23:42 - 00:17
  { -1, -1, -1, -1} // Ende-Markierung
};

// Die Schaltzeiten fuer Timer3 jeweils: Einschaltzeit, Ausschaltzeit {h, m, h, m}
int8_t timearr3[][4] = {
  {0, 1, 0, 9},     // 00:01 - 00:09
  {0, 10, 0, 15},   // 00:10 - 00:15
  {0, 35, 0, 50},   // 00:35 - 00:50
  {1, 10, 1, 25},   // 01:10 - 01:25
  { -1, -1, -1, -1} // Ende-Markierung
};

// Drei Timer-Objekte erstellen. Uebergabe: (Pin, Start-Zustand, Schaltzeiten-Array)
MULTI_TIMER timer1(13, 0, *timearr1);
MULTI_TIMER timer2(A2, 0, *timearr2);
MULTI_TIMER timer3(5, 0, *timearr3);

void setup() {
  Serial.begin(115200);
}

void loop() {
  static uint32_t lastMillis;
  uint32_t nowMillis = millis();
  if (nowMillis - lastMillis > 1000) { // die serielle Ausgabe nur einmal pro Sekunde
    lastMillis = nowMillis;
    nowMillis = (nowMillis * MULTIPLY) % (24 * HOUR_MILLIS); // die Millis von den letzten 24 Stunden berechnen (Modulo)
    uint8_t hour = int(nowMillis / HOUR_MILLIS); // Stunden und Minuten werden davon berechnet
    uint8_t minute = int((nowMillis % HOUR_MILLIS) / MINUTE_MILLIS);
    sprintf(buf, "Uhrzeit (hh:mm) = %02i:%02i\n\0", hour, minute);
    Serial.print(buf);
    // Fuer jeden Timer muss regelmaessig das entsprechende Handle aufgerufen werden,
    // damit die Schaltzeiten ueberprueft werden koennen.
    timer1.handle(hour, minute);
    timer2.handle(hour, minute);
    timer3.handle(hour, minute);
  }
}


Angehängte Datei(en)
.zip  MultiTimer.zip (Größe: 1,95 KB / Downloads: 1)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
03.12.2019, 11:14
Beitrag #7
RE: Multi-Timer-Class
Sieht auf den ersten Blick gut aus. Ich nehme ja an, Du hast es getestet.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
03.12.2019, 11:26
Beitrag #8
RE: Multi-Timer-Class
(03.12.2019 11:14)Tommy56 schrieb:  Sieht auf den ersten Blick gut aus. Ich nehme ja an, Du hast es getestet.
Ja, funktionieren tut es und auch der Speicherverbrauch ist geringer:
Code:
Der Sketch verwendet 3980 Bytes (12%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 349 Bytes (17%) des dynamischen Speichers, 1699 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Bei der alten Version:
Code:
Der Sketch verwendet 4012 Bytes (12%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 583 Bytes (28%) des dynamischen Speichers, 1465 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Nur, falls Dir am Code noch etwas auffällt.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Fehlermeldung 'class DS3231' has no member named 'lostPower' Schneggl 1 283 12.10.2019 13:25
Letzter Beitrag: hotsystems
  undefined reference und non-class type in template class BennIY 3 396 03.10.2019 18:41
Letzter Beitrag: Tommy56
  Timer Sketch für OLED SSD1331 Talon 20 1.950 17.02.2019 10:48
Letzter Beitrag: Tommy56
Sad Neuling verzweifelt braucht Hilfe delay durch timer ersetzen Lois 1 998 06.02.2019 16:15
Letzter Beitrag: Tommy56
  Timer Richtig dastellen Harlekin 5 793 04.02.2019 12:54
Letzter Beitrag: Tommy56
  Timer auf einzelnen PIN setzen? ardufan01 16 1.672 21.01.2019 22:24
Letzter Beitrag: MicroBahner
  Timer Jack 9 2.859 22.05.2018 08:53
Letzter Beitrag: Jack
  "undefined reference to Class::Methode" obwohl definiert da_user 9 1.732 21.02.2018 23:33
Letzter Beitrag: Tommy56
  timer Mega 2560 4x tone Output see 6 3.590 11.01.2018 20:11
Letzter Beitrag: Tommy56
  Timer 0 Mathias 8 3.023 02.12.2017 17:26
Letzter Beitrag: MicroBahner

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste