Frage zur Function Erstellung void() Werteabfrage

Hallo und guten Morgen,

ich möchte das Setup "Laufzeit" der Ventile in eine Function packen. Ich habe insgesamt drei Ventile zu steuern die unterschiedliche Setups bekommen. So wie ich es jetzt Rudimentär gemacht habe funktioniert es für das erste Ventil. Die anderen beiden habe ich der Einfachheit halber noch nicht eingefügt.

Für jedes Setup in die LOOP immer wiederkehrende Codezeilen zu schreiben möchte ich verhindern.

Ich habe schon mehrere Versuche gestartet und die makierten Codezeilen in eine Void function gepackt. Leider bekomme ich die Werte nur zurück wenn ich den Backbutton drücke oder ich hänge komplett in der Schleife fest.

Es geht mir darum die Encoder Werte nach drücken des Switch in der Variablen "laufzeitVentil1" zu speichern. Dann durch drücken des Back Buttons wieder eine Ebene höher zu kommen.

Die ENCODER PINS sind so gewählt, da ich die digital Pins durch ein 4 x Relais und eine TimeModul belegt habe. Wenn es erforderlich ist, kann ich sicherlich die RELAIS Pins auf die jetzigen Encoder Pins legen.

Ich hoffe Ihr habt für einen Wiedereinsteiger einen Lösungsansatz den ich auch verstehe.

Viele Grüße

Michael

I

#include <UTouch.h>
#include <UTouchCD.h>

#include <memorysaver.h>
#include <UTFT.h>
// Encoder
boolean Richtung;
int Pin_clk_Letzter;  
int Pin_clk_Aktuell;
 
// Definition der Eingangs-Pins
int pin_clk = A2;  
int pin_dt = A0; 
int button_pin = A4;

 
int laufzeitVentil1;

  
//==== Creating Objects
UTFT    myGLCD(SSD1289,38,39,40,41); //Parameters should be adjusted to your Display/Schield model
UTouch  myTouch( 6, 5, 4, 3, 2);

//==== Defining Variables
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];


int x, y;

char currentPage, selectedUnit;

void setup() {
// Initial setup

// Initial setup ***ENCODER***
     // Eingangs-Pins Encoder werden initialisiert...
   pinMode (pin_clk,INPUT);
   pinMode (pin_dt,INPUT);
   pinMode (button_pin,INPUT);
    
   // ...und deren Pull-Up Encoder Widerstände aktiviert
   digitalWrite(pin_clk, true);
   digitalWrite(pin_dt, true);
   digitalWrite(button_pin, true);
 
 Serial.begin (115200);
  
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);
  
  drawHomeScreen();  // Draws the Home Screen
  currentPage = '0'; // Indicates that we are at Home Screen
  selectedUnit = '0'; // Indicates the selected unit for the first example, cms or inches
}


//====================================================
void loop() { 
  
  // Home Screen
  if (currentPage == '0') {
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x=myTouch.getX(); // X coordinate where the screen has been pressed
      y=myTouch.getY(); // Y coordinates where the screen has been pressed
      // If we press the Ventil 1 Sensor Button 
      if ((x>=35) && (x<=285) && (y>=90) && (y<=130)) {
        drawFrame(35, 90, 285, 130); // Custom Function -Highlighs the buttons when it's pressed
        currentPage = '1'; // Indicates that we are the first example
        myGLCD.clrScr(); // Clears the screen
        drawVenti1setup(); // Ab hier Anzeige für Ventilsetup Display
        }
        }
       }
        // Ventil 1 Setup 
  if (currentPage == '1') {    
   
  if (myTouch.dataAvailable()) {
      myTouch.read();
      x=myTouch.getX(); // X coordinate where the screen has been pressed
      y=myTouch.getY(); // Y coordinates where the screen has been pressed
      myGLCD.clrScr(); // Clears the screen
        }

        // **** Ab hier würde ich das alles in eine Funktion packen wollen
        // zum Beispiel void VentilSetup-1()

        
       // Auslesen des aktuellen Statuses  
   Pin_clk_Aktuell = digitalRead(pin_clk);
    
   // Überprüfung auf Änderung
   if (Pin_clk_Aktuell != Pin_clk_Letzter)
   { 
          
        if (digitalRead(pin_dt) != Pin_clk_Aktuell) 
        {  
            // Pin_CLK hat sich zuerst verändert
            laufzeitVentil1 ++;
            Richtung = true;
        } 
          
        else
        {       // Andernfalls hat sich Pin_DT zuerst verändert
            Richtung = false;
            laufzeitVentil1--;
        }

   if (laufzeitVentil1 < 0) { //verhindern von minus Werten
            laufzeitVentil1 = 0;
        }
// Nur zur Information für mich Begin
        Serial.print("Aktuelle Position: ");
        Serial.println(laufzeitVentil1);
        Serial.println("------------------------------");
        myGLCD.printNumI(laufzeitVentil1, CENTER, 130); 
   }    
 // Nur zur Information für mich Ende
 
 // Vorbereitung für den nächsten Druchlauf:
   // Der Wert des aktuellen Durchlaufs ist beim nächsten Druchlauf der vorherige Wert
   Pin_clk_Letzter = Pin_clk_Aktuell;
    
   // Reset-Funktion um aktuelle Position zu speichern
   if (!digitalRead(button_pin) && laufzeitVentil1 >=0)
     {
       laufzeitVentil1 = laufzeitVentil1;
       delay(500);
       // Nur zur Information für mich Begin
       Serial.println(laufzeitVentil1);
       // Nur zur Information für mich Ende
     }
     // *** Hier Ende der Funktion **** 
 
        // If we press the Back Button
        
        if ((x>=10) && (x<=60) &&(y>=10) && (y<=36)) {
          drawFrame(10, 10, 60, 36);
          currentPage = '0'; // Indicates we are at home screen
          myGLCD.clrScr();
          //gesamtlaufzeit = laufzeit1 + laufzeit2 + laufzeit3 + laufzeit4; //Addition er einzelnen Ventillaufzeiten zur Gesamtlaufzeit
          drawHomeScreen(); // Draws the home screen
          
        }
      }
  }
     

void drawHomeScreen() {
  // Title
  //Serial.print(gesamtlaufzeit);
  myGLCD.setBackColor(0,0,0); // Sets the background color of the area where the text will be printed to black
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(BigFont); // Sets font to big
  myGLCD.print("NATURGARTEN REGEN", CENTER, 10); // Prints the string on the screen
  myGLCD.setColor(255, 0, 0); // Sets color to red
  myGLCD.drawLine(0,32,319,32); // Draws the red line
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(SmallFont); // Sets the font to small
  myGLCD.print("Halbautomatische Bewaesseung", CENTER, 41); // Prints the string
  myGLCD.setFont(BigFont);
  myGLCD.print("Magnetventil auswahl", CENTER, 64);
  
   // Button - Ventil 1
  myGLCD.setColor(16, 167, 103); // Sets green color
  myGLCD.fillRoundRect (35, 90, 285, 130); // Draws filled rounded rectangle
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.drawRoundRect (35, 90, 285, 130); // Draws rounded rectangle without a fill, so the overall appearance of the button looks like it has a frame
  myGLCD.setFont(BigFont); // Sets the font to big
  myGLCD.setBackColor(16, 167, 103); // Sets the background color of the area where the text will be printed to green, same as the button
  myGLCD.print("Ventil 1", CENTER, 102); // Prints the string

  // Button - Ventil 2
  myGLCD.setColor(16, 167, 103);
  myGLCD.fillRoundRect (35, 140, 285, 180);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (35, 140, 285, 180);
  myGLCD.setFont(BigFont);
  myGLCD.setBackColor(16, 167, 103);
  myGLCD.print("Ventil 2", CENTER, 152);

 // Button - Ventil 3
  myGLCD.setColor(16, 167, 103);
  myGLCD.fillRoundRect (35, 190, 285, 230);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (35, 190, 285, 230);
  myGLCD.setFont(BigFont);
  myGLCD.setBackColor(16, 167, 103);
  myGLCD.print("Ventil 3", CENTER, 202);
  }

void drawVenti1setup() {
  myGLCD.setColor(100, 155, 203);
  myGLCD.fillRoundRect (10, 10, 60, 36);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (10, 10, 60, 36);
  myGLCD.setFont(BigFont);
  myGLCD.setBackColor(100, 155, 203);
  myGLCD.print("<-", 18, 15);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.setFont(SmallFont);
  myGLCD.print("Back to Main Menu", 70, 18);
  myGLCD.setFont(BigFont);
  myGLCD.print("REGEN-DAUER", CENTER, 50);
  myGLCD.print("Ventil 1", CENTER, 76);
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawLine(0,100,319,100);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(SevenSegNumFont);

  
}

void encoderWert() {
 //TFT-TOUCH Definitionen
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);
  //myGLCD.setColor(100, 155, 203); // Textfarbe
  myGLCD.setColor(255, 255, 255); // Textfarbe
  myGLCD.setFont(SevenSegNumFont);
   
  }


// Highlights the button when pressed
void drawFrame(int x1, int y1, int x2, int y2) {
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (x1, y1, x2, y2);
}

Du willst 3 Ventile vom Touchscreen steuerbar machen?
Deine Frage bezieht sich also auf das Touchdisplay und nicht auf die Ventile?
Ich würde alle Parameter in ein 2 dimensionales Array oder in viele Arrays packen und dann eine Funktion mit dem einzigen Parameter den Index aufrufen.
Grüße Uwe

Erstellung void() Werteabfrage

Es gibt eine void Werte.
Void, heißt unbestimmt/undefiniert
Also quasi das Gegenteil von "Werte".

Void function

Warum muss sie unbedingt als void deklariert werden?
evtl. wäre doch ein Rückgabewert ganz praktisch.

Tipp:
Hänge deine Encoderabfrage in einen Timerinterrupt.
(leider sagst du nicht, welchen Arduino du nutzt)

ich möchte das Setup "Laufzeit" der Ventile in eine Function packen

Was verstehst du unter einem Setup?

Eine Funktion liefert generell aus Eingangswerten ein Ergebnis.
Im Laufe der Rechenvorschrift kann die Funktion auch noch nebenbei andere Sachen machen und neben den Eingangswerten auf andere Sachen zugreifen (auch schreibend), so dass auch Funktionen Sinn machen, die kein Ergebnis liefern (das ominöse void Ergebnis).

Ich rate mal, statt "Laufzeit" willst du eigentlich eine Ventilposition errechnen.
Diese Berechnung braucht neben den aktuellen Zuständen der zwei Pins auch deren vorige Zustände und die alte Ventilposition (Von dir Laufzeit genannt). Am besten speicherst du diese Werte in einer Datenstruktur je Ventil und übergibst diese (als Referenz) an deine Funktion, die dann die aktuelle Position zurückliefert (und gleichzeitig in der Struktur für den nächsten Aufruf speichert).

Wenn diese Datenstruktur eine Klasse wäre, könnte diese eine Methode haben, welche diese Funktion realisiert.

Hallo,

ich versuche noch einmal das Ziel zu erklären. Fällt mir noch ein wenig schwer.

  • Erstellen eines Setups für drei Magnetventile die eine Beregnungsanlage versorgen.
    Die drei Ventile haben unterschiedliche Laufzeiten/öffnungszeiten
    z.B Ventil 1= 15 Minuten, Ventil 2 = 30 Minuten etc.
    in meinem Beispielsketch habe ich die Wert Eingabe für ein Ventil erstellt.
    Allerdings noch innerhalb der void loop()

Funktioniert auch soweit !!

Als Eingabe Medium habe ich einen ROTARY ENCODER
Ist der Wert eingestellt,wird durch drücken des Switch der Wert in der Variablen laufzeitVentil1 gespeichert .

Ziel:
Die Eingabe ausserhalb der void loop() zu steuern.

Frage: Wie kann ich die Auslagerung des Codes realisieren, so dass ich nicht für jedes der drei Ventile wieder neuen Code "Copy/Paste" in der void loop() einfüge.

Hardware:
Arduino MEGA 2560
Touch Display 3.2" TFT LCD Touch Screen with SD slot for Arduino and Raspberry Pi – SainSmart.com

Shield : SainSmart TFT LCD Adjustable Shield for Arduino Mega 2560 R3 1280 A082 Plug – SainSmart.com

4 fach Relais Modul: 4-Relais Modul 5V mit Optokoppler Low-Level-Trigger kompatibel mit Ard – AZ-Delivery

Rotary Encoder

arduino rtc ds3231 Realtime Clock

Ich hoffe das ich das soweit richtig beschrieben habe. Für meine vorherige wohl doch etwas konfuse Fragestellung "Sorry"

Viele Grüße

Michael

Auch wenn mir dein Ausdruck Setup sehr ungewohnt/unverständlich erscheint:

Was du suchst, ist sicher eine Funktion, die mehrfach aufgerufen werden kann, was dir

  1. copy/paste für Code-Teile erspart.
  2. loop() übersichtlicher macht.

Meine Vorschläge

  1. statt einer void Funktion eine mit Rückgabewert machen
  2. die erforderlichen und je Ventil vorhandenen Daten einer Struktur zusammenfassen
  3. Die Vorschläge 1. und 2. zusammenzufassen und aus der Funktion eine Klassen-Methode machen
    haben dich wohl erschlagen.

Aber Programmieren ist ein iterativer Prozess. Die Ideen kann man auch Schritt für Schritt umsetzen.
Fangen wir an mit Schritt

  1. Ja. mach doch.
    z.B. so ähnlich (ungetestet):
void VentilSetup(
  const byte pin_clk, const byte pin_dt, // Pin Nummern
  bool& clk_Letzter, // interne Merker  
  int& laufzeitVentil,  // Ergebnisse
  bool& richtung
  ) 
{        
       // Auslesen des aktuellen Statuses  
   bool Pin_clk_Aktuell = digitalRead(pin_clk);
    
   // Überprüfung auf Änderung
   if (Pin_clk_Aktuell != clk_Letzter)
   { 
        if (digitalRead(pin_dt) != Pin_clk_Aktuell) 
        {  
            // Pin_CLK hat sich zuerst verändert
            laufzeitVentil ++;
            richtung = true;
        } 
          
        else
        {       // Andernfalls hat sich Pin_DT zuerst verändert
            richtung = false;
            laufzeitVentil--;
        }
   }
   if (laufzeitVentil < 0) { //verhindern von minus Werten
       laufzeitVentil = 0;
   }

   
   // Vorbereitung für den nächsten Druchlauf:
   // Der Wert des aktuellen Durchlaufs ist beim nächsten Druchlauf der vorherige Wert
   clk_Letzter = Pin_clk_Aktuell;
}

Werte, die überschrieben werden, werden als Referenz übergeben. Wenn sie zum nächsten loop() Durchlauf erhalten bleiben müssen, am besten global definieren. Für alle Parameter braucht jedes Ventil natürlich eigene Variable.

Delays haben in einer Funktion nichts zu suchen. Für's erste hab ich mal die Wertübergabe bei Tastendruck rausgelassen.

Vorschlag 2 würde den jeweiligen Aufruf
VentilSetup(pin_clk, pin_dt , Pin_clk_Letzter, laufzeitVentil1, Richtung);
optisch vereinfachen.

Als Rückgabewert (Vorschlag 1) bietet sich entweder die aktuelle Laufzeit an, oder z.b. ein bool bei erfolgtem Tastendruck, wenn diese Auswertung innerhalb der Funktion erfolgt.

Aber, das kann man nach und nach ändern/verschönern.

michael_x:
Auch wenn mir dein Ausdruck Setup sehr ungewohnt/unverständlich erscheint:

Was du suchst, ist sicher eine Funktion, die mehrfach aufgerufen werden kann, was dir

  1. copy/paste für Code-Teile erspart.
  2. loop() übersichtlicher macht.

Meine Vorschläge

  1. statt einer void Funktion eine mit Rückgabewert machen
  2. die erforderlichen und je Ventil vorhandenen Daten einer Struktur zusammenfassen
  3. Die Vorschläge 1. und 2. zusammenzufassen und aus der Funktion eine Klassen-Methode machen
    haben dich wohl erschlagen.

Aber Programmieren ist ein iterativer Prozess. Die Ideen kann man auch Schritt für Schritt umsetzen.
Fangen wir an mit Schritt

  1. Ja. mach doch.
    z.B. so ähnlich (ungetestet):
void VentilSetup(

const byte pin_clk, const byte pin_dt, // Pin Nummern
  bool& clk_Letzter, // interne Merker 
  int& laufzeitVentil,  // Ergebnisse
  bool& richtung
  )
{       
      // Auslesen des aktuellen Statuses 
  bool Pin_clk_Aktuell = digitalRead(pin_clk);
   
  // Überprüfung auf Änderung
  if (Pin_clk_Aktuell != clk_Letzter)
  {
        if (digitalRead(pin_dt) != Pin_clk_Aktuell)
        { 
            // Pin_CLK hat sich zuerst verändert
            laufzeitVentil ++;
            richtung = true;
        }
         
        else
        {      // Andernfalls hat sich Pin_DT zuerst verändert
            richtung = false;
            laufzeitVentil--;
        }
  }
  if (laufzeitVentil < 0) { //verhindern von minus Werten
      laufzeitVentil = 0;
  }

// Vorbereitung für den nächsten Druchlauf:
  // Der Wert des aktuellen Durchlaufs ist beim nächsten Druchlauf der vorherige Wert
  clk_Letzter = Pin_clk_Aktuell;
}




Werte, die überschrieben werden, werden als Referenz übergeben. Wenn sie zum nächsten loop() Durchlauf erhalten bleiben müssen, am besten global definieren. **Für alle Parameter braucht jedes Ventil natürlich eigene Variable**.

Delays haben in einer Funktion nichts zu suchen. Für's erste hab ich mal die Wertübergabe bei Tastendruck rausgelassen. 

Vorschlag 2 würde den jeweiligen Aufruf
`VentilSetup(pin_clk, pin_dt , Pin_clk_Letzter, laufzeitVentil1, Richtung);`
optisch vereinfachen.

Als Rückgabewert (Vorschlag 1) bietet sich entweder die aktuelle Laufzeit an, oder z.b. ein bool bei erfolgtem Tastendruck, wenn diese Auswertung innerhalb der Funktion erfolgt.

Aber, das kann man nach und nach ändern/verschönern.

Vielen Dank,

ja ich gestehe, ich habe mir das umsetzten schneller vorgestellt. Merke doch, das viel an Wissen bei mir im laufe der letzten 35 Jahre durch andere Dinge überschrieben wurde. Ich werde es nach Deinen Tipps versuchen umzusetzten.

Gruß
Michael