Ich peil doch noch einiges nicht so... braucht noch Zeit. Ich habe es jetzt erst einmal so gelöst, dass die Magnetventil Klasse eine Membervariable vom Typ Feuchtemesser hat. So wie es im Eröffnungspost auch schon vorgesehen war. Man muss erst einmal pro Feuchtemesser eine Instanz anlegen. Eine Referenz dieser Instanz wird dann mit einer begin() Methode der Magnetventilklasse an diese übergeben.
Zwei Getter-Methoden habe ich doppelt, damit ich über die jeweilige Magnetventilklasse auf die Daten der Feuchtemesserklasse zugreifen kann.
So sieht das jetzt aus:
Klassen:
#ifndef _SOLENOIDVALVE_
#define _SOLENOIDVALVE_
#include <Arduino.h>
#include <stdint.h>
class MoistureMeter {
private:
uint8_t analogPin_;
uint16_t maxValue_;
uint16_t minValue_;
uint16_t threshold_;
public:
MoistureMeter() {}
MoistureMeter(uint8_t analogPin, uint16_t min = 3, uint16_t max = 6)
: analogPin_{analogPin}, maxValue_{min}, minValue_{max}, threshold_{max - ((max - min)/3)}{}
void setMinMax(uint16_t, uint16_t);
uint8_t getAnalogPin(void);
uint16_t getMoistureMax(void);
uint16_t getMoistureMin(void);
uint16_t getMoistureThreshold(void);
};
class SolenoidValve {
private:
uint8_t pin_;
uint32_t timeDuration_;
uint32_t timeMarker_;
bool pinStatus_;
MoistureMeter mMeter_;
public:
enum class Status {CLOSED, OPEN, WAIT};
protected:
Status opStatus_ = Status::CLOSED;
public:
SolenoidValve(uint8_t pin = 3, uint32_t timeDuration = 30000)
: pin_{pin}, timeDuration_{timeDuration} {}
void begin(uint8_t, MoistureMeter&);
Status getValveStatus(void);
void setValveStatus(SolenoidValve::Status);
uint32_t getTimeMarker(void);
void setTimeMarker(void);
uint32_t getTimeDuration(void);
bool getPinStatus(void);
void setMoistureMeter(MoistureMeter);
uint16_t getMoistureTheshold(void);
uint8_t getAnalogPin(void);
};
Hauptprogramm
#include <Arduino.h>
#include "adc.hpp"
#include "SolenoidValve.h"
//////////////////////////////////////////////////
// Functions forward declaration(s)
//////////////////////////////////////////////////
uint16_t adcMeasurement(uint8_t analogPin);
void checkSolenoidValve(SolenoidValve &sv, uint16_t measurement );
//////////////////////////////////////////////////
// Global constants and variables
//////////////////////////////////////////////////
// Soil moisture meter
MoistureMeter mMeter_1(PIN_A0, 403, 832);
MoistureMeter mMeter_2(PIN_A1, 399, 847);
// SolenoidValve
constexpr uint8_t PIN_SOLENOID_VALVE_ONE {3}; // Default Pin. Can be overwritten with begin()
constexpr uint8_t PIN_SOLENOID_VALVE_TWO {4};
constexpr uint8_t MAX_SOLENOIDVALVES {2};
SolenoidValve solValve[MAX_SOLENOIDVALVES]; // Two solenoid valves with Standard parameters
//////////////////////////////////////////////////////////////////////////////
/// @brief Setup for main program
///
//////////////////////////////////////////////////////////////////////////////
void setup()
{
#ifdef SERIAL_OUTPUT
Serial.begin(115200);
#endif
solValve[0].begin(PIN_SOLENOID_VALVE_ONE, mMeter_1);
solValve[1].begin(PIN_SOLENOID_VALVE_TWO, mMeter_2);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief main program
///
//////////////////////////////////////////////////////////////////////////////
void loop()
{
for (uint8_t idx = 0; idx < MAX_SOLENOIDVALVES; idx++) {
uint16_t adcResult = adcMeasurement(solValve[idx].getAnalogPin());
#ifdef SERIAL_OUTPUT
Serial.print(F("Pin ")); Serial.print(solValve[idx].getAnalogPin());
Serial.print(F(" : ")); Serial.print(adcResult);
Serial.print(F(" Valve: ")); Serial.print(idx+1);
Serial.print(F(" "));
#endif
checkSolenoidValve(solValve[idx], adcResult );
}
delay(2000);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief This function checks whether a solenoid valve must be
/// opened (soil too dry) or whether it can be closed
/// again (soil moist enough).
///
/// @param sv Reference to a Solenoid valve object
/// @param measurement Measured value from soil moisture sensor
//////////////////////////////////////////////////////////////////////////////
void checkSolenoidValve(SolenoidValve &sv, uint16_t measurement ) {
SolenoidValve::Status statusValve = sv.getValveStatus();
switch(statusValve) {
case SolenoidValve::Status::CLOSED:
if (measurement > sv.getMoistureTheshold()) {
#ifdef SERIAL_OUTPUT
Serial.println(F("Bodenfeuchte gering: Ventil öffnen."));
#endif
sv.setValveStatus(SolenoidValve::Status::OPEN);
sv.setTimeMarker(); // Start for minimum opening time
} else {
#ifdef SERIAL_OUTPUT
Serial.println(F("Bodenfeuchte ausreichend: Ventil geschlossen."));
#endif
}
break;
case SolenoidValve::Status::OPEN:
if (measurement < sv.getMoistureTheshold()) {
#ifdef SERIAL_OUTPUT
Serial.println(F("Bodenfeuchte OK. Ventil schließen."));
#endif
sv.setValveStatus(SolenoidValve::Status::WAIT);
} else {
#ifdef SERIAL_OUTPUT
Serial.println(F("Ventil offen!"));
#endif
}
break;
case SolenoidValve::Status::WAIT:
if (measurement > sv.getMoistureTheshold()) { // Test moisture twice
sv.setValveStatus(SolenoidValve::Status::OPEN);
} else if ((millis() - sv.getTimeMarker()) > sv.getTimeDuration() ) {
#ifdef SERIAL_OUTPUT
Serial.println(F("Ventil schließen"));
#endif
sv.setValveStatus(SolenoidValve::Status::CLOSED);
} else {
#ifdef SERIAL_OUTPUT
Serial.print(F("Mindesöffungszeit für Ventil noch nicht abgelaufen."));
Serial.print(F(" Rest: "));
Serial.print((sv.getTimeDuration() - (millis() - sv.getTimeMarker())) / 1000 );
Serial.println(F(" Sekunden"));
#endif
}
break;
}
}
Damit habe ich eigentlich mein Ziel erreicht. Ich nehme an es geht eleganter, aber das bekomme ich mit meinem Momentanen Wissenstand nicht hin...
Wenn es also noch Tipps gibt nehme ich die gerne auf..
Vielen Dank auch für Deinen Beitrag. Ich habe das quasi aus einem Lehrbuch. Darum habe ich mir das angewöhnt, weil ich so seht schnell Membervariablen erkennen kann. Allerdings habe ich die Unterstriche jetzt hinten angefügt, was die Lesbarkeit vielleicht doch etwas verbessert. 