Benutzer-Werkzeuge

Webseiten-Werkzeuge


arduino:flaschenkuehler:programmversion_0.3

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.3 [20.07.2017 11:04] Frickelpietarduino:flaschenkuehler:programmversion_0.3 [18.05.2023 12:34] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 2: Zeile 2:
 In dieser Version soll die Regelung des Peltier-Elements in Angriff genommen werden. Um den PID-Regler einstellen zu können wäre es gut, wenn man die Daten der seriellen Schnittstelle direkt in Excel oder so speichern könnte. In dieser Version soll die Regelung des Peltier-Elements in Angriff genommen werden. Um den PID-Regler einstellen zu können wäre es gut, wenn man die Daten der seriellen Schnittstelle direkt in Excel oder so speichern könnte.
  
-Der Flaschenkühler soll mindestens zwei Anzeigemodi unterstützen: einfach und erweitertUm zwischen verschiedenen Anzeigemodi wechseln zu können, muss die Dauer erfasst werden, die ein Taster gedrückt wurde. Diese Funktion stellt sehr komfortabel die Bibliothek [[https://github.com/fasteddy516/ButtonEvents|ButtonEvents]] zur Verfügung.+Das OLED-Display hat nun drei Anzeigemodi: einfach, erweitert und grafischZwischen den Anzeigemodi kann durch einen langen Druck auf den oberen oder unteren Taster gewechselt werden. Diese Funktion stellt sehr komfortabel die Bibliothek [[https://github.com/fasteddy516/ButtonEvents|ButtonEvents]] zur Verfügung.
  
-http://www.serialcominstruments.com/serial.php+Im einfachen und erweiterten Anzeigemodus werden die Soll- und Isttemperaturen nun in einer Schrittweite von 0,5°C temperaturabhängig in spezifischen Farbwerte angezeigt. 30°C werden in rot angezeigt, 0°C in türkis. Die Farbwerte habe ich mit [[http://www.barth-dev.de/online/rgb565-color-picker/|diesem Online-Tool]] erzeugt.
  
-http://www.serialcominstruments.com/instrument4.php+Ab dieser Programmversion erscheint nach 100 Betriebsstunden eine Aufforderung auf dem Startbildschirm, den Flaschenkühler zu reinigenDas Reinigungsintervall kann mit einem (schnellen) Doppeldruck auf Taster 1 zurückgesetzt werdenDas Zurücksetzen wird mit einer entsprechenden Anzeige auf dem OLED-Display quittiert
  
-Tags: #Arduino #Flaschenkühler #Peltier+Zur Glättung der analogen Inputs, also der Thermistoren, wird ab dieser Programmversion die Bibliothek [[https://github.com/dxinteractive/ResponsiveAnalogRead|ResponsiveAnalogRead]] verwendet. Was die Bibliothek leistet wird sehr anschaulich auf [[http://damienclarke.me/code/posts/writing-a-better-noise-reducing-analogread|dieser Webseite]] erklärt. Die Anzeige der Isttemperatur auf dem Display wird dadurch sehr viel stabiler. Die Ausführung des Codes verlangsamt sich dadurch zwar um etwa 1 %, andererseits muss nun das Display nicht mehr alle 500 Millisekunden aktualisiert werden, sondern nur noch dann, wenn sich die Isttemperatur tatsächlich verändert hat. Dadurch wird die Ausführung des Programms um ca. 129 % beschleunigt. 
 + 
 +Eine erhebliche Beschleunigung der Ausführung des Codes (nämlich um ca. 229 %) konnte dadurch erreicht werden, den PID-Regler nicht in jeder Programmschleife einmal auszuführen, sondern nur alle 10 Millisekunden. 
 + 
 +<code> 
 +// Flaschenkühler - Programmversion 0.3 
 +// Diese Version steuert einen PC-Lüfter mit 4-Pin-Anschluss ... 
 +// ... liest das Tachosignal aus ... 
 +// ... berechnet die Drehzahl des Lüfters ... 
 +// ... liest einen Thermistor aus und berechnet die Temperatur ... 
 +// ... stellt über ein Poti die ZieltemperatureHotSidee ein ... 
 +// ... regelt den Lüfter mit einem PID-Modul ... 
 +// ... zeigt verschiedene Werte auf einem OLED-Display an ... 
 +// ... zählt die Betriebsstunden (viertelstundengenau) und speichert sie im EEPROM ... 
 +// ... pollt die Taster und speichert die Solltemperatur im EEPROM. 
 + 
 +//------------------------- 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 <RunningAverage.h>       // Bibliothek für Berechnung von Mittelwerten 
 +#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 
 + 
 +//------------------------- Definition der Inputs und Outputs ---------------------// 
 +#define potiPin         A0        // Input-Pin für den Lüfter 
 +#define thermistorPin   A1        // Input-Pin für den Thermistor 
 +#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 button1Pin      8         // Taster 1 
 +#define fanPin          9         // PWM-Pin für Lüfter 
 +#define button2Pin      12        // Taster 2 
 + 
 + 
 +//------------------------- 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 thermistorValue = 0;         // Variable in der der Wert des Thermistors gespeichert wird 
 +int potiValue = 0;                 // variable to store the value coming from the sensor 
 + 
 +// PWM Frequenzen 
 +uint16_t frequencyFan = 25000;     // PWM-Frequenz für den Lüfter (in Hz) 
 +uint16_t frequencyPeltier = 50000; // PWM-Frequenz für den Lüfter (in Hz) 
 + 
 +// Lüfter 
 +int tachoSignal;                   // Tachosignal 
 +uint32_t pulseOn = 0;              // Ansteigende Signalflanke (Variablenformat nicht verändern!) 
 +uint32_t pulseOff = 0;             // Abfallende Signalflanke (Variablenformat nicht verändern!) 
 +uint32_t 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 
 +float rpmAverage = 0;              // Gemittelte Drehzahl des Lüfters in U/min 
 +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; 
 + 
 +// Temperaturen 
 +float temperatureHotSide = 0; 
 +float previousTempHotSide = 0;     // Wird verwendet um festzustellen, ob die Anzeige der Isttemperatur auf dem OLED-Display aktualisiert werden muss. 
 + 
 +// 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 
 +int addrOperatingTime = 0;         // Startadresse für eine Variable im Datentyp float (4 Byte!) 
 +int addrTargetTemp = 4;            // Startadresse für eine Variable im Datentyp double (8 Byte!) 
 +int addrDisplayMode = 13;          // Adresse für den Anzeigemodus (2 Byte reserviert) 
 +int 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 
 +unsigned long colors[] = {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 
 +int displayMode;                   // Anzeigemodus ("0" = Einfach; "1" = Erweitert; "2" = grafisch) 
 +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 refreshActualtemp = true; 
 +bool refreshFan = true;            // Wird wahr, wenn der Anzeigebereich für den Lüfter aktualisiert werden muss 
 +int x = 0; 
 + 
 +// Instantiiert ButtonEvents-Objekte 
 +ButtonEvents button1; 
 +ButtonEvents button2; 
 + 
 +// Instantiiert ein RunningAverage-Objekt zur Bechnung von Mittelwerten 
 +RunningAverage averageRPM(25);         // Mittelwert aus 25 Messungen 
 + 
 +// Instantiirt ResponsiveAnalogRead-Objekte zur Glättung der analogen Inputs 
 +ResponsiveAnalogRead analog(thermistorPin, true); 
 + 
 +// Definiert den PID-Regler 
 +double Setpoint, Input, Output; 
 +double Kp=2, Ki=5, Kd=1; 
 +PID fanPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, REVERSE); 
 + 
 +// Definiert die Tracking-Variablen für die IF-Abfragen 
 +unsigned long previousMillisCalculateTemperatures = 0; // Auslesen der analogen Inputs und Berechnung der Temperaturen 
 +unsigned long previousMillisCalculatePID = 0;          // Berechnung der PID-Regler (Lüfter und Peltier-Element) 
 +unsigned long previousMillisCalculateFanSpeed = 0;     // Berechnung der Drehzahl des Lüfters 
 +unsigned long previousMillisDisplayActualtemp = 0;     // Ausgabe der Ist-Temperatur an das OLED-Display 
 +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 intervalCalculateTemperatures = 10;// Auslesen der analogen Inputs und Berechnung der Temperaturen 
 +const unsigned long intervalCalculatePID = 10;         // Berechnung der PID-Regler (Lüfter und Peltier-Element) 
 +const unsigned long intervalCalculateFanSpeed = 100;   // Berechnung der Drehzahl des Lüfters 
 +const unsigned long intervalDisplayActualtemp = 500;   // Ausgabe der Ist-Temperatur an das OLED-Display 
 +const unsigned long intervalDisplayFanSpeed = 500;     // 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 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(70); 
 +  button1.holdTime(1000); 
 +  button2.attach(button2Pin); 
 +  button2.debounceTime(10); 
 +  button2.doubleTapTime(70); 
 +  button2.holdTime(1000); 
 +   
 +  // Initialisiert timer1 und timer2 (timer0 bleibt unberührt) 
 +  InitTimersSafe();  
 + 
 +  // Definiert die Frequenzen für die angegebenen Pins 
 +  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); 
 + 
 +  // Liest die im EEPROM gespeicherten Variablen aus 
 +  displayMode = EEPROM.read(addrDisplayMode); 
 +  operatingTime = EEPROM.readFloat(addrOperatingTime); 
 +  serviceInterval = EEPROM.readFloat(addrServiceInterval); 
 +  Setpoint = EEPROM.readDouble(addrTargetTemp); 
 + 
 +  //operatingTime = 0;                 // Soll auf "0" gesetzt werden, bis die Testphase abgeschlossen ist 
 +  //Setpoint = 0; 
 +  //serviceInterval = 0; 
 +   
 +  // Meldung "Klar zum Start!" 
 +  Serial.println("<Arduino is ready! Turn the potentiometer, please ...>");  
 +  Serial.print("<Operating Time of the System: "); 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)154); tft.print("hler"); 
 +  tft.setCursor(20, 55); 
 +  tft.print("Programmversion"); 
 +  tft.setCursor(45, 75); 
 +  tft.setTextSize(2); 
 +  tft.print("0.3"); 
 +  if (serviceInterval >= 1.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) { 
 +    Setpoint = Setpoint + 0.5; 
 +    EEPROM.updateDouble(addrTargetTemp, Setpoint); 
 +    //Serial.print("Updated Setpoint: "); Serial.println(Setpoint); 
 +    refreshTargettemp = true; 
 +    if (Setpoint >= 30.00) { 
 +      Setpoint = 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; 
 +    previousTempHotSide = 150; 
 +    refreshFan= true; 
 +    x = 0; 
 +  }  
 +  if (button1.doubleTapped() == true) { 
 +    serviceInterval = 0; 
 +    EEPROM.updateFloat(addrServiceInterval, serviceInterval); 
 +    Serial.println("Service Interval reseted!"); 
 +    serviceIntervalReset = true; 
 +  } 
 +   
 +  if (button2.tapped() == true) { 
 +    Setpoint = Setpoint - 0.5; 
 +    EEPROM.updateDouble(addrTargetTemp, Setpoint); 
 +    //Serial.print("Updated Setpoint: "); Serial.println(Setpoint); 
 +    refreshTargettemp = true; 
 +    if (Setpoint <= 0.00) { 
 +      Setpoint = 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; 
 +    previousTempHotSide = 150; 
 +    refreshFan= true; 
 +    x = 0; 
 +  }  
 + 
 + 
 + 
 + 
 +//------------------------- Auslesen der analogen Inputs (Thermistoren) und Berechnung der Temperaturen ---------------------//   
 +  if ((unsigned long)(currentMillis - previousMillisCalculateTemperatures) >= intervalCalculateTemperatures) { 
 +    // Lese die analogen Inputs aus 
 +    potiValue = analogRead(potiPin);                    // Poti 
 +    analog.update();                                    // Das ResponsiveAnalogRead-Objekt wird aktualisiert 
 + 
 +    thermistorValue = analog.getValue();                // Das Ergebnis wird ausgelesen 
 +    
 +    // Berechnung der Temperatur 
 +    thermistorValue = 1023 / thermistorValue - 1;        
 +    thermistorValue = 10000 / thermistorValue;          // Der Wert wird in einen Widerstand umgerechnet 
 +   
 +    //float temperatureHotSide; 
 +    temperatureHotSide = thermistorValue / 10000;       // (R/Ro) 
 +    temperatureHotSide = log(temperatureHotSide);       // ln(R/Ro) 
 +    temperatureHotSide /= 3950;                         // 1/B * ln(R/Ro) 
 +    temperatureHotSide += 1.0 / (25 + 273.15);          // + (1/To) 
 +    temperatureHotSide = 1.0 / temperatureHotSide;      // Invert 
 +    temperatureHotSide -= 273.15;                       // convert to C 
 +     
 +    previousMillisCalculateTemperatures = currentMillis; 
 +  } 
 + 
 +//------------------------- Regelung des Lüfters (TEST) ---------------------//  
 +  if ((unsigned long)(currentMillis - previousMillisCalculatePID) >= intervalCalculatePID) { 
 +    Input = temperatureHotSide;                                 // Input ist die temperatureHotSide des Thermistors in *C 
 +    fanPID.Compute();                                   // PID-Regler wir aufgerufen 
 +    pwmWrite(fanPin, Output);                           // Gibt den Output des PID-Reglers an den Lüfter 
 + 
 +    // Wenn der Output des PID-Reglers Null ist, wird der Lüfter ausgeschaltet. 
 +    if (Output > 0) { 
 +      digitalWrite(powerPin, HIGH); 
 +      //Serial.print("HIGH"); Serial.print("; "); 
 +    } 
 +    else { 
 +      digitalWrite(powerPin, LOW); 
 +      //Serial.print("LOW"); Serial.print("; "); 
 +    } 
 +   
 +    //use this functions instead of analogWrite on 'initialized' pins 
 +    pwmWrite(peltierPin, potiValue / 4);                // Nur zu Testzwecken 
 +     
 +    previousMillisCalculatePID = 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 > 7000 && duration < 150000) {       // Liegt die Variable über bzw. unter den angegebenen Werten, liegt ein Messfehler vor 
 +      rpm = float(100000 * 2 * 60 / duration);        // Berechnung der RPM 
 +    } 
 +    else { 
 +      rpm = 0; 
 +    } 
 +    //averageRPM.addValue(rpm); 
 +  } 
 + 
 +  // Berechnung der gemittelten Drehzahl des Lüfters 
 +  if ((unsigned long)(currentMillis - previousMillisCalculateFanSpeed) >= intervalCalculateFanSpeed) { 
 +    averageRPM.addValue(rpm);                         // Aktualisiert das RunningAverage-Objekt  
 +     
 +    // Wenn der Lüfter angehalten wird, soll die Drehzahl "0" angezeigt werden 
 +    if (Output == 0) { 
 +      rpm = 0; 
 +      averageRPM.addValue(rpm); 
 +    } 
 + 
 +    // Liest die durchschnittliche Drehzahl aus und speichert das Ergebnis in eine Variable 
 +    rpmAverage = averageRPM.getAverage(); 
 + 
 +    // 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 (Output > 0) {                                    // Wenn der Lüfter sich drehen sollte ... 
 +        if (rpmAverage == 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 (rpmAverage > 0) {                    // ... und die gemittelte Drehzahl größer "0" ist ... 
 +          fanAlert = false; 
 +        } 
 +      } 
 +      else if (Output == 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)154); tft.print("ckgesetzt"); 
 +    delay(2000); 
 +    tft.fillScreen(BLACK);  
 +    refreshPeltier = true; 
 +    refreshTargettemp = true; 
 +    previousTempHotSide = 150; 
 +    refreshFan= true; 
 +    serviceIntervalReset = false; 
 +  } 
 +   
 +  // Anzeigemodus "0" (einfach) 
 +  if (displayMode == 0) { 
 +    // Anzeige Infobereich Zieltemperatur 
 +    if (refreshTargettemp == true) { 
 +      tft.setCursor(15, 49); 
 +      int i = Setpoint * 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.setTextSize(0); 
 +      tft.print("Solltemperatur"); 
 +      tft.setCursor(15, 62); 
 +      tft.setTextSize(2); 
 +        if (Setpoint < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(Setpoint); tft.print(" "); tft.print((char)247); tft.print("C");  
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      refreshTargettemp = false; 
 +    } 
 +   
 +    // Anzeige Infobereich Isttemperatur 
 +    if ((unsigned long)(currentMillis - previousMillisDisplayActualtemp) >= intervalSerialPrint) { 
 +      if (temperatureHotSide != previousTempHotSide) { 
 +        tft.setCursor(15, 85); 
 +        int i = temperatureHotSide * 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.setTextSize(0); 
 +        tft.print("Isttemperatur");   
 +        tft.setCursor(15, 98); 
 +        tft.setTextSize(2); 
 +        if (temperatureHotSide < 10.00) { 
 +          tft.print("0"); 
 +        } 
 +        tft.print(temperatureHotSide); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +        tft.setTextColor(BLACK, BLACK); 
 +        tft.print((char)218); 
 +        previousTempHotSide = temperatureHotSide; 
 +      } 
 +      previousMillisDisplayActualtemp = currentMillis; 
 +    }     
 +  } 
 +   
 +  // Anzeigemodus "1" (erweitert) 
 +  if (displayMode == 1) { 
 +    // Anzeige Infobereich Peltier-Element   
 +    if (refreshPeltier == true) {     
 +      tft.setCursor(0, 32); 
 +      tft.setTextColor(WHITE, BLACK);   
 +      tft.setTextSize(0); 
 +      tft.print("Infos Peltier-Element"); 
 +      refreshPeltier = false; 
 +    } 
 +   
 +    // Anzeige Infobereich Zieltemperatur 
 +    if (refreshTargettemp == true) { 
 +      tft.setCursor(15, 49); 
 +      int i = Setpoint * 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.setTextSize(0); 
 +      tft.print("Solltemperatur"); 
 +      tft.setCursor(15, 62); 
 +      tft.setTextSize(2); 
 +        if (Setpoint < 10.00) { 
 +        tft.print("0"); 
 +      } 
 +      tft.print(Setpoint); tft.print(" "); tft.print((char)247); tft.print("C");  
 +      tft.setTextColor(BLACK, BLACK); 
 +      tft.print((char)218); 
 +      refreshTargettemp = false; 
 +    } 
 +   
 +    // Anzeige Infobereich Isttemperatur 
 +    if ((unsigned long)(currentMillis - previousMillisDisplayActualtemp) >= intervalDisplayActualtemp) { 
 +      if (temperatureHotSide != previousTempHotSide) { 
 +        tft.setCursor(15, 85); 
 +        int i = temperatureHotSide * 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.setTextSize(0); 
 +        tft.print("Isttemperatur");   
 +        tft.setCursor(15, 98); 
 +        tft.setTextSize(2); 
 +        if (temperatureHotSide < 10.00) { 
 +          tft.print("0"); 
 +        } 
 +        tft.print(temperatureHotSide); tft.print(" "); tft.print((char)247); tft.print("C"); 
 +        tft.setTextColor(BLACK, BLACK); 
 +        tft.print((char)218); 
 +        previousTempHotSide = temperatureHotSide; 
 +      } 
 +      previousMillisDisplayActualtemp = currentMillis; 
 +    } 
 + 
 +    // 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)154); tft.print("fterfehlfunktion!");  
 +        refreshFan = false; 
 +      } 
 +    }   
 +    else if (fanAlert == false) { 
 +      if (rpmAverage > 0) {                    // Wenn die Drehzahl größer "0" ist, aktualisiere den Anzeigebereich all 500 Millisekunden 
 +        if ((unsigned long)(currentMillis - previousMillisDisplayFanSpeed) >= intervalDisplayFanSpeed) {  
 +          tft.setCursor(0, 121);   
 +          tft.setTextSize(0); 
 +          tft.setTextColor(WHITE, BLACK); 
 +          tft.print("L"); tft.print((char)154); tft.print("fter ");  tft.print(int(rpmAverage)); tft.print(" U/min"); 
 +          tft.setTextColor(BLACK, BLACK); 
 +          for (int i=0; i<5; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +            tft.print((char)218); 
 +          } 
 +          refreshFan = true; 
 +          previousMillisDisplayFanSpeed = currentMillis; 
 +        } 
 +      }   
 +      else if (rpmAverage == 0) { 
 +        if (refreshFan == true) { 
 +          tft.setCursor(0, 121);   
 +          tft.setTextSize(0); 
 +          tft.setTextColor(WHITE, BLACK); 
 +          tft.print("L"); tft.print((char)154); tft.print("fter aus");  
 +          tft.setTextColor(BLACK, BLACK); 
 +          for (int i=0; i<12; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +            tft.print((char)218); 
 +          } 
 +          refreshFan = false; 
 +        } 
 +      } 
 +    } 
 +  } 
 +   
 +  // Anzeigemodus "2" (grafisch) 
 +  if (displayMode == 2) { 
 +    // Anzeige Isttemperatur 
 +    if ((unsigned long)(currentMillis - previousMillisDisplayActualtemp) >= intervalDisplayActualtemp) { 
 +      if (temperatureHotSide != previousTempHotSide) { 
 +        tft.setCursor(0, 32); 
 +        tft.setTextSize(0); 
 +        int i = temperatureHotSide * 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.print("Ist ");   
 +        if (temperatureHotSide < 10.00) { 
 +          tft.print("0"); 
 +        } 
 +        tft.print(temperatureHotSide); 
 +        tft.setTextColor(BLACK, BLACK); 
 +        tft.print((char)218); 
 +        previousTempHotSide = temperatureHotSide; 
 +      } 
 +      previousMillisDisplayActualtemp = currentMillis; 
 +    }     
 +    // Anzeige Solltemperatur 
 +    if (refreshTargettemp == true) { 
 +      tft.setCursor(64, 32); 
 +      tft.setTextColor(WHITE, BLACK); 
 +      tft.setTextSize(0); 
 +      tft.print("Soll "); 
 +        if (Setpoint < 10.00) { 
 +        tft.print("0"); 
 +        } 
 +      tft.print(Setpoint);  
 +      refreshTargettemp = false; 
 +    }         
 +    // Anzeige Graphen 
 +    if ((unsigned long)(currentMillis - previousMillisDisplayGraph) >= intervalDisplayGraph) { 
 + 
 +      x++; 
 +      if (x >= 128) { 
 +        x = 0; 
 +        //tft.fillScreen(BLACK); 
 +        tft.fillRect(0, 40, 128, 80, BLACK); 
 +        //tft.drawLine(0, 44, 127, 44, WHITE); 
 +        //tft.drawLine(0, 114, 127, 114, WHITE); 
 +        //previousTempHotSide = 150; 
 +        //refreshTargettemp = true; 
 +        //refreshFan = true; 
 +        //refreshPeltier = true; 
 +      } 
 +       
 +      // Graph Solltemperatur 
 +      int y = 114 - Setpoint * 2;  
 +      tft.drawPixel(x, y, WHITE); 
 +       
 +      // Graph Isttemperatur 
 +      int z = 114 - temperatureHotSide *2; 
 +      int i = temperatureHotSide * 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.drawPixel(x, z, colors[i]); 
 + 
 +      // Graph Lüfterdrehzahl 
 +      int d = 114 - rpmAverage / 21; 
 +      tft.drawPixel(x, d, BLUE); 
 +       
 +      //Serial.print("x = ");Serial.print(x); 
 +      //Serial.print("; y = ");Serial.print(y); 
 +      //Serial.print("; z = ");Serial.print(z); 
 +      //Serial.print("; d = ");Serial.println(d); 
 + 
 +    // Anzeige Peltier-Element   
 +    if (refreshPeltier == true) {     
 +      tft.setCursor(0, 121); 
 +      tft.setTextColor(BLUEBERRY, BLACK);   
 +      tft.setTextSize(0); 
 +      tft.print("Peltier"); 
 +      refreshPeltier = false; 
 +    } 
 +     
 +    // Anzeige Lüfter 
 +    if (rpmAverage > 0) { 
 +      if ((unsigned long)(currentMillis - previousMillisDisplayFanSpeed) >= intervalDisplayFanSpeed) {  
 +        tft.setCursor(60, 121);   
 +        tft.setTextSize(0); 
 +        tft.setTextColor(BLUE, BLACK); 
 +        tft.print(" U/min "); tft.print(int(rpmAverage));  
 +        tft.setTextColor(BLACK, BLACK); 
 +        for (int i=0; i<3; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +          tft.print((char)218); 
 +        } 
 +        refreshFan = true; 
 +        previousMillisDisplayFanSpeed = currentMillis; 
 +      } 
 +    } 
 +    if (rpmAverage == 0) { 
 +      if (refreshFan == true) { 
 +        tft.setCursor(60, 121);   
 +        tft.setTextSize(0); 
 +        tft.setTextColor(BLUE, BLACK); 
 +        tft.print(int(rpmAverage)); tft.print(" U/min"); 
 +        tft.setTextColor(BLACK, BLACK); 
 +        for (int i=0; i<3; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden 
 +          tft.print((char)218); 
 +        } 
 +        refreshFan = false; 
 +      } 
 +    } 
 +       
 +    previousMillisDisplayGraph = currentMillis; 
 +    } 
 +  } 
 +//------------------------- Ausgabe an die serielle Schnittstelle ---------------------// 
 +  if ((unsigned long)(currentMillis - previousMillisSerialPrint) >= intervalSerialPrint) { 
 + 
 +    // Ausgabe für den seriellen Monitor  
 +    Serial.print("Setpoint: ");Serial.print(Setpoint); 
 +    Serial.print("; Input: ");Serial.print(Input); 
 +    Serial.print("; Output: ");Serial.print(Output); 
 +    //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(rpmAverage); 
 +    //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); 
 + 
 +    loopCounter = 0; 
 +     
 +  //Speichere die aktuelle Zeit in die zughörige Variable 
 +  previousMillisSerialPrint = currentMillis; 
 +  } 
 +
 +</code> 
 +Der Sketch verwendet 24248 Bytes (78%) 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 #Peltier
arduino/flaschenkuehler/programmversion_0.3.1500541470.txt.gz · Zuletzt geändert: 18.05.2023 12:16 (Externe Bearbeitung)