#include <Arduino.h>
#include <Wire.h> // I2C Kommunikation
#include <RTClib.h> // DS1307 RTC Bibliothek
#include <HX711.h> // HX711 Wägezellenbibliothek
#include <LiquidCrystal_I2C.h> // I²C LCD Display
#include <AccelStepper.h> // Stepper
// Stepper A4988
// AccelStepper Setup für A4988 (DRIVER-Modus)
AccelStepper stepper(AccelStepper::DRIVER, 7, 6); // STEP an D5, DIR an D4
// LCD-Display
// Adressierung des LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Waage
// Erstelle ein HX711-Objekt
HX711 scale;
// variablen für die Waage
long weight_raw = 0;
long weight = 0;
unsigned long load_cell_millis = 0;
unsigned long load_measurement_intervall = 1000;
// Belegung der Waage
#define DOUT 5
#define CLK 4
// ds1307 Modul
// Setzen des Objektes
RTC_DS1307 rtc;
// Variablen für das RTC
int hour = 0;
int minute = 0;
bool feeding_operator = false;
// Variablen für das Ultrasonic
const byte trigger_pin = 12;
const byte echo_pin = 11;
// Variablen für das Ultrasonic
float distance = 0;
bool measuring = false;
long duration = 0;
// Timer für das Ultrasonic
unsigned long last_measurement = 0;
unsigned long measurement_interval = 200;
// Variablen für die Aktuatoren
const byte led_red_pin = 9;
const byte led_green_pin = 8;
const byte fan_pin = 3;
byte actuator_pins[3] = {led_red_pin, led_green_pin, fan_pin};
// Flags für die Aktuatoren
bool led_red_flag = false;
bool led_green_flag = false;
bool fan_flag = false;
byte actuator_flags[3] = {led_red_flag, led_green_flag, fan_flag};
// Pin für den Taster
const byte start_button_pin = 10;
// Variablen für den Taster
bool button_read = false;
bool button_on = false;
bool switch0 = false;
unsigned long button_millis = 0;
// Allgemeine Timer
unsigned long serial_millis = 0;
// Setzen der state-machine
enum current_operation_state {
device_off, // (0)
device_on, // (1)
start_feeding, // (2)
device_alarm // (3)
};
current_operation_state operation_state = device_off;
unsigned long operation_millis = 0;
enum current_function_state {
stepper_off, // (0)
stepper_run // (1)
};
current_function_state function_state = stepper_off;
unsigned long function_millis = 0;
// Vorausdeklaration der Void_Abschnitte
void update_serial_monitor();
void update_lcd();
void update_load_cell();
void update_ultrasonic();
void update_time_modul();
void update_button();
void update_operational_state();
void execute_operational_state();
void update_functional_state();
void execute_functional_state();
void manage_stepper_motor();
void execute_outputs();
void setup() {
// Starten des Seriellen Monitors
Serial.begin(9600);
Serial.println("Serieller Monitor gestartet.");
// Starten der Load Cell
scale.begin(DOUT, CLK);
Serial.println("Wägezelle bereit!");
// Starten des RTC
rtc.begin();
if (rtc.begin()) {
Serial.println("RTC initialisiert");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// Initialisierung des LCD
lcd.begin(20, 4);
lcd.backlight();
Serial.println("LCD-Display initialisiert");
// Setzen der Outputs für die Aktuatoren
Serial.println("Setzen der Outputs der Aktuatoren:");
for (byte i = 0; i < 3; i++) {
Serial.print("PINs: ");
pinMode(actuator_pins[i], OUTPUT);
Serial.print(actuator_pins[i]);
Serial.println(" auf Output gesetzt.");
}
// Setzen des Inputs des Tasters
pinMode(start_button_pin, INPUT_PULLUP);
// Setzen der In/OutPuts für das Ultrasonic
pinMode(trigger_pin, OUTPUT);
pinMode(echo_pin, INPUT);
// Setzen der Einstellungen für den Stepper-Motor
stepper.setMaxSpeed(10);
stepper.setAcceleration(100);
stepper.setCurrentPosition(0);
}
void loop() {
// Ausführung der Funktionen
// Auslesen des Seriellen-Monitors
update_serial_monitor();
// Funktion zum Updaten des LCD
update_lcd();
// Funktion zum Auslesen der Load-Zelle
update_load_cell();
// Funktion zum Auslesen des Ultrasonic
update_ultrasonic();
// Funktion zum Auslesen des DS1307
update_time_modul();
// Funktion zum Auslesen des Tasters
update_button();
// Funktion zum Updaten des OPs
update_operational_state();
// Funktion zum Ausführen des OPs
execute_operational_state();
// Funktion zum Updaten des FSs
update_functional_state();
// Funktion zum Ausführen des FSs
execute_functional_state();
// Funktion zur Steuerung des Stepper Motors
manage_stepper_motor();
// Funktion zum Setzen der Outputs
execute_outputs();
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_serial_monitor() {
// Variablen für diesen Abschnitt
unsigned long serial_timer = millis() - serial_millis;
if (serial_timer > 250) {
Serial.print("Dist.: ");
Serial.print(distance);
Serial.print(" Gew.: ");
Serial.print(weight);
Serial.print(" Tast.: ");
Serial.print(switch0);
Serial.print(" Uhr: ");
Serial.print(hour);
Serial.print(":");
Serial.print(minute);
Serial.print(" feed: ");
Serial.print(feeding_operator);
Serial.print(" OP: ");
Serial.print(operation_state);
Serial.print(" FP: ");
Serial.print(function_state);
Serial.print(" Flags: ");
Serial.print(actuator_flags[0]);
Serial.print(actuator_flags[1]);
Serial.println(actuator_flags[2]);
serial_millis = millis();
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_lcd() {}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_load_cell() {
// Variablen für diesen Abschnitt
unsigned long load_cell_timer = millis() - load_cell_millis;
if (load_cell_timer > load_measurement_intervall) {
if (scale.is_ready()) {
weight_raw = scale.get_units(1);
weight = (weight_raw / 2100.0) * 5000.0;
} else {
Serial.println("Fehler Load_Cell");
}
load_cell_millis = millis();
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_ultrasonic() {
// Variablen für diesen Abschnitt
unsigned long last_measurement_timer = millis() - last_measurement;
if (last_measurement_timer >= measurement_interval) {
last_measurement = millis();
}
if (!measuring) {
digitalWrite(trigger_pin, LOW);
delayMicroseconds(2);
digitalWrite(trigger_pin, HIGH);
delayMicroseconds(10);
digitalWrite(trigger_pin, LOW);
measuring = true;
}
if (measuring) {
duration = pulseIn(echo_pin, HIGH, 30000);
if (duration > 0) {
distance = duration * 0.0343 / 2;
measuring = false;
}
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_time_modul() {
DateTime now = rtc.now();
hour = now.hour();
minute = now.minute();
if ((hour == 8 || hour == 18) && minute == 0) {
feeding_operator = true;
} else {
feeding_operator = false;
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_button() {
// Variablen für diesen Abschnitt
unsigned long button_timer = millis() - button_millis;
button_read = digitalRead(start_button_pin);
if (button_read) {
button_millis = millis();
}
if (!button_read && !button_on && button_timer > 20) {
button_on = true;
}
if (button_read && button_on) {
button_on = false;
switch0 = !switch0;
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_operational_state() {
// Variablen für diesen Abschnitt
unsigned long operation_timer = millis() - operation_millis;
if (switch0) {
switch (operation_state) {
case device_on:
if (!feeding_operator && distance > 50 && weight < 2000) {
operation_state = start_feeding;
operation_millis = millis();
} else if (distance < 50) {
operation_state = device_alarm;
}
break;
case start_feeding:
function_state = stepper_run;
if (weight > 2000 || operation_timer > 10000) {
function_state = stepper_off;
operation_state = device_on;
}
break;
case device_alarm:
function_state = stepper_off;
if (distance > 50) {
operation_state = device_on;
}
break;
default:
operation_state = device_on;
break;
}
} else {
operation_state = device_off;
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void execute_operational_state() {
switch(operation_state) {
case device_off:
actuator_flags[0] = true;
actuator_flags[1] = false;
actuator_flags[2] = false;
break;
case device_on:
actuator_flags[0] = false;
actuator_flags[1] = true;
actuator_flags[2] = false;
break;
case start_feeding:
actuator_flags[0] = false;
actuator_flags[1] = true;
actuator_flags[2] = true;
break;
case device_alarm:
actuator_flags[0] = true;
actuator_flags[1] = false;
actuator_flags[2] = false;
}
}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void update_functional_state() {}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void execute_functional_state() {}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void manage_stepper_motor() {}
//=====================================================================//
//============================FUNCTIONS================================//
//=====================================================================//
void execute_outputs() {
for (byte i = 0; i < 3; i++) {
digitalWrite(actuator_pins[i], actuator_flags[i]);
}
}
//=====================================================================//
//================================END==================================//
//=====================================================================//