Go Down

Topic: Einsteigerfragen: Kann mein Code optimiert werden? Welches Board für Wifi?  (Read 625 times) previous topic - next topic

agmue

In #6 habe ich einen Link zu Programmierrichtlinien ergänzt.

Als Einzelkämpfer ist das egal, in der Gruppe macht eine Richtlinie Sinn.

In #7 hast Du schon (wieder) eine Menge richtig gemacht, dennoch Anmerkungen von mir:

1. Typ:
Code: [Select]
float Menge[] = {55, 25, 30, 50};
Wegen der Deutlichkeit würde ich {55.0, 25.0, 30.0, 50.0} schreiben.

2. Zahl der Elemente:
Code: [Select]
const byte FL[Kreise] = {20, 20, 20, 20};
Der Zugriff auf nicht vorhandene Elemente eines Feldes ist ein häufiger Fehler vom Typ "Programm schmiert manchmal ab". Leider wird das zur Laufzeit vom Programm nicht erkannt. Mit der zusätzlichen Angabe der Anzahl der Elemente kann man dieses Problem zumindest manchmal frühzeitig erkennen.

3. Schleife hin zu loop öffnen: (ungetestet)
Code: [Select]
 // Pumpenaktivierung
  static byte x = 0;
  if (Pumpenfolge < Kreise)
  {
    if ((Pumpenstatus[x] == HIGH) && (Pumpenfolge == x)) //Wenn die Pumpe aus ist und an der Reihe
    {
      digitalWrite (R[x], LOW); // Pumpe einschalten
      Pumpenstatus[x] = LOW; // Pumpenstatus anpassen
      StartMillis_Pumpe[x] = CurrentMillis; //Startpumkt der Pumpe setzen
    }
    else if ((Pumpenstatus[x] == LOW) && (CurrentMillis - StartMillis_Pumpe[x] >= Pumpenlaufzeit[x]) && (Pumpenfolge == x)) //Wenn die Pumpe an ist, die Laufzeit erreicht und an der Reihe
    {
      digitalWrite (R[x], HIGH); // Pumpe ausschalten
      Pumpenstatus[x] = HIGH; // Pumpenstatus anpassen
      Pumpenfolge = x + 1; // Aktiviert die nächste Pumpe und bleibt nach der letzten Pumpe auf ungültigem Wert stehen
    }
  }
  x = (1 + x) % Kreise;
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

olli_h

Hiho und guten Abend, vielen Dank für die Wegweiser und "Hausaufgaben", hab mich mal mit den structs befasst und den code entsprechend umgebaut:

Code: [Select]
const byte Kreise = 4; // Anzahl der Kreise, Achtung bei Änderung auch die Arrays mit anpassen!

//Strukturdefinition
struct Pumpenkreis_st
{
  const byte Nr; //Pumpennummer
  const byte FL; //Förderleistung des Pumpenkreises bis 255 ml/s
  const byte R; //Belegung der Pins für die Pumpenrelais
  float Menge; // Auszubringende Mengen in ml, hier wird float benötigt um die spätere Division durch FL hinzubekommen
  byte Skip; // Kenner ob und wie viele Gießintervalle ausgelassen werden sollen pro Bereich
  uint32_t StartMillis_Pumpe; //Startpunkte der einzelnen Pumpen
  bool Pumpenstatus; //Status ob Pumpe läuft oder nicht
  uint32_t Pumpenlaufzeit; //Länge der Pumpenlaufzeiten pro Kreis
  byte CurrentSkip; // Zähler für die aktuelle Anzahl der Intervalle die bereits ausgelassen worden sind
  byte Folge;

  void init() //Initialisierung
  {
    pinMode (R, OUTPUT); //Pins für die Relais setzen
    digitalWrite (R, HIGH); //Relais schlaten bei LOW, daher Grundzustand HIGH
    CurrentSkip = Skip; //erste Skipwerte setzen
    Folge = Kreise; //Pumpenfolge auf ungültig setzen
  }

  uint32_t calc() //Berechnet die Pumpenlaufzeiten
  {
    if (CurrentSkip < 1) //Wenn nicht geskipt wird, Berechnung aus Menge und Förderleistung
    {
      Pumpenlaufzeit = Menge / FL * 1000;
      CurrentSkip = Skip; //Rücksetzung der Skipvariable auf Ausgangswert
    }
    else
    {
      Pumpenlaufzeit = 0; // Wenn geskipt wird, dann keine Laufzeit
      CurrentSkip--; //Runterzählen der Skipvariable bis 0
    }
    return Pumpenlaufzeit;
  }
  byte start(uint32_t Now, byte Folge) //Lässt die Pumpen laufen, braucht die aktuelle Zeit und die Pumpenfolge als Parameter
  {
    if ((Pumpenstatus == HIGH) && (Folge == Nr)) //Wenn die Pumpe aus ist und an der Reihe
    {
      digitalWrite (R, LOW); // Pumpe einschalten
      Pumpenstatus = LOW; // Pumpenstatus anpassen
      StartMillis_Pumpe = Now; //Startpumkt der Pumpe setzen
    }
    else if ((Pumpenstatus == LOW) && (Now - StartMillis_Pumpe >= Pumpenlaufzeit) && (Folge == Nr)) //Wenn die Pumpe an ist, die Laufzeit erreicht und an der Reihe
    {
      digitalWrite (R, HIGH); // Pumpe ausschalten
      Pumpenstatus = HIGH; // Pumpenstatus anpassen
      Folge++; // Aktiviert die nächste Pumpe und bleibt nach der letzten Pumpe auf ungültigem Wert stehen
    }
    return Folge;
  }

  void ausgabe() //  Gibt Daten auf dem Serial Monitor aus
  {
    Serial.print("Pumpenlaufzeit ");
    Serial.print(Nr);
    Serial.print(": ");
    Serial.println(Pumpenlaufzeit);
  }

};

//Array für Pumpenkreise deklarieren und befüllen
Pumpenkreis_st Pumpenkreis [Kreise]
{ //Nr, FL, R, Menge, Skip, StartMillis_Pumpe, Pumpenstatus, Pumpenlaufzeit, CurrentSkip
  {0,  20, 2, 55.0,  0,    0,                 HIGH,         0,               0           },
  {1,  20, 3, 25.0,  1,    0,                 HIGH,         0,               0           },
  {2,  20, 4, 30.0,  0,    0,                 HIGH,         0,               0           },
  {3,  20, 5, 50.0,  2,    0,                 HIGH,         0,               0           },
};

float ToFirst_h = 0.005; //Zeit bis Start erste Bewässerung in Stunden, 18s zum Testen

uint32_t CurrentMillis; //Aktuell vergangene Zeit seit Start des Controllers
float Intervall_h; // Länge des Intervalls in dem Wasser ausgebracht werden soll in Stunden
uint32_t StartMillis; //Startpunkt des Intervalls bis zur Bewässerung
uint32_t NextIntervall; //Länge des nächsten Intervalls bis zur Bewässerung

uint32_t Pumpenlaufzeit_ges; //Summe aller Pumpenlaufzeiten + Puffer
byte Pumpenfolge = Kreise; // Zeigt welche Pumpe an der Reihe ist. Mit Setzen auf Kreise erst mal ungültig, damit am Anfang nix läuft.
byte Failcode; // Fehlerkenner für Unterbrechung von loop Teilen und Anzeige

uint32_t Monitorintervall = 3000; //Intervall für Ausgabe auf dem Seriellen Monitor
uint32_t StartMonitor = 0;

void setup()
{
  // Initialwerte für Bewässerung
  Serial.begin(9600);
  Failcode = 0; //Fehlercode 0 = kein Fehler
  Intervall_h = 0.005; //Bewässerung alle 18s für Test - später 24 oder 12

  for (Pumpenkreis_st &Pk : Pumpenkreis) Pk.init(); //Pumpenkreis_st ist die Struktur, Pumpenkreis das Array vom Typ Pumpenkreis_st, Pk ist die einzelne Variable im Array Pumpenkreis vom Typ Pumpenkreis_stt, init ist die Methode die innerhalb Pumpenkreis_st aufgerufen wird

  StartMillis = millis(); // Startzeit setzen
  NextIntervall = ToFirst_h * 3600000; //Erstes Intervall setzen in Millis
}

void loop()
{
  CurrentMillis = millis();

  // Bewässerungsintervall
  if (CurrentMillis - StartMillis >= NextIntervall)
  {
    NextIntervall = Intervall_h * 3600000; //Nächstes Intervall setzen in Millis
    StartMillis = CurrentMillis; //Start zurücksetzen
    Pumpenlaufzeit_ges = 2000; //Puffer und Reset der Gesamtlaufzeit
    for (Pumpenkreis_st &Pk : Pumpenkreis) Pumpenlaufzeit_ges = Pumpenlaufzeit_ges + Pk.calc(); //Aufruf Struktur über for in Kurzform wie im Setup kommentiert, Methode calc gibt hier die einzelnen Pumpenlaufzeiten zurück, Summierung in Gesamtlaufzeit
    if (Pumpenlaufzeit_ges > NextIntervall) Failcode = 1; //Prüfung ob Gesamtlaufzeit Pumpen + Puffer unter Intervall liegt
    if (Failcode == 0) Pumpenfolge = 0; // Setzt die Pumpenfolge auf den ersten gültigen Wert und startet damit die Pumpenschleife
  }

  // Pumpenaktivierung
  for (Pumpenkreis_st &Pk : Pumpenkreis) Pumpenfolge = Pk.start(CurrentMillis, Pumpenfolge); //Aufruf wie oben, Methode start bekommt aktuelle Zeit und Pumpenfolge übergeben, gibt die neue Pumpenfolge zurück

  if (CurrentMillis - StartMonitor >= Monitorintervall) //Ausgabe im Intervall
  {
    for (Pumpenkreis_st &Pk : Pumpenkreis) Pk.ausgabe(); //Ausgabe einiger Strukturwerte
    Serial.print("Gesamtlaufzeit der Pumpen: ");
    Serial.println(Pumpenlaufzeit_ges);
    Serial.print("NextIntervall: ");
    Serial.println(NextIntervall);
    Serial.print("Fehler: ");
    Serial.println(Failcode);
    Serial.print("Pumpenfolge: ");
    Serial.println(Pumpenfolge);
    StartMonitor = CurrentMillis;
  }
}


Macht auch wieder das was er soll, Kritik wie immer erwünscht :-)

Der Umbau in class steht noch an.

Ich bin mir nicht ganz sicher, wie man das am besten mit den Variablen macht. Hab irgendwie ein ungutes Gefühl aus einer struct/class Methode globale Variablen zu ändern, obwohl das hier und da einiges vereinfachen würde. Aber eigentlich sollte ja so eine class problemlos in andere codes übertragbar sein und ob sie da die gleichen globalen Variablen findet ist ja eher fraglich, also hab ich mal versucht alles zu übergeben. Hab allerdings auch irgendwo gelesen, dass Variablen per Referenz übergeben werden können, muss ich mir mal anschauen.

Die ESP 32 sind heute auch schon gekommen ... das steht dann auch noch an, vom Uno da drauf umzuziehen ...

Grüssle Olli


combie

Quote
Ich bin mir nicht ganz sicher, wie man das am besten mit den Variablen macht. Hab irgendwie ein ungutes Gefühl aus einer struct/class Methode globale Variablen zu ändern, obwohl das hier und da einiges vereinfachen würde. Aber eigentlich sollte ja so eine class problemlos in andere codes übertragbar sein und ob sie da die gleichen globalen Variablen findet ist ja eher fraglich, also hab ich mal versucht alles zu übergeben. Hab allerdings auch irgendwo gelesen, dass Variablen per Referenz übergeben werden können, muss ich mir mal anschauen.
Ja, ich nenne Funktionen, welche auf globale Variablen zugreifen, oder statische Variablen enthalten Wegwerf Funktionen.
Oder auch wegwerf Klassen, wenn es darin geschieht.

Weil eben nicht/schlecht wieder verwendbar.


Beispiel:
Du hast eine Methode ausgabe() in der Klasse/Struktur erfunden.
Gute Idee!
Ich peppe die mal jetzt mal etwas auf, so dass sie die globale Variable Serial zur Ausgabe übergeben bekommt.
Das ist dann schon mal eine Abhängigkeit weniger.
Auch hast du jetzt die Möglichkeit deine Objekte z.B.  in Dateien zu drucken.
Eben alles, was Print implementiert, nimmt deine Klasse.


Code: [Select]

class Pumpenkreis_st : public Printable
{
  private:
   const int kreis;

  public:
    Pumpenkreis_st(const int kreis):kreis(kreis){}

    virtual size_t printTo(Print & print) const override
    {
      size_t len = 0;
      len += print.print("Kreis ");
      len += print.print(kreis);
      return len;
    }

};

Pumpenkreis_st Pumpenkreis[] {1,2,3,4};


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

void loop()
{
  for (Pumpenkreis_st &Pk : Pumpenkreis) Serial.println(Pk); //Ausgabe einiger Strukturwerte
}







Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
Quelle: Jean-Paul Sartre

gregorss

...
Ich bin gerade eben erst in diesen Thread gestolpert und habe Deinen Code nur sehr oberflächlich quergelesen. Aufgefallen sind mir dabei zwei Dinge:

  • Ich finde Codes außerordentlich lästig, wenn sie zu breit sind und ich horizontal scrollen muss. Da ich meine Programme zum Lesen und Korrigieren gerne ausdrucke und auf dem Balkon lese, sind 80 Zeichen Breite mein Maximum. Notfalls verteile ich Kommentare halt auf mehrere Zeilen. Siehe z.B. hier, drittes Code-Schnipselchen.
  • Den Körper der for-Schleife solltest Du der besseren Lesbarkeit/Verständlichkeit wegen unbedingt klammern. Ich meine das for() nach dem Kommentar '// Pumpenaktivierung'

Das nur mal auf die Schnelle mein Senf dazu.

Gruß

Gregor
Nicht lange fackeln, lass' Backen wackeln! (Seeed)

agmue

Auch zwei Senfkörnchen von mir: Als fauler Mensch mag ich kreis(X_kreis), da ich mir keine zwei Namen ausdenken muß. Zur Verdeutlichung, daß es sich aber um unterschiedliche Dinge handelt, meine Lernversion:

Code: [Select]

class Pumpenkreis_st : public Printable
{
  private:
    const int kreis;

  public:
    Pumpenkreis_st(const int X_kreis): kreis(X_kreis) {}

    virtual size_t printTo(Print & print) const override
    {
      size_t len = 0;
      len += print.print("Kreis ");
      len += print.print(kreis);
      return len;
    }

};

Pumpenkreis_st Pumpenkreis[] {1, 2, 3, 4};


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

void loop()
{
  for (Pumpenkreis_st &Pk : Pumpenkreis) Serial.println(Pk); //Ausgabe einiger Strukturwerte
}

X_kreis enthält die Werte {1, 2, 3, 4}, womit die Konstante kreis, bei einer Variablen als Anfangswert, gefüllt wird. Die Methode verwendet dann die Konstante kreis.

Variablen, die für alle Elemente den gleichen Anfangswert bekommen, können ihren Wert auch vom Konstruktor erhalten:

Code: [Select]
//Strukturdefinition
class Pumpenkreis_st
{
    const byte Nr; //Pumpennummer
    const byte FL; //Förderleistung des Pumpenkreises bis 255 ml/s
    const byte R; //Belegung der Pins für die Pumpenrelais
    float Menge; // Auszubringende Mengen in ml, hier wird float benötigt um die spätere Division durch FL hinzubekommen
    byte Skip; // Kenner ob und wie viele Gießintervalle ausgelassen werden sollen pro Bereich
    uint32_t StartMillis_Pumpe; //Startpunkte der einzelnen Pumpen
    bool Pumpenstatus; //Status ob Pumpe läuft oder nicht
    uint32_t Pumpenlaufzeit; //Länge der Pumpenlaufzeiten pro Kreis
    byte CurrentSkip; // Zähler für die aktuelle Anzahl der Intervalle die bereits ausgelassen worden sind
    byte Folge;

  public:
    Pumpenkreis_st(const byte Nr, const byte FL, const byte R, float Menge, byte Skip):
      Nr(Nr), FL(FL), R(R), Menge(Menge), Skip(Skip), StartMillis_Pumpe(0), Pumpenstatus(HIGH), Pumpenlaufzeit(0), CurrentSkip(0) {}

...

//Array für Pumpenkreise deklarieren und befüllen
Pumpenkreis_st Pumpenkreis [Kreise]
{ //Nr, FL, R, Menge, Skip, StartMillis_Pumpe, Pumpenstatus, Pumpenlaufzeit, CurrentSkip
  {0,  20, 2, 55.0,  0},
  {1,  20, 3, 25.0,  1},
  {2,  20, 4, 30.0,  0},
  {3,  20, 5, 50.0,  2}
};
...


Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

michael_x

Das Wesentliche an combie's Beispiel ist die Ermunterung, eigene Klassen als Erweiterung von Printable zu definieren, um Printable::printTo zu überladen.

Setzt natürlich voraus, dass klar ist, was bei
   MeineKlasse x = ...;
   Serial.println(x);
ausgegeben werden sollte.

Wenn man schon dabei ist, extra eine Funktion/Methode ausgabe() zu erfinden ...

Karma +

olli_h

Hiho zusammen, mal wieder ein update von mir.

Vielen Dank für die Kommentare, hab wie immer versucht das meiste umzusetzen, und die Sache läuft immer noch  :D. Zwischenzeitlich bin ich von Uno auf ESP32 umgezogen. Ging im Wesentlichen problemlos, bis auf das Übertragen des Codes, was etwas nervig ist. Der Boot Button muss im richtigen Moment gedrückt werden und wenn ich den 5V Pin belegt habe, weigert er sich generell Code anzunehmen... ist das normal?

Ich hab nun das Ganze als Class umgebaut und in .h und .cpp Datei geordnet. Ist Code Breite verhandelbar? 100 Zeichen bekomme ich ganz gut hin. Hab ich den Rest so einigermaßen richtig hinbekommen?

Die Sache mit dem Printable check ich noch nicht so ganz. Hab auch irgendwie wenig Material gefunden und noch wenig Zeit mich damit zu beschäftigen. Hab es mal kurz probiert auf die 3 Dateien richtig zu verteilen, aber da gab es Probleme mit dem virtual sitze_t. Hab hier was gefunden, das könnte mich weiter bringen. Gibts da noch irgendwo info Quellen?

Hier mal der aktuelle Stand:

.ino

Code: [Select]
//****************20******************40******************60******************80*****************100
#include "Pumpenkreis_cl.h"

const byte Kreise = 4; // Anzahl der Kreise, Achtung bei Änderung auch die Arrays mit anpassen!

//Array für Pumpenkreise deklarieren, füllen der Variablen, die nicht durchgängig gleich sind
Pumpenkreis_cl Pumpenkreis [Kreise]
{ //Nr, FL, R, Menge, Skip, StartMillis_Pumpe, Pumpenstatus, Pumpenlaufzeit, CurrentSkip
  {0,  20, 12, 55.0,  0},
  {1,  20, 14, 25.0,  1},
  {2,  20, 27, 30.0,  0},
  {3,  20, 26, 50.0,  2},
};

float ToFirst_h = 0.005; //Zeit bis Start erste Bewässerung in Stunden, 18s zum Testen

uint32_t CurrentMillis; //Aktuell vergangene Zeit seit Start des Controllers
float Intervall_h; // Länge des Intervalls in dem Wasser ausgebracht werden soll in Stunden
uint32_t StartMillis; //Startpunkt des Intervalls bis zur Bewässerung
uint32_t NextIntervall; //Länge des nächsten Intervalls bis zur Bewässerung

uint32_t Pumpenlaufzeit_ges; //Summe aller Pumpenlaufzeiten + Puffer

//Zeigt welche Pumpe an der Reihe ist. Mit Setzen auf Kreise ungültig, damit am Anfang nix läuft.
byte Pumpenfolge = Kreise;
byte Failcode; // Fehlerkenner für Unterbrechung von loop Teilen und Anzeige

uint32_t Monitorintervall = 3000; //Intervall für Ausgabe auf dem Seriellen Monitor
uint32_t StartMonitor = 0;

void setup()
{
  // Initialwerte für Bewässerung
  Serial.begin(9600);
  Failcode = 0; //Fehlercode 0 = kein Fehler
  Intervall_h = 0.005; //Bewässerung alle 18s für Test - später 24 oder 12
 
  //Pumpenkreis_cl ist die Klasse, Pumpenkreis das Array vom Typ Pumpenkreis_cl,
  //Pk ist die einzelne Variable im Array Pumpenkreis vom Typ Pumpenkreis_cl,
  //init ist die Methode die innerhalb Pumpenkreis_cl aufgerufen wird
  for (Pumpenkreis_cl &Pk : Pumpenkreis)
  {
    Pk.init(Kreise);
  }
  StartMillis = millis(); // Startzeit setzen
  NextIntervall = ToFirst_h * 3600000; //Erstes Intervall setzen in Millis
}

void loop()
{
  CurrentMillis = millis();

  // Bewässerungsintervall
  if (CurrentMillis - StartMillis >= NextIntervall)
  {
    NextIntervall = Intervall_h * 3600000; //Nächstes Intervall setzen in Millis
    StartMillis = CurrentMillis; //Start zurücksetzen
    Pumpenlaufzeit_ges = 2000; //Puffer und Reset der Gesamtlaufzeit

    //Aufruf Struktur über for in Kurzform wie im Setup kommentiert,
    //Methode calc gibt hier die einzelnen Pumpenlaufzeiten zurück, Summierung in Gesamtlaufzeit
    for (Pumpenkreis_cl &Pk : Pumpenkreis)
    {
      Pumpenlaufzeit_ges = Pumpenlaufzeit_ges + Pk.calc();
    }
   
    //Prüfung ob Gesamtlaufzeit Pumpen + Puffer unter Intervall liegt
    if (Pumpenlaufzeit_ges > NextIntervall) Failcode = 1;
   
    // Setzt die Pumpenfolge auf den ersten gültigen Wert und startet damit die Pumpenschleife
    if (Failcode == 0) Pumpenfolge = 0;
  }

  // Pumpenaktivierung
  //Aufruf wie oben, Methode start bekommt aktuelle Zeit und Pumpenfolge übergeben,
  //gibt die neue Pumpenfolge zurück
  for (Pumpenkreis_cl &Pk : Pumpenkreis)
  {
    Pumpenfolge = Pk.start(CurrentMillis, Pumpenfolge);
  }
 
  if (CurrentMillis - StartMonitor >= Monitorintervall) //Ausgabe im Intervall
  {
    for (Pumpenkreis_cl &Pk : Pumpenkreis) Pk.ausgabe(); //Ausgabe einiger Strukturwerte
    Serial.print("Gesamtlaufzeit der Pumpen: ");
    Serial.println(Pumpenlaufzeit_ges);
    Serial.print("NextIntervall: ");
    Serial.println(NextIntervall);
    Serial.print("Fehler: ");
    Serial.println(Failcode);
    Serial.print("Pumpenfolge: ");
    Serial.println(Pumpenfolge);
    StartMonitor = CurrentMillis;
  }
}


.h
Code: [Select]
//****************20******************40******************60******************80*****************100
#ifndef Pumpenkreis_cl_h
#define Pumpenkreis_cl_h
#include "Arduino.h"
class Pumpenkreis_cl
{
  private:
    const byte Nr; //Pumpennummer
    const byte FL; //Förderleistung des Pumpenkreises bis 255 ml/s
    const byte R; //Belegung der Pins für die Pumpenrelais
    float Menge; // Auszubringende Mengen in ml, hier float für die spätere Division durch FL
    byte Skip; // Kenner ob und wie viele Gießintervalle ausgelassen werden sollen pro Bereich
    uint32_t StartMillis_Pumpe; //Startpunkte der einzelnen Pumpen
    bool Pumpenstatus; //Status ob Pumpe läuft oder nicht
    uint32_t Pumpenlaufzeit; //Länge der Pumpenlaufzeiten pro Kreis
    byte CurrentSkip; //die aktuelle Anzahl der Intervalle die bereits ausgelassen worden sind
    byte Folge;

  public:
    //Konstuktor - heißt wie Klasse, Variablen werden aufgeführt, die im Array initialisiert werden
    //Variablen mit durchgehend gleichen Werten werden im Konstruktor initialisiert (cpp Datei)
   
    Pumpenkreis_cl(const byte Nr, const byte FL, const byte R, float Menge, byte Skip);
   
    void init(byte Kreise); //Initialisierung, braucht Kreise als Parameter

    uint32_t calc(); //Berechnet die Pumpenlaufzeiten
 
    byte start(uint32_t Now, byte Folge); //Lässt Pumpen laufen, braucht akt. Zeit und Pumpenfolge

    void ausgabe(); //  Gibt Daten auf dem Serial Monitor aus
};
#endif


.cpp
Code: [Select]
//****************20******************40******************60******************80*****************100
#include "Arduino.h"
#include "Pumpenkreis_cl.h"

//Konstruktor mit Initalisierung der Variablen, konstante Werte übers Array werden direkt gesezt
Pumpenkreis_cl::Pumpenkreis_cl(const byte Nr, const byte FL, const byte R, float Menge, byte Skip):
  Nr(Nr), FL(FL), R(R), Menge(Menge), Skip(Skip),
  StartMillis_Pumpe(0), Pumpenstatus(HIGH), Pumpenlaufzeit(0), CurrentSkip(0) {}

void Pumpenkreis_cl :: init(byte Kreise) //Initialisierung
{
  pinMode (R, OUTPUT); //Pins für die Relais setzen
  digitalWrite (R, HIGH); //Relais schlaten bei LOW, daher Grundzustand HIGH
  CurrentSkip = Skip; //erste Skipwerte setzen
  Folge = Kreise; //Pumpenfolge auf ungültig setzen
}

uint32_t Pumpenkreis_cl :: calc() //Berechnet die Pumpenlaufzeiten
{
  if (CurrentSkip < 1) //Wenn nicht geskipt wird, Berechnung aus Menge und Förderleistung
  {
    Pumpenlaufzeit = Menge / FL * 1000;
    CurrentSkip = Skip; //Rücksetzung der Skipvariable auf Ausgangswert
  }
  else
  {
    Pumpenlaufzeit = 0; // Wenn geskipt wird, dann keine Laufzeit
    CurrentSkip--; //Runterzählen der Skipvariable bis 0
  }
  return Pumpenlaufzeit;
}

//Lässt Pumpen laufen, braucht aktuelle Zeit und Pumpenfolge
byte Pumpenkreis_cl :: start(uint32_t Now, byte Folge)
{
  //Wenn die Pumpe aus ist und an der Reihe
  if ((Pumpenstatus == HIGH) && (Folge == Nr))
  {
    digitalWrite (R, LOW); // Pumpe einschalten
    Pumpenstatus = LOW; // Pumpenstatus anpassen
    StartMillis_Pumpe = Now; //Startpumkt der Pumpe setzen
  }
  //Wenn die Pumpe an ist, die Laufzeit erreicht und an der Reihe
  else if ((Pumpenstatus == LOW) && (Now - StartMillis_Pumpe >= Pumpenlaufzeit) && (Folge == Nr))
  {
    digitalWrite (R, HIGH); // Pumpe ausschalten
    Pumpenstatus = HIGH; // Pumpenstatus anpassen
    Folge++; // Aktiviert nächste Pumpe, bleibt nach der letzten Pumpe auf ungültigem Wert stehen
  }
  return Folge;
}

void Pumpenkreis_cl :: ausgabe() //  Gibt Daten auf dem Serial Monitor aus
{
  Serial.print("Pumpenlaufzeit ");
  Serial.print(Nr);
  Serial.print(": ");
  Serial.println(Pumpenlaufzeit);
}


Grüsse Olli


noiasca

Quote
Der Boot Button muss im richtigen Moment gedrückt werden und wenn ich den 5V Pin belegt habe, weigert er sich generell Code anzunehmen... ist das normal?
ja, habe ich auch auf einigen Boards.
Nimm OTA, geht sowieso schneller ;-)
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

agmue

Der Boot Button muss im richtigen Moment gedrückt werden ...
Für Faule wie mich: EN-Pin - 10µF Elektrolyt - GND

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

gregorss

Ist Code Breite verhandelbar? 100 Zeichen bekomme ich ganz gut hin.
Ja, klar ist das verhandelbar :-)

Ob und wie Du Deinen Code organisierst/formatierst/usw. hängt im Wesentlichen davon ab, wer damit arbeiten soll. Wenn Du der Einzige bist, der sich damit herumschlagen muss, kannst Du es machen, wie es Dir passt.

Wichtig werden Vorgaben zu Zeilenlänge oder Formatierung/Klammerung dann, wenn mehrere Leute mit dem Code zurecht kommen sollen. Oder z. B. dann, wenn Du sicher sein möchtest, dass Du auch in ein paar Wochen oder Monaten noch verstehen können möchtest, was Du Dir jetzt, wo Du grad im Code steckst, beim Programmieren gedacht hast.

Gruß

Gregor
Nicht lange fackeln, lass' Backen wackeln! (Seeed)

Go Up