Moin liebe gemeinde,
jetzt springe ich auch mal auf den Zug des Ardoino auf.
Nachdem ich einige kleine Sketche erfolgreich umgesetzt habe, wollte ich mal an OOP versuchen.
Die einzelnen Klassen, die ich baue möchte ich später in eine Libery schreiben.
jetzt erst mal zu "meiner" Timer-Klasse.
```cpp
class TTimer
{ unsigned long period;
unsigned long currentTime;
unsigned long startTime;
bool t_activ = false;
public:
typedef void (*t_Action)();
void activ(bool val){ // timer aktivieren / deaktivieren
t_activ = val;
if (t_activ){
startTime = millis();
}
}
void OnTimer(t_Action func){ // Funktion übergeben die aufgerufen werden soll
this->func = func;
}
void SetTimer(unsigned long t_msec){ // Intervall des Timer's
period = t_msec;
}
void tic(){
currentTime = millis();
if (t_activ){
if (currentTime - startTime >= period) {
t_Action(); // hier Function aufrufen
}
}
}
private:
t_Action func;
};
bool toggle;
TTimer myTimer;
void setup() {
pinMode(7, OUTPUT); // put your setup code here, to run once:
myTimer.SetTimer(400);
myTimer.OnTimer(Blinken);
myTimer.activ(true);
}
void loop() {
myTimer.tic();
}
void Blinken(){
toggle = !toggle;
digitalWrite(7, toggle);
}
1. Kann mir jemand sagen, wo mein denkfehler liegt?
2. gibt es eine möglichkeit, das sich eine Klasse nach dem Konstrukt immer wieder aufruft?
Liebe Grüße Jörg
und danke schon mal im vorraus...
was denkst du denn?
oder besser:
Was macht dein Sketch, was soll er statt dessen machen?
jein. Grundsätzlich musst du deinen tick aufrufen. Es gäbe aber ein paar Tricks dass das jemand anderer für dich macht.
Würde ich an deiner Stelle aber vorerst nicht umsetzen.
Das aufrufen einer .tick, .run, .update Member Function im loop ist durchaus üblich.
sorry, ich dachte das wäre offensichtlich...
die Klasse TTimer soll nach jedem ablauf von 400ms (SetTimer)
die Funktion Blinken (OnTimer) aufrufen wenn TTimer (activ=true) ist
Du gibst jedem Objekt (Instanz) einen exakten Zeitpunkt zur Durchführung seiner Tätigkeiten.
In der Arduino Welt ist der Loop deine zentrale Ablaufsteuerung.
Also rufst du darin auch die member functions so auf wie du sie benötigst.
Und die tick/run/update brauchst halt einmal pro Durchlauf.
Du kannst dich auch einlesen zu Factory - bedenke aber, du bist da teilweise auf kleinen 8bittern unterwegs.
Oder bei @MicroBahner s Moba Tools Library reinschauen - da werden auch Objekte angetriggert.
Aber ich denke es gibt vorher noch genug andere Themen beim Erlernen von OOP.
Übrigens: Groß Kleinschreibung: member functions durchgängig mit Kleinbuchstaben beginnen lassen. So wie globale Funktionen auch.
... \sketchbook\_ArduinoCC\ducky_42-sketch_mar13b\ducky_42-sketch_mar13b.ino:29:21: warning: statement has no effect [-Wunused-value]
t_Action(); // hier Function aufrufen
Dann hättest Du gesehen, dass das mit deinem Funktionsaufruf so nicht geht - Du hast den Typ angegeben statt des Funktionspointers.
Ich finde es auch sehr unübersichtlich eine interne Variable genauso zu benennen wie einen Methodenparameter. Und die verbreitete 'Sitte', die Namen von private Variable mit einem '_' zu beginnen finde ich auch sehr übersichtlich.
Danke!
Dann werde ich mal weiter lesen.
Ich komme von Pascal (Delphi) da gibt es doch große Unterschiede!
Zumal Arduino "nur" einen Task zur verfügung hat.
Nochmals danke
Aber da ich jetzt auch schon aufgeräumt habe, poste ich meine kleinen Änderungen hier auch mal:
class TTimer {
unsigned long period;
unsigned long startTime;
bool t_activ = false;
public:
using t_Action = void (*)();
void activ(bool val) { // timer aktivieren / deaktivieren
t_activ = val;
if (t_activ) { startTime = millis(); }
}
void OnTimer(t_Action func_) { // Funktion übergeben die aufgerufen werden soll
func = func_;
}
void SetTimer(unsigned long t_msec) { // Intervall des Timer's
period = t_msec;
}
void tic() {
if (t_activ) {
if (millis() - startTime >= period) {
startTime = millis();
func(); // hier Function aufrufen
}
}
}
private:
t_Action func;
};
bool toggle;
TTimer myTimer;
void setup() {
pinMode(7, OUTPUT); // put your setup code here, to run once:
myTimer.SetTimer(400);
myTimer.OnTimer(Blinken);
myTimer.activ(true);
}
void loop() { myTimer.tic(); }
void Blinken() {
digitalWrite(7, !digitalRead(7));
}
Zumindest blinkt es jetzt ...
"typedef" würde ich durch "using" ersetzen (ist mehr c++ style ), im ursprünglichen Code war der Funktionsaufruf verkehrt, currentTime war überflüssig, in tic() hat "startTime = millis();" gefehlt.
Im Prinzip war das der einzige Fehler, der das Aufrufen der Funktion verhindert hat.
Die von @noiasca ergänzte Zeile, um den Timer immer wieder neu 'aufzuziehen':
und seine weiteren Tips und Ergänzungen solltest Du dir auf jeden Fall auch zu Herzen nehmen
P.S. die Warnungen einzuschalten ist immer eine gute Idee. Viele Warnungen sind eigentlich Fehler. Leider ist das bei der IDE kein Standard ( Vielleicht weil die internen Programme leider auch oft Warnungen erzeugen ).