#include <TM1637Display.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Servo.h>
#include "OneButton.h" //we need the OneButton library
const byte CLK = 4; // define the connections pins
const byte DIO = 3;
const byte irSensorInnenPin = 2; // Digitaler Pin für den ersten IR Zähler (Vorwärtszähler)
const byte irSensorAussenPin = 7; // Digitaler Pin für den zweiten IR Zähler (Rückwärtszähler)
const byte servoPin = 9; // Pin für den Servo Motor
const byte buttonPin = 8; // Pin für den Taster
const byte redPin = 10; // PIN für die rote LED
const byte greenPin = 11; // Pin für die grüne LED
const long debouncetime = 50;
enum KlappenStates {
staKlappeZu,
staKlappeOffen,
staKlappeOffenZwang
};
KlappenStates KlappenState = staKlappeZu;
enum HuhnStates {
staKlappeIstZu,
staKlappeIstOffen,
staKlappeIstOffen2,
staHuhnWillRaus1,
staHuhnWillRaus2,
staHuhnWillRaus3,
staHuhnWillRaus4,
staHuhnWillRaus5,
staHuhnWillRein1,
staHuhnWillRein2,
staHuhnWillRein3,
staHuhnWillRein4,
staHuhnWillRein5
};
HuhnStates HuhnState = staKlappeIstZu;
unsigned long lastAction = 0;
int counter = 0; // Zähler für IR-Erfassung
int maxCounter = 5; // Grenzwert für das Schließen der Klappe
bool sensorInnenTriggered = false;
bool sensorAussenTriggered = false;
// Variablen für den Wechsel der LCD Anzeige
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
const long displayInterval = 5000; // Intervall für den Wechsel (5 Sekunden)
bool zeigeZustand = false; // Anzeigestatus (false = Uhrzeit/Datum, true = Klappenstatus)
unsigned long zustandChangeMillis = 0; // Zeitstempel des letzten Zustandswechsels
TM1637Display display = TM1637Display(CLK, DIO); // create a display object of type TM1637Display
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS1307 rtc;
Servo servoMotor;
OneButton button(buttonPin, true); //attach a button to the library
void setup() {
Serial.begin(115200); // Initialisiert die serielle Kommunikation für Debugging
display.clear();
display.setBrightness(7); // set the brightness to 7 (0:dimmest, 7:brightest)
display.showNumberDec(counter); // Wert des Zählers anzeigen
// LCD Display starten
lcd.begin(16, 2);
lcd.backlight();
// Überprüfe, ob die RTC korrekt initialisiert werden kann
if (!rtc.begin()) {
Serial.println("RTC konnte nicht gefunden werden");
while (1); // Bleibe in einer Endlosschleife, wenn die RTC nicht gefunden wird
}
// Überprüfe, ob die RTC läuft. Falls nicht, setze die Zeit auf die Kompilierungszeit
if (!rtc.isrunning()) {
Serial.println("RTC läuft NICHT!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// Pin-Modi für LEDs und Taster
button.attachClick(singleclick); // link the function to be called on a singleclick event.
pinMode(redPin, OUTPUT); // RedPin als Ausgang definieren
pinMode(greenPin, OUTPUT); // GreenPin als Ausgang definieren
// Setzt die IR-Sensor-Pins als Eingang
pinMode(irSensorInnenPin, INPUT_PULLUP);
pinMode(irSensorAussenPin, INPUT_PULLUP);
// Initialisiert den Servo
servoMotor.attach(servoPin);
klappeSchliessen();
rtc.adjust(DateTime(2024,9,18,19,58,40));
}
void loop() {
currentMillis = millis();
DateTime jetzt = rtc.now(); // Lese die aktuelle Zeit von der RTC
button.tick(); // check the status of the button
bool sensorInnenTriggered = digitalRead(irSensorInnenPin); // Zustand der IR-Sensoren abfragen
bool sensorAussenTriggered = digitalRead(irSensorAussenPin);
// Wenn der Zustand gewechselt wurde, wird der Zeitstempel gesetzt
if (currentMillis - zustandChangeMillis >= displayInterval) {
zeigeZustand = !zeigeZustand; // Wechsel zwischen Uhrzeit/Datum und Klappenzustand
lcd.clear();
if (zeigeZustand) { // Klappenstatus anzeigen
lcd.setCursor(0, 0);
lcd.print("Klappe ");
switch (KlappenState){
case staKlappeZu:
lcd.print("Zu ");
break;
case staKlappeOffen:
lcd.print("Offen");
break;
case staKlappeOffenZwang:
lcd.print("Offen Zwang");
break;
}
lcd.setCursor(0, 1);
lcd.print("Huehner innen ");
lcd.print(counter);
}
zustandChangeMillis = currentMillis; // Setzt den Zeitstempel des letzten Zustandwechsels
}
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
display.showNumberDec(counter); // Wert des Zählers anzeigen
// Anzeige auf dem LCD je nach Zustand
if (!zeigeZustand) {
// Setze den Cursor auf die erste Zeile und gib das Datum aus
lcd.setCursor(0, 0);
lcd.print("Datum ");
printDigits(jetzt.day());
lcd.print('.');
printDigits(jetzt.month());
lcd.print('.');
lcd.print(jetzt.year());
// Setze den Cursor auf die zweite Zeile und gib die Uhrzeit aus
lcd.setCursor(0, 1);
lcd.print("Uhrzeit ");
printDigits(jetzt.hour());
lcd.print(':');
printDigits(jetzt.minute());
lcd.print(':');
printDigits(jetzt.second());
}
if (KlappenState == staKlappeOffenZwang){
//nix machen
} else if (jetzt.hour() == 7 && jetzt.minute() == 0 && jetzt.second() == 0 && (KlappenState == staKlappeZu)) {// Überprüft, ob es 7 Uhr morgens ist und die Klappe geschlossen ist
klappeOeffnen();
} else if (jetzt.hour() >= 20 && counter==maxCounter && (KlappenState == staKlappeOffen)) {
klappeSchliessen();
}
}
//Hühnerzähler
switch (HuhnState){
case staKlappeIstZu:
//nix machen
break;
case staKlappeIstOffen:
if (currentMillis - lastAction >= 200) { //Letzten Tastendruck ignorieren
lastAction = currentMillis;
HuhnState = staKlappeIstOffen2;
Serial.print(counter);
Serial.println(" Huehner innen");
}
break;
case staKlappeIstOffen2:
if (!sensorInnenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRaus1;
Serial.print("A ");
}
if (!sensorAussenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRein1;
Serial.print("I ");
}
break;
case staHuhnWillRaus1: //Debounce
if (currentMillis - lastAction >= debouncetime) {
if (!sensorInnenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRaus2;
Serial.print("B ");
} else {
HuhnState = staKlappeIstOffen;
Serial.print("C ");
}
}
break;
case staHuhnWillRaus2: //Warten freigabe Innensensor
if (sensorInnenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRaus3;
Serial.print("D ");
}
break;
case staHuhnWillRaus3: //Warten Aussensensor
if (!sensorAussenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRaus4;
Serial.print("E ");
}
break;
case staHuhnWillRaus4: //Debounce
if (currentMillis - lastAction >= debouncetime) {
if (!sensorAussenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRaus5;
Serial.print("F ");
} else {
HuhnState = staKlappeIstOffen;
Serial.print("G ");
}
}
break;
case staHuhnWillRaus5: //Warten freigabe Aussensensor
if (sensorAussenTriggered) {
lastAction = currentMillis;
HuhnState = staKlappeIstOffen;
Serial.println("Huhn ist draussen");
counter--;
counter = constrain(counter, 0, maxCounter);
}
break;
case staHuhnWillRein1: //Debounce
if (currentMillis - lastAction >= debouncetime) {
if (!sensorAussenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRein2;
Serial.print("J ");
} else {
HuhnState = staKlappeIstOffen;
Serial.print("K ");
}
}
break;
case staHuhnWillRein2: //Warten freigabe Aussensensor
if (sensorAussenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRein3;
Serial.print("L ");
}
break;
case staHuhnWillRein3: //Warten Innensensor
if (!sensorInnenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRein4;
Serial.print("M ");
}
break;
case staHuhnWillRein4: //Debounce
if (currentMillis - lastAction >= debouncetime) {
if (!sensorInnenTriggered) {
lastAction = currentMillis;
HuhnState = staHuhnWillRein5;
Serial.print("N ");
} else {
HuhnState = staKlappeIstOffen;
Serial.print("O ");
}
}
break;
case staHuhnWillRein5: //Warten freigabe Aussensensor
if (sensorInnenTriggered) {
lastAction = currentMillis;
HuhnState = staKlappeIstOffen;
Serial.println("Huhn ist drin");
counter++;
counter = constrain(counter, 0, maxCounter);
}
break;
}
/*
Serial.print("Innen ");
Serial.print(sensorInnenTriggered);
Serial.print("; Aussen ");
Serial.print(sensorAussenTriggered);
Serial.print("; HuhnState ");
Serial.println(HuhnState);
*/
}
void singleclick() { // what happens when the button is clicked
if ((KlappenState == staKlappeOffen) || (KlappenState == staKlappeOffenZwang)) {
klappeSchliessen();
} else {
klappeOeffnen();
KlappenState = staKlappeOffenZwang;
}
zustandChangeMillis = millis();
}
void printDigits(int digits) {
if (digits < 10)
lcd.print('0');
lcd.print(digits);
}
// Funktion zum Steuern des Servo-Motors und der LED
void klappeOeffnen() {
servoMotor.write(180); // Klappe auf Position offen bewegen
KlappenState = staKlappeOffen;
HuhnState = staKlappeIstOffen;
LedGruen(); // Grüne LED leuchtet
Serial.println("Klappe ist auf");
}
void klappeSchliessen() {
servoMotor.write(0); // Klappe auf Position geschlossen bewegen
KlappenState = staKlappeZu;
HuhnState = staKlappeIstZu;
LedRot(); // Rote LED leuchtet
counter = maxCounter; //Alle Hühner sind drinn
Serial.println("Klappe ist zu");
}
// Funktionen zur LED Steuerung
void LedRot() {
digitalWrite(redPin, HIGH);
digitalWrite(greenPin, LOW);
}
void LedGruen() {
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
}Innen
Aussen