Benutzer-Werkzeuge

Webseiten-Werkzeuge


arduino:flaschenkuehler:programmversion_0.5

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
arduino:flaschenkuehler:programmversion_0.5 [20.08.2017 19:18] Frickelpietarduino:flaschenkuehler:programmversion_0.5 [18.05.2023 12:34] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
-====== Flaschenkühler - Programmversion 0.5 (RC2)======+====== Flaschenkühler - Programmversion 0.5 ======
  
 Diese Programmversion wurde einem ausführlichen Praxistest unterzogen (ca. 150 Stunden). Die dabei gewonnenen Erkenntnisse flossen in letzte Programmverbesserungen ein. Diese Programmversion wurde einem ausführlichen Praxistest unterzogen (ca. 150 Stunden). Die dabei gewonnenen Erkenntnisse flossen in letzte Programmverbesserungen ein.
  
-Es zeigte sich, dass der grafische Anzeigemodus in der Art und Weise, wie er mit dem Arduino Nano umgesetzt werden kann, wenig informativ ist. Er wurde ersetzt und durch einen "Expertenmodus" ersetzt, der die folgenden Werte im Textformat ausgibt:+Es zeigte sich, dass der grafische Anzeigemodus in der Art und Weise, wie er mit dem Arduino Nano umgesetzt werden kann, wenig informativ ist. Ich habe ihn daher ersetzt durch einen "Expertenmodus", der die folgenden Werte im Textformat ausgibt:
   * Solltemperatur   * Solltemperatur
   * Isttemperatur Becherrand   * Isttemperatur Becherrand
Zeile 14: Zeile 14:
 Der dadurch frei gewordene dynamische Speicher wird genutzt, um auch den Thermistor am Becherboden auszulesen. Er fleißt aber nicht in die Regelung des Peltier-Elements ein. Der dadurch frei gewordene dynamische Speicher wird genutzt, um auch den Thermistor am Becherboden auszulesen. Er fleißt aber nicht in die Regelung des Peltier-Elements ein.
  
-Außerdem wurde der Wert für den Activity threshold für Thermistor Nr. 4 von 4 (default) auf 8 verdoppelt, damit die Anzeige der Isttemperatur in allen Anzeigemodi weniger "zappelt"+Außerdem wurde der Wert für den Activity threshold für die Thermistoren Nr. 2, Nr. 3 und Nr. 4 von 4 (default) auf 6 erhöht, damit die Isttemperatur am Kühlbecherrand und des Kühlkörpers weniger "zappeln"
  
-Schließlich wurde der Wert reduziert, der auf die gemessene Umgebungstemperatur addiert wird und der Setpoint für den PID-Regler des Lüfters ist. Experimentell zeigt sich, dass die Reduktion der Kühlkörpertemperatur um 1 °C dazu führt, dass das Peltierelement mit 5% weniger Leistung aufbringen muss, um eine Temperatur von 8°C halten zu können. Es zeigt sich, dass ein Offset von 8 °C optimal ist. Wird der Offset-Wert kleiner angesetzt, läuft der Lüfter sehr häufig mit hohen Drehzahlen.  +<del>Schließlich wurde der Wert reduziert, der auf die gemessene Umgebungstemperatur addiert wird und der Setpoint für den PID-Regler des Lüfters ist. Experimentell zeigt sich, dass die Reduktion der Kühlkörpertemperatur um 1 °C dazu führt, dass das Peltierelement mit 5% weniger Leistung aufbringen muss, um eine Temperatur von 8°C halten zu können. Es zeigt sich, dass ein Offset von 8 °C optimal ist. Wird der Offset-Wert kleiner angesetzt, läuft der Lüfter sehr häufig mit hohen Drehzahlen.</del>  
  
-Tags: #Arduino #Flaschenkühler+Das Array mit den Farbwerten für die Temperaturanzeigen auf dem OLED-Display wurde mit PROGMEM in das EEPROM verlegt, da sonst der Arbeitsspeicher sehr knapp wird. Dadurch werden ziemlich genau 10 % des Arbeitsspeichers freigegeben. 
 + 
 +To Dos: 
 +  * Nach etwa 250 Betriebsstunden zeigt der Thermistor am Becherrand viel zu hohe Temperaturen an. Ich fürchte, er ist kaputt. Kurz darauf hat der Thermistor am Becherboden das gleiche Verhalten gezeigt. 
 +  * Da Thermistoren offenbar kaputt gehen können, sollte für die Kühlung der heißen Seite eine Schutzfunktion für Überhitzung programmiert werden. Diese könnte so aussehen, dass der Lüfter in einen vom PID-Regler unabhängigen Notfallmodus schaltet, wenn der Duty Cycle des Peltierelements über eine gewisse Zeit über beispielsweise 30 % liegt. Der Prozentwert sollte von der passiven Kühlfähigkeit des Kühlkörpers abhängig sein. 
 + 
 +<code> 
 +// Flaschenkühler - Programmversion 0.5 
 +// Diese Version des Programms ... 
 +// ... regelt ein Peltier-Element und einen Lüfter mit jeweils einem PID-Regler ... 
 +// ... misst dafür vier Thermistoren und berechnet die Temperaturen ... 
 +// ... stellt die Solltemperatur des Kühlbechers über zwei Taster ein ... 
 +// ... speichert die Solltemperatur im EEPROM  ... 
 +// ... misst das Tachosignal des Lüfters aus und berechnet die Drehzahl ... 
 +// ... überwacht die Funktion des Lüfters ... 
 +// ... zeigt verschiedene Werte auf einem OLED-Display an ... 
 +// ... unterstützt verschiedene Anzeigemodi ... 
 +// ... zählt die Betriebsstunden (viertelstundengenau) und speichert sie im EEPROM ... 
 +// ... empfiehlt alle 100 Stunden eine Reinigung ... 
 +// ... gibt Daten an die serielle Schnittstelle in einem Format uas, das mit SerialComInstruments interpretiert werden kann ... 
 +// ... und ist damit eigentlich fertig. 
 + 
 +//------------------------- Eingebundene Bibliotheken ---------------------// 
 +#include <Adafruit_GFX.h>                    // Grafik-Bibliothek für OLED-Display 
 +#include <Adafruit_SSD1351.h>                // Bibliothek für OLED-Display (Adafruit OLED Breakout Board 1.27"
 +#include <SPI.h>                             // Bibliothek Serial Peripheral Interface (SPI) 
 +#include <PWM.h>                             // Bibliothek für Änderung der Frequenz der Timer 
 +#include <RunningMedian.h>                   // Bibliothek für Berechnung von Medianwerten 
 +#include <ResponsiveAnalogRead.h>            // Bibliothek zur Glättung analoger Inpots 
 +#include <PID_v1.h>                          // Bibliothek für PID-Regler 
 +#include <ButtonEvents.h>                    // Bibliothek zum Entprellen der Taster 
 +#include <EEPROMex.h>                        // Bibliothek für Lesen und Schreiben des EEPROMS 
 +#include <avr/pgmspace.h>                    // Bibliothek, um Konstanten im Flashmemory zu speichern 
 + 
 +//------------------------- Definition der Inputs und Outputs ---------------------// 
 +#define thermistor1Pin  A1                   // Input-Pin für den Thermistor 1 (Umgebungstemperatur) 
 +#define thermistor2Pin  A3                   // Input-Pin für den Thermistor 2 (Kühlkörper) 
 +#define thermistor3Pin  A5                   // Input-Pin für den Thermistor 3 (Kühlbecherboden) 
 +#define thermistor4Pin  A7                   // Input-Pin für den Thermistor 4 (Kühlbecherrand) 
 +#define tachoPin        2                    // Pin für Tachosignal des Lüfters 
 +#define peltierPin      3                    // PWM-Pin für Peltier-Element (hier zunächst nur als Funktionstest) 
 +#define powerPin        4                    // Schaltet den MOSFET für den Lüfter 
 +#define dc              5                    //  
 +#define cs              6                    // Chip Select 
 +#define rst                                // Reset 
 +#define button2Pin      8                    // Taster 2 
 +#define fanPin          9                    // PWM-Pin für Lüfter 
 +#define button1Pin      12                   // Taster 1 
 + 
 + 
 +//------------------------- Definition der Farben ---------------------// 
 +#define BLACK           0x0000 
 +//#define BLUE            0x0418 
 +//#define BLUEBERRY       0xF810 
 +#define RED             0xF800 
 +//#define GREEN           0x07E0 
 +//#define CYAN            0x07FF 
 +//#define MAGENTA         0xF81F 
 +//#define YELLOW          0xFFE0   
 +#define WHITE           0xFFFF 
 + 
 + 
 +//------------------------- Definition der Variablen ---------------------// 
 +float thermistor1Value = 0;                  // Variable in der der Wert von Thermistor 1 gespeichert wird 
 +float thermistor2Value = 0;                  // Variable in der der Wert von Thermistor 2 gespeichert wird 
 +float thermistor3Value = 0;                  // Variable in der der Wert von Thermistor 3 gespeichert wird 
 +float thermistor4Value = 0;                  // Variable in der der Wert von Thermistor 4 gespeichert wird 
 + 
 +// Temperaturen 
 +float tempAmbient = 0;                       // Umgebungstemperatur 
 +float tempDissipator = 0;                    // Kühlkörpertemperatur 
 +float tempCupbase = 0;                       // Kühlbecherboden 
 +float tempCupedge = 0;                       // Kühlbecherrand 
 +float previousTempCupedge = 0;               // Wird verwendet um festzustellen, ob die Anzeige der Isttemperatur auf dem OLED-Display aktualisiert werden muss. 
 +float TargetTemp = 0;                        // Solltemperatur 
 + 
 +// PWM Frequenzen 
 +unsigned short frequencyFan = 25000;         // PWM-Frequenz für den Lüfter (in Hz) 
 +unsigned short frequencyPeltier = 16000;     // PWM-Frequenz für den Lüfter (in Hz) 
 + 
 +// Lüfter 
 +bool tachoSignal;                            // Tachosignal 
 +unsigned long pulseOn = 0;                   // Ansteigende Signalflanke (Variablenformat nicht verändern!) 
 +unsigned long pulseOff = 0;                  // Abfallende Signalflanke (Variablenformat nicht verändern!) 
 +unsigned long duration;                      // Zeit in Mikrosekunden zwischen ansteigender und abfallender Flanke (Variablenformat nicht verändern!) 
 +bool high = false;                           // Statevariable 
 +int rpm = 0;                                 // Drehzahl des Lüfters in U/Min 
 +int rpmArray[10];                            // Array für die bestimmung der größten Drehzahl aus den letzten 10 Werten 
 +unsigned char a = 0; 
 +int rpmMax = 0;                              // Maximale Drehzahl des Lüfter (aus den letzten 10 Wertens) 
 +int previousRPMMax = 0;                      // Zur Bestimmung von Änderungen der Lüfterdrehzahl 
 +bool fanAlert = false;                       // Wird wahr, wenn der Lüfter blockiert ist 
 +bool fanAlertState = true; 
 +unsigned long fanAlertDelay = 2000;          // Gibt die Verzögerung des Alarms "Lüfterfehlfunktion" in Millisekunden an 
 +unsigned long previousMillis = 0; 
 + 
 +// Betriebsstundenzähler und Serviceintervall 
 +float operatingTime;                         // Betriebsstunden als Dezimalwert 
 +long lastTime = 0; 
 +float serviceInterval;                       // Serviceintervall als Dezimalwert 
 +bool serviceIntervalReset = false;           // Wird wahr, wenn das Service Intervall zurückgesetzt wird 
 + 
 +// Adressen im EEPROM 
 +unsigned char addrOperatingTime = 0;         // Startadresse für eine Variable im Datentyp float (4 Byte!) 
 +unsigned char addrTargetTemp = 4;            // Startadresse für eine Variable im Datentyp double (8 Byte!) 
 +unsigned char addrDisplayMode = 13;          // Adresse für den Anzeigemodus (2 Byte reserviert) 
 +unsigned char addrServiceInterval = 15;      // Startadresse für eine Variable im Datentyp float (4 Byte!) 
 + 
 +// Definiert das OLED 
 +Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst); 
 + 
 +// Definiert ein Array, aus dem Farbwerte ausgelesen werden. Das Array wird mit PROGMEM in den Flash-Speicher geladen, um dynamischen Speicher zu sparen. 
 +const unsigned int colors[] PROGMEM = {0x07FF, 0x07DF, 0x077F, 0x06FF, 0x069F, 0x063F, 0x05DF, 0x057F, 0x053F, 0x049F, 0x043F, 0x03DF, 0x037F, 0x031F, 0x029F, 0x023F, 0x01DF, 0x017F, 0x011F, 0x009F,  
 +0x003F, 0x001F, 0x101F, 0x201F, 0x281F, 0x381F, 0x401F,0x501F, 0x601F, 0x681F, 0x781F, 0x801F, 0x901F, 0x981F, 0xA81F, 0xB81F, 0xC01F, 0xD01F, 0xD81F, 0xE81F,  
 +0xF81F, 0xF81F, 0xF81D, 0xF81B, 0xF81A, 0xF818, 0xF817, 0xF815, 0xF813, 0xF812, 0xF810, 0xF80F, 0xF80D, 0xF80C, 0xF80A, 0xF808, 0xF807, 0xF805, 0xF804, 0xF802, 0xF800}; 
 + 
 +// Informationsanzeige 
 +char displayMode;                              // Anzeigemodus ("0" = Einfach; "1" = Erweitert; "2" = Experte) 
 +bool refreshPeltier = true;                    // Wird wahr, wenn der Anzeigebereich für das Peltier-Element aktualisiert werden muss 
 +bool refreshTargettemp = true;                 // Wird wahr, wenn der Anzeigebereich für die Solltemperatur aktualisiert werden muss 
 +bool refreshFan = true;                        // Wird wahr, wenn der Anzeigebereich für den Lüfter aktualisiert werden muss 
 +unsigned char i = 0; 
 + 
 +// Instantiiert ButtonEvents-Objekte 
 +ButtonEvents button1; 
 +ButtonEvents button2; 
 + 
 +// Instantiiert ein RunningMedian-Objekt zur Bechnung von Medianwerten 
 +RunningMedian medianDuration(5);    // Median aus 5 Werten 
 + 
 +// Instantiirt ResponsiveAnalogRead-Objekte zur Glättung der analogen Inputs 
 +ResponsiveAnalogRead thermistor1(thermistor1Pin, true); 
 +ResponsiveAnalogRead thermistor2(thermistor2Pin, true); 
 +ResponsiveAnalogRead thermistor3(thermistor3Pin, true);  
 +ResponsiveAnalogRead thermistor4(thermistor4Pin, true); 
 + 
 +// Definiert die PID-Regler 
 +double setpointFan, inputFan, outputFan; 
 +double fanP = 40, fanI = 1, fanD = 2; 
 +PID fanPID(&inputFan, &outputFan, &setpointFan, fanP, fanI, fanD, REVERSE); 
 + 
 +double setpointPeltier, inputPeltier, outputPeltier; 
 +double peltierP = 30, peltierI = 0.5, peltierD = 0; 
 +PID peltierPID(&inputPeltier, &outputPeltier, &setpointPeltier, peltierP, peltierI, peltierD, REVERSE); 
 +double previousOutputPeltier = 0; 
 + 
 + 
 +// Definiert die Tracking-Variablen für die IF-Abfragen 
 +unsigned long previousMillisControllers = 0;           // Auslesen der analogen Inputs und Berechnung der Temperaturen 
 +unsigned long previousMillisCalculateFanSpeed = 0;     // Berechnung der Drehzahl des Lüfters 
 +unsigned long previousMillisDisplayCoolingPower  = 0;  // Berechnung der PID-Regler (Lüfter und Peltier-Element) 
 +unsigned long previousMillisDisplayFanSpeed = 0;       // Ausgabe der gemittelten Lüfterdrehzahl an das OLED-Display 
 +//unsigned long previousMillisDisplayGraph = 0;          // Ausgabe der gemittelten Lüfterdrehzahl an das OLED-Display 
 +unsigned long previousMillisSerialPrint = 0;           // Ausgabe an die serielle Schnittstelle 
 + 
 +// Definiert die Intervalle für die IF-Abfragen in Millisekunden 
 +const unsigned long intervalControllers = 100;          // Auslesen der analogen Inputs und Berechnung der Temperaturen 
 +const unsigned long intervalCalculateFanSpeed = 100;   // Berechnung der Drehzahl des Lüfters 
 +const unsigned long intervalDisplayCoolingPower = 1000;// Berechnung der PID-Regler (Lüfter und Peltier-Element) 
 +const unsigned long intervalDisplayFanSpeed = 1000;    // Ausgabe der gemittelten Lüfterdrehzahl an das OLED-Display 
 +//const unsigned long intervalDisplayGraph = 1000;       // Ausgabe der gemittelten Lüfterdrehzahl an das OLED-Display 
 +const unsigned long intervalSerialPrint = 500;         // Ausgabe an die serielle Schnittstelle 
 + 
 +//int loopCounter = 0; 
 + 
 + 
 +//------------------------- Setup ---------------------// 
 +void setup() { 
 +  Serial.begin(115200); 
 +  
 +  // Initialisiert das OLED-Dispaly 
 +  tft.begin(); 
 + 
 +  // Definiert AREF als externe Referenzspannung 
 +  analogReference(EXTERNAL);                         // Dieser Befehl darf auf keinen Fall auskommentiert werden: Das könnte die Hardware zerstören! 
 +   
 +  // Definiert die Pins 
 +  pinMode(tachoPin, INPUT_PULLUP);                    // Tachosignal des Lüfters 
 +  pinMode(powerPin, OUTPUT);                          // Schaltet den MOSFET für den Lüfter 
 +  pinMode(fanPin, OUTPUT);                            // PWM-Signal für Lüfter 
 +  pinMode(peltierPin, OUTPUT);                        // PWM-Signal für Peltier-Element 
 +  pinMode(button1Pin, INPUT_PULLUP);                  // Intur Taster 1 
 +  pinMode(button2Pin, INPUT_PULLUP);                  // Input Taster 2 
 + 
 +  // Initialisiert die ButtonEvents-Objekte 
 +  button1.attach(button1Pin); 
 +  button1.debounceTime(10); 
 +  button1.doubleTapTime(50); 
 +  button1.holdTime(500); 
 +  button2.attach(button2Pin); 
 +  button2.debounceTime(10); 
 +  button2.doubleTapTime(50); 
 +  button2.holdTime(500); 
 +   
 +  // Initialisiert timer1 und timer2 (timer0 bleibt unberührt) 
 +  InitTimersSafe();  
 + 
 +  // Definiert die Frequenzen für die angegebenen Pins 
 +  SetPinFrequencySafe(fanPin, frequencyFan); 
 +  SetPinFrequencySafe(peltierPin, frequencyPeltier); 
 + 
 +  // Definiert die ResponsiveAnalogRead-Objekte 
 +  thermistor2.setActivityThreshold(6); 
 +  thermistor3.setActivityThreshold(6); 
 +  thermistor4.setActivityThreshold(6); 
 +   
 +  /* 
 +  bool successFan = SetPinFrequencySafe(fanPin, frequencyFan); 
 +  bool successPeltier = SetPinFrequencySafe(peltierPin, frequencyPeltier); 
 + 
 +  //if the pin frequency was set successfully, turn pin 13 on 
 +  if(successFan) { 
 +    pinMode(13, OUTPUT); 
 +    digitalWrite(13, HIGH); 
 +    Serial.print("PWM frequency PIN D9 and D10 is set to: "); Serial.println(frequencyFan); 
 +  } 
 +  if(successPeltier) { 
 +    Serial.print("PWM frequency PIN D3 and D11 is set to: "); Serial.println(frequencyPeltier); 
 +  } 
 +  */ 
 +  // Initialisiert die PID-Regler 
 +  fanPID.SetMode(AUTOMATIC); 
 +  peltierPID.SetMode(AUTOMATIC); 
 + 
 +  // Liest die im EEPROM gespeicherten Variablen aus 
 +  displayMode = EEPROM.read(addrDisplayMode); 
 +  operatingTime = EEPROM.readFloat(addrOperatingTime); 
 +  serviceInterval = EEPROM.readFloat(addrServiceInterval); 
 +  TargetTemp = EEPROM.readDouble(addrTargetTemp); 
 + 
 +  // Meldung "Klar zum Start!" 
 +  Serial.println("<Bottlecooler is ready! Enjoy your drink, please ...>");  
 +  Serial.print("<Operating Time: "); Serial.print(operatingTime); Serial.println(" hours>"); 
 +  Serial.print("<Service Interval: "); Serial.print(serviceInterval); Serial.println(" hours>"); 
 +   
 +  // Startbildschirm 
 +  tft.fillScreen(BLACK); 
 +  tft.setCursor(25, 32); 
 +  tft.setTextColor(WHITE, BLACK); 
 +  tft.setTextSize(0); 
 +  tft.print("Flaschenk"); tft.print((char)129); tft.print("hler"); 
 +  tft.setCursor(20, 55); 
 +  tft.print("Programmversion"); 
 +  tft.setCursor(45, 75); 
 +  tft.setTextSize(2); 
 +  tft.print("0.5"); 
 +  if (serviceInterval >= 100.00) { 
 +    tft.setCursor(0, 96); 
 +    tft.setTextColor(RED, BLACK); 
 +    tft.setTextSize(0); 
 +  tft.print("Reinigung empfohlen!"); 
 +  } 
 +  tft.setCursor(10, 108); 
 +  tft.setTextColor(WHITE, BLACK); 
 +  tft.setTextSize(0); 
 +  tft.print("Betriebsstunden:"); 
 +  tft.setCursor(10, 121); 
 +  tft.print(operatingTime); tft.print(" Stunden");  
 +   
 +  delay(2000); 
 +  tft.fillScreen(BLACK); 
 +
 + 
 + 
 +//------------------------- Loop ---------------------// 
 +void loop() { 
 +  // Aktuelle Zeit abfragen 
 +  unsigned long currentMillis = millis(); 
 + 
 +//loopCounter++; 
 + 
 + 
 +//------------------------- Abfrage der Taster ---------------------// 
 +// Lesen und entprellen des Tasters 
 +  button1.update(); 
 +  button2.update(); 
 + 
 +  if (button1.tapped() == true) { 
 +    TargetTemp = TargetTemp + 0.5; 
 +    EEPROM.updateDouble(addrTargetTemp, TargetTemp); 
 +    Serial.print("Updated TargetTemp: "); Serial.println(TargetTemp); 
 +    refreshTargettemp = true; 
 +    if (TargetTemp >= 30.00) { 
 +      TargetTemp = 30.00; 
 +    } 
 +  } 
 +  if (button1.held() == true) { 
 +    displayMode++; 
 +    if (displayMode > 2) { 
 +      displayMode = 0; 
 +    } 
 +    tft.fillScreen(BLACK);                       // Der Bildschirm muss einmalig gelöscht werden 
 +    EEPROM.update(addrDisplayMode, displayMode); 
 +    //Serial.print("Displaymode: "); Serial.println(displayMode); 
 +    refreshPeltier = true; 
 +    refreshTargettemp = true; 
 +    previousTempCupedge = 150; 
 +    refreshFan = true; 
 +  }  
 +  if (button1.doubleTapped() == true) { 
 +    serviceInterval = 0; 
 +    EEPROM.updateFloat(addrServiceInterval, serviceInterval); 
 +    Serial.println("Service Interval reseted!"); 
 +    serviceIntervalReset = true; 
 +  } 
 +   
 +  if (button2.tapped() == true) { 
 +    TargetTemp = TargetTemp - 0.5; 
 +    EEPROM.updateDouble(addrTargetTemp, TargetTemp); 
 +    Serial.print("Updated TargetTemp: "); Serial.println(TargetTemp); 
 +    refreshTargettemp = true; 
 +    if (TargetTemp <= 0.00) { 
 +      TargetTemp = 0.00; 
 +    } 
 +  } 
 +  if (button2.held() == true) { 
 +    displayMode--; 
 +    if (displayMode < 0) { 
 +      displayMode = 2; 
 +    } 
 +    tft.fillScreen(BLACK);                       // Der Bildschirm muss einmalig gelöscht werden 
 +    EEPROM.update(addrDisplayMode, displayMode); 
 +    //Serial.print("Displaymode: "); Serial.println(displayMode); 
 +    refreshPeltier = true; 
 +    refreshTargettemp = true; 
 +    previousTempCupedge = 150; 
 +    refreshFan = true; 
 +  }  
 + 
 + 
 +//------------------------- Auslesen der analogen Inputs (Thermistoren), Berechnung der Temperaturen und Regelung ---------------------//   
 +  if ((unsigned long)(currentMillis - previousMillisControllers) >= intervalControllers) { 
 +    // Widerstandswerte (gemessen) 
 +    // R1 (A1) = 10000, T1 = 9750 
 +    // R2 (A3) = 10500, T2 = 9880 
 +    // R3 (A5) = 10400, T3 = 9860 
 +    // R4 (A7) = 10300, T4 = 9820 
 +     
 +    // Thermistor 1: Umgebungstemperatur 
 +    thermistor1.update();    
 + 
 +    thermistor1Value = thermistor1.getValue();            // Das Ergebnis wird ausgelesen 
 +    // Debug 
 +    Serial.print("T1: "); Serial.print(thermistor1Value);    Serial.print("; ");   
 +    // Berechnung der Temperatur 
 +    thermistor1Value = 1023 / thermistor1Value - 1;        
 +    thermistor1Value = 10000 / thermistor1Value;          // Der Wert wird in einen Widerstand umgerechnet 
 +    tempAmbient = thermistor1Value / 9750;                // (R/Ro) 
 +    tempAmbient = log(tempAmbient);                       // ln(R/Ro) 
 +    tempAmbient /= 3950;                                  // 1/B * ln(R/Ro) 
 +    tempAmbient += 1.0 / (25 + 273.15);                   // + (1/To) 
 +    tempAmbient = 1.0 / tempAmbient;                      // Invert 
 +    tempAmbient -= 273.15;                                // convert to C 
 + 
 + 
 +    // Thermistor 2: Kühlkörper 
 +    thermistor2.update();                                 // Das ResponsiveAnalogRead-Objekt wird aktualisiert 
 + 
 +    thermistor2Value = thermistor2.getValue();            // Das Ergebnis wird ausgelesen 
 +    // Debug 
 +    Serial.print("T2: "); Serial.print(thermistor2Value);    Serial.print("; ");   
 +    // Berechnung der Temperatur 
 +    thermistor2Value = 1023 / thermistor2Value - 1;        
 +    thermistor2Value = 10500 / thermistor2Value;          // Der Wert wird in einen Widerstand umgerechnet 
 +    tempDissipator = thermistor2Value / 9880;             // (R/Ro) 
 +    tempDissipator = log(tempDissipator);                 // ln(R/Ro) 
 +    tempDissipator /= 3950;                               // 1/B * ln(R/Ro) 
 +    tempDissipator += 1.0 / (25 + 273.15);                // + (1/To) 
 +    tempDissipator = 1.0 / tempDissipator;                // Invert 
 +    tempDissipator -= 273.15;                             // convert to C 
 + 
 +     
 +    // Thermistor 3: Kühlbecherboden 
 +    thermistor3.update();                                 // Das ResponsiveAnalogRead-Objekt wird aktualisiert 
 + 
 +    thermistor3Value = thermistor3.getValue();            // Das Ergebnis wird ausgelesen 
 +    // Debug 
 +    Serial.print("T3: "); Serial.print(thermistor3Value);    Serial.print("; "); 
 +    // Berechnung der Temperatur 
 +    thermistor3Value = 1023 / thermistor3Value - 1;        
 +    thermistor3Value = 10400 / thermistor3Value;          // Der Wert wird in einen Widerstand umgerechnet 
 +    tempCupbase = thermistor3Value / 9860;                // (R/Ro) 
 +    tempCupbase = log(tempCupbase);                       // ln(R/Ro) 
 +    tempCupbase /= 3950;                                  // 1/B * ln(R/Ro) 
 +    tempCupbase += 1.0 / (25 + 273.15);                   // + (1/To) 
 +    tempCupbase = 1.0 / tempCupbase;                      // Invert 
 +    tempCupbase -= 273.15;                                // convert to C 
 +     
 +     
 +    // Thermistor 4: Kühlbecherrand 
 +    thermistor4.update();                                 // Das ResponsiveAnalogRead-Objekt wird aktualisiert 
 + 
 +    thermistor4Value = thermistor4.getValue();            // Das Ergebnis wird ausgelesen 
 +    // Debug 
 +    Serial.print("T4: "); Serial.print(thermistor4Value); Serial.println(); 
 +    // Berechnung der Temperatur 
 +    thermistor4Value = 1023 / thermistor4Value - 1;        
 +    thermistor4Value = 10300 / thermistor4Value;          // Der Wert wird in einen Widerstand umgerechnet 
 +    tempCupedge = thermistor4Value / 9820;                // (R/Ro) 
 +    tempCupedge = log(tempCupedge);                       // ln(R/Ro) 
 +    tempCupedge /= 3950;                                  // 1/B * ln(R/Ro) 
 +    tempCupedge += 1.0 / (25 + 273.15);                   // + (1/To) 
 +    tempCupedge = 1.0 / tempCupedge;                      // Invert 
 +    tempCupedge -= 273.15;                                // convert to C    
 + 
 +     
 +    // PID-Regler Lüfter 
 +    inputFan = tempDissipator;                                 // Input ist die Kühlkörpertemperatur in *C 
 +    setpointFan = tempAmbient + 10.00;                          // Umgebungstemperatur + 8 *C 
 +    fanPID.Compute();                                          // PID-Regler wir aufgerufen 
 +    pwmWrite(fanPin, outputFan);                               // Gibt den Output des PID-Reglers an den Lüfter 
 + 
 +    // Wenn der Output des PID-Reglers Null ist, wird der Lüfter ausgeschaltet. 
 +    if (outputFan > 0) { 
 +      digitalWrite(powerPin, HIGH); 
 +      //Serial.print("HIGH"); Serial.print("; "); 
 +    } 
 +    else { 
 +      digitalWrite(powerPin, LOW); 
 +      //Serial.print("LOW"); Serial.print("; "); 
 +    } 
 + 
 + 
 +    // PID-Regler Peltier-Element 
 +    inputPeltier = tempCupedge;                               // Input ist die temperatureHotSide des Thermistors in *C 
 +    setpointPeltier = TargetTemp; 
 +    peltierPID.Compute();                                     // PID-Regler wir aufgerufen 
 +    pwmWrite(peltierPin, outputPeltier);                      // Gibt den Output des PID-Reglers an das Peltier-Element 
 + 
 +    // Überpüft, ob outputPeltier sich geändert hat. 
 +    if (byte(previousOutputPeltier) != byte(outputPeltier)) { // Änderungen hinter dem Komma sollen ignoriert werden 
 +      refreshPeltier = true; 
 +      //Serial.println("refreshPeltier: "); 
 +      previousOutputPeltier = outputPeltier; 
 +    } 
 +     
 +    previousMillisControllers = currentMillis; 
 +  } 
 + 
 + 
 +//------------------------- Tachosignal und Drehzahl des Lüfters ---------------------// 
 +  // Messung der Pulsweite des Tachosignals 
 +  tachoSignal = digitalRead(tachoPin); 
 +  if (tachoSignal == HIGH && high != true) {          // Zeit in micros bei ansteigender Flanke 
 +    pulseOn = micros(); 
 +    high = true; 
 +  } 
 +  else if (tachoSignal == LOW && high == true) { 
 +    pulseOff = micros();                              // Zeit in micros bei fallender Flanke  
 +    high = false; 
 +    duration = pulseOff - pulseOn;                    // Aus der Differenz wir die Dauer berechnet, die das Tachosignal HIGH ist 
 +    if (duration > 7500 && duration < 30000) {        // Liegt die Variable über bzw. unter den angegebenen Werten, liegt ein Messfehler vor 
 +      medianDuration.add(duration);                   // Speichert die Daten in ein Arr 
 +    } 
 +  } 
 +   
 +  // Berechnung der Drehzahl des Lüfters 
 +  if ((unsigned long)(currentMillis - previousMillisCalculateFanSpeed) >= intervalCalculateFanSpeed) { 
 +     
 +    //Berechnung der Drehzal 
 +    if (outputFan == 0) {                              // Wenn der Lüfter ausgeschaltet wird, soll die Drehzahl "0" angezeigt werden 
 +      rpm = 0; 
 +    } 
 +    else { 
 +      rpm = float(100000 * 2 * 60 / medianDuration.getMedian());        // Berechnung der RPM 
 +    } 
 +     
 +    // Bestimmung der höchsten Drehzahl aus den letzten 10 Werten 
 +    a++;                                                // Es werden 10 Werte in einem Array gespeichert 
 +    rpmArray[a] = rpm; 
 +    if (a > 9) { 
 +      a = 0; 
 +    }     
 +    unsigned char kmax=0;                               // Es wird der größte Wert in dem Arrach bestimmt 
 +    int max=0; 
 +    for (unsigned char k=0; k<10; k++) { 
 +      if (rpmArray[k] > max) { 
 +        max = rpmArray[k]; 
 +       kmax = k; 
 +      } 
 +    }  
 +    rpmMax = rpmArray[kmax]; 
 + 
 +    // Überpüft, ob rpmMax sich geändert hat. 
 +    if (previousRPMMax != rpmMax) {                       // Änderungen hinter dem Komma sollen ignoriert werden 
 +      refreshFan = true; 
 +      //Serial.println("refreshFan"); 
 +      previousRPMMax = rpmMax; 
 +    } 
 + 
 + 
 +    /*/Debugging 
 +    Serial.print("; pulseOn: ");Serial.print(pulseOn); 
 +    Serial.print("; pulseOff: ");Serial.print(pulseOff); 
 +    Serial.print("; Duration: "); Serial.print(duration); 
 +    Serial.print("; RPM: "); Serial.print(rpm); 
 +    Serial.print("; average RPM: "); Serial.print(rpmMax); 
 +    //Serial.print("; fanAlert: "); Serial.print(fanAlert); 
 +    //Serial.print("; temperatureHotSide: "); Serial.println(temperatureHotSide); 
 +    //Serial.print("; operatingTime: "); Serial.print(operatingTime);  
 +    //Serial.print("; serviceInterval: "); Serial.print(serviceInterval);  
 +    //Serial.print("; Displaymode: "); Serial.print(displayMode); 
 +    Serial.print("; Loops: "); Serial.println(loopCounter); 
 +    */ 
 +   
 +    // Meldet eine Fehlfunktion des Lüfters, wenn das Tachosignal "0" ist, obwohl der Lüfter sich drehen sollte 
 +    if (millis() >= 10000) {                               // Diese Funktion wird erst nach 10 Sekunden aktiv. 
 +      if (outputFan > 0) {                                 // Wenn der Lüfter sich drehen sollte ... 
 +        if (rpmMax == 0) {                                 // ... aber die gemittelte Drehzahl gleich "0" ist ...       
 +          if (millis() - previousMillis > fanAlertDelay) { // ... und eine definierte Zeit verstrichen ist. 
 +            previousMillis = millis(); 
 +            fanAlert = true; 
 +            fanAlertState = true; 
 +            Serial.println("Fan blocked!"); 
 +            refreshFan = true;  
 +          }  
 +        } 
 +        else if (rpmMax > 0) {                               // ... und die gemittelte Drehzahl größer "0" ist ... 
 +          fanAlert = false; 
 +        } 
 +      } 
 +      else if (outputFan == 0) {                             // Wenn der Lüfter sich nicht drehen soll kann nicht festgestellt werden, ob er blockiert ist. 
 +        fanAlert = false; 
 +        previousMillis = millis();                           // Muss aktualisiert werden, damit 
 +        if (fanAlert != fanAlertState) { 
 +          refreshFan = true; 
 +          fanAlertState = false; 
 +        } 
 +      } 
 +    } 
 +  previousMillisCalculateFanSpeed = currentMillis; 
 +  } 
 + 
 + 
 +//------------------------- Betriebsstunden ---------------------// 
 +// Die Betriebsstunden werden alle 15 Minuten im EEPROM gespeichert. Die Einheit der Variable operatinTime ist also 0,25 Stunden. 
 +  if (millis() - lastTime >= 900000) { 
 +    // Betriebsstundenzähler 
 +    operatingTime = operatingTime + 0.25; 
 +    lastTime = millis(); 
 +    EEPROM.updateFloat(addrOperatingTime, operatingTime); 
 +    Serial.print("Updated operatingTime: "); Serial.println(operatingTime); 
 +    // Serviceintervallzähler 
 +    serviceInterval = serviceInterval + 0.25; 
 +    EEPROM.updateFloat(addrServiceInterval, serviceInterval); 
 +  } 
 + 
 + 
 +//------------------------- Ausgabe an das Display ---------------------// 
 +  // Anzeige "Serviceintervall zurückgesetzt 
 +  if (serviceIntervalReset == true) { 
 +    tft.fillScreen(BLACK);  
 +    tft.setCursor(15, 65); 
 +    tft.setTextColor(WHITE, BLACK); 
 +    tft.setTextSize(0); 
 +    tft.print("Service Intervall"); 
 +    tft.setCursor(26, 85); 
 +    tft.print("zur"); tft.print((char)129); tft.print("ckgesetzt"); 
 +    delay(2000); 
 +    tft.fillScreen(BLACK);  
 +    refreshPeltier = true; 
 +    refreshTargettemp = true; 
 +    previousTempCupedge = 150; 
 +    refreshFan= true; 
 +    serviceIntervalReset = false; 
 +  } 
 +   
 +  // Anzeigemodus "0" (Einfach) 
 +  if (displayMode == 0) { 
 +    // Anzeige Infobereich Zieltemperatur 
 +    if (refreshTargettemp == true) {               // Wenn die Solltemperatur verändert wurde, muss die Anzeige aktualisiert werden. 
 +      tft.setCursor(15, 49); 
 +      i = TargetTemp * 2;            // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                            // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                          // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK);  
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Solltemperatur"); 
 +      tft.setCursor(15, 62); 
 +      tft.setTextSize(2); 
 +        if (TargetTemp < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(TargetTemp); tft.print(" "); tft.print((char)247); tft.print("C");  
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      refreshTargettemp = false; 
 +    } 
 +   
 +    // Anzeige Infobereich Isttemperatur 
 +    if (tempCupedge != previousTempCupedge) {        // Wenn sich die Isttemperatur verändert hat, muss das Display aktualisiert werden. 
 +      tft.setCursor(15, 85); 
 +      i = tempCupedge * 2;             // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                              // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                            // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Isttemperatur");   
 +      tft.setCursor(15, 98); 
 +      tft.setTextSize(2); 
 +      if (tempCupedge < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(tempCupedge); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      previousTempCupedge = tempCupedge; 
 +    } 
 +  } 
 +   
 +  // Anzeigemodus "1" (Erweitert) 
 +  if (displayMode == 1) { 
 +    // Anzeige Infobereich Peltier-Element   
 +    if ((unsigned long)(currentMillis - previousMillisDisplayCoolingPower) >= intervalDisplayCoolingPower) {       
 +      if (outputPeltier > 0) { 
 +        if (refreshPeltier == true) { 
 +          tft.setCursor(0, 32);   
 +          tft.setTextSize(0); 
 +          tft.setTextColor(WHITE, BLACK); 
 +          tft.print("K"); tft.print((char)129); tft.print("hlleistung ");  tft.print(int(outputPeltier * 0.39 + 0.55)); tft.print(" %"); 
 +          tft.setTextColor(BLACK, BLACK); 
 +          for (i=0; i<3; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +            tft.print((char)218); 
 +          } 
 +          refreshPeltier = false; 
 +        } 
 +      } 
 +      else if (outputPeltier == 0) { 
 +        if (refreshPeltier == true) {     
 +          tft.setCursor(0, 32); 
 +          tft.setTextColor(WHITE, BLACK);   
 +          tft.setTextSize(0); 
 +          tft.print("K"); tft.print((char)129); tft.print("hlelement aus"); 
 +          tft.setTextColor(BLACK, BLACK); 
 +          for (i=0; i<3; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +            tft.print((char)218); 
 +          } 
 +          refreshPeltier = false; 
 +        }        
 +      } 
 +    previousMillisDisplayCoolingPower = currentMillis; 
 +    } 
 + 
 +     
 +    // Anzeige Infobereich Solltemperatur 
 +    if (refreshTargettemp == true) { 
 +      tft.setCursor(15, 49); 
 +      i = TargetTemp * 2;          // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                          // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                        // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK);  
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Solltemperatur"); 
 +      tft.setCursor(15, 62); 
 +      tft.setTextSize(2); 
 +        if (TargetTemp < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(TargetTemp); tft.print(" "); tft.print((char)247); tft.print("C");  
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      refreshTargettemp = false; 
 +    } 
 +   
 +    // Anzeige Infobereich Isttemperatur 
 +    if (tempCupedge != previousTempCupedge) { 
 +      tft.setCursor(15, 85); 
 +      i = tempCupedge * 2;       // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                        // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                      // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Isttemperatur");   
 +      tft.setCursor(15, 98); 
 +      tft.setTextSize(2); 
 +      if (tempCupedge < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(tempCupedge); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      previousTempCupedge = tempCupedge; 
 +    } 
 + 
 + 
 +    // Anzeige Infobereich Lüfter 
 +    if (fanAlert == true) { 
 +      if (refreshFan == true) { 
 +        tft.setCursor(0, 121);   
 +        tft.setTextSize(0); 
 +        tft.setTextColor(RED, BLACK); 
 +        tft.print("L"); tft.print((char)129); tft.print("fterfehlfunktion!");  
 +        refreshFan = false; 
 +      } 
 +    }   
 +    else if (fanAlert == false) { 
 +      if ((unsigned long)(currentMillis - previousMillisDisplayFanSpeed) >= intervalDisplayFanSpeed) {  
 +        if (rpmMax > 0) {                    // Wenn die Drehzahl größer "0" ist, aktualisiere den Anzeigebereich all 500 Millisekunden 
 +          if (refreshFan == true) { 
 +            tft.setCursor(0, 121);   
 +            tft.setTextSize(0); 
 +            tft.setTextColor(WHITE, BLACK); 
 +            tft.print("L"); tft.print((char)129); tft.print("fter ");  tft.print(rpmMax); tft.print(" U/min"); 
 +            tft.setTextColor(BLACK, BLACK); 
 +            for (i=0; i<5; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +              tft.print((char)218); 
 +            } 
 +            refreshFan = false; 
 +          } 
 +        } 
 +        else if (rpmMax == 0) { 
 +          if (refreshFan == true) { 
 +            tft.setCursor(0, 121);   
 +            tft.setTextSize(0); 
 +            tft.setTextColor(WHITE, BLACK); 
 +            tft.print("L"); tft.print((char)129); tft.print("fter aus");  
 +            tft.setTextColor(BLACK, BLACK); 
 +            for (i=0; i<12; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +              tft.print((char)218); 
 +            } 
 +            refreshFan = false; 
 +          } 
 +        } 
 +        previousMillisDisplayFanSpeed = currentMillis; 
 +      } 
 +    } 
 +  } 
 + 
 +  // Anzeigemodus "2" (Experte) 
 +  if (displayMode == 2) {     
 + 
 +    // Anzeige Soll- und Umgebungstemperatur 
 +    if (refreshTargettemp == true) {               // Wenn die Solltemperatur verändert wurde, muss die Anzeige aktualisiert werden. 
 +      // Solltemperatur 
 +      tft.setCursor(0, 32); 
 +      i = TargetTemp * 2;            // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                            // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                          // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK);  
 +      tft.setTextSize(0); 
 +      tft.print("Solltemp. "); 
 +        if (TargetTemp < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(TargetTemp); tft.print(" "); tft.print((char)247); tft.print("C");  
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      refreshTargettemp = false; 
 +    } 
 + 
 +    // Anzeige Isttemperaturen 
 +    if (tempCupedge != previousTempCupedge) {   
 +      tft.setCursor(0, 50); 
 +      i = tempCupedge * 2;       // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                        // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                      // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Becherrand ");   
 +      if (tempCupedge < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(tempCupedge); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 + 
 +      tft.setCursor(0, 63); 
 +      i = tempCupbase * 2;       // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                        // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                      // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Becherboden ");   
 +      if (tempCupbase < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(tempCupbase); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 + 
 +      // Umgebungstemperatur 
 +      tft.setCursor(0, 76); 
 +      i = tempAmbient * 2;       // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                        // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                      // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(1); 
 +      tft.print("Umgebung ");   
 +      if (tempAmbient < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(tempAmbient); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 + 
 +      // Kühlkörper 
 +      tft.setCursor(0, 89); 
 +      i = tempDissipator * 2;       // Berechnet den Index für den Array "colors" 
 +      if (i < 0) i = 0;                        // i soll nicht kleiner als "0" werden 
 +      if (i > 60) i = 60;                      // i soll nicht größer als "60" werden 
 +      //tft.setTextColor(colors[i], BLACK); 
 +      tft.setTextColor((pgm_read_word_near(colors +i)), BLACK); 
 +      tft.setTextSize(1); 
 +      tft.print("K"); tft.print((char)129); tft.print("hlk"); tft.print((char)148); tft.print("rper ");  
 +      if (tempDissipator < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(tempDissipator); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +             
 +      previousTempCupedge = tempCupedge; 
 +    } 
 + 
 +    // Anzeige Kühlleistung 
 +    if ((unsigned long)(currentMillis - previousMillisDisplayCoolingPower) >= intervalDisplayCoolingPower) {       
 +      if (outputPeltier > 0) { 
 +        if (refreshPeltier == true) { 
 +          tft.setCursor(0, 108);   
 +          tft.setTextSize(0); 
 +          tft.setTextColor(WHITE, BLACK); 
 +          tft.print("K"); tft.print((char)129); tft.print("hlleistung ");  tft.print(int(outputPeltier * 0.39 + 0.55)); tft.print(" %"); 
 +          tft.setTextColor(BLACK, BLACK); 
 +          for (i=0; i<3; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +            tft.print((char)218); 
 +          } 
 +          refreshPeltier = false; 
 +        } 
 +      } 
 +      else if (outputPeltier == 0) { 
 +        if (refreshPeltier == true) {     
 +          tft.setCursor(0, 108); 
 +          tft.setTextColor(WHITE, BLACK);   
 +          tft.setTextSize(0); 
 +          tft.print("K"); tft.print((char)129); tft.print("hlelement aus"); 
 +          tft.setTextColor(BLACK, BLACK); 
 +          for (i=0; i<3; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +            tft.print((char)218); 
 +          } 
 +          refreshPeltier = false; 
 +        }        
 +      } 
 +    previousMillisDisplayCoolingPower = currentMillis; 
 +    } 
 +     
 +    // Anzeige Lüfter 
 +    if (fanAlert == true) { 
 +      if (refreshFan == true) { 
 +        tft.setCursor(0, 121);   
 +        tft.setTextSize(0); 
 +        tft.setTextColor(RED, BLACK); 
 +        tft.print("L"); tft.print((char)129); tft.print("fterfehlfunktion!");  
 +        refreshFan = false; 
 +      } 
 +    }   
 +    else if (fanAlert == false) { 
 +      if ((unsigned long)(currentMillis - previousMillisDisplayFanSpeed) >= intervalDisplayFanSpeed) {  
 +        if (rpmMax > 0) {                    // Wenn die Drehzahl größer "0" ist, aktualisiere den Anzeigebereich all 500 Millisekunden 
 +          if (refreshFan == true) { 
 +            tft.setCursor(0, 121);   
 +            tft.setTextSize(0); 
 +            tft.setTextColor(WHITE, BLACK); 
 +            tft.print("L"); tft.print((char)129); tft.print("fter ");  tft.print(rpmMax); tft.print(" U/min"); 
 +            tft.setTextColor(BLACK, BLACK); 
 +            for (i=0; i<5; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +              tft.print((char)218); 
 +            } 
 +            refreshFan = false; 
 +          } 
 +        } 
 +        else if (rpmMax == 0) { 
 +          if (refreshFan == true) { 
 +            tft.setCursor(0, 121);   
 +            tft.setTextSize(0); 
 +            tft.setTextColor(WHITE, BLACK); 
 +            tft.print("L"); tft.print((char)129); tft.print("fter aus");  
 +            tft.setTextColor(BLACK, BLACK); 
 +            for (i=0; i<12; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +              tft.print((char)218); 
 +            } 
 +            refreshFan = false; 
 +          } 
 +        } 
 +        previousMillisDisplayFanSpeed = currentMillis; 
 +      } 
 +    } 
 + 
 +  } 
 +//------------------------- Ausgabe an die serielle Schnittstelle ---------------------// 
 +  if ((unsigned long)(currentMillis - previousMillisSerialPrint) >= intervalSerialPrint) { 
 + 
 +    // Ausgabe für den seriellen Monitor  
 +/* 
 +    //Serial.print("tempAmbient: ");Serial.print(tempAmbient); 
 +    //Serial.print("; tempDissipator: ");Serial.print(tempDissipator); 
 +    //Serial.print("; tempCupbase: ");Serial.print(tempCupbase); 
 +     
 +    Serial.print("; setpointFan: ");Serial.print(setpointFan); 
 +    //Serial.print("; inputFan: ");Serial.print(inputFan); 
 +    Serial.print("; outputFan: ");Serial.print(outputFan); 
 +    //Serial.print("; setpointPeltier: ");Serial.print(setpointPeltier); 
 +    //Serial.print("; inputPeltier: ");Serial.print(inputPeltierFan); 
 +    //Serial.print("; outputPeltier: ");Serial.print(outputPeltier);  
 +     
 +    //Serial.print("; pulseOn: ");Serial.print(pulseOn); 
 +    //Serial.print("; pulseOff: ");Serial.print(pulseOff); 
 +    //Serial.print("; Duration: "); Serial.print(duration); 
 +    Serial.print("; RPM: "); Serial.print(rpm); 
 +    Serial.print("; average RPM: "); Serial.print(rpmMax); 
 +    //Serial.print("; fanAlert: "); Serial.print(fanAlert); 
 +    //Serial.print("; temperatureHotSide: "); Serial.println(temperatureHotSide); 
 +    //Serial.print("; operatingTime: "); Serial.print(operatingTime);  
 +    //Serial.print("; serviceInterval: "); Serial.print(serviceInterval);  
 +    //Serial.print("; Displaymode: "); Serial.print(displayMode); 
 +    Serial.print("; Loops: "); Serial.println(loopCounter); 
 +*/   
 +     
 +    /* 
 +    // Ausgabe für SerialComInstruments 4.1 
 +    Serial.print("#1M"); Serial.print(setpointFan); Serial.print("<"); 
 +    Serial.print("#2M"); Serial.print(tempDissipator); Serial.print("<"); 
 +    Serial.print("#3M"); Serial.print(rpmMax); Serial.print("<"); 
 + 
 +    Serial.print("#4M"); Serial.print(TargetTemp); Serial.print("<"); 
 +    //Serial.print("#5M"); Serial.print(tempCupbase); Serial.print("<"); 
 +    Serial.print("#6M"); Serial.print(outputPeltier); Serial.print("<"); 
 + 
 +    Serial.print("#7M"); Serial.print(tempAmbient); Serial.print("<"); 
 +    //Serial.print("#8M"); Serial.print(loopCounter); Serial.print("<"); 
 +     
 +    Serial.print("#9M"); Serial.print(tempCupedge); Serial.println("<"); 
 +    */ 
 +    //loopCounter = 0; 
 +     
 +  //Speichere die aktuelle Zeit in die zughörige Variable 
 +  previousMillisSerialPrint = currentMillis; 
 +  } 
 +
 +</code> 
 +Der Sketch verwendet 25586 Bytes (83%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes. 
 +Globale Variablen verwenden 1504 Bytes (73%) des dynamischen Speichers, 544 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes. 
 + 
 +Tags: #Arduino #Flaschenkühler #OLED
arduino/flaschenkuehler/programmversion_0.5.1503249482.txt.gz · Zuletzt geändert: 18.05.2023 12:16 (Externe Bearbeitung)