// Kuluçka Makinesi Kontrol Yazılımı - Optimize Edilmiş Sürüm
#include <LiquidCrystal.h>
#include <DHT.h>
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>
// --- Pin Tanımları ---
#define DHTPIN 2
#define FAN_PIN 3
#define HEATER_PIN 5
#define HUMIDIFIER_PIN 6
#define TURNER_PIN 7
#define BUZZER_PIN 8
#define BUTTON_PIN A0
// --- Nesne Tanımları ---
DHT dht(DHTPIN, DHT22);
LiquidCrystal lcd(9, 10, 4, 11, 12, 13);
RTC_DS3231 rtc;
// --- LCD Özel Karakterler ---
byte degreeChar[8] = {B00110,B01001,B01001,B00110,0,0,0,0};
byte alarmChar[8] = {B00100,B01110,B01110,B01110,B11111,0,B00100,0};
// --- Tür Profili Yapısı ---
struct SpeciesProfile {
char name[10];
uint8_t totalDays;
float normalTemp[2];
float finalTemp[2];
float normalHum[2];
float finalHum[2];
uint16_t turnInterval;
uint16_t turnDuration;
uint8_t fanSpeed;
uint8_t coolingDay;
bool stopTurning;
};
SpeciesProfile profiles[] = {
{"Tavuk", 21, {37.5,38.5}, {37.0,37.5}, {50,60}, {65,75}, 10800, 300, 170, 0, true},
{"Hindi", 28, {37.2,37.8}, {37.0,37.3}, {55,65}, {70,80}, 14400, 420, 200, 0, true},
{"Bildrcn",17, {37.8,38.3}, {37.5,37.8}, {55,60}, {70,75}, 7200, 180, 128, 0, true},
{"Kaz", 30, {37.4,37.8}, {36.8,37.2}, {60,65}, {75,85}, 21600, 600, 255, 25, true}
};
// --- Global Değişkenler ---
uint8_t currentProfile = 0;
uint32_t startTime = 0;
float temp, humidity;
uint8_t remainingDays = 0;
bool coolingActive = false;
bool finalStage = false;
enum MenuState { MAIN_MENU, PROFILE_SELECT };
MenuState menuState = MAIN_MENU;
// --- Kurulum ---
void setup() {
lcd.begin(16, 2);
lcd.createChar(0, degreeChar);
lcd.createChar(1, alarmChar);
dht.begin();
rtc.begin();
pinMode(FAN_PIN, OUTPUT);
pinMode(HEATER_PIN, OUTPUT);
pinMode(HUMIDIFIER_PIN, OUTPUT);
pinMode(TURNER_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
EEPROM.get(0, currentProfile);
startTime = rtc.now().unixtime();
}
// --- Ana Döngü ---
void loop() {
DateTime now = rtc.now();
temp = dht.readTemperature();
humidity = dht.readHumidity();
remainingDays = profiles[currentProfile].totalDays - ((now.unixtime() - startTime) / 86400);
finalStage = remainingDays <= 3;
controlSystems();
handleMenu(readButtons());
updateDisplay();
checkAlarms();
if (remainingDays <= 0) endIncubation();
delay(2000);
}
// --- Sistem Kontrolleri ---
void controlSystems() {
float tempTarget = finalStage ? profiles[currentProfile].finalTemp[0] : profiles[currentProfile].normalTemp[0];
float humTarget = finalStage ? profiles[currentProfile].finalHum[0] : profiles[currentProfile].normalHum[0];
digitalWrite(HEATER_PIN, temp < tempTarget ? HIGH : LOW);
digitalWrite(HUMIDIFIER_PIN, humidity < humTarget ? HIGH : LOW);
if (finalStage && profiles[currentProfile].stopTurning) {
digitalWrite(TURNER_PIN, LOW);
} else {
manageTurner();
}
if (currentProfile == 3 && remainingDays == profiles[3].coolingDay) activateCooling();
analogWrite(FAN_PIN, finalStage ? profiles[currentProfile].fanSpeed + 30 : profiles[currentProfile].fanSpeed);
}
void manageTurner() {
static uint32_t lastTurn = 0;
if (millis() - lastTurn > profiles[currentProfile].turnInterval * 1000UL) {
digitalWrite(TURNER_PIN, HIGH);
delay(profiles[currentProfile].turnDuration * 1000UL);
digitalWrite(TURNER_PIN, LOW);
lastTurn = millis();
}
}
void activateCooling() {
coolingActive = true;
digitalWrite(HEATER_PIN, LOW);
analogWrite(FAN_PIN, 255);
delay(1800000); // 30 dakika
coolingActive = false;
}
// --- Menü Butonları ---
int readButtons() {
int adc = analogRead(BUTTON_PIN);
if(adc < 50) return 1;
if(adc < 250) return 2;
if(adc < 450) return 3;
if(adc < 650) return 4;
if(adc < 850) return 5;
return 0;
}
void handleMenu(int btn) {
static uint32_t lastPress = 0;
if (millis() - lastPress < 200) return;
switch (menuState) {
case MAIN_MENU:
if (btn == 5) menuState = PROFILE_SELECT;
break;
case PROFILE_SELECT:
if (btn == 1) currentProfile = (currentProfile + 1) % 4;
if (btn == 4) currentProfile = (currentProfile + 3) % 4;
if (btn == 5) {
EEPROM.put(0, currentProfile);
startTime = rtc.now().unixtime();
menuState = MAIN_MENU;
}
break;
}
lastPress = millis();
}
// --- LCD Güncelleme ---
void updateDisplay() {
static char lastLine1[17] = "";
static char lastLine2[17] = "";
char line1[17], line2[17];
snprintf(line1, sizeof(line1), "%s D:%02d%s",
profiles[currentProfile].name,
remainingDays,
finalStage ? " FINAL" : "");
snprintf(line2, sizeof(line2), "S:%.1f%c H:%d%%%s",
temp,
(char)223, // Derece
(int)humidity,
finalStage ? " NO-TRN" : "");
if (strcmp(line1, lastLine1) != 0 || strcmp(line2, lastLine2) != 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
strncpy(lastLine1, line1, sizeof(lastLine1));
strncpy(lastLine2, line2, sizeof(lastLine2));
}
}
// --- Alarm Kontrol ---
void checkAlarms() {
bool tempAlarm = temp > (finalStage ? profiles[currentProfile].finalTemp[1] : profiles[currentProfile].normalTemp[1]);
bool humAlarm = humidity > (finalStage ? profiles[currentProfile].finalHum[1] : profiles[currentProfile].normalHum[1]);
if (tempAlarm || humAlarm) {
digitalWrite(BUZZER_PIN, HIGH);
lcd.setCursor(15, 0);
lcd.write((uint8_t)1);
} else {
digitalWrite(BUZZER_PIN, LOW);
}
}
// --- Kuluçka Bitiş ---
void endIncubation() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("TEBRIKLER!");
lcd.setCursor(0, 1);
lcd.print("KULUCKA TAMAMLANDI");
while (true) {
digitalWrite(BUZZER_PIN, HIGH);
delay(500);
digitalWrite(BUZZER_PIN, LOW);
delay(500);
}
}