// Reflow BGA Rework Kontrolcüsü
// Sürüm: 2.5 (ESP32 WROOM ve ILI9341 için)
// Tarih: 24-05-2025
// Şirket: ÖZTÜRK BİLİŞİM
// Yazar: Gökhan Öztürk
// Açıklama:
// ESP32 WROOM ve ILI9341 TFT ekran için uyarlanmış reflow kontrolcüsü.
// Kurşunsuz lehimleme (BGA için optimize) profili için tasarlanmıştır.
// MAX6675 termokupl sensörü, 4 buton (Ayar, Arttırma, Azaltma, Başlat) kullanılır.
// PID kontrolü 10 adımlıdır. Parametreler Preferences ile kalıcı olarak saklanır.
// Ekran yenileme optimize edilmiştir; sadece değişen değerler güncellenir.
// Uyarı:
// Yüksek voltajla çalışmak tehlikelidir! Lütfen dikkatli olun ve uygun bilgiye sahip
// olmadan işlem yapmayın. Bu yazılım ve donanımın kullanımı tamamen kendi
// sorumluluğunuzdadır.
// Gerekli Kütüphaneler
#include <TFT_eSPI.h> // ILI9341 TFT ekran için
#include <max6675.h> // MAX6675 termokupl sensörü için
#include <PID_v1.h> // PID kontrolü için
#include <Preferences.h> // ESP32 kalıcı depolama için
// **** TÜR TANIMLAMALARI ****
typedef enum REFLOW_STATE {
REFLOW_STATE_IDLE,
REFLOW_STATE_STEP1,
REFLOW_STATE_STEP2,
REFLOW_STATE_STEP3,
REFLOW_STATE_STEP4,
REFLOW_STATE_STEP5,
REFLOW_STATE_STEP6,
REFLOW_STATE_STEP7,
REFLOW_STATE_STEP8,
REFLOW_STATE_STEP9,
REFLOW_STATE_STEP10,
REFLOW_STATE_COMPLETE,
REFLOW_STATE_TOO_HOT,
REFLOW_STATE_ERROR,
REFLOW_STATE_SETTINGS
} reflowState_t;
typedef enum REFLOW_STATUS {
REFLOW_STATUS_OFF,
REFLOW_STATUS_ON
} reflowStatus_t;
typedef enum SWITCH {
SWITCH_NONE,
SWITCH_SET,
SWITCH_UP,
SWITCH_DOWN,
SWITCH_START
} switch_t;
typedef enum DEBOUNCE_STATE {
DEBOUNCE_STATE_IDLE,
DEBOUNCE_STATE_CHECK,
DEBOUNCE_STATE_RELEASE
} debounceState_t;
typedef enum SETTING_PARAM {
SETTING_TEMP,
SETTING_KP,
SETTING_KI,
SETTING_KD,
SETTING_DURATION
} settingParam_t;
// **** SABİTLER ****
#define TEMPERATURE_ROOM 50
#define SENSOR_SAMPLING_TIME 1000
#define DEBOUNCE_PERIOD_MIN 100
#define SETTINGS_TRANSITION_DELAY 100
#define TFT_UPDATE_INTERVAL 500
#define BUZZER_TOGGLE_PERIOD 1000
// **** PID ve Sıcaklık Parametreleri ****
float temperatureSteps[10] = {150, 175, 200, 210, 220, 230, 235, 245, 200, 100};
float pidKpSteps[10] = {100, 120, 150, 180, 200, 250, 280, 300, 250, 200};
float pidKiSteps[10] = {0.025, 0.030, 0.035, 0.040, 0.045, 0.050, 0.050, 0.050, 0.040, 0.030};
float pidKdSteps[10] = {20, 25, 30, 40, 50, 100, 150, 200, 150, 100};
float stepDurations[10] = {60, 30, 30, 30, 20, 20, 20, 30, 30, 30};
// Durum mesajları
const char* lcdMessagesReflowStatus[] = {
"Hazir",
"Adim 1",
"Adim 2",
"Adim 3",
"Adim 4",
"Adim 5",
"Adim 6",
"Adim 7",
"Reflow",
"Soguma",
"Soguma Son",
"Tamamlandi",
"Cok Sicak",
"Hata",
"Ayar Modu"
};
// Pin tanımları (ESP32 için)
#define LED_RED_PIN 13
#define LED_GREEN_PIN 12
#define BUZZER_PIN 14
#define SWITCH_SET_PIN 27
#define SWITCH_UP_PIN 26
#define SWITCH_DOWN_PIN 25
#define SWITCH_START_PIN 33
#define SSR_PIN 32
#define THERMOCOUPLE_SO_PIN 19 // SPI MISO
#define THERMOCOUPLE_CS_PIN 5
#define THERMOCOUPLE_CLK_PIN 18 // SPI SCLK
// **** PID KONTROL DEĞİŞKENLERİ ****
double setpoint;
double input;
double output;
double kp;
double ki;
double kd;
int windowSize;
unsigned long windowStartTime;
unsigned long nextCheck;
unsigned long nextRead;
unsigned long timerStep;
unsigned long buzzerToggleTime;
unsigned long buzzerPeriod;
unsigned long lastSettingTransition;
unsigned long lastTftUpdate;
bool buzzerState = false;
reflowState_t reflowState = REFLOW_STATE_IDLE;
reflowStatus_t reflowStatus = REFLOW_STATUS_OFF;
debounceState_t debounceStateSet = DEBOUNCE_STATE_IDLE;
debounceState_t debounceStateUp = DEBOUNCE_STATE_IDLE;
debounceState_t debounceStateDown = DEBOUNCE_STATE_IDLE;
debounceState_t debounceStateStart = DEBOUNCE_STATE_IDLE;
long lastDebounceTimeSet;
long lastDebounceTimeUp;
long lastDebounceTimeDown;
long lastDebounceTimeStart;
switch_t switchStatus = SWITCH_NONE;
int timerSeconds;
int currentStep = 0;
settingParam_t currentParam = SETTING_TEMP;
reflowState_t lastReflowState = REFLOW_STATE_IDLE;
float lastInput = -1;
float lastSettingValue = -1;
float lastSetpoint = -1;
float lastDuration = -1;
// PID kontrol arayüzü
PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
// TFT ekran arayüzü
TFT_eSPI tft = TFT_eSPI();
// MAX6675 termokupl arayüzü
MAX6675 thermocouple(THERMOCOUPLE_CLK_PIN, THERMOCOUPLE_CS_PIN, THERMOCOUPLE_SO_PIN);
// Preferences arayüzü
Preferences preferences;
// Preferences'dan parametreleri okuma
void readPreferences() {
preferences.begin("reflow", false);
for (int i = 0; i < 10; i++) {
temperatureSteps[i] = preferences.getFloat(("temp" + String(i)).c_str(), temperatureSteps[i]);
pidKpSteps[i] = preferences.getFloat(("kp" + String(i)).c_str(), pidKpSteps[i]);
pidKiSteps[i] = preferences.getFloat(("ki" + String(i)).c_str(), pidKiSteps[i]);
pidKdSteps[i] = preferences.getFloat(("kd" + String(i)).c_str(), pidKdSteps[i]);
stepDurations[i] = preferences.getFloat(("dur" + String(i)).c_str(), stepDurations[i]);
}
preferences.end();
}
// Preferences'a parametreleri kaydetme
void savePreferences() {
preferences.begin("reflow", false);
for (int i = 0; i < 10; i++) {
preferences.putFloat(("temp" + String(i)).c_str(), temperatureSteps[i]);
preferences.putFloat(("kp" + String(i)).c_str(), pidKpSteps[i]);
preferences.putFloat(("ki" + String(i)).c_str(), pidKiSteps[i]);
preferences.putFloat(("kd" + String(i)).c_str(), pidKdSteps[i]);
preferences.putFloat(("dur" + String(i)).c_str(), stepDurations[i]);
}
preferences.end();
}
// TFT ekranı güncelleme
void updateTFT() {
if (millis() - lastTftUpdate < TFT_UPDATE_INTERVAL) return;
lastTftUpdate = millis();
if (reflowState != lastReflowState) {
tft.fillScreen(TFT_BLACK);
lastReflowState = reflowState;
lastInput = -1;
lastSettingValue = -1;
lastSetpoint = -1;
lastDuration = -1;
}
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextSize(2);
if (reflowState == REFLOW_STATE_SETTINGS) {
tft.setCursor(10, 10);
tft.print("Adim ");
tft.print(currentStep + 1);
tft.print(": ");
switch (currentParam) {
case SETTING_TEMP: tft.print("Sicaklik"); break;
case SETTING_KP: tft.print("Kp"); break;
case SETTING_KI: tft.print("Ki"); break;
case SETTING_KD: tft.print("Kd"); break;
case SETTING_DURATION: tft.print("Sure"); break;
}
float currentValue;
switch (currentParam) {
case SETTING_TEMP: currentValue = temperatureSteps[currentStep]; break;
case SETTING_KP: currentValue = pidKpSteps[currentStep]; break;
case SETTING_KI: currentValue = pidKiSteps[currentStep]; break;
case SETTING_KD: currentValue = pidKdSteps[currentStep]; break;
case SETTING_DURATION: currentValue = stepDurations[currentStep]; break;
}
if (currentValue != lastSettingValue) {
tft.fillRect(10, 50, 300, 30, TFT_BLACK);
tft.setCursor(10, 50);
tft.print(currentValue);
if (currentParam == SETTING_TEMP) tft.print(" C");
else if (currentParam == SETTING_DURATION) tft.print(" s");
lastSettingValue = currentValue;
}
} else {
tft.setCursor(10, 10);
tft.print(lcdMessagesReflowStatus[reflowState]);
if (reflowState == REFLOW_STATE_ERROR) {
tft.fillRect(10, 50, 300, 30, TFT_BLACK);
tft.setCursor(10, 50);
tft.print("Termokupl Hatasi!");
lastInput = -1;
lastSetpoint = -1;
} else if (input != lastInput) {
tft.fillRect(10, 50, 300, 30, TFT_BLACK);
tft.setCursor(10, 50);
tft.print("Sicaklik: ");
tft.print(input);
tft.print(" C");
lastInput = input;
}
if (reflowState != REFLOW_STATE_ERROR && setpoint != lastSetpoint) {
tft.fillRect(10, 90, 300, 30, TFT_BLACK);
tft.setCursor(10, 90);
tft.print("Hedef: ");
tft.print(setpoint);
tft.print(" C");
lastSetpoint = setpoint;
}
if (reflowState != REFLOW_STATE_ERROR && reflowState != REFLOW_STATE_SETTINGS) {
tft.fillRect(10, 130, 300, 30, TFT_BLACK);
tft.setCursor(10, 130);
tft.print("Adim: ");
tft.print(currentStep + 1);
tft.print(" Sure: ");
tft.print(timerSeconds);
tft.print(" s");
}
}
}
void setup() {
// Pin başlatma
pinMode(SSR_PIN, OUTPUT);
digitalWrite(SSR_PIN, LOW);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
pinMode(LED_RED_PIN, OUTPUT);
digitalWrite(LED_RED_PIN, HIGH);
pinMode(LED_GREEN_PIN, OUTPUT);
digitalWrite(LED_GREEN_PIN, HIGH);
pinMode(SWITCH_SET_PIN, INPUT_PULLUP);
pinMode(SWITCH_UP_PIN, INPUT_PULLUP);
pinMode(SWITCH_DOWN_PIN, INPUT_PULLUP);
pinMode(SWITCH_START_PIN, INPUT_PULLUP);
// Preferences'dan parametreleri oku
readPreferences();
// TFT ekran başlatma
tft.init();
tft.setRotation(1); // Yatay mod
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.print("BGA Rework Station");
tft.setCursor(10, 50);
tft.print("Surum 2.5");
digitalWrite(BUZZER_PIN, HIGH);
delay(2500);
digitalWrite(BUZZER_PIN, LOW);
tft.fillScreen(TFT_BLACK);
// Seri haberleşme
Serial.begin(115200); // ESP32 için daha yüksek baud rate
// PID ayarları
windowSize = 2000;
reflowOvenPID.SetOutputLimits(0, windowSize);
reflowOvenPID.SetSampleTime(SENSOR_SAMPLING_TIME);
// Zamanlayıcılar
nextCheck = millis();
nextRead = millis();
lastSettingTransition = millis();
lastTftUpdate = millis();
buzzerToggleTime = millis();
}
void loop() {
unsigned long now;
// Termokupl okuma
if (millis() > nextRead) {
nextRead += SENSOR_SAMPLING_TIME;
input = thermocouple.readCelsius();
if (isnan(input)) {
reflowState = REFLOW_STATE_ERROR;
reflowStatus = REFLOW_STATUS_OFF;
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
}
}
// Durum kontrolü
if (millis() > nextCheck) {
nextCheck += 1000;
if (reflowStatus == REFLOW_STATUS_ON) {
digitalWrite(LED_RED_PIN, !digitalRead(LED_RED_PIN));
timerSeconds++;
Serial.print(timerSeconds);
Serial.print(" ");
Serial.print(setpoint);
Serial.print(" ");
Serial.print(input);
Serial.print(" ");
Serial.println(output);
} else {
digitalWrite(LED_RED_PIN, HIGH);
}
}
// TFT ekranı güncelle
updateTFT();
// Reflow durum makinesi (orijinal mantık korunuyor)
switch (reflowState) {
case REFLOW_STATE_IDLE:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (input >= TEMPERATURE_ROOM) {
reflowState = REFLOW_STATE_TOO_HOT;
} else if (switchStatus == SWITCH_SET && (millis() - lastSettingTransition) > SETTINGS_TRANSITION_DELAY) {
lastSettingTransition = millis();
reflowState = REFLOW_STATE_SETTINGS;
currentStep = 0;
currentParam = SETTING_TEMP;
} else if (switchStatus == SWITCH_START) {
Serial.println("Zaman Hedef Giris Cikis");
timerSeconds = 0;
windowStartTime = millis();
setpoint = temperatureSteps[0];
kp = pidKpSteps[0];
ki = pidKiSteps[0];
kd = pidKdSteps[0];
reflowOvenPID.SetTunings(kp, ki, kd);
reflowOvenPID.SetMode(AUTOMATIC);
reflowState = REFLOW_STATE_STEP1;
currentStep = 0;
buzzerToggleTime = millis();
}
break;
case REFLOW_STATE_STEP1:
reflowStatus = REFLOW_STATUS_ON;
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (input >= temperatureSteps[0]) {
timerStep = millis() + (stepDurations[1] * 1000);
kp = pidKpSteps[1];
ki = pidKiSteps[1];
kd = pidKdSteps[1];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[1];
reflowState = REFLOW_STATE_STEP2;
currentStep = 1;
}
break;
case REFLOW_STATE_STEP2:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (millis() > timerStep) {
timerStep = millis() + (stepDurations[2] * 1000);
setpoint = temperatureSteps[1];
if (input >= temperatureSteps[1]) {
kp = pidKpSteps[2];
ki = pidKiSteps[2];
kd = pidKdSteps[2];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[2];
reflowState = REFLOW_STATE_STEP3;
currentStep = 2;
}
}
break;
// Diğer adımlar (STEP3-STEP10, COMPLETE, TOO_HOT, ERROR) orijinal kodla aynı
// Sadece digitalWrite pinleri ve buzzer kontrolü ESP32 pinlerine uyarlandı
case REFLOW_STATE_STEP3:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (millis() > timerStep) {
timerStep = millis() + (stepDurations[3] * 1000);
setpoint = temperatureSteps[2];
if (input >= temperatureSteps[2]) {
kp = pidKpSteps[3];
ki = pidKiSteps[3];
kd = pidKdSteps[3];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[3];
reflowState = REFLOW_STATE_STEP4;
currentStep = 3;
}
}
break;
case REFLOW_STATE_STEP4:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (millis() > timerStep) {
timerStep = millis() + (stepDurations[4] * 1000);
setpoint = temperatureSteps[3];
if (input >= temperatureSteps[3]) {
kp = pidKpSteps[4];
ki = pidKiSteps[4];
kd = pidKdSteps[4];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[4];
reflowState = REFLOW_STATE_STEP5;
currentStep = 4;
}
}
break;
case REFLOW_STATE_STEP5:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (millis() > timerStep) {
timerStep = millis() + (stepDurations[5] * 1000);
setpoint = temperatureSteps[4];
if (input >= temperatureSteps[4]) {
kp = pidKpSteps[5];
ki = pidKiSteps[5];
kd = pidKdSteps[5];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[5];
reflowState = REFLOW_STATE_STEP6;
currentStep = 5;
}
}
break;
case REFLOW_STATE_STEP6:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (millis() > timerStep) {
timerStep = millis() + (stepDurations[6] * 1000);
setpoint = temperatureSteps[5];
if (input >= temperatureSteps[5]) {
kp = pidKpSteps[6];
ki = pidKiSteps[6];
kd = pidKdSteps[6];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[6];
reflowState = REFLOW_STATE_STEP7;
currentStep = 6;
}
}
break;
case REFLOW_STATE_STEP7:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (millis() > timerStep) {
timerStep = millis() + (stepDurations[7] * 1000);
setpoint = temperatureSteps[6];
if (input >= temperatureSteps[6]) {
kp = pidKpSteps[7];
ki = pidKiSteps[7];
kd = pidKdSteps[7];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[7];
reflowState = REFLOW_STATE_STEP8;
currentStep = 7;
buzzerToggleTime = millis();
}
}
break;
case REFLOW_STATE_STEP8:
if (millis() > buzzerToggleTime) {
buzzerToggleTime = millis() + BUZZER_TOGGLE_PERIOD;
buzzerState = !buzzerState;
digitalWrite(BUZZER_PIN, buzzerState ? HIGH : LOW);
}
if (input >= (temperatureSteps[7] - 5)) {
timerStep = millis() + (stepDurations[8] * 1000);
kp = pidKpSteps[8];
ki = pidKiSteps[8];
kd = pidKdSteps[8];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[8];
reflowState = REFLOW_STATE_STEP9;
currentStep = 8;
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
}
break;
case REFLOW_STATE_STEP9:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (input <= temperatureSteps[8]) {
timerStep = millis() + (stepDurations[9] * 1000);
kp = pidKpSteps[9];
ki = pidKiSteps[9];
kd = pidKdSteps[9];
reflowOvenPID.SetTunings(kp, ki, kd);
setpoint = temperatureSteps[9];
reflowState = REFLOW_STATE_STEP10;
currentStep = 9;
}
break;
case REFLOW_STATE_STEP10:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (input <= temperatureSteps[9]) {
buzzerPeriod = millis() + 1000;
digitalWrite(LED_GREEN_PIN, LOW);
digitalWrite(BUZZER_PIN, HIGH);
reflowStatus = REFLOW_STATUS_OFF;
reflowState = REFLOW_STATE_COMPLETE;
savePreferences();
currentStep = 0;
}
break;
case REFLOW_STATE_COMPLETE:
if (millis() > buzzerPeriod) {
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_GREEN_PIN, HIGH);
reflowState = REFLOW_STATE_IDLE;
buzzerState = false;
}
break;
case REFLOW_STATE_TOO_HOT:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (input < TEMPERATURE_ROOM) {
reflowState = REFLOW_STATE_IDLE;
}
break;
case REFLOW_STATE_ERROR:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (!isnan(input)) {
reflowState = REFLOW_STATE_IDLE;
}
break;
case REFLOW_STATE_SETTINGS:
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
if (switchStatus == SWITCH_SET && (millis() - lastSettingTransition) > SETTINGS_TRANSITION_DELAY) {
lastSettingTransition = millis();
currentParam = (settingParam_t)((currentParam + 1) % 5);
if (currentParam == SETTING_TEMP) {
currentStep = (currentStep + 1) % 10;
if (currentStep == 0) {
reflowState = REFLOW_STATE_IDLE;
savePreferences();
}
}
}
if (switchStatus == SWITCH_UP && (millis() - lastSettingTransition) > SETTINGS_TRANSITION_DELAY) {
lastSettingTransition = millis();
switch (currentParam) {
case SETTING_TEMP:
temperatureSteps[currentStep] += 5.0;
if (temperatureSteps[currentStep] > 300) temperatureSteps[currentStep] = 300;
break;
case SETTING_KP:
pidKpSteps[currentStep] += 10.0;
if (pidKpSteps[currentStep] > 500) pidKpSteps[currentStep] = 500;
break;
case SETTING_KI:
pidKiSteps[currentStep] += 0.01;
if (pidKiSteps[currentStep] > 0.1) pidKiSteps[currentStep] = 0.1;
break;
case SETTING_KD:
pidKdSteps[currentStep] += 10.0;
if (pidKdSteps[currentStep] > 500) pidKdSteps[currentStep] = 500;
break;
case SETTING_DURATION:
stepDurations[currentStep] += 5.0;
if (stepDurations[currentStep] > 120) stepDurations[currentStep] = 120;
break;
}
}
if (switchStatus == SWITCH_DOWN && (millis() - lastSettingTransition) > SETTINGS_TRANSITION_DELAY) {
lastSettingTransition = millis();
switch (currentParam) {
case SETTING_TEMP:
temperatureSteps[currentStep] -= 5.0;
if (temperatureSteps[currentStep] < 50) temperatureSteps[currentStep] = 50;
break;
case SETTING_KP:
pidKpSteps[currentStep] -= 10.0;
if (pidKpSteps[currentStep] < 0) pidKpSteps[currentStep] = 0;
break;
case SETTING_KI:
pidKiSteps[currentStep] -= 0.01;
if (pidKiSteps[currentStep] < 0) pidKiSteps[currentStep] = 0;
break;
case SETTING_KD:
pidKdSteps[currentStep] -= 10.0;
if (pidKdSteps[currentStep] < 0) pidKdSteps[currentStep] = 0;
break;
case SETTING_DURATION:
stepDurations[currentStep] -= 5.0;
if (stepDurations[currentStep] < 10) stepDurations[currentStep] = 10;
break;
}
}
break;
}
// Buton debounce işlemleri
if (digitalRead(SWITCH_SET_PIN) == LOW) {
if (debounceStateSet == DEBOUNCE_STATE_IDLE) {
lastDebounceTimeSet = millis();
debounceStateSet = DEBOUNCE_STATE_CHECK;
} else if (debounceStateSet == DEBOUNCE_STATE_CHECK && (millis() - lastDebounceTimeSet) > DEBOUNCE_PERIOD_MIN) {
debounceStateSet = DEBOUNCE_STATE_RELEASE;
}
} else if (debounceStateSet == DEBOUNCE_STATE_RELEASE) {
switchStatus = SWITCH_SET;
debounceStateSet = DEBOUNCE_STATE_IDLE;
} else {
debounceStateSet = DEBOUNCE_STATE_IDLE;
switchStatus = SWITCH_NONE;
}
if (digitalRead(SWITCH_UP_PIN) == LOW) {
if (debounceStateUp == DEBOUNCE_STATE_IDLE) {
lastDebounceTimeUp = millis();
debounceStateUp = DEBOUNCE_STATE_CHECK;
} else if (debounceStateUp == DEBOUNCE_STATE_CHECK && (millis() - lastDebounceTimeUp) > DEBOUNCE_PERIOD_MIN) {
debounceStateUp = DEBOUNCE_STATE_RELEASE;
}
} else if (debounceStateUp == DEBOUNCE_STATE_RELEASE) {
switchStatus = SWITCH_UP;
debounceStateUp = DEBOUNCE_STATE_IDLE;
} else {
debounceStateUp = DEBOUNCE_STATE_IDLE;
if (switchStatus == SWITCH_UP) switchStatus = SWITCH_NONE;
}
if (digitalRead(SWITCH_DOWN_PIN) == LOW) {
if (debounceStateDown == DEBOUNCE_STATE_IDLE) {
lastDebounceTimeDown = millis();
debounceStateDown = DEBOUNCE_STATE_CHECK;
} else if (debounceStateDown == DEBOUNCE_STATE_CHECK && (millis() - lastDebounceTimeDown) > DEBOUNCE_PERIOD_MIN) {
debounceStateDown = DEBOUNCE_STATE_RELEASE;
}
} else if (debounceStateDown == DEBOUNCE_STATE_RELEASE) {
switchStatus = SWITCH_DOWN;
debounceStateDown = DEBOUNCE_STATE_IDLE;
} else {
debounceStateDown = DEBOUNCE_STATE_IDLE;
if (switchStatus == SWITCH_DOWN) switchStatus = SWITCH_NONE;
}
if (digitalRead(SWITCH_START_PIN) == LOW) {
if (debounceStateStart == DEBOUNCE_STATE_IDLE) {
lastDebounceTimeStart = millis();
debounceStateStart = DEBOUNCE_STATE_CHECK;
} else if (debounceStateStart == DEBOUNCE_STATE_CHECK && (millis() - lastDebounceTimeStart) > DEBOUNCE_PERIOD_MIN) {
debounceStateStart = DEBOUNCE_STATE_RELEASE;
}
} else if (debounceStateStart == DEBOUNCE_STATE_RELEASE) {
switchStatus = SWITCH_START;
debounceStateStart = DEBOUNCE_STATE_IDLE;
} else {
debounceStateStart = DEBOUNCE_STATE_IDLE;
if (switchStatus == SWITCH_START) switchStatus = SWITCH_NONE;
}
// PID ve SSR kontrolü
if (reflowStatus == REFLOW_STATUS_ON) {
now = millis();
reflowOvenPID.Compute();
if ((now - windowStartTime) > windowSize) {
windowStartTime += windowSize;
}
if (output > (now - windowStartTime)) {
digitalWrite(SSR_PIN, HIGH);
} else {
digitalWrite(SSR_PIN, LOW);
}
} else {
digitalWrite(SSR_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
}
}
Loading
esp32-devkit-c-v4
esp32-devkit-c-v4