#include <Wire.h>
#include <Adafruit_PCD8544.h>
#include <Adafruit_SHT31.h>
#include <RTClib.h>
#include <EEPROM.h>
#include <avr/wdt.h>
#define RELAY1 5
#define RELAY2 6
#define RELAY3 7
#define RELAY4 8
#define ROW1 22
#define ROW2 24
#define ROW3 26
#define ROW4 28
#define COL1 30
#define COL2 32
#define COL3 34
#define COL4 36
#define BACKLIGHT_PIN A5
#define SHT31_1_ADDR 0x44
#define SHT31_2_ADDR 0x45
#define EEPROM_TYPE 0
#define EEPROM_START_TIME 1
#define EEPROM_TEMP 5
#define EEPROM_HUM 9
#define EEPROM_ERROR_FLAG 13
#define EEPROM_TEMP_OFFSET1 14
#define EEPROM_HUM_OFFSET1 18
#define EEPROM_TEMP_OFFSET2 22
#define EEPROM_HUM_OFFSET2 26
#define EEPROM_MOTOR_DURATION 30
#define EEPROM_MOTOR_INTERVAL 34
#define EEPROM_CHECKSUM 38
#define EEPROM_LAST_POWER_TIME 42
#define EEPROM_START_TIME_BACKUP1 100
#define EEPROM_START_TIME_BACKUP2 104
#define MENU_MAIN 0
#define MENU_SETTINGS 1
#define MENU_MOTOR 2
#define MENU_SENSORS 3
#define MENU_CALIBRATION 4
#define TEMP_HYSTERESIS 0.3
#define HUM_HYSTERESIS 2.0
#define DEBOUNCE_DELAY 250
const unsigned long MOTOR_INTERVAL_DEFAULT = 7200000;
const unsigned long MOTOR_DURATION_DEFAULT = 3000;
const unsigned long BACKLIGHT_TIMEOUT = 10000;
const unsigned long MESSAGE_DURATION = 2000;
const unsigned long EEPROM_WRITE_INTERVAL = 300000;
#define MAX_ERRORS 3
#define SENSOR_TIMEOUT 5000
#define DEBUG true
struct SensorData {
float temp;
float hum;
bool isValid;
};
struct MotorSettings {
unsigned long duration;
unsigned long interval;
};
struct IncubatorSettings {
int type;
float targetTemp;
float targetHum;
int totalDays;
uint32_t startTime;
bool motorActive;
bool heaterState;
bool humidifierState;
float tempOffset1;
float tempOffset2;
float humOffset1;
float humOffset2;
};
struct ErrorManager {
int tempErrors;
int humErrors;
int rtcErrors;
unsigned long lastSensorRead;
unsigned long lastEEPROMWrite;
bool safeMode;
ErrorManager() {
tempErrors = 0;
humErrors = 0;
rtcErrors = 0;
lastSensorRead = 0;
lastEEPROMWrite = 0;
safeMode = false;
}
void resetErrors() {
tempErrors = 0;
humErrors = 0;
rtcErrors = 0;
}
bool checkSensor(float value, float min, float max) {
if (isnan(value) || value < min || value > max) {
return false;
}
return true;
}
};
Adafruit_PCD8544 lcd(A0, A1, A2, A3, A4);
Adafruit_SHT31 sht31_1 = Adafruit_SHT31();
Adafruit_SHT31 sht31_2 = Adafruit_SHT31();
RTC_DS3231 rtc;
const char* typeNames[] = {"Tavuk", "Kaz", "Bildircin", "Manuel"};
IncubatorSettings settings;
MotorSettings motorSettings;
ErrorManager errorMgr;
int currentMenu = MENU_MAIN;
bool inSubMenu = false;
unsigned long lastKeyPressTime = 0;
unsigned long lastDebounceTime = 0;
bool backlightState = false;
unsigned long previousMillis = 0;
char lastKey = 0;
float tempOffset1 = 0.0;
float humOffset1 = 0.0;
float tempOffset2 = 0.0;
float humOffset2 = 0.0;
bool isFirstMotorActivation = true;
char messageBuffer[40];
void handleMainMenu(char key);
void handleSettingsMenu(char key);
void handleMotorMenu(char key);
void handleCalibrationMenu(char key);
void handleNormalOperation(char key);
void showMainMenu();
void showSettingsMenu();
void showMotorMenu();
void showSensorInfo();
void showCalibrationMenu();
void showMessage(const char* message);
void showError(const char* message);
void setupChicken();
void setupGoose();
void setupQuail();
void setupManual();
void resetSystem();
void askForReset();
void saveState();
void savePersistentState();
void loadState();
void loadMotorSettings();
uint8_t calculateChecksum();
void updateSensorsAndControl();
void updateMainDisplay(float temp, float hum, int currentDay);
void updateBacklight();
void testMotor();
void controlMotor(uint32_t currentTime);
void controlTemperature(float currentTemp);
void controlHumidity(float currentHum);
void checkAndUpdateSettings(int currentDay);
void getAverageReadings(float &avgTemp, float &avgHum);
char getKey();
float getNumberInput();
void enterSafeMode(const char* errorMsg);
void handlePowerFailure();
void debugPrint(const char* message);
void debugPrint(const char* message, int value);
void debugPrint(const char* message, float value);
void debugPrint(const char* message, uint32_t value);
void resetAllOffsets();
void saveTimeWithBackup(uint32_t timeToSave);
uint32_t getStartTimeFromEEPROM();
void calibrateTemperature1();
void calibrateHumidity1();
void calibrateTemperature2();
void calibrateHumidity2();
SensorData readSHT31_1();
SensorData readSHT31_2();
uint32_t getTimeFromRTC();
int getMotorCountdown();
void setMotorDuration();
void setMotorInterval();
uint32_t getTimeFromRTC() {
DateTime now = rtc.now();
return now.unixtime();
}
void debugPrint(const char* message) {
if (DEBUG) {
Serial.println(message);
}
}
void debugPrint(const char* message, int value) {
if (DEBUG) {
Serial.print(message);
Serial.println(value);
}
}
void debugPrint(const char* message, float value) {
if (DEBUG) {
Serial.print(message);
Serial.println(value);
}
}
void debugPrint(const char* message, uint32_t value) {
if (DEBUG) {
Serial.print(message);
Serial.println(value);
}
}
void saveTimeWithBackup(uint32_t timeToSave) {
Serial.print("Zaman kaydediliyor: ");
Serial.println(timeToSave);
EEPROM.put(EEPROM_START_TIME, timeToSave);
delay(10);
wdt_reset();
EEPROM.put(EEPROM_START_TIME_BACKUP1, timeToSave);
delay(10);
wdt_reset();
EEPROM.put(EEPROM_START_TIME_BACKUP2, timeToSave);
delay(10);
wdt_reset();
uint32_t readBack;
EEPROM.get(EEPROM_START_TIME, readBack);
if (readBack != timeToSave) {
Serial.println("UYARI: Zaman kaydı doğrulanamadı!");
} else {
Serial.println("Zaman başarıyla kaydedildi ve doğrulandı.");
}
}
uint32_t getStartTimeFromEEPROM() {
uint32_t time1, time2, time3;
EEPROM.get(EEPROM_START_TIME, time1);
EEPROM.get(EEPROM_START_TIME_BACKUP1, time2);
EEPROM.get(EEPROM_START_TIME_BACKUP2, time3);
Serial.print("Okunan zamanlar - Ana: ");
Serial.print(time1);
Serial.print(", Yedek1: ");
Serial.print(time2);
Serial.print(", Yedek2: ");
Serial.println(time3);
uint32_t currentTime = getTimeFromRTC();
Serial.print("Şimdiki zaman: ");
Serial.println(currentTime);
if (time1 == time2 || time1 == time3) return time1;
if (time2 == time3) return time2;
if (time1 > 1577836800 && time1 < currentTime) return time1;
if (time2 > 1577836800 && time2 < currentTime) return time2;
if (time3 > 1577836800 && time3 < currentTime) return time3;
return 0;
}
void setup() {
Serial.begin(9600);
debugPrint("Kuluçka Makinesi Başlatılıyor...");
Wire.begin();
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
pinMode(ROW1, INPUT_PULLUP);
pinMode(ROW2, INPUT_PULLUP);
pinMode(ROW3, INPUT_PULLUP);
pinMode(ROW4, INPUT_PULLUP);
pinMode(COL1, OUTPUT);
pinMode(COL2, OUTPUT);
pinMode(COL3, OUTPUT);
pinMode(COL4, OUTPUT);
pinMode(BACKLIGHT_PIN, OUTPUT);
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, LOW);
digitalWrite(RELAY4, HIGH);
digitalWrite(BACKLIGHT_PIN, LOW);
settings.heaterState = false;
settings.humidifierState = false;
lcd.begin();
lcd.setContrast(50);
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Kulucka");
lcd.println("Makinesi v2.4");
lcd.println("Baslatiliyor...");
lcd.display();
delay(2000);
if (!sht31_1.begin(SHT31_1_ADDR)) {
showError("Sensor 1 Hata!");
debugPrint("Sensor 1 başlatılamadı!");
delay(2000);
}
if (!sht31_2.begin(SHT31_2_ADDR)) {
showError("Sensor 2 Hata!");
debugPrint("Sensor 2 başlatılamadı!");
delay(2000);
}
sht31_1.heater(false);
sht31_2.heater(false);
if (!rtc.begin()) {
showError("RTC Hatasi!");
debugPrint("RTC başlatılamadı!");
delay(2000);
}
if (rtc.lostPower()) {
showError("RTC Pil Zayif!");
debugPrint("RTC pil zayıf, tarih ayarlanıyor");
delay(2000);
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
loadState();
loadMotorSettings();
debugPrint("Yüklenen ayarlar:");
debugPrint("Tip:", settings.type);
debugPrint("Başlangıç zamanı:", settings.startTime);
debugPrint("Güncel RTC zamanı:", getTimeFromRTC());
debugPrint("Hedef sıcaklık:", settings.targetTemp);
debugPrint("Hedef nem:", settings.targetHum);
handlePowerFailure();
if (settings.type == 4 || settings.type == 255) {
settings.type = 4;
showMainMenu();
currentMenu = MENU_MAIN;
isFirstMotorActivation = false;
} else {
float avgTemp = 0.0, avgHum = 0.0;
SensorData sensor1 = readSHT31_1();
SensorData sensor2 = readSHT31_2();
if (sensor1.isValid && sensor2.isValid) {
avgTemp = (sensor1.temp + sensor2.temp) / 2.0;
avgHum = (sensor1.hum + sensor2.hum) / 2.0;
} else if (sensor1.isValid) {
avgTemp = sensor1.temp;
avgHum = sensor1.hum;
} else if (sensor2.isValid) {
avgTemp = sensor2.temp;
avgHum = sensor2.hum;
}
uint32_t currentTime = getTimeFromRTC();
int currentDay = 1;
if (settings.startTime > 0 && currentTime > settings.startTime) {
currentDay = (currentTime - settings.startTime) / 86400 + 1;
if (currentDay > settings.totalDays) {
currentDay = settings.totalDays;
}
}
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Kulucka Aktif");
lcd.setCursor(0,16);
sprintf(messageBuffer, "Gun: %d/%d", currentDay, settings.totalDays);
lcd.println(messageBuffer);
lcd.setCursor(0,32);
lcd.println("Devam ediyor...");
lcd.display();
delay(2000);
updateMainDisplay(avgTemp, avgHum, currentDay);
currentMenu = -1;
if (millis() < 3000) {
isFirstMotorActivation = true;
previousMillis = 0;
debugPrint("Güç kesintisi sonrası, ilk motor dönüşü aktifleştirildi");
} else {
isFirstMotorActivation = false;
}
}
uint32_t currentTime = getTimeFromRTC();
EEPROM.put(EEPROM_LAST_POWER_TIME, currentTime);
wdt_enable(WDTO_8S);
debugPrint("Watchdog timer aktifleştirildi (8s)");
}
void loop() {
wdt_reset();
updateBacklight();
char key = getKey();
if (currentMenu == MENU_SETTINGS) {
if(key) {
handleSettingsMenu(key);
}
}
else if (currentMenu == MENU_MOTOR) {
if(key) {
handleMotorMenu(key);
}
}
else if (currentMenu == MENU_CALIBRATION) {
if(key) {
handleCalibrationMenu(key);
}
}
else if (settings.type == 4 || currentMenu == MENU_MAIN) {
if(key) {
handleMainMenu(key);
}
}
else {
updateSensorsAndControl();
if(key) {
handleNormalOperation(key);
}
savePersistentState();
}
delay(100);
}
void handlePowerFailure() {
uint32_t currentTime = getTimeFromRTC();
uint32_t lastPowerTime = 0;
EEPROM.get(EEPROM_LAST_POWER_TIME, lastPowerTime);
if (lastPowerTime > 0 && currentTime > lastPowerTime) {
uint32_t downtime = currentTime - lastPowerTime;
if (downtime > 3600) {
sprintf(messageBuffer, "Guc Kesintisi\nSure: %d saat", (int)(downtime / 3600));
showMessage(messageBuffer);
debugPrint("Güç kesintisi tespit edildi:");
debugPrint("Son güç zamanı:", lastPowerTime);
debugPrint("Şimdiki zaman:", currentTime);
debugPrint("Kesinti süresi (saat):", (int)(downtime / 3600));
}
}
EEPROM.put(EEPROM_LAST_POWER_TIME, currentTime);
}
void updateSensorsAndControl() {
float avgTemp, avgHum;
getAverageReadings(avgTemp, avgHum);
uint32_t currentTime = getTimeFromRTC();
int currentDay = 0;
if (settings.startTime > 0 && settings.startTime <= currentTime) {
currentDay = (currentTime - settings.startTime) / 86400 + 1;
if (currentDay <= 0 || currentDay > settings.totalDays) {
currentDay = 1;
}
} else {
currentDay = 1;
}
checkAndUpdateSettings(currentDay);
controlTemperature(avgTemp);
controlHumidity(avgHum);
controlMotor(currentTime);
updateMainDisplay(avgTemp, avgHum, currentDay);
}
void getAverageReadings(float &avgTemp, float &avgHum) {
SensorData sensor1 = readSHT31_1();
SensorData sensor2 = readSHT31_2();
if(sensor1.isValid && sensor2.isValid) {
avgTemp = (sensor1.temp + sensor2.temp) / 2.0;
avgHum = (sensor1.hum + sensor2.hum) / 2.0;
if(abs(sensor1.temp - sensor2.temp) > 15.0) {
errorMgr.tempErrors++;
if(errorMgr.tempErrors > MAX_ERRORS) {
enterSafeMode("Sicaklik Fark!\nCok Fazla!");
}
} else {
errorMgr.tempErrors = 0;
}
}
else if(sensor1.isValid) {
avgTemp = sensor1.temp;
avgHum = sensor1.hum;
}
else if(sensor2.isValid) {
avgTemp = sensor2.temp;
avgHum = sensor2.hum;
}
else {
errorMgr.tempErrors++;
if(errorMgr.tempErrors > MAX_ERRORS) {
enterSafeMode("Tum Sensorler\nHatali!");
}
avgTemp = 0;
avgHum = 0;
}
}
void handleMainMenu(char key) {
switch(key) {
case '1':
setupChicken();
showMessage("Tavuk secildi\n21 gun");
currentMenu = -1;
break;
case '2':
setupGoose();
showMessage("Kaz secildi\n30 gun");
currentMenu = -1;
break;
case '3':
setupQuail();
showMessage("Bildircin secildi\n18 gun");
currentMenu = -1;
break;
case '4':
setupManual();
currentMenu = -1;
break;
case '5':
showSettingsMenu();
currentMenu = MENU_SETTINGS;
break;
}
}
void handleNormalOperation(char key) {
switch(key) {
case 'A':
settings.targetTemp += 0.1;
if(settings.targetTemp > 39.0) settings.targetTemp = 39.0;
saveState();
break;
case 'B':
settings.targetTemp -= 0.1;
if(settings.targetTemp < 35.0) settings.targetTemp = 35.0;
saveState();
break;
case 'C':
settings.targetHum += 1.0;
if(settings.targetHum > 85) settings.targetHum = 85;
saveState();
break;
case 'D':
settings.targetHum -= 1.0;
if(settings.targetHum < 30) settings.targetHum = 30;
saveState();
break;
case '5':
showSettingsMenu();
currentMenu = MENU_SETTINGS;
break;
case '6':
testMotor();
break;
}
}
void handleSettingsMenu(char key) {
switch(key) {
case '1':
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Sicaklik (C):");
lcd.setCursor(0,8);
lcd.print("Mevcut: ");
lcd.println(settings.targetTemp, 1);
lcd.setCursor(0,16);
lcd.println("Yeni Deger:");
lcd.display();
settings.targetTemp = getNumberInput();
if(settings.targetTemp < 35.0) settings.targetTemp = 35.0;
if(settings.targetTemp > 39.0) settings.targetTemp = 39.0;
saveState();
showSettingsMenu();
break;
case '2':
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Nem (%):");
lcd.setCursor(0,8);
lcd.print("Mevcut: ");
lcd.println(settings.targetHum, 1);
lcd.setCursor(0,16);
lcd.println("Yeni Deger:");
lcd.display();
settings.targetHum = getNumberInput();
if(settings.targetHum < 30) settings.targetHum = 30;
if(settings.targetHum > 85) settings.targetHum = 85;
saveState();
showSettingsMenu();
break;
case '3':
showMotorMenu();
currentMenu = MENU_MOTOR;
break;
case '4':
showCalibrationMenu();
currentMenu = MENU_CALIBRATION;
break;
case '5':
showSensorInfo();
break;
case '6':
askForReset();
break;
case '*':
if (settings.type == 4) {
showMainMenu();
currentMenu = MENU_MAIN;
} else {
currentMenu = -1;
float avgTemp, avgHum;
getAverageReadings(avgTemp, avgHum);
uint32_t currentTime = getTimeFromRTC();
int currentDay = (currentTime - settings.startTime) / 86400 + 1;
if (currentDay <= 0 || currentDay > settings.totalDays) currentDay = 1;
updateMainDisplay(avgTemp, avgHum, currentDay);
}
break;
}
}
void handleMotorMenu(char key) {
Serial.print("Motor Menu Key: ");
Serial.println(key);
switch(key) {
case '1':
setMotorInterval();
break;
case '2':
setMotorDuration();
break;
case '*':
showSettingsMenu();
currentMenu = MENU_SETTINGS;
break;
}
}
void handleCalibrationMenu(char key) {
switch(key) {
case '1':
calibrateTemperature1();
break;
case '2':
calibrateHumidity1();
break;
case '3':
calibrateTemperature2();
break;
case '4':
calibrateHumidity2();
break;
case '5':
resetAllOffsets();
break;
case '*':
showSettingsMenu();
currentMenu = MENU_SETTINGS;
break;
}
}
void resetAllOffsets() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Offsetleri");
lcd.println("Sifirlamak Icin");
lcd.setCursor(0,16);
lcd.println("# tusu: Evet");
lcd.println("* tusu: Hayir");
lcd.display();
while(true) {
char key = getKey();
if(key == '#') {
settings.tempOffset1 = 0.0;
settings.tempOffset2 = 0.0;
settings.humOffset1 = 0.0;
settings.humOffset2 = 0.0;
EEPROM.put(EEPROM_TEMP_OFFSET1, 0.0f);
delay(10);
EEPROM.put(EEPROM_HUM_OFFSET1, 0.0f);
delay(10);
EEPROM.put(EEPROM_TEMP_OFFSET2, 0.0f);
delay(10);
EEPROM.put(EEPROM_HUM_OFFSET2, 0.0f);
delay(10);
wdt_reset();
lcd.clearDisplay();
lcd.setCursor(0,16);
lcd.println("Offsetler");
lcd.println("Sifirlandi!");
lcd.display();
delay(2000);
showCalibrationMenu();
break;
}
else if(key == '*') {
showCalibrationMenu();
break;
}
wdt_reset();
}
}
void setMotorDuration() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Sure (sn):");
lcd.setCursor(0,8);
lcd.print("Mevcut: ");
lcd.println(motorSettings.duration / 1000);
lcd.setCursor(0,16);
lcd.println("Yeni Deger:");
lcd.display();
float seconds = getNumberInput();
if(seconds < 1) seconds = 1;
if(seconds > 7) seconds = 7;
motorSettings.duration = seconds * 1000;
EEPROM.put(EEPROM_MOTOR_DURATION, motorSettings.duration);
showMotorMenu();
}
void setMotorInterval() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Aralik (dk):");
lcd.setCursor(0,8);
lcd.print("Mevcut: ");
lcd.println(motorSettings.interval / 60000);
lcd.setCursor(0,16);
lcd.println("Yeni Deger:");
lcd.display();
float minutes = getNumberInput();
if(minutes < 60) minutes = 60;
if(minutes > 480) minutes = 480;
motorSettings.interval = minutes * 60000;
EEPROM.put(EEPROM_MOTOR_INTERVAL, motorSettings.interval);
showMotorMenu();
}
void setupChicken() {
settings.type = 0;
settings.targetTemp = 37.8;
settings.targetHum = 65;
settings.totalDays = 21;
uint32_t currentTime = getTimeFromRTC();
settings.startTime = currentTime;
EEPROM.put(EEPROM_TYPE, settings.type);
delay(5);
saveTimeWithBackup(settings.startTime);
settings.motorActive = true;
settings.heaterState = false;
settings.humidifierState = false;
isFirstMotorActivation = true;
saveState();
debugPrint("Tavuk kuluçkası başladı. Zaman:", settings.startTime);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Tavuk Kuluckasi");
lcd.setCursor(0,16);
lcd.println("Baslatildi!");
lcd.setCursor(0,32);
DateTime now = rtc.now();
sprintf(messageBuffer, "Gun: 1/%d", settings.totalDays);
lcd.println(messageBuffer);
lcd.setCursor(0,40);
sprintf(messageBuffer, "Saat: %02d:%02d", now.hour(), now.minute());
lcd.println(messageBuffer);
lcd.display();
delay(3000);
}
void setupGoose() {
settings.type = 1;
settings.targetTemp = 37.7;
settings.targetHum = 60;
settings.totalDays = 30;
uint32_t currentTime = getTimeFromRTC();
settings.startTime = currentTime;
EEPROM.put(EEPROM_TYPE, settings.type);
delay(5);
saveTimeWithBackup(settings.startTime);
settings.motorActive = true;
settings.heaterState = false;
settings.humidifierState = false;
isFirstMotorActivation = true;
saveState();
debugPrint("Kaz kuluçkası başladı. Zaman:", settings.startTime);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Kaz Kuluckasi");
lcd.setCursor(0,16);
lcd.println("Baslatildi!");
lcd.setCursor(0,32);
DateTime now = rtc.now();
sprintf(messageBuffer, "Gun: 1/%d", settings.totalDays);
lcd.println(messageBuffer);
lcd.setCursor(0,40);
sprintf(messageBuffer, "Saat: %02d:%02d", now.hour(), now.minute());
lcd.println(messageBuffer);
lcd.display();
delay(3000);
}
void setupQuail() {
settings.type = 2;
settings.targetTemp = 37.7;
settings.targetHum = 65;
settings.totalDays = 18;
uint32_t currentTime = getTimeFromRTC();
settings.startTime = currentTime;
EEPROM.put(EEPROM_TYPE, settings.type);
delay(5);
saveTimeWithBackup(settings.startTime);
settings.motorActive = true;
settings.heaterState = false;
settings.humidifierState = false;
isFirstMotorActivation = true;
saveState();
debugPrint("Bıldırcın kuluçkası başladı. Zaman:", settings.startTime);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Bildircin Kulucka");
lcd.setCursor(0,16);
lcd.println("Baslatildi!");
lcd.setCursor(0,32);
DateTime now = rtc.now();
sprintf(messageBuffer, "Gun: 1/%d", settings.totalDays);
lcd.println(messageBuffer);
lcd.setCursor(0,40);
sprintf(messageBuffer, "Saat: %02d:%02d", now.hour(), now.minute());
lcd.println(messageBuffer);
lcd.display();
delay(3000);
}
void setupManual() {
settings.type = 3;
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Manuel Ayar");
lcd.setCursor(0,8);
lcd.println("Sicaklik (C):");
lcd.display();
float temp = getNumberInput();
if(temp < 35.0) temp = 35.0;
if(temp > 39.0) temp = 39.0;
settings.targetTemp = temp;
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Nem (%):");
lcd.display();
float hum = getNumberInput();
if(hum < 30) hum = 30;
if(hum > 85) hum = 85;
settings.targetHum = hum;
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Gun Sayisi:");
lcd.display();
int days = (int)getNumberInput();
if(days < 1) days = 1;
if(days > 60) days = 60;
settings.totalDays = days;
uint32_t currentTime = getTimeFromRTC();
settings.startTime = currentTime;
EEPROM.put(EEPROM_TYPE, settings.type);
delay(5);
saveTimeWithBackup(settings.startTime);
settings.motorActive = true;
settings.heaterState = false;
settings.humidifierState = false;
isFirstMotorActivation = true;
saveState();
debugPrint("Manuel kuluçka başladı. Zaman:", settings.startTime);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Manuel Kulucka");
lcd.setCursor(0,16);
lcd.println("Baslatildi!");
lcd.setCursor(0,32);
DateTime now = rtc.now();
sprintf(messageBuffer, "Gun: 1/%d", settings.totalDays);
lcd.println(messageBuffer);
lcd.setCursor(0,40);
sprintf(messageBuffer, "Saat: %02d:%02d", now.hour(), now.minute());
lcd.println(messageBuffer);
lcd.display();
delay(3000);
}
void resetSystem() {
settings.type = 4;
saveState();
showMainMenu();
}
void askForReset() {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Sifirlama?");
lcd.println("#-Evet *-Hayir");
lcd.display();
while(true) {
char key = getKey();
if(key == '#') {
settings.type = 4;
saveState();
showMainMenu();
currentMenu = MENU_MAIN;
break;
}
else if(key == '*') {
showSettingsMenu();
currentMenu = MENU_SETTINGS;
break;
}
wdt_reset();
}
}
void checkAndUpdateSettings(int currentDay) {
switch(settings.type) {
case 0:
if (currentDay >= 19) {
settings.targetTemp = 37.5;
settings.targetHum = 75;
settings.motorActive = false;
}
break;
case 1:
if (currentDay >= 27) {
settings.targetTemp = 37.5;
settings.targetHum = 80;
settings.motorActive = false;
}
break;
case 2:
if (currentDay >= 16) {
settings.targetTemp = 37.5;
settings.targetHum = 75;
settings.motorActive = false;
}
break;
}
}
void controlTemperature(float currentTemp) {
static float lastTemp = 0;
static unsigned long lastTime = 0;
unsigned long currentTime = millis();
float tempRate = 0;
if (lastTime > 0) {
tempRate = (currentTemp - lastTemp) * 60000 / (currentTime - lastTime);
}
if(!errorMgr.safeMode) {
if(currentTemp < (settings.targetTemp - TEMP_HYSTERESIS)) {
digitalWrite(RELAY1, LOW);
settings.heaterState = true;
}
else if(currentTemp > (settings.targetTemp + TEMP_HYSTERESIS) ||
(tempRate > 0.5 && currentTemp > settings.targetTemp)) {
digitalWrite(RELAY1, HIGH);
settings.heaterState = false;
}
}
lastTemp = currentTemp;
lastTime = currentTime;
}
void controlHumidity(float currentHum) {
if(!errorMgr.safeMode) {
if(currentHum < (settings.targetHum - HUM_HYSTERESIS)) {
digitalWrite(RELAY2, LOW);
settings.humidifierState = true;
}
else if(currentHum > (settings.targetHum + HUM_HYSTERESIS)) {
digitalWrite(RELAY2, HIGH);
settings.humidifierState = false;
}
}
}
void controlMotor(uint32_t currentTime) {
if (!settings.motorActive || errorMgr.safeMode) return;
unsigned long currentMillis = millis();
if (isFirstMotorActivation) {
if (currentMillis > 60000) {
debugPrint("İlk motor aktivasyonu yapılıyor");
digitalWrite(RELAY4, LOW);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Motor");
lcd.println("Ilk Donus");
lcd.println("Yapiliyor...");
lcd.display();
for (unsigned long start = millis(); millis() - start < motorSettings.duration;) {
delay(100);
wdt_reset();
}
digitalWrite(RELAY4, HIGH);
debugPrint("İlk motor aktivasyonu tamamlandı");
previousMillis = currentMillis;
isFirstMotorActivation = false;
saveTimeWithBackup(settings.startTime);
delay(20);
wdt_reset();
}
}
else if (currentMillis - previousMillis >= motorSettings.interval) {
debugPrint("Periyodik motor dönüşü yapılıyor");
digitalWrite(RELAY4, LOW);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Motor");
lcd.println("Donduruluyor...");
lcd.display();
for (unsigned long start = millis(); millis() - start < motorSettings.duration;) {
delay(100);
wdt_reset();
}
digitalWrite(RELAY4, HIGH);
debugPrint("Motor dönüşü tamamlandı");
previousMillis = currentMillis;
}
}
void testMotor() {
if(errorMgr.safeMode) {
showMessage("Guvenli Mod!\nMotor Pasif");
return;
}
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("Motor Test");
lcd.println("Calistiriliyor...");
lcd.display();
digitalWrite(RELAY4, LOW);
for (unsigned long start = millis(); millis() - start < 1000;) {
delay(100);
wdt_reset();
}
digitalWrite(RELAY4, HIGH);
showMessage("Motor Testi\nTamamlandi");
}
SensorData readSHT31_1() {
SensorData data;
for (int attempt = 0; attempt < 3; attempt++) {
data.temp = sht31_1.readTemperature() + settings.tempOffset1;
data.hum = sht31_1.readHumidity() + settings.humOffset1;
if (!isnan(data.temp) && !isnan(data.hum)) {
break;
}
delay(100);
wdt_reset();
}
data.isValid = (!isnan(data.temp) && !isnan(data.hum) &&
data.temp > -10 && data.temp < 60 &&
data.hum >= 0 && data.hum <= 100);
return data;
}
SensorData readSHT31_2() {
SensorData data;
for (int attempt = 0; attempt < 3; attempt++) {
data.temp = sht31_2.readTemperature() + settings.tempOffset2;
data.hum = sht31_2.readHumidity() + settings.humOffset2;
if (!isnan(data.temp) && !isnan(data.hum)) {
break;
}
delay(100);
wdt_reset();
}
data.isValid = (!isnan(data.temp) && !isnan(data.hum) &&
data.temp > -10 && data.temp < 60 &&
data.hum >= 0 && data.hum <= 100);
return data;
}
int getMotorCountdown() {
unsigned long timeSinceLastMotor = millis() - previousMillis;
if(timeSinceLastMotor >= motorSettings.interval) return 0;
return (motorSettings.interval - timeSinceLastMotor) / 60000;
}
void loadState() {
uint8_t storedType;
EEPROM.get(EEPROM_TYPE, storedType);
debugPrint("EEPROM'dan tip okundu:", (int)storedType);
if (storedType == 255 || storedType < 0 || storedType > 4) {
debugPrint("Geçersiz tip, varsayılanlar yükleniyor");
settings.type = 4;
settings.targetTemp = 37.5;
settings.targetHum = 65.0;
settings.totalDays = 0;
settings.startTime = 0;
settings.motorActive = false;
settings.heaterState = false;
settings.humidifierState = false;
settings.tempOffset1 = 0;
settings.tempOffset2 = 0;
settings.humOffset1 = 0;
settings.humOffset2 = 0;
isFirstMotorActivation = false;
EEPROM.put(EEPROM_TYPE, settings.type);
delay(5);
EEPROM.put(EEPROM_START_TIME, settings.startTime);
delay(5);
EEPROM.put(EEPROM_TEMP, settings.targetTemp);
delay(5);
EEPROM.put(EEPROM_HUM, settings.targetHum);
delay(5);
EEPROM.put(EEPROM_TEMP_OFFSET1, settings.tempOffset1);
delay(5);
EEPROM.put(EEPROM_HUM_OFFSET1, settings.humOffset1);
delay(5);
EEPROM.put(EEPROM_TEMP_OFFSET2, settings.tempOffset2);
delay(5);
EEPROM.put(EEPROM_HUM_OFFSET2, settings.humOffset2);
delay(5);
wdt_reset();
return;
}
settings.type = storedType;
uint32_t storedTime = getStartTimeFromEEPROM();
settings.startTime = storedTime;
Serial.print("Ana EEPROM'dan okunan zaman: ");
Serial.println(settings.startTime);
EEPROM.get(EEPROM_TEMP, settings.targetTemp);
EEPROM.get(EEPROM_HUM, settings.targetHum);
EEPROM.get(EEPROM_TEMP_OFFSET1, tempOffset1);
EEPROM.get(EEPROM_HUM_OFFSET1, humOffset1);
EEPROM.get(EEPROM_TEMP_OFFSET2, tempOffset2);
EEPROM.get(EEPROM_HUM_OFFSET2, humOffset2);
settings.tempOffset1 = tempOffset1;
settings.humOffset1 = humOffset1;
settings.tempOffset2 = tempOffset2;
settings.humOffset2 = humOffset2;
if (settings.targetTemp < 30.0 || settings.targetTemp > 40.0) {
settings.targetTemp = 37.5;
}
if (settings.targetHum < 0.0 || settings.targetHum > 100.0) {
settings.targetHum = 65.0;
}
uint32_t currentTime = getTimeFromRTC();
if (settings.type >= 0 && settings.type <= 3) {
if (settings.startTime == 0 || settings.startTime > currentTime ||
(currentTime - settings.startTime) > 86400 * 100) {
Serial.println("UYARI: Geçersiz başlangıç zamanı, şimdiki zamanla ayarlanıyor");
settings.startTime = currentTime;
saveTimeWithBackup(settings.startTime);
}
int daysPassed = (currentTime - settings.startTime) / 86400 + 1;
Serial.print("Hesaplanan gün: ");
Serial.println(daysPassed);
switch(settings.type) {
case 0: settings.totalDays = 21; break;
case 1: settings.totalDays = 30; break;
case 2: settings.totalDays = 18; break;
case 3: break;
}
}
if (settings.type <= 3) {
settings.motorActive = true;
uint32_t currentTime = getTimeFromRTC();
if (settings.startTime > 0 && currentTime > settings.startTime) {
int currentDay = (currentTime - settings.startTime) / 86400 + 1;
if ((settings.type == 0 && currentDay >= 19) ||
(settings.type == 1 && currentDay >= 27) ||
(settings.type == 2 && currentDay >= 16)) {
settings.motorActive = false;
}
}
}
isFirstMotorActivation = true;
debugPrint("Ayarlar yüklendi: Tip:", settings.type);
debugPrint("Başlangıç zamanı:", settings.startTime);
debugPrint("Hedef sıcaklık:", settings.targetTemp);
debugPrint("Hedef nem:", settings.targetHum);
}
void loadMotorSettings() {
EEPROM.get(EEPROM_MOTOR_DURATION, motorSettings.duration);
EEPROM.get(EEPROM_MOTOR_INTERVAL, motorSettings.interval);
if (motorSettings.duration < 1000 || motorSettings.duration > 8000) {
motorSettings.duration = MOTOR_DURATION_DEFAULT;
}
if (motorSettings.interval < 3600000 || motorSettings.interval > 28800000) {
motorSettings.interval = MOTOR_INTERVAL_DEFAULT;
}
if (motorSettings.duration > 7000) {
motorSettings.duration = 7000;
}
debugPrint("Motor ayarları yüklendi:");
debugPrint("Süre (ms):", motorSettings.duration);
debugPrint("Aralık (ms):", motorSettings.interval);
}
void saveState() {
EEPROM.put(EEPROM_TYPE, settings.type);
EEPROM.put(EEPROM_START_TIME, settings.startTime);
delay(10);
wdt_reset();
EEPROM.put(EEPROM_TEMP, settings.targetTemp);
EEPROM.put(EEPROM_HUM, settings.targetHum);
EEPROM.put(EEPROM_TEMP_OFFSET1, settings.tempOffset1);
EEPROM.put(EEPROM_HUM_OFFSET1, settings.humOffset1);
EEPROM.put(EEPROM_TEMP_OFFSET2, settings.tempOffset2);
EEPROM.put(EEPROM_HUM_OFFSET2, settings.humOffset2);
delay(10);
wdt_reset();
uint8_t checksum = calculateChecksum();
EEPROM.put(EEPROM_CHECKSUM, checksum);
delay(20);
wdt_reset();
debugPrint("Ayarlar EEPROM'a kaydedildi");
}
void savePersistentState() {
static uint8_t lastType = 255;
static float lastTargetTemp = 0;
static float lastTargetHum = 0;
static unsigned long lastSaveTime = 0;
if (millis() - lastSaveTime < EEPROM_WRITE_INTERVAL) {
return;
}
if (settings.type != lastType) {
EEPROM.put(EEPROM_TYPE, settings.type);
lastType = settings.type;
}
if (abs(settings.targetTemp - lastTargetTemp) > 0.1) {
EEPROM.put(EEPROM_TEMP, settings.targetTemp);
lastTargetTemp = settings.targetTemp;
}
if (abs(settings.targetHum - lastTargetHum) > 0.1) {
EEPROM.put(EEPROM_HUM, settings.targetHum);
lastTargetHum = settings.targetHum;
}
static unsigned long lastTimeUpdate = 0;
if (millis() - lastTimeUpdate > 21600000) {
saveTimeWithBackup(settings.startTime);
lastTimeUpdate = millis();
}
lastSaveTime = millis();
}
uint8_t calculateChecksum() {
uint8_t checksum = 0;
checksum += settings.type;
checksum += (uint8_t)(settings.targetTemp * 10);
checksum += (uint8_t)(settings.targetHum * 10);
checksum += (uint8_t)(settings.totalDays);
checksum += (uint8_t)(settings.startTime & 0xFF);
return checksum;
}
void showMainMenu() {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Kulucka Tipi:");
lcd.setCursor(0,8);
lcd.println("1-Tavuk");
lcd.setCursor(0,16);
lcd.println("2-Kaz");
lcd.setCursor(0,24);
lcd.println("3-Bildircin");
lcd.setCursor(0,32);
lcd.println("4-Manuel");
lcd.setCursor(0,40);
lcd.println("5-Ayarlar");
lcd.display();
}
void showSettingsMenu() {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Ayarlar:");
lcd.setCursor(0,8);
lcd.println("1-Sicaklik");
lcd.setCursor(0,16);
lcd.println("2-Nem");
lcd.setCursor(0,24);
lcd.println("3-Motor");
lcd.setCursor(0,32);
lcd.println("4-Kalibrasyon");
lcd.setCursor(0,40);
lcd.println("5-Sens 6-Reset");
lcd.display();
}
void showMotorMenu() {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Motor Ayarlari:");
lcd.setCursor(0,8);
lcd.print("Aralik: ");
lcd.print(motorSettings.interval / 60000);
lcd.println(" dk");
lcd.setCursor(0,16);
lcd.print("Sure: ");
lcd.print(motorSettings.duration / 1000);
lcd.println(" sn");
lcd.setCursor(0,24);
lcd.println("1-Aralik D.");
lcd.setCursor(0,32);
lcd.println("2-Sure D.");
lcd.display();
}
void showSensorInfo() {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Sensor Bilgileri:");
SensorData sensor1 = readSHT31_1();
SensorData sensor2 = readSHT31_2();
lcd.setCursor(0,8);
lcd.print("S1: ");
if (sensor1.isValid) {
lcd.print(sensor1.temp, 1);
lcd.print("C ");
lcd.print(sensor1.hum, 1);
lcd.print("%");
} else {
lcd.print("Hata!");
}
lcd.setCursor(0,16);
lcd.print("S2: ");
if (sensor2.isValid) {
lcd.print(sensor2.temp, 1);
lcd.print("C ");
lcd.print(sensor2.hum, 1);
lcd.print("%");
} else {
lcd.print("Hata!");
}
lcd.setCursor(0,24);
lcd.print("Fark: ");
if (sensor1.isValid && sensor2.isValid) {
lcd.print(abs(sensor1.temp - sensor2.temp), 1);
lcd.print("C ");
lcd.print(abs(sensor1.hum - sensor2.hum), 1);
lcd.print("%");
} else {
lcd.print("--");
}
lcd.setCursor(0,32);
lcd.print("OfsT: ");
lcd.print(settings.tempOffset1, 1);
lcd.print("/");
lcd.print(settings.tempOffset2, 1);
lcd.setCursor(0,40);
lcd.print("OfsH: ");
lcd.print(settings.humOffset1, 1);
lcd.print("/");
lcd.print(settings.humOffset2, 1);
lcd.display();
while(true) {
char key = getKey();
if(key == '*') {
showSettingsMenu();
currentMenu = MENU_SETTINGS;
break;
}
wdt_reset();
}
}
void showCalibrationMenu() {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("Kalibrasyon:");
lcd.setCursor(0,8);
lcd.println("1-S1 Sicaklik");
lcd.setCursor(0,16);
lcd.println("2-S1 Nem");
lcd.setCursor(0,24);
lcd.println("3-S2 Sicaklik");
lcd.setCursor(0,32);
lcd.println("4-S2 Nem");
lcd.setCursor(0,40);
lcd.println("5-Offsetleri Sifirla");
lcd.display();
}
void showMessage(const char* message) {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,16);
lcd.println(message);
lcd.display();
unsigned long startTime = millis();
while (millis() - startTime < MESSAGE_DURATION) {
delay(100);
wdt_reset();
}
}
void showError(const char* message) {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.println("HATA!");
lcd.setCursor(0,16);
lcd.println(message);
lcd.display();
}
void updateMainDisplay(float temp, float hum, int currentDay) {
lcd.clearDisplay();
lcd.setTextSize(1);
lcd.setCursor(0,0);
lcd.print("S:");
if (temp < 100 && temp > -40) {
lcd.print(temp, 1);
lcd.print(settings.heaterState ? "+" : " ");
} else {
lcd.print("--.-");
}
lcd.print("/");
lcd.print(settings.targetTemp, 1);
lcd.print("C");
lcd.setCursor(0,8);
lcd.print("N:");
if (hum < 100 && hum >= 0) {
lcd.print(hum, 1);
lcd.print(settings.humidifierState ? "+" : " ");
} else {
lcd.print("--.-");
}
lcd.print("/");
lcd.print(settings.targetHum, 1);
lcd.print("%");
lcd.setCursor(0,16);
lcd.print("G:");
if (settings.type >= 0 && settings.type <= 3) {
int dayNum = 1;
uint32_t currentTime = getTimeFromRTC();
if (settings.startTime > 0 && currentTime >= settings.startTime) {
dayNum = (currentTime - settings.startTime) / 86400 + 1;
if (dayNum > settings.totalDays) {
dayNum = settings.totalDays;
}
if (dayNum <= 0) {
dayNum = 1;
}
}
lcd.print(dayNum);
lcd.print("/");
lcd.print(settings.totalDays);
Serial.print("Gün hesaplama: Şimdi=");
Serial.print(currentTime);
Serial.print(", Başlangıç=");
Serial.print(settings.startTime);
Serial.print(", Fark=");
Serial.print(currentTime - settings.startTime);
Serial.print(", Gün=");
Serial.println(dayNum);
lcd.setCursor(0,24);
lcd.print(typeNames[settings.type]);
if (settings.motorActive) {
lcd.print(" M:");
lcd.print(getMotorCountdown());
lcd.print("dk");
}
} else {
lcd.print("--/--");
}
DateTime now = rtc.now();
lcd.setCursor(0,32);
if (now.hour() < 10) lcd.print("0");
lcd.print(now.hour());
lcd.print(":");
if (now.minute() < 10) lcd.print("0");
lcd.print(now.minute());
lcd.setCursor(0,40);
if (settings.type >= 0 && settings.type <= 3 && settings.startTime > 0) {
uint32_t currentTime = getTimeFromRTC();
int dayNum = (currentTime - settings.startTime) / 86400 + 1;
if (dayNum > 0 && dayNum <= settings.totalDays &&
dayNum >= settings.totalDays - 2) {
lcd.print("!SON GUNLER!");
} else if (errorMgr.safeMode) {
lcd.print("!GUVENLI MOD!");
} else {
SensorData sensor1 = readSHT31_1();
SensorData sensor2 = readSHT31_2();
lcd.print("S:");
lcd.print(sensor1.isValid ? "1" : "-");
lcd.print(sensor2.isValid ? "2" : "-");
lcd.print(" 5-Menu 6-Motor");
}
} else {
lcd.print("S:-- 5-Menu 6-Motor");
}
if (settings.type >= 0 && settings.type <= 3 && settings.startTime > 0) {
uint32_t currentTime = getTimeFromRTC();
int dayNum = (currentTime - settings.startTime) / 86400 + 1;
if (dayNum > 0 && dayNum <= settings.totalDays) {
int progress = map(dayNum, 0, settings.totalDays, 0, 80);
lcd.drawRect(2, 47, 80, 2, BLACK);
lcd.fillRect(2, 47, progress, 2, BLACK);
}
}
lcd.display();
}
void updateBacklight() {
unsigned long currentTime = millis();
if (backlightState && (currentTime - lastKeyPressTime >= BACKLIGHT_TIMEOUT)) {
digitalWrite(BACKLIGHT_PIN, LOW);
backlightState = false;
}
}
char getKey() {
static unsigned long lastDebounceTime = 0;
static char lastKey = 0;
const unsigned long debounceDelay = 250;
char keys[4][4] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
unsigned long currentTime = millis();
if (currentTime - lastDebounceTime < debounceDelay) {
return 0;
}
for(int i = 0; i < 4; i++) {
digitalWrite(COL1 + i*2, LOW);
for(int j = 0; j < 4; j++) {
if(digitalRead(ROW1 + j*2) == LOW) {
lastKeyPressTime = currentTime;
if (!backlightState) {
digitalWrite(BACKLIGHT_PIN, HIGH);
backlightState = true;
}
digitalWrite(COL1 + i*2, HIGH);
lastDebounceTime = currentTime;
return keys[j][i];
}
}
digitalWrite(COL1 + i*2, HIGH);
}
return 0;
}
float getNumberInput() {
String input = "";
bool hasDecimal = false;
while(true) {
char key = getKey();
if(key) {
if(key >= '0' && key <= '9') {
if(input.length() < 5) {
input += key;
lcd.print(key);
lcd.display();
}
}
else if(key == '*' && !hasDecimal) {
if(!input.length()) input = "0";
input += '.';
hasDecimal = true;
lcd.print('.');
lcd.display();
}
else if(key == '#' && input.length() > 0) {
return input.toFloat();
}
}
wdt_reset();
}
}
void calibrateTemperature1() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S1 Sicaklik Kal.:");
lcd.setCursor(0,8);
lcd.println("Referans olcum:");
lcd.display();
float refTemp = getNumberInput();
SensorData sensor1 = readSHT31_1();
if (!sensor1.isValid) {
showError("Sensor 1\nHatali!");
delay(2000);
showCalibrationMenu();
return;
}
float rawTemp = sht31_1.readTemperature();
float newOffset = refTemp - rawTemp;
settings.tempOffset1 = newOffset;
tempOffset1 = newOffset;
EEPROM.put(EEPROM_TEMP_OFFSET1, tempOffset1);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S1 Sicaklik");
lcd.println("Kalibr. Tamam");
lcd.setCursor(0,16);
lcd.print("Yeni Offset: ");
lcd.print(settings.tempOffset1, 1);
lcd.display();
delay(2000);
showCalibrationMenu();
}
void calibrateHumidity1() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S1 Nem Kalibr.:");
lcd.setCursor(0,8);
lcd.println("Referans olcum:");
lcd.display();
float refHum = getNumberInput();
SensorData sensor1 = readSHT31_1();
if (!sensor1.isValid) {
showError("Sensor 1\nHatali!");
delay(2000);
showCalibrationMenu();
return;
}
float rawHum = sht31_1.readHumidity();
float newOffset = refHum - rawHum;
settings.humOffset1 = newOffset;
humOffset1 = newOffset;
EEPROM.put(EEPROM_HUM_OFFSET1, humOffset1);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S1 Nem");
lcd.println("Kalibr. Tamam");
lcd.setCursor(0,16);
lcd.print("Yeni Offset: ");
lcd.print(settings.humOffset1, 1);
lcd.display();
delay(2000);
showCalibrationMenu();
}
void calibrateTemperature2() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S2 Sicaklik Kal.:");
lcd.setCursor(0,8);
lcd.println("Referans olcum:");
lcd.display();
float refTemp = getNumberInput();
SensorData sensor2 = readSHT31_2();
if (!sensor2.isValid) {
showError("Sensor 2\nHatali!");
delay(2000);
showCalibrationMenu();
return;
}
float rawTemp = sht31_2.readTemperature();
float newOffset = refTemp - rawTemp;
settings.tempOffset2 = newOffset;
tempOffset2 = newOffset;
EEPROM.put(EEPROM_TEMP_OFFSET2, tempOffset2);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S2 Sicaklik");
lcd.println("Kalibr. Tamam");
lcd.setCursor(0,16);
lcd.print("Yeni Offset: ");
lcd.print(settings.tempOffset2, 1);
lcd.display();
delay(2000);
showCalibrationMenu();
}
void calibrateHumidity2() {
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S2 Nem Kalibr.:");
lcd.setCursor(0,8);
lcd.println("Referans olcum:");
lcd.display();
float refHum = getNumberInput();
SensorData sensor2 = readSHT31_2();
if (!sensor2.isValid) {
showError("Sensor 2\nHatali!");
delay(2000);
showCalibrationMenu();
return;
}
float rawHum = sht31_2.readHumidity();
float newOffset = refHum - rawHum;
settings.humOffset2 = newOffset;
humOffset2 = newOffset;
EEPROM.put(EEPROM_HUM_OFFSET2, humOffset2);
lcd.clearDisplay();
lcd.setCursor(0,0);
lcd.println("S2 Nem");
lcd.println("Kalibr. Tamam");
lcd.setCursor(0,16);
lcd.print("Yeni Offset: ");
lcd.print(settings.humOffset2, 1);
lcd.display();
delay(2000);
showCalibrationMenu();
}
void enterSafeMode(const char* errorMsg) {
if (!errorMgr.safeMode) {
errorMgr.safeMode = true;
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY4, HIGH);
digitalWrite(RELAY3, LOW);
settings.heaterState = false;
settings.humidifierState = false;
showError(errorMsg);
debugPrint("GÜVENLİ MOD AKTİFLEŞTİRİLDİ:");
debugPrint(errorMsg);
EEPROM.write(EEPROM_ERROR_FLAG, 1);
}
}