// Include Header Files
#include "configuration.h"
#include "globals.h"
// Konstanten für Prescaler-Werte von Timer 1
//const uint8_t PRESCALER_1 = 0x01; // ~31.4 kHz
//const uint8_t PRESCALER_8 = 0x02; // ~3.92 kHz
//const uint8_t PRESCALER_64 = 0x03; // ~490 Hz (Standard)
const uint8_t PRESCALER_256 = 0x04; // ~122 Hz
//const uint8_t PRESCALER_1024 = 0x05; // ~31 Hz
// Variablen: (Initial Werte)
double setPoint = 25.00; //Soll Temperature
double temperature; //Ist Temperature
double outputVal;
double threshold = 1.00;
int TEMPupdate_DELAY = 1000; //In Milliseconds
int Input_DELAY = 1000; //In Milliseconds
int myPID_Time_Step = 500; //In Milliseconds
int LongClickTime = 250; //In Milliseconds
boolean heater_aktiv = false;
boolean main_menue_aktiv = true;
byte setup_menue = 0;
byte change_myPID_values = 0;
byte PID_ANALOG_DIGITAL = 0;
// pid settings and gains (Initial Werte)
byte OUTPUT_MIN = 0;
byte OUTPUT_MAX = 255;
double KP = 4.00;
double KI = 0.00;
double KD = 0.00;
boolean relayState;
// LCD initialisieren: RS, E, D4, D5, D6, D7
LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
// Rotary Encoder initialisieren: CLK, DT
ESPRotary rotary(ROTARY_PIN_CLK, ROTARY_PIN_DT);
Button2 btn_rotary(BUTTON_PIN);
// Timer zur Abfrage der Temperatur Istwerte
BlockNot TEMPupdate_Timer(TEMPupdate_DELAY); //In Milliseconds
// Timer zur Aktualisierung von Werten
BlockNot Input_Timer(Input_DELAY); //In Milliseconds
//input/output variables passed by reference, so they are updated automatically
//Ausgang = Analog
AutoPID myPID(&temperature, &setPoint, &outputVal, OUTPUT_MIN, OUTPUT_MAX, KP, KI, KD);
//Ausgang = Digital
AutoPIDRelay myPIDRelay(&temperature, &setPoint, &relayState, myPID_Time_Step, KP, KI, KD);
void setup() {
//Serial.begin(9600);
// Timer 1 Prescaler konfigurieren
TCCR1B = (TCCR1B & 0b11111000) | PRESCALER_256;
eeprom_laden();
pinMode(HEATER_PIN, OUTPUT);
analogWrite(HEATER_PIN, 0);
TEMPupdate_Timer.setDuration(TEMPupdate_DELAY);
TEMPupdate_Timer.START_RESET;
Input_Timer.START_RESET;
while (!Input_Timer.FIRST_TRIGGER) {} //warte auf erstes Trigger Signal
myPID.setTimeStep(myPID_Time_Step);
myPID.setBangBang(threshold);
myPID.stop();
myPIDRelay.setBangBang(threshold);
myPIDRelay.stop();
lcd.begin(20, 2);
lcd.clear();
// Rotary Encoder Initialisieren
rotary.begin(ROTARY_PIN_CLK, ROTARY_PIN_DT, CLICKS_PER_STEP);
rotary.setChangedHandler(rotate);
// Rotary Encoder Btn Initialisieren
btn_rotary.begin(BUTTON_PIN);
btn_rotary.setLongClickTime(LongClickTime);
btn_rotary.setClickHandler(click);
btn_rotary.setLongClickDetectedHandler(longClick);
print_main_menue();
}
void myPID_value_change() {
if (Input_Timer.FIRST_TRIGGER) {
switch (change_myPID_values) {
case 1:
myPID.setGains(KP, KI, KD);
myPIDRelay.setGains(KP, KI, KD);
break;
case 2:
myPID.setTimeStep(myPID_Time_Step);
myPIDRelay.setTimeStep(myPID_Time_Step);
break;
case 3:
myPID.setBangBang(threshold);
myPIDRelay.setBangBang(threshold);
break;
case 4: // Wechsel von PID und PIDRelay
myPID.stop();
myPIDRelay.stop();
print_output_power();
heater_aktiv = false;
break;
}
myPID.reset();
myPIDRelay.reset();
change_myPID_values = 0;
}
}
void loop() {
rotary.loop();
btn_rotary.loop();
myPID_value_change();
temperature = IST_Temp_Berechnung();
if (heater_aktiv) {
switch (PID_ANALOG_DIGITAL) { // Abfrage welcher PID ist aktiv
case 0: //AutoPID (Ausgang Analog)
myPID.run();
analogWrite(HEATER_PIN, outputVal);
break;
case 1: //AutoPIDRelay (Ausgang Digital)
myPIDRelay.run();
digitalWrite(HEATER_PIN, relayState);
break;
}
} else {
switch (PID_ANALOG_DIGITAL) { // Abfrage welcher PID ist aktiv
case 0: //AutoPID (Ausgang Analog)
if (!myPID.isStopped()) {
myPID.stop();
analogWrite(HEATER_PIN, 0);
}
break;
case 1: //AutoPIDRelay (Ausgang Digital)
if (!myPID.isStopped()) {
myPIDRelay.stop();
digitalWrite(HEATER_PIN, false);
}
break;
}
}
if (TEMPupdate_Timer.TRIGGERED) {
if (main_menue_aktiv) {
print_temperature(temperature, 5, 1);
print_output_power();
} else {
print_temperature(temperature, 13, 0);
}
}
}