#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Pindefinitionen für das Display
const int RS= 8;
const int EN= 9;
const int DB7= 7;
const int DB6= 6;
const int DB5= 5;
const int DB4= 4;
const int LED= 10;
// Pin für die Temperatursensoren
const int One_Wire_Bus = 3;
// Pins für die Relais
const int VentilRelaisPin =12;
const int PumpeRelaisPin =13;
// Variablen für Auswertung der Tasten
const int dec=-1;
const int inc=1;
const int Tasterrechts= inc;
const int Tasteroben= 1;
const int Tasterunten= 2;
const int Tasterlinks= dec;
const int Tasterselect= 4;
const int KeinTaster= 5;
// --Displayzustände--
// Definition der Zustände
const byte Z_Statusanzeige = 0;
const byte Z_SetPoolSoll = 1;
const byte Z_SetHystereseEin = 2;
const byte Z_SetHystereseAus = 3;
// Zustandsvaiable
byte Display = Z_Statusanzeige;
// --Betriebszustände--
// Definition der Zustände
const byte Z_Aus=0;
const byte Z_Umwaelzen=1;
const byte Z_Solarbetrieb=2;
const byte Z_WarteAufVentil=3;
// Zustandsvaiablen
byte PumpeVentil=Z_Aus; //PumpeVentilAlt=Z_Aus;
// Werte für bestimmte Zeichen im Display
const unsigned char Pfeillinks=127,Pfeilrechts=126,CharGrad=223;
// --Variablen für die Temperaturen--
// Sensortemperaturen
float PoolIst=0, SolarIst=0;
// SOLL, SOLLMAX und SOLLMIN-Werte für die Pooltemperatur
float PoolSoll=29.5, PoolSollMax=32 , PoolSollMin=20;
// Ein- bzw. Ausschalthysterese für Solarbetrieb
int HystereseEin=6, HystereseEinMin=0, HystereseEinMax=9;
int HystereseAus=2, HystereseAusMin=0, HystereseAusMax=8;
// Einige Merker
bool zustandwechsel=false, wertwechsel=false, TempAenderung=false;
bool ein=true, aus=false;
// --Variablen für die Timer--
const byte stop=0, start=1, laeuft=2;
// Displaytimer
const int DisplayTimeoutZeit = 5 *1000; // nach X Sekunden (*Millisekunden) ohne Tastendruck soll das Display wieder auf Statusanzeige schalten
bool DisplayTimeout=false;
byte DisplayTimer=stop;
// Solarsteuerung
const int SolarEinWartezeit= 10000, SolarAusWartezeit= 10000; // X Minuten*Millisekunden
bool SolarEinTimeout=false, SolarAusTimeout=false;
byte SolarEinTimer=stop, SolarAusTimer=stop;
// Fahrzeit des 3-Wege-Ventils
const unsigned long VentilStellZeit=5*1000; // X Sekunden (*Millisekunden)
bool VentilTimeout=false;
byte VentilTimer=stop;
// Ablesung Temperaturwerte
unsigned int AbleseFrequenz=3*1000;
// Erzeugen der Objekte für Display und Temperatursensoren
LiquidCrystal lcd(RS, EN, DB4, DB5, DB6, DB7);
OneWire oneWire(One_Wire_Bus);
DallasTemperature sensors(&oneWire);
void Pumpe(bool EinAus){
digitalWrite(PumpeRelaisPin, EinAus); // Pumpe ein oder aus
}
void Solarbetrieb(bool EinAus){
//void SolarbetriebEin(void){
static bool MerkerEinAus=aus;
if (VentilTimer==stop){
Serial.println("Pumpe ausschalten");
Pumpe(aus); // Pumpe währen der Ventilfahrt abschalten
if (EinAus==ein){
Serial.println("Ventil auf 'Solar' stellen");
//Ventil(solar);
}
else if(EinAus==aus){
Serial.println("Ventil auf 'Pool' stellen");
//Ventil(pool);
}
Serial.println("Warte Ventilstellzeit");
MerkerEinAus=EinAus;
VentilTimer=start;
PumpeVentil=Z_WarteAufVentil;
}
if (VentilTimeout==true){
Serial.println("Pumpe nach Ventilstellzeit wieder einschalten");
if (MerkerEinAus==ein){
Pumpe(ein);
PumpeVentil=Z_Solarbetrieb;
Serial.println("Solarbetrieb Ein!!");
}
else{
Pumpe(aus);
PumpeVentil=Z_Aus;
Serial.println("Solarbetrieb Aus!!");
}
VentilTimeout=false;
}
}
/*
void SolarbetriebAus (void){
PumpeVentil=Z_Aus;
}
*/
void UpdateTimer (void){
TimerDisplay();
TimerSolarEin();
TimerSolarAus();
TimerVentil();
}
// Prüft ob min<=wert>=max
bool imBereich(float wert, float min, float max){
if((wert-min)*(wert-max) <= 0) return true;
return false;
}
void TimerVentil(){
static unsigned long startmillis= 0;
if (VentilTimer==start){
Serial.println("Starte Ventiltimer");
startmillis=millis();
VentilTimer=laeuft;
}
if (VentilTimer==laeuft){
if (millis()-startmillis > VentilStellZeit){
Serial.print("Ventiltimer abgelaufen " );
VentilTimeout=true;
VentilTimer=stop;
}
}
}
void TimerSolarEin(){
static unsigned long startmillis= 0;
if (SolarEinTimer==start){ //
startmillis=millis();
SolarEinTimer=laeuft;
SolarEinTimeout=false;
Serial.print("SolarEinTimer gestartet " );
Serial.println(SolarEinTimer);
}
if (SolarEinTimer==laeuft){
if ((millis()-startmillis) > SolarEinWartezeit){
SolarEinTimeout=true;
Serial.print("SolarEinTimer abgelaufen " );
Serial.println(SolarEinTimer, SolarEinTimeout);
}
}
}
void TimerSolarAus(){
static unsigned long startmillis= 0;
if (SolarAusTimer==start){ //
startmillis=millis();
SolarAusTimer=laeuft;
SolarAusTimeout=false;
Serial.print("SolarAusTimer gestartet " );
Serial.println(SolarAusTimer);
}
if (SolarAusTimer==laeuft){
if ((millis()-startmillis) > SolarAusWartezeit){
SolarAusTimeout=true;
Serial.print("SolarAusTimer abgelaufen " );
Serial.println(SolarAusTimer, SolarAusTimeout);
}
}
}
void TimerDisplay(){
static unsigned long startmillis= 0;
if (DisplayTimer==start){
Serial.println("Starte Displaytimer");
startmillis=millis();
DisplayTimer=laeuft;
}
if (DisplayTimer==laeuft){
if (millis()-startmillis > DisplayTimeoutZeit){
DisplayTimeout=true;
DisplayTimer=stop;
}
}
}
void HoleTemperaturen(){
static unsigned long letzteAblesung=0;
static float PoolIstAlt=0, SolarIstAlt=0;
static bool firstrun=true;
TempAenderung=false;
if ((millis() - letzteAblesung > AbleseFrequenz)||firstrun){
firstrun=false;
sensors.requestTemperatures();
letzteAblesung = millis();
PoolIstAlt=PoolIst;
SolarIstAlt=SolarIst;
PoolIst=(float)(round(sensors.getTempCByIndex(0)*10))/10; // Runden der Temperaturen auf
SolarIst=(float)(round(sensors.getTempCByIndex(1)*10))/10; // eine Nachkommastelle
/*Serial.print("Pool: ");
Serial.print(PoolIst);
Serial.print(" Solar: ");
Serial.println(SolarIst);*/
if(PoolIst!=PoolIstAlt||SolarIst!=SolarIstAlt){
TempAenderung=true;
Serial.println("Tempänderung!!");
}
}
}
int Holetaster()
{
short Taster=KeinTaster, Analogwert = 0;
static short Tastermerker=KeinTaster;
Analogwert = analogRead(A0); // Auslesen der Taster am Analogen Pin A0.
if (Analogwert > 1000) Taster=Tastermerker=KeinTaster; //Auswerten des gedrückten Tasters
else if (Analogwert < 50) Taster= Tasterrechts;
else if (Analogwert < 300) Taster= Tasteroben;
else if (Analogwert < 500) Taster= Tasterunten;
else if (Analogwert < 700) Taster= Tasterlinks;
else if (Analogwert < 900) Taster= Tasterselect;
else Taster= KeinTaster; // Default = kein Taster gedrückt.
if (Taster!=KeinTaster&&Tastermerker==KeinTaster)//Entprellen des Tasters, gedrückte Taster erst nach loslassen
{
Tastermerker=Taster;
return Taster;
}
return KeinTaster; // Ausgabe wenn kein Taster gedrückt wurde.
}
void SteuerungDisplay(int Taster){
if (DisplayTimeout){
Statusanzeige();
DisplayTimeout=false;
}
if (TempAenderung&&Display==Z_Statusanzeige){
Statusanzeige();
}
if (Taster==Tasterselect)
{
zustandwechsel=true;
DisplayTimer=start;
TimerDisplay();
switch(Display){
case Z_Statusanzeige: SetPoolSoll(NULL); break;
case Z_SetPoolSoll: SetHystereseEin(NULL); break;
case Z_SetHystereseEin: SetHystereseAus(NULL); break;
case Z_SetHystereseAus: Statusanzeige(); break;
//case Z_Statusanzeige: Z_SetPoolSoll(); break;
}
}
if (Taster==Tasterlinks||Taster==Tasterrechts){
wertwechsel=true;
DisplayTimer=start;
TimerDisplay();
switch(Display){
case Z_Statusanzeige: break;
case Z_SetPoolSoll: SetPoolSoll(Taster); break;
case Z_SetHystereseEin: SetHystereseEin(Taster); break;
case Z_SetHystereseAus: SetHystereseAus(Taster); break;
//case Z_Statusanzeige: Z_SetPoolSoll(); break;
}
}
}
void SteuerungPumpeVentil(){
//Serial.println("SteuerungPumpeVentil");
if (PoolIst>=PoolSoll){//gewünschte Temperatur erreicht
Serial.println("PoolSoll OK, alles aus!");
SolarEinTimer=stop; // alle Timer stoppen
SolarAusTimer=stop;
SolarEinTimeout=false;
SolarAusTimeout=false;
if (PumpeVentil=Z_Solarbetrieb){
Solarbetrieb(aus);
//Umwaelzen();????
}
return;
}
switch (PumpeVentil){
case Z_Aus:
case Z_Umwaelzen:{
if (SolarEinTimer==stop &&((SolarIst-PoolIst)>=HystereseEin)){
//PumpeVentilAlt=PumpeVentil; //Speichern des Zustands
SolarEinTimer=start;
Serial.println("Starte SolarEinTimer" );
TimerSolarEin();
break;
}
if ((SolarEinTimer==laeuft)&&((SolarIst-PoolIst) < HystereseEin)){
SolarEinTimer=stop;
Serial.println("Stoppe SolarEinTimer" );
//PumpeVentil=PumpeVentilAlt; //Wiederherstellen des vorherigen Zustands Z_Aus oder Z_Umwaelzen
break;
}
if (SolarEinTimeout){
Serial.println("Solarbetrieb einschalten" );
SolarEinTimer=stop;
SolarEinTimeout=false;
Solarbetrieb(ein);
break;
}
break;
}
case Z_WarteAufVentil: Solarbetrieb(NULL);
case Z_Solarbetrieb: {
if (SolarAusTimer==stop&&((SolarIst-PoolIst)<=HystereseAus)){
SolarAusTimer=start;
Serial.println("Starte SolarAusTimer" );
TimerSolarAus();
break;
}
if (SolarAusTimer==laeuft&&((SolarIst-PoolIst) > HystereseAus)){
SolarAusTimer=stop;
Serial.println("Stoppe SolarAusTimer" );
break;
}
if (SolarAusTimeout){
Serial.println("Solarbetrieb Aus!" );
SolarAusTimer=stop;
SolarAusTimeout=false;
Solarbetrieb(aus);
break;
}
break;
}
}
}
void Statusanzeige()
{
char strPoolIst[7],strSolarIst[7],Zeile2[16];
dtostrf(PoolIst, 4, 1,strPoolIst); // Umwandeln der Temperaturen von floats in strings
dtostrf(SolarIst, 4, 1,strSolarIst); // zu Anzeige nur einer Nachkommastelle
sprintf(Zeile2,"%s%cC %s%cC",strPoolIst,CharGrad,strSolarIst,CharGrad);
lcd.setCursor(0,0);
lcd.print(F(" Pool Solar "));
lcd.setCursor(0,1);
lcd.print(Zeile2);
Serial.println(F("Display=Statusanzeige"));
Display=Z_Statusanzeige;
}
void SetPoolSoll(int incdec)
{
char strPoolSoll[7],Zeile2[16];
//Wert nur verändern, wenn Min-und Max Grenzen eingehalten werden
if (imBereich(PoolSoll+incdec*0.5,PoolSollMin,PoolSollMax))
PoolSoll+=incdec*0.5;
dtostrf(PoolSoll, 4, 1,strPoolSoll);
if (zustandwechsel){
lcd.setCursor(0,0);
lcd.print(" Pool SOLL: ");
}
if (zustandwechsel||wertwechsel){
lcd.setCursor(0,1);
sprintf(Zeile2,"-%c %s%cC %c+",Pfeillinks,strPoolSoll,CharGrad,Pfeilrechts);
lcd.print(Zeile2);
zustandwechsel=false;
wertwechsel=false;
}
Display=Z_SetPoolSoll;
}
void SetHystereseEin(int incdec)
{
if (imBereich(HystereseEin+incdec,HystereseEinMin,HystereseEinMax))
HystereseEin+=incdec;
if (zustandwechsel){
lcd.setCursor(0,0);
lcd.print(" EIN Hysterese: ");
}
if (zustandwechsel||wertwechsel){
char Zeile2[16];
lcd.setCursor(0,1);
sprintf(Zeile2,"-%c %d%cC %c+",Pfeillinks,HystereseEin,CharGrad,Pfeilrechts);
lcd.print(Zeile2);
zustandwechsel=false;
wertwechsel=false;
}
Display=Z_SetHystereseEin;
}
void SetHystereseAus(int incdec)
{
if (imBereich(HystereseAus+incdec,HystereseAusMin,HystereseAusMax))
HystereseAus+=incdec;
if (zustandwechsel){
lcd.setCursor(0,0);
lcd.print(" AUS Hysterese: ");
}
if (zustandwechsel||wertwechsel){
char Zeile2[16];
lcd.setCursor(0,1);
sprintf(Zeile2,"-%c %d%cC %c+",Pfeillinks,HystereseAus,CharGrad,Pfeilrechts);
lcd.print(Zeile2);
zustandwechsel=false;
wertwechsel=false;
}
Display=Z_SetHystereseAus;
}
void setup()
{
Serial.begin(115200); //seriellen Monitor aktivieren
Serial.println(F("Start..."));
pinMode(10, OUTPUT);
pinMode(VentilRelaisPin, OUTPUT); // Pin für Ventilrelais wird als Ausgang definiert
pinMode(PumpeRelaisPin, OUTPUT); // Pin für Pumpenrelaiss wird als Ausgang definiert
digitalWrite(PumpeRelaisPin, LOW); // Pumpe aus
digitalWrite(VentilRelaisPin, LOW); // Ventil in Poolstellung fahren
digitalWrite(10, HIGH); // Beleuchtung für das LCD einschalten
lcd.begin(16, 2); // Starten der Programmbibliothek für das Display
sensors.begin(); // Starten der Programmbibliothek für das Temperatursensoren
sensors.setWaitForConversion(false); //Ablesung der Sensoren asynchron
//HoleTemperaturen();
//Statusanzeige();
}
void loop()
{
int Taster;
HoleTemperaturen();
Taster = Holetaster(); // Abfrage der Taster
SteuerungDisplay(Taster);
SteuerungPumpeVentil();
UpdateTimer();
}