#include <MAX6675_Thermocouple.h>
#include <PID_v2.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// MAX6675 pin tanımlamaları
int thermoDO = 2; // MISO (Data Out) pin
int thermoCS = 3; // CS (Chip Select) pin
int thermoCLK = 4; // CLK (Clock) pin
MAX6675_Thermocouple thermocouple(thermoCLK, thermoCS, thermoDO);
// Buton pin tanımlamaları
#define UP_BUTTON_PIN 5
#define DOWN_BUTTON_PIN 6
#define SELECT_BUTTON_PIN 7
// Buzzer ve Röle pin tanımlamaları
#define BUZZER_PIN 8
#define RELAY_PIN 9
#define START_BUTTON_PIN 10
// PID kontrol parametreleri
double Setpoint, Input, Output;
double Kp, Ki, Kd; // PID ayarları
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
// 8 kademeli PID ayarları
double setpoints[8] = {50, 100, 150, 200, 250, 300, 350, 400}; // Hedef sıcaklık değerleri
double Kp_values[8] = {2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5};
double Ki_values[8] = {5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5};
double Kd_values[8] = {1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7};
// Kademeler arası geçiş süreleri (saniye cinsinden)
int transitionTimes[8] = {30, 60, 90, 120, 150, 180, 210, 240};
int currentStage = 0; // Mevcut PID kademe
unsigned long lastButtonUpdate = 0;
unsigned long lastDisplayUpdate = 0;
unsigned long stageStartTime = 0;
enum MenuState { MAIN_MENU, SELECT_STAGE, ADJUST_SETTINGS, ADJUST_TIMES } menuState = MAIN_MENU;
int selectedSettingIndex = 0;
int selectedTimeIndex = 0;
bool systemStarted = false; // Sistem başlatıldı mı?
// I2C LCD tanımlaması
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C adresi 0x27 olan 20x4 LCD ekran
void setup() {
Serial.begin(9600);
// Buton pin ayarları
pinMode(UP_BUTTON_PIN, INPUT_PULLUP);
pinMode(DOWN_BUTTON_PIN, INPUT_PULLUP);
pinMode(SELECT_BUTTON_PIN, INPUT_PULLUP);
// Buzzer ve Röle pin ayarları
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
// Başlat butonu pin ayarları
pinMode(START_BUTTON_PIN, INPUT_PULLUP);
// PID başlangıç değerleri (sistem başlatılmadan önce etkisiz)
Setpoint = setpoints[currentStage];
Kp = Kp_values[currentStage];
Ki = Ki_values[currentStage];
Kd = Kd_values[currentStage];
myPID.SetTunings(Kp, Ki, Kd);
myPID.SetMode(MANUAL); // Başlangıçta PID devrede değil
// LCD ekranı başlat
lcd.init();
lcd.backlight();
lcd.clear();
}
void loop() {
unsigned long now = millis();
// Buton değişikliklerini kontrol et
if (now - lastButtonUpdate > 100) {
handleButtonPress();
lastButtonUpdate = now;
}
if (systemStarted) {
// Sensörden sıcaklık değerini oku
Input = thermocouple.readCelsius();
// PID hesapla
myPID.Compute();
// PID çıkışına göre röleyi kontrol et
if (Output > 0) {
digitalWrite(RELAY_PIN, HIGH);
} else {
digitalWrite(RELAY_PIN, LOW);
}
// Kademeler arasında geçiş kontrolü
if (now - stageStartTime >= transitionTimes[currentStage] * 1000) {
if (currentStage < 7) {
currentStage++;
Setpoint = setpoints[currentStage];
Kp = Kp_values[currentStage];
Ki = Ki_values[currentStage];
Kd = Kd_values[currentStage];
myPID.SetTunings(Kp, Ki, Kd);
stageStartTime = now; // Yeni kademenin başladığı zamanı güncelle
} else {
// 8. kademeye ulaşıldığında işlemi bitir ve buzzer'ı çalıştır
Serial.println("Process Completed!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Process Completed!");
digitalWrite(BUZZER_PIN, HIGH);
delay(3000); // Buzzer'ı 3 saniye boyunca çalıştır
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(RELAY_PIN, LOW); // Röleyi kapat
systemStarted = false; // Sistemi durdur
myPID.SetMode(MANUAL); // PID'i devre dışı bırak
}
}
}
// LCD ekranı güncelle
if (now - lastDisplayUpdate > 500) {
updateLCD();
lastDisplayUpdate = now;
}
}
void handleButtonPress() {
if (digitalRead(UP_BUTTON_PIN) == LOW) {
delay(50); // Debounce
if (digitalRead(UP_BUTTON_PIN) == LOW) {
switch (menuState) {
case MAIN_MENU:
case SELECT_STAGE:
case ADJUST_SETTINGS:
case ADJUST_TIMES:
currentStage--;
if (currentStage < 0) currentStage = 0;
break;
}
}
}
if (digitalRead(DOWN_BUTTON_PIN) == LOW) {
delay(50); // Debounce
if (digitalRead(DOWN_BUTTON_PIN) == LOW) {
switch (menuState) {
case MAIN_MENU:
case SELECT_STAGE:
case ADJUST_SETTINGS:
case ADJUST_TIMES:
currentStage++;
if (currentStage > 7) currentStage = 7;
break;
}
}
}
if (digitalRead(SELECT_BUTTON_PIN) == LOW) {
delay(50); // Debounce
if (digitalRead(SELECT_BUTTON_PIN) == LOW) {
handleSelectButtonPress();
delay(500); // Debounce
}
}
if (digitalRead(START_BUTTON_PIN) == LOW) {
delay(50); // Debounce
if (digitalRead(START_BUTTON_PIN) == LOW) {
handleStartButtonPress();
delay(500); // Debounce
}
}
}
void handleSelectButtonPress() {
switch (menuState) {
case MAIN_MENU:
if (currentStage == 0) {
menuState = SELECT_STAGE;
} else if (currentStage == 1) {
menuState = ADJUST_SETTINGS;
} else if (currentStage == 2) {
menuState = ADJUST_TIMES;
} else if (currentStage == 3) {
// Başlat menü seçildi
if (!systemStarted) {
systemStarted = true;
myPID.SetMode(AUTOMATIC); // PID'i devreye sok
Setpoint = setpoints[currentStage];
Kp = Kp_values[currentStage];
Ki = Ki_values[currentStage];
Kd = Kd_values[currentStage];
myPID.SetTunings(Kp, Ki, Kd);
stageStartTime = millis(); // Kademenin başladığı zamanı başlat
digitalWrite(RELAY_PIN, HIGH); // Röleyi aç
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System Started!");
Serial.println("System Started!");
}
}
break;
case SELECT_STAGE:
menuState = MAIN_MENU;
break;
case ADJUST_SETTINGS:
setpoints[currentStage] += 10; // Setpoint artırma
if (setpoints[currentStage] > 500) setpoints[currentStage] = 10; // Maksimum setpoint sınırı
break;
case ADJUST_TIMES:
transitionTimes[currentStage] += 10; // Zaman ayarını 10 saniye artır
if (transitionTimes[currentStage] > 3600) transitionTimes[currentStage] = 10; // Maksimum süre sınırı
break;
}
}
void handleStartButtonPress() {
switch (menuState) {
case ADJUST_SETTINGS:
case ADJUST_TIMES:
menuState = MAIN_MENU;
break;
case MAIN_MENU:
case SELECT_STAGE:
if (systemStarted) {
systemStarted = false;
myPID.SetMode(MANUAL); // PID'i devre dışı bırak
digitalWrite(RELAY_PIN, LOW); // Röleyi kapat
digitalWrite(BUZZER_PIN, LOW); // Buzzer'ı kapat
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System Stopped!");
Serial.println("System Stopped!");
}
break;
}
}
void updateLCD() {
lcd.clear();
switch (menuState) {
case MAIN_MENU:
lcd.setCursor(0, 0);
lcd.print(currentStage == 0 ? ">Select Stage" : " Select Stage");
lcd.setCursor(0, 1);
lcd.print(currentStage == 1 ? ">Adjust Settings" : " Adjust Settings");
lcd.setCursor(0, 2);
lcd.print(currentStage == 2 ? ">Adjust Times" : " Adjust Times");
lcd.setCursor(0, 3);
lcd.print(currentStage == 3 ? ">Start System" : " Start System");
break;
case SELECT_STAGE:
lcd.setCursor(0, 0);
lcd.print("Select Stage:");
lcd.setCursor(0, 1);
lcd.print("Current: ");
lcd.print(currentStage + 1);
lcd.setCursor(0, 2);
lcd.print("Setpoint: ");
lcd.print(setpoints[currentStage]);
lcd.print(" C");
break;
case ADJUST_SETTINGS:
lcd.setCursor(0, 0);
lcd.print("Adjust Settings:");
lcd.setCursor(0, 1);
lcd.print("Stage ");
lcd.print(currentStage + 1);
lcd.setCursor(0, 2);
lcd.print("Setpoint: ");
lcd.print(setpoints[currentStage]);
lcd.print(" C");
break;
case ADJUST_TIMES:
lcd.setCursor(0, 0);
lcd.print("Adjust Transition:");
lcd.setCursor(0, 1);
lcd.print("Stage ");
lcd.print(currentStage + 1);
lcd.setCursor(0, 2);
lcd.print("Time: ");
lcd.print(transitionTimes[currentStage]);
lcd.print(" s");
break;
}
if (systemStarted) {
lcd.setCursor(0, 3);
lcd.print("Temp: ");
lcd.print(Input);
lcd.print(" C");
lcd.setCursor(0, 4);
lcd.print("Set: ");
lcd.print(Setpoint);
lcd.print(" C");
}
}