Espresso

Programmierung

Anmerkung


Wie zuvor schon angesprochen, wird die Maschine von einem Arduino gesteuert, der auch die gesamte Logik zur Temperatursteuerung enthält. Der hier abgebildete Code kann sich jederzeit ändern und wird dies in näherer Zukunft auch häufiger tun.

Dieser Code ist "Work-in-Progress" und steht hier ohne Garantie zur Einsicht. Die Nutzung erfolgt auf eigenes Risiko.

Programmcode



/* ABOUT ============================================== */
/*  Espressomaschinen-Steuerung          */
static String versionString = "ver25 2016-04-10";
/*  Jan Kube     -   www.jankube.de      */


#include "max6675.h"
#include "KUBE_PID.h"


/* EINSTELLUNGEN ====================================== */
// Timing-Allgemein
static int    ZEIT_kaffeeBezug                           = 30000;     // 30sek Kaffeebezug
static int    ZEIT_dampfPause                            = 500;       // Pumpenwartezeit bei Dampfbezug
static int    ZEIT_entlueftung                           = 7500;      // Millisekunden zwischen Entlueftung
static long   ZEIT_automatischeAbschaltung               = 600000;    // auto aus nach 10 Minuten Untaetigkeit
static long   ZEIT_letzteAktion                          = 0;         // Nach 10 Min Untaetigkeit soll automatisch abgeschaltet werden 
// Temperatur-Variablen
static double TEMPERATUR_Ziel_Heizung_Wasser             = 105.0;     // ZielTemperatur fuer Wasser-Heizung bei Kaffeebezug
static double TEMPERATUR_Ziel_Heizung_Dampf              = 95.0;      // ZielTemperatur fuer Dampf-Heizung  bei Kaffeebezug
static double TEMPERATUR_Ziel_Heizung_BG                 = 95.0;      // ZielTemperatur fuer BG-Heizung     bei Kaffee- und Dampfbezug
static double TEMPERATUR_Ziel_Heizung_Wasser_Dampfbezug  = 140.0;     // ZielTemperatur fuer Wasser-Heizung bei Dampfbezug
static double TEMPERATUR_Ziel_Heizung_Dampf_Dampfbezug   = 130.0;     // ZielTemperatur fuer Dampf-Heizung  bei Dampfbezug
static double TEMPERATUR_max                             = 175.0;     // Hoechst-Temperatur
static double TEMPERATUR_min                             = 5.0;       // Niedrigst-Temperatur
// Temperatur-Arbeitsvariablen
static double SENSOR_Heizung_Wasser                      = 20.0;      // Messwert von Temperatursensor an Wasserheizung
static double SENSOR_Heizung_Dampf                       = 20.0;      // Messwert von Temperatursensor an Dampfheizung
static double SENSOR_Heizung_BG                          = 20.0;      // Messwert von Temperatursensor an BG
// Fehler
static boolean FEHLER                                    = false;     // Allgemeine Variable fuer Fehler-Alarm



/* WASSER ======================================== */
// PID Einstellungen
static double PID_Heizung_Wasser_Eingabe                 = 0.0;       // Momentaner Temperaturzustand als Eingabewert fuer PID
static double PID_Heizung_Wasser_Ziel                    = TEMPERATUR_Ziel_Heizung_Wasser;    // Sollwert
static double PID_Heizung_Wasser_kp                      = 20.0;      // Proportional (Gegenwart)       55.0
static double PID_Heizung_Wasser_ki                      = 0.0;       //0.0001; // Integral     (Vergangenheit)    0.0001
static double PID_Heizung_Wasser_kd                      = 90.0;      // Derivativ    (Zukunft)         70.0

/* PID DAMPF ======================================== */
// PID Einstellungen
static double PID_Heizung_Dampf_Eingabe                  = 0.0;       // Momentaner Temperaturzustand als Eingabewert fuer PID
static double PID_Heizung_Dampf_Ziel                     = TEMPERATUR_Ziel_Heizung_Dampf;    // Sollwert
static double PID_Heizung_Dampf_kp                       = 25.0;      // Proportional (Gegenwart)       25.0
static double PID_Heizung_Dampf_ki                       = 0.0;       // Integral     (Vergangenheit)   0.6
static double PID_Heizung_Dampf_kd                       = 95.0;      // Derivativ    (Zukunft)         24.0
// PID Dampf Arbeitsvariablen

/* PID BG ========================================== */
// PID Einstellungen
static double PID_Heizung_BG_Eingabe                     = 0.0;       // Momentaner Temperaturzustand als Eingabewert fuer PID
static double PID_Heizung_BG_Ziel                        = TEMPERATUR_Ziel_Heizung_BG;    // Sollwert
static double PID_Heizung_BG_kp                          = 60.0;      // Proportional (Gegenwart)       11.0
static double PID_Heizung_BG_ki                          = 0.0;       // Integral     (Vergangenheit)    0.001
static double PID_Heizung_BG_kd                          = 50.0;      // Derivativ    (Zukunft)         24.0



/* ANSCHLUESSE ======================================= */
// Ausgaenge
static int    PIN_Pumpe                                  = 7;         // Pumpenanschluss
static int    PIN_Ventil_BG                              = 8;         // 3-Wege-Ventil, welches an der Bruehgruppe sitzt
static int    PIN_Ventil_Wasser                          = 6;         // Ventil, welches den Weg zur BG oeffnet
static int    PIN_Ventil_Dampf                           = 16;        // Ventil, welches den Weg zur Dampflanze oeffnet
static int    PIN_Heizung_Wasser                         = 9;         // Hauptheizung fuer Wasser (mit Temperatursensoren, 1400W)
static int    PIN_Heizung_Dampf                          = 5;         // Zusatzheizung fuer Dampf (der Hauptheizung vorgeschaltet, 900W)
static int    PIN_Heizung_BG                             = 4;         // TODO: Heizung der Bruehgruppe (250W)
// Eingaenge
static int    PIN_Schalter_Wasser                        = 11;        // Schalter fuer den Bezug von Wasser aus der Dampflanze
static int    PIN_Schalter_Dampf                         = 10;        // Schalter fuer den Bezug von Dampf aus der Dampflanze
static int    PIN_Schalter_Kaffee                        = 15;        // Schalter fuer den Bezug von Kaffee (Wasser aus der BG)
// Temperatursensoren
static int    Sensor_DO                                  = 12;         // MISO: Sensor Data Out (gemeinsam)
static int    Sensor_CLK                                 = 13;         // Clock (gemeinsam)
static int    Sensor1_CS                                 = 19;        // Select Chip 1  // Dampf
static int    Sensor2_CS                                 = 18;        // Select Chip 2  // BG
static int    Sensor3_CS                                 = 17;        // Select Chip 3  // Wasser




/* BIBLIOTHEKEN ======================================= */

/* TEMPERATURSENSOREN */
MAX6675 Sensor1(Sensor_CLK, Sensor1_CS, Sensor_DO);
MAX6675 Sensor2(Sensor_CLK, Sensor2_CS, Sensor_DO);
MAX6675 Sensor3(Sensor_CLK, Sensor3_CS, Sensor_DO);

/* PIDs */
// PID Wasser
KUBE_PID PID_Heizung_Wasser ( 
  &PID_Heizung_Wasser_Eingabe, 
  &PID_Heizung_Wasser_Ziel, 
  PID_Heizung_Wasser_kp, 
  PID_Heizung_Wasser_ki, 
  PID_Heizung_Wasser_kd, 
  PIN_Heizung_Wasser
);
// PID Dampf
KUBE_PID PID_Heizung_Dampf ( 
  &PID_Heizung_Dampf_Eingabe, 
  &PID_Heizung_Dampf_Ziel, 
  PID_Heizung_Dampf_kp, 
  PID_Heizung_Dampf_ki, 
  PID_Heizung_Dampf_kd, 
  PIN_Heizung_Dampf 
);
// PID BG
KUBE_PID PID_Heizung_BG ( 
  &PID_Heizung_BG_Eingabe, 
  &PID_Heizung_BG_Ziel, 
  PID_Heizung_BG_kp, 
  PID_Heizung_BG_ki, 
  PID_Heizung_BG_kd, 
  PIN_Heizung_BG 
);



/* SETUP ============================================== */
void setup() {
  // Kommunikation mit dem Rechner beginnen
  Serial.begin(9600);
  nachricht("I Jan Kube");
  nachricht("I Espressomaschine Steuerung " + versionString);
  nachricht("I www.jankube.de");
  nachricht("I Beginne mit der Konfiguration");
  
  // PINS KONFIGURIEREN
  // Ausgaenge
  pinMode(PIN_Pumpe,                  OUTPUT);
  pinMode(PIN_Ventil_BG,              OUTPUT);
  pinMode(PIN_Ventil_Wasser,          OUTPUT);
  pinMode(PIN_Ventil_Dampf,           OUTPUT);
  pinMode(PIN_Heizung_Wasser,         OUTPUT);
  pinMode(PIN_Heizung_Dampf,          OUTPUT);
  pinMode(PIN_Heizung_BG,             OUTPUT);
  pinMode(Sensor1_CS,                 OUTPUT); // Select Chip 1
  pinMode(Sensor2_CS,                 OUTPUT); // Select Chip 2
  pinMode(Sensor3_CS,                 OUTPUT); // Select Chip 3
  // Eingaenge
  pinMode(PIN_Schalter_Wasser,        INPUT_PULLUP);
  pinMode(PIN_Schalter_Dampf,         INPUT_PULLUP);
  pinMode(PIN_Schalter_Kaffee,        INPUT_PULLUP);
  
  // ALLES AUSSCHALTEN
  allesAus();
  
  // Durchspuelen
  digitalWrite(PIN_Ventil_Dampf, HIGH);
  digitalWrite(PIN_Pumpe, HIGH);
  delay(2000);
  
  // ALLES AUSSCHALTEN
  allesAus();
  
  // Status ausgeben
  nachricht("I Konfiguration abgeschlossen");
}



/* METHODEN =========================================== */
void allesAus() {
  // Nacheinander alles abschalten, die Ventile zuletzt.
  digitalWrite(PIN_Pumpe,          LOW);
  delay(10);
  digitalWrite(PIN_Heizung_Wasser, LOW);
  delay(10);
  digitalWrite(PIN_Heizung_Dampf,  LOW);
  delay(10);
  digitalWrite(PIN_Heizung_BG,     LOW);
  delay(10);
  digitalWrite(PIN_Ventil_BG,      LOW);
  delay(10);
  digitalWrite(PIN_Ventil_Wasser,  LOW);
  delay(10);
  digitalWrite(PIN_Ventil_Dampf,   LOW);
  delay(10);

  // Zaehler fuer automatische Abschaltung zuruecksetzen
  ZEIT_letzteAktion = millis();
}



void nachricht(String msg) {
  // Serielle Nachricht nur dann schicken, wenn ueberhaupt eine Verbindung besteht
  if (Serial) {
    // Nachricht seriell verschicken
    Serial.println(msg);
  }
}



void bezugWasser() {
  // Status ausgeben
  nachricht("I Starte Wasserbezug");

  if (!FEHLER) {
    // Leitung oeffnen, Wasser pumpen
    digitalWrite(PIN_Ventil_Dampf, HIGH);
    digitalWrite(PIN_Pumpe, HIGH);
    
    // Wasser (aus Dampfrohr) ausgeben, solange Schalter an ist (LOW = AN)
    while ( digitalRead(PIN_Schalter_Wasser)==LOW && !FEHLER ) {
      // Temperaturen mit PID regeln
      pid_wasser();
      pid_dampf();
      pid_bg();
    }
  }
  
  // Schalter aus
  allesAus();

  // Status ausgeben
  nachricht("I Wasserbezug abgeschlossen");
}



void bezugDampf() {
  // Status ausgeben
  nachricht("I Starte Dampfbezug");
  
  // Temperaturen nach oben korrigieren (fuer Dampfbezug)
  PID_Heizung_Wasser_Ziel = TEMPERATUR_Ziel_Heizung_Wasser_Dampfbezug;
  PID_Heizung_Dampf_Ziel  = TEMPERATUR_Ziel_Heizung_Dampf_Dampfbezug;

  if (!FEHLER) {
    // Leitung oeffnen, Dampheizung anschalten
    digitalWrite(PIN_Ventil_Dampf, HIGH);
    digitalWrite(PIN_Heizung_Dampf, HIGH);
    
    // Impuls-Pumpensteuerung vorbereiten
    long pumpeSchaltZeitpunkt = millis(); // Zeit fuer Pumpensteuerung ohne delay()
    
    // Dampf ausgeben, solange Schalter an ist (LOW = AN)
    while ( digitalRead(PIN_Schalter_Dampf)==LOW && !FEHLER ) {
      // Temperaturen mit PID regeln
      pid_wasser();
      pid_dampf();
      pid_bg();
      
      // Pumpen-Impulssteuerung: Aus-Zeit berechnen
      long schaltzeit = millis() - pumpeSchaltZeitpunkt;
      // Anschalten?
      if (schaltzeit>ZEIT_dampfPause) {   // Pumpe lange genug aus -> Impuls geben
        digitalWrite(PIN_Pumpe, HIGH);    // an
        delay(100);
        digitalWrite(PIN_Pumpe, LOW);     // aus
        // Zeitsteuerung aktualisieren
        pumpeSchaltZeitpunkt = millis();
      } 
    }
  }
  
  // Schalter ist aus
  allesAus();
  
  // hohe Dampf-Temperaturen wieder nach unten korrigieren (fuer Wasser-/Kaffeebezug)
  PID_Heizung_Wasser_Ziel = TEMPERATUR_Ziel_Heizung_Wasser;
  PID_Heizung_Dampf_Ziel  = TEMPERATUR_Ziel_Heizung_Dampf;
  
  // Status ausgeben
  nachricht("I Dampfbezug abgeschlossen");
}



void bezugKaffee() {

  if (!FEHLER) {
    // Status ausgeben
    nachricht("I Starte Kaffeebezug");

    // Ventile auf
    digitalWrite(PIN_Ventil_BG, HIGH);     // BG-Ventil oeffnen
    digitalWrite(PIN_Ventil_Wasser, HIGH); // Ventil auf dem Wasserweg zur BG oeffnen
    
    // PRAEINFUSION: Startzeit merken
    long startzeit = millis();
    // Pumpe fuer Praeinfusion an
    digitalWrite(PIN_Pumpe, HIGH);
    // 3 Sek. lang pumpen, aber PID weiter regeln
    while (millis() - startzeit < 3000) {
      // Temperaturen mit PID regeln
      pid_wasser();
      pid_dampf();
      pid_bg();
    }
    // Pumpe fuer Praeinfusion an
    digitalWrite(PIN_Pumpe, LOW);
    // weitere 2 Sek. lang warten, um Puck quellen zu lassen (also insgesamt 5 Sek. Praeinfusion)
    while (millis() - startzeit < 5000) {
      // Temperaturen mit PID regeln
      pid_wasser();
      pid_dampf();
      pid_bg();
    }
    
    // KAFFEEBEZUG starten
    digitalWrite(PIN_Pumpe, HIGH);
    
    // Kaffee ausgeben, solange Schalter an ist (LOW = AN)
    while ( digitalRead(PIN_Schalter_Kaffee)==LOW && !FEHLER ) {   // && (millis()-kaffeeBezugsstart<ZEIT_kaffeeBezug) ) {
      // Temperaturen mit PID regeln
      pid_wasser();
      pid_dampf();
      pid_bg();
    }

    // Schalter ist aus
    allesAus();
    
    // Status ausgeben
    nachricht("I Kaffeebezug abgeschlossen");
  }
}



void pid_wasser() {

  // SCHRITT 1: Temperatur aktualisieren
  SENSOR_Heizung_Wasser = Sensor3.readCelsius();
  Serial.print(" \t Heizung Wasser: ");
  Serial.print(SENSOR_Heizung_Wasser);
  // Auf Fehler pruefen: Zu warm oder zu kalt?
  if (SENSOR_Heizung_Wasser > TEMPERATUR_max || SENSOR_Heizung_Wasser < TEMPERATUR_min) {
    FEHLER = true;
  }

  // SCHRITT 2: PID-Ausgabe berechnen
  PID_Heizung_Wasser_Eingabe = SENSOR_Heizung_Wasser;
  PID_Heizung_Wasser.ausgabeBerechnen();
  
  // SCHRITT 3: Heizungs-SSR steuern
  PID_Heizung_Wasser.relaisSteuern();
}



void pid_dampf() {

  // SCHRITT 1: Temperatur aktualisieren
  SENSOR_Heizung_Dampf = Sensor1.readCelsius();
  Serial.print(" \t Heizung Dampf: ");
  Serial.print(SENSOR_Heizung_Dampf);
  // Auf Fehler pruefen: Zu warm oder zu kalt?
  if (SENSOR_Heizung_Dampf > TEMPERATUR_max || SENSOR_Heizung_Dampf < TEMPERATUR_min) {
    FEHLER = true;
  }

  // SCHRITT 2: PID-Ausgabe berechnen
  PID_Heizung_Dampf_Eingabe = SENSOR_Heizung_Dampf;
  PID_Heizung_Dampf.ausgabeBerechnen();

  // SCHRITT 3: Heizungs-SSR steuern
  PID_Heizung_Dampf.relaisSteuern();
}



void pid_bg() {

  // SCHRITT 1: Temperatur aktualisieren
  SENSOR_Heizung_BG = Sensor2.readCelsius();
  Serial.print(" \t Heizung BG: ");
  Serial.println(SENSOR_Heizung_BG);
  // Auf Fehler pruefen: Zu warm oder zu kalt?
  if (SENSOR_Heizung_BG > TEMPERATUR_max || SENSOR_Heizung_BG < TEMPERATUR_min) {
    FEHLER = true;
  }

  // SCHRITT 2: PID-Ausgabe berechnen
  PID_Heizung_BG_Eingabe = SENSOR_Heizung_BG;
  PID_Heizung_BG.ausgabeBerechnen();

  // SCHRITT 3: Heizungs-SSR steuern
  PID_Heizung_BG.relaisSteuern();
}



void automatischAbschalten() {
  // Automatische Abschaltung nach 10 min des Nichtstuns
  if (millis() - ZEIT_letzteAktion > ZEIT_automatischeAbschaltung) {  // 10 min
    while (true) {
      allesAus();
      Serial.println(" AUS NACH ZU LANGE AN ");
      Serial.print(" millis: ");
      Serial.print(millis());
      Serial.print(" ZEIT_letzteAktion: ");
      Serial.print(ZEIT_letzteAktion);
      Serial.print(" ZEIT_automatischeAbschaltung: ");
      Serial.println(ZEIT_automatischeAbschaltung);
      delay(10000);
    }
  }
}



void fehlerAbschalten() {
  while (true) {
    allesAus();
    Serial.println("AUS NACH FEHLER");
    delay(10000);
  }
}



/* LOOP =============================================== */
void loop() {
  
  // Solange kein Fehler passiert ist...
  if (!FEHLER) {

    // Temperaturen mit PID regeln
    pid_wasser();
    pid_dampf();
    pid_bg();

    // Schalter abfragen (LOW=AN)
    if (digitalRead(PIN_Schalter_Wasser) == LOW) {
      bezugWasser();
    }
    if (digitalRead(PIN_Schalter_Dampf)  == LOW) {
      bezugDampf();
    }
    if (digitalRead(PIN_Schalter_Kaffee) == LOW) {
      bezugKaffee();
    }
    
    // automatisch abschalten? (bei 10 Min keine Aktion)
    automatischAbschalten();
    
  // Wenn ein Fehler passiert ist, nichts mehr machen.
  } else {
    fehlerAbschalten();
  }

}


Sie können die komplette Arduino-Programmierung (Version 25) hier herunterladen .

KUBE_PID Bibliothek


/**********************************************************************************************
 * Arduino KUBE_PID Library - Version 0.1
 * by Jan Kube <kontakt@jankube.de> http://jankube.de/
 * 
 * based on PID Library by Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
 *
 * This Library is licensed under GPLv3
 **********************************************************************************************/

#if ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

#include <KUBE_PID.h>

/*Constructor (...)*********************************************************/
KUBE_PID::KUBE_PID(double* Eingabe, double* Ziel, double Kp, double Ki, double Kd, int pin)
{
  // Einstellungen im Constructor uebernehmen

  // Verweise
  PID_Eingabe = Eingabe;
  PID_Ziel    = Ziel;
  // Anschluesse
  PID_SSR_PIN = pin;
  // Einstellungen
  PID_kp = Kp;   // Proportional
  PID_ki = Ki;   // Integral
  PID_kd = Kd;   // Derivativ
  PID_Taktlaenge        = 50;    // In welchen Intervallen soll (ggf.) berechnet werden?
  PID_Relais_Taktlaenge = 1000;  // In welchen Intervallen soll (ggf.) geschaltet werden?
  PID_MIN = 0;     // Untergrenze fuer PID_Ausgabe
  PID_MAX = 1000;  //  Obergrenze fuer PID_Ausgabe
  // Arbeitsvariablen
  PID_Ausgabe                = 0;
	PID_Schaltzeitpunkt        = millis();
  PID_Relais_Schaltzeitpunkt = 0;    // Wann wurde zuletzt geschaltet?
  PID_Fehlersumme            = 0;
  PID_letzterFehler          = 0;
  PID_Relais_Strom           = LOW;  // Strom-Zustand merken
	
}
 
 
/* ausgabeBerechnen() **********************************************************************/ 
bool KUBE_PID::ausgabeBerechnen()
{

  /**
  * PID-ZIELWERT BERECHNEN
  */

  // Zeit seit letzter Berechnung
  long PID_Berechnungsstart = millis();
  long PID_ZeitAenderung = (PID_Berechnungsstart - PID_Schaltzeitpunkt);

  // Schon wieder neu berechnen?
  if (PID_ZeitAenderung >= PID_Taktlaenge) {

    // alle verschiedenen Fehler berechnen
    double PID_Fehler = *PID_Ziel - *PID_Eingabe;
    PID_Fehlersumme = PID_Fehlersumme + (PID_Fehler * PID_ZeitAenderung);
    double PID_FehlerAenderung = (PID_Fehler - PID_letzterFehler) / PID_ZeitAenderung;

    // I-Wert (Fehlersumme) limitieren (Min und Max auf je 5-Fache Taktlaenge)
    // damit I nicht voellig uebertrieben gross wird. 
    if (PID_Fehlersumme < (0-PID_MAX)*5/PID_ki) {
      PID_Fehlersumme = (0-PID_MAX)*5/PID_ki;
    } else if (PID_Fehlersumme > (PID_MAX)*5/PID_ki) {
      PID_Fehlersumme = PID_MAX*5/PID_ki;
    }
    // PID Ausgaben berechnen
    double PID_P = (PID_kp * PID_Fehler);           // P
    double PID_I = (PID_ki * PID_Fehlersumme);      // I
    double PID_D = (PID_kd * PID_FehlerAenderung);  // D
    // Ausgaben kombinieren
    PID_Ausgabe =  PID_P + PID_I + PID_D;

    // Fehler und Schaltzeit fuer naechsten Takt merken
    PID_letzterFehler  = PID_Fehler;
    PID_Schaltzeitpunkt = PID_Berechnungsstart;

    // Min und Max einhalten: 
    if (PID_Ausgabe > PID_MAX) {
      PID_Ausgabe = PID_MAX;
    } else if (PID_Ausgabe < PID_MIN) {
      PID_Ausgabe = PID_MIN;
    }

    /*
    Serial.print(" \tFehler: ");
    Serial.print(PID_Fehler);

    Serial.print(" \tkp: ");
    Serial.print(PID_kp);
    Serial.print(" \tki: ");
    Serial.print(PID_ki);
    Serial.print(" \tkd: ");
    Serial.print(PID_kd);

    Serial.print(" \tP: ");
    Serial.print(PID_P);
    Serial.print(" \tI: ");
    Serial.print(PID_I);
    Serial.print(" \tD: ");
    Serial.print(PID_D);

    Serial.print(" \tAusgabe PID: ");
    Serial.println(PID_Ausgabe);
    */
  }

}


/* relaisSteuern() *************************************************************************/
bool KUBE_PID::relaisSteuern()
{

  /**
  * VORBEREIUNG
  */

  // Heizung steuern: Ziel-Status ermitteln
  int ziel_zeit_an   = PID_Ausgabe;
  int ziel_zeit_aus  = PID_Relais_Taktlaenge - ziel_zeit_an;
  long taktStartzeit = millis(); // Startzeit des aktuellen Taktes merken
  // Zeit seit letztem Schalten berechnen
  long zeitdifferenz = taktStartzeit-PID_Relais_Schaltzeitpunkt;



  /**
  * ZIEL-STATUS ERMITTELN
  */

  // Immer an
  if (ziel_zeit_an>0.95*PID_Relais_Taktlaenge) {
    // Stromstatus und Schaltzeit merken
    PID_Relais_Strom = HIGH;
    PID_Relais_Schaltzeitpunkt = taktStartzeit;
  }

  // Immer aus
  else if (ziel_zeit_aus>0.95*PID_Relais_Taktlaenge) {
    // Stromstatus und Schaltzeit merken
    PID_Relais_Strom=LOW;
    PID_Relais_Schaltzeitpunkt = taktStartzeit;
  }

  // aus und lange genug aus? -> Anschalten
  if (PID_Relais_Strom==LOW && zeitdifferenz>ziel_zeit_aus) {
    // Stromstatus und Schaltzeit merken
    PID_Relais_Strom = HIGH;
    PID_Relais_Schaltzeitpunkt = taktStartzeit;
  }

  // an und lange genug an? -> Ausschalten
  else if (PID_Relais_Strom==HIGH && zeitdifferenz>ziel_zeit_an) {
    // Stromstatus und Schaltzeit merken
    PID_Relais_Strom = LOW;
    PID_Relais_Schaltzeitpunkt = taktStartzeit;
  }



  //Schalten
  digitalWrite(PID_SSR_PIN, PID_Relais_Strom);
  
}


Sie können die komplette Arduino-Bibliothek zur zeitdiskreten PID-Steuerung hier herunterladen .


© 2018 - Jan Kube