Ausgelagerte Funktion im Loop nutzen

Hallo,

ich bräuchte etwas Hilfe bei meinem Projekt. Ich find irgendwie nicht die richtige Lösung (obwohl es wahrscheinlich super einfach ist und ich evtl. einfach nur auf dem Schlauch stehe).

Ich hab mir eine kleine Schaltung gebaut, mit einem Arduino und einem Relais, dass die Umwälzpumpe meiner Solaranlage an, bzw. ausschaltet, je nach Aussen und Wassertemperatur.
Das Programm ist noch nicht komplett fertig, es fehlen noch ein paar Funktionen, die ich gerne einfügen will, aber das ist nicht das Thema.

Es geht mir eigentlich nur darum, mir Schreibarbeit zu ersparen und zeitgleich den Code etwas übersichtlicher zu halten.

Worum es mir hauptsächlich geht, ist die Ausgabe an den Seriellen Monitor, da würd ich gerne mehrmals die Temperatur anzeigen lassen.
Um nicht jedesmal 20 Zeilen Code da reinzuballern, würd ichs gern auslagern.

Ich hab mir noch ein LCD bestellt, auf dem ich die serielle Ausgabe anzeigen lassen möchte.

Es geht um den Abschnitt:
" // Serielle Ausgabe"
im unteren Teil des "void loop"

Das ist mein bisheriger Code:

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 4
#define LED_GREEN 12
#define LED_RED 13
#define RELAY 2

OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature. 

int numberOfDevices; // Number of temperature devices found

DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address

void setup(void) {
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(RELAY, OUTPUT);

  Serial.begin(9600);  // start serial port
  sensors.begin();  // Start up the library
  
  numberOfDevices = sensors.getDeviceCount();  // Grab a count of devices on the wire

    // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");

  // Loop through each device, print out address
  for(int i=0;i<numberOfDevices; i++) {
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)) {
      Serial.print("Found device ");
      Serial.print(i, DEC);
		} else {
		  Serial.print("Found ghost device at ");
		  Serial.print(i, DEC);
		  Serial.print(" but could not detect address. Check power and cabling");
		}
  }
}

void loop(void) { 
  sensors.requestTemperatures(); // Send the command to get temperatures
  
    // Search the wire for address
    sensors.getAddress(tempDeviceAddress, 0);
    float tempCWasser = sensors.getTempC(tempDeviceAddress);
    sensors.getAddress(tempDeviceAddress, 1);
    float tempCAussen = sensors.getTempC(tempDeviceAddress);
   
    float minimumAussen = 20.0;
    float minimumWasser = 40.0;

    // tempCAussen >= minimumAussen
    // tempCWasser >= minimumWasser

    if(tempCAussen >= minimumAussen){
      if(tempCWasser < minimumWasser){
        Serial.println("Aussentemperatur hoch genug");
        Serial.println("2 Minuten Pumpe laufen lassen");
        RelayEin();
        delay(10000); // 2min laufen lassen zum testen
        if(tempCWasser < minimumWasser){
          Serial.println("Wasser ist nicht warm genug, 30min warten");
          RelayAus();
          delay(20000); // 30min warten bis erneuter Versuch
        }      
        else if(tempCWasser >= minimumWasser){
        Serial.println("Wasser ist warm genug, Pumpe einschalten");
        RelayEin();
        }
      }
      else{
      Serial.println("Wasser ist warm genug, Pumpe einschalten");
      RelayEin();
      }
    }
    else{
      Serial.println("Aussentemperatur nicht hoch genug");
      RelayAus();
    }

    // Serielle Ausgabe
    if(tempCAussen >= minimumAussen){
      Serial.print("Aussen: ");
      Serial.print(tempCAussen);
      Serial.println("°C (✓)");    
    }
    else{
      Serial.print("Aussen: ");
      Serial.print(tempCAussen);
      Serial.println("°C (X)");
    }
    if(tempCWasser >= minimumWasser){   
      Serial.print("Wasser: ");
      Serial.print(tempCWasser);
      Serial.println("°C (✓)");    
    }
    else{
      Serial.print("Wasser: ");
      Serial.print(tempCWasser);
      Serial.println("°C (X)");
    }
    Serial.println();

    delay(2000);
}

//Relais einschalten & grüne LED einschalten
void RelayEin(){
  digitalWrite(LED_RED, LOW);
  digitalWrite(LED_GREEN, HIGH);
  digitalWrite(RELAY, HIGH);
}

//Relais auschlaten & rote LED einschalten
void RelayAus(){
  digitalWrite(LED_RED, HIGH);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(RELAY, LOW);
}

Jetzt würde ich gerne den Serial.print-Teil um die Wasser und Aussentemperaturausgabe in eine Funktion auslagern, um dieses mehrfach nutzen zu können

versucht hab ich es mit:

im loop:

AusgabeAussen();
AusgabeWasser();

unterhalb des loops:

// Ausgabe Aussentemperatur
void AusgabeAussen(){
    if(tempCAussen >= minimumAussen){
      Serial.print("Aussen: ");
      Serial.print(tempCAussen);
      Serial.println("°C (✓)");    
    }
    else{
      Serial.print("Aussen: ");
      Serial.print(tempCAussen);
      Serial.println("°C (X)");
    }
}

// Ausgabe Wassertemperatur
void AusgabeWasser(){
    if(tempCWasser >= minimumWasser){   
      Serial.print("Wasser: ");
      Serial.print(tempCWasser);
      Serial.println("°C (✓)");    
    }
    else{
      Serial.print("Wasser: ");
      Serial.print(tempCWasser);
      Serial.println("°C (X)");
    }
}

Ich denke auch, ich weiss, warum das nicht funktioniert:
die Funktion unterhalb des Loops bekommt die Werte aus den Variablen nicht, bzw. weiss nicht, was die Variablen sein sollen (z.B. "minimumWasser") und umgekehrt.

Aber hab keine Ahnung, wie ich der das mitteilen soll, oder wie ich das umschreiben muss.

MfG
Der_Affenkoenig

nicht in der loop deklarieren sondern dort wo auch

deklariert wird.

Du kannst Variablen unterschiedlich deklarieren, Lokal (spart Speicher) oder Global (frist Speicher).
Du hast deine Variablen lokal deklariert, du kannst sie also nur in deiner Funktion zb. hier im Loop benutzen.
Wenn du sie Global deklarierst, oberhalb des Setup (besser übersichtlich) oder auch innerhalb des Setup kann jede Funktion die Variable lesen.
Du hast aber auch die Möglichkeit deine lokalen Variablen an die aufgerufene Funktion zu übergeben, in der Klammer die zu deiner Funktion führt.
Dieter

Sinnvoll wäre, die Temperatur (oder alles variable) als Parameter mitzugeben.

void Ausgabe(const char* text, float val, float min ){
    Serial.print(text);
    Serial.print(val,1);
    if(val >= min) {
       Serial.println("°C (✓)");    
    }
    else{
      Serial.println("°C (X)");
    }
}

Danke, so hats funktioniert.

hab jetzt die minimum temperaturen ganz oben deklariert.
Musste allerdings die Sensorabfrage in die Funktion nochmal reinsetzen, damit er die sich ziehen konnte.

void AusgabeAussen(){
  sensors.requestTemperatures(); // Send the command to get temperatures
  sensors.getAddress(tempDeviceAddress, 1);
  float tempCAussen = sensors.getTempC(tempDeviceAddress);

  if(tempCAussen >= minimumAussen){
  Serial.print("Aussen: ");
  Serial.print(tempCAussen);
  Serial.println("°C (✓)");    
}
else{
  Serial.print("Aussen: ");
  Serial.print(tempCAussen);
  Serial.println("°C (X)");
}
}

Ich halte globale Variablen für keine gute Idee!
In Wegwerffunktionen (setup und loop) kann man das tun, aber in selbst geschriebenenen, sollte man das vermeiden.

Wenn die Temperatur noch jemals irgendwo anders gebraucht wird, ist den Sketch jetzt vermurkster als am Anfang, als dich gestört hat, dass du die Ausgabe doppelt hattest.

Vielleicht hatte ich da etwas falsch/missverständlich geschrieben.

Mich hat nicht gestört, dass die Ausgabe irgendwo mehrmals ist.
Sondern mich hat gestört, dass ich hätte müssen den ganzen Text mehrmals in den Sketch miteinbringen um ihn mehrfach abzurufen.

Der Part sieht jetzt halt so aus:

    if(tempCAussen >= minimumAussen){
      if(tempCWasser < minimumWasser){
        Serial.println("Aussentemperatur hoch genug");
        Serial.println("2 Minuten Pumpe laufen lassen");
        AusgabeAussen();
        AusgabeWasser();
        RelayEin();
        delay(10000); // 2min laufen lassen zum testen
        if(tempCWasser < minimumWasser){
          Serial.println("Wasser ist nicht warm genug, 30min warten");
          AusgabeAussen();
          AusgabeWasser();
          RelayAus();
          delay(20000); // 30min warten bis erneuter Versuch
        }      
        else if(tempCWasser >= minimumWasser){
        Serial.println("Wasser ist warm genug, Pumpe einschalten");
        AusgabeAussen();
        AusgabeWasser();
        RelayEin();
        }
      }
      else{
      Serial.println("Wasser ist warm genug, Pumpe einschalten");
      AusgabeAussen();
      AusgabeWasser();
      RelayEin();
      }
    }
    else{
      Serial.println("Aussentemperatur nicht hoch genug");
      AusgabeAussen();
      AusgabeWasser();
      RelayAus();
    }

Darin hab ich die Funkton jetzt 6x verwendet.
Ohne die Funktion hätt ich da jedesmal das hier 6x komplett reinschreiben müssen:

    // Serielle Ausgabe
    if(tempCAussen >= minimumAussen){
      Serial.print("Aussen: ");
      Serial.print(tempCAussen);
      Serial.println("°C (✓)");    
    }
    else{
      Serial.print("Aussen: ");
      Serial.print(tempCAussen);
      Serial.println("°C (X)");
    }
    if(tempCWasser >= minimumWasser){   
      Serial.print("Wasser: ");
      Serial.print(tempCWasser);
      Serial.println("°C (✓)");    
    }
    else{
      Serial.print("Wasser: ");
      Serial.print(tempCWasser);
      Serial.println("°C (X)");
    }
    Serial.println();

    delay(2000);
}

Klar, wäre auch gegangen, Strg+C, Strg+V,.......... finde es so aber besser/kompakter.

Und der Monitor gibt jetzt bei jedem Statuswechsel die Temperaturen an:
Screenshot 2024-01-14 140110

Arrays und Structs sind deine Freunde.

such mach nach "Arduino F-Makro" und wende es an.

Oder auch STRG-T

oder statt

 if(tempCAussen >= minimumAussen){
  Serial.print("Aussen: ");
  Serial.print(tempCAussen);
  Serial.println("°C (✓)");    
}
else{
  Serial.print("Aussen: ");
  Serial.print(tempCAussen);
  Serial.println("°C (X)");
}

vieleicht

  Serial.print(F("Aussen: "));
  Serial.print(tempCAussen);
  Serial.println(F("°C "));    
  if(tempCAussen >= minimumAussen) {
    Serial.println(F("(✓)"));    
  }
  else {
    Serial.println(F("(X)"));
  }

oder vielleicht:

  Serial.print(F("Aussen: "));
  Serial.print(tempCAussen);
  Serial.println(F("°C "));    
  Serial.println((tempCAussen >= minimumAussen)?"(✓)":"(X)");

Deine delay() brechen Dir das Genick.
Wenn nicht gleich, dann aber irgendwann.

Das sieht mir sehr nach endlichem Automaten / Schrittkette aus.
Es wäre schön, mal einen kompletten Code zu sehen.
Dann könnte man daraus etwas machen, was auch funktioniert.

Na, da habe ich etwas übertrieben.
Sechs mal eine Funktion aufrufen ist schonmal besser als sechsmal Code kopieren.

Allerdings, je häufiger eine Funktion aufgerufen wird, umso relevanter ist es, dass diese nicht überflüssigen Code (Temperatur lesen) enthält.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.