#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Pinbelegungen für Taster, Ultraschall-Sensor, LEDs und Summer
const int buttonPin = 2;
const int trigPin = 3;
const int echoPin = 4;
const int buzzerPin = 10;
const int redPin = 11;
const int greenPin = 12;
const int bluePin = 13;
// Zustände für Stromzustand und Backlight
enum PowerState { OFF,
ON };
PowerState currentPowerState = OFF;
bool backlightState = false;
// Betriebsmodi
enum OpMode { OP_OK,
OP_OUT_OF_RANGE,
OP_ERROR };
OpMode currentOpMode = OP_OK;
OpMode previousOpMode = OP_OK; // Variable, um den vorherigen Betriebsmodus zu speichern
// LCD initialisieren
LiquidCrystal_I2C lcd(0x27, 16, 2); // Anpassen der Adresse, falls abweichend
// Einstellungen für den Sensor und Alarme
int minDistance = 30;
int maxDistance = 300;
int measuredDistance = 0;
bool distanceAlarm = false;
// Variablen für Tasterabfrage
static unsigned long lastButtonPress = 0;
static bool buttonWasPressed = false;
int buttonState = digitalRead(buttonPin);
void setup() {
// Initialisierung der Pins
pinMode(buttonPin, INPUT_PULLUP);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
lcd.init(); // LCD initialisieren
lcd.begin(16, 2); // Anpassen der Displaygröße, wenn nötig
}
void loop() {
int buttonState = digitalRead(buttonPin);
// Tasterflanken erkennen
if (buttonState == LOW && !buttonWasPressed) {
lastButtonPress = millis();
buttonWasPressed = true;
if (currentPowerState == OFF) {
currentPowerState = ON;
backlightState = true; // Backlight einschalten, wenn Power an ist
} else {
currentPowerState = OFF;
backlightState = false; // Backlight ausschalten, wenn Power aus ist
}
} else if (buttonState == HIGH && buttonWasPressed) {
buttonWasPressed = false;
}
// Steuerung des LCD-Backlights
if (backlightState) {
lcd.backlight(); // Backlight einschalten
} else {
lcd.noBacklight(); // Backlight ausschalten
}
// Hauptprogrammablauf je nach Stromzustand
switch (currentPowerState) {
case OFF:
lcd.clear();
noTone(buzzerPin);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
break;
case ON:
measuredDistance = getDistance();
currentOpMode = checkDistanceState(measuredDistance);
decideTextToShow(measuredDistance, currentOpMode); // Aufruf mit dem aktuellen Betriebsmodus
controlLED(currentOpMode);
driveLogic(distanceAlarm);
switch (currentOpMode) {
case OP_ERROR:
errorAlarm();
break;
case OP_OUT_OF_RANGE:
infoAlarm();
break;
default:
noTone(buzzerPin);
break;
}
break;
}
}
// Funktion zur Überprüfung des Distanzalarms und Festlegung des Betriebsmodus
OpMode checkDistanceState(int distance) {
if (distance < minDistance) {
return OP_ERROR;
} else if (distance > maxDistance) {
return OP_OUT_OF_RANGE;
} else {
return OP_OK;
}
}
// Funktion für die Fahr-Logik
void driveLogic(bool alarmStatus) {
if (alarmStatus == false) {
// Fahrprogramm für Normalzustand
} else {
// Fahrprogramm für Alarmzustand
}
}
// Funktion zur Anzeige des Texts auf dem LCD
void decideTextToShow(int distance, OpMode currentOpMode) {
if (currentOpMode != previousOpMode) { // Überprüfen, ob sich der Betriebsmodus geändert hat
lcd.clear(); // LCD nur löschen, wenn sich der Betriebsmodus ändert
previousOpMode = currentOpMode; // Aktuellen Betriebsmodus als vorherigen speichern
}
lcd.setCursor(0, 0);
if (distance < minDistance) {
lcd.print("Warning:");
lcd.setCursor(0, 1);
lcd.print("Too close!");
} else if (distance > maxDistance) {
lcd.print("Information:");
lcd.setCursor(0, 1);
lcd.print("Too far...");
} else {
lcd.print("Distance:");
lcd.setCursor(0, 1);
lcd.print(" " + String(distance) + " cm");
}
}
// Funktion zur Steuerung der RGB LED basierend auf dem Betriebsmodus
void controlLED(OpMode mode) {
static unsigned long previousMillis = 0;
const long interval = 200; // Blinkintervall für den Fehlerzustand
switch (mode) {
case OP_OK:
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
break;
case OP_OUT_OF_RANGE:
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, HIGH);
break;
case OP_ERROR:
if (millis() - previousMillis >= interval) {
previousMillis = millis();
if (digitalRead(redPin) == HIGH) {
digitalWrite(redPin, LOW);
} else {
digitalWrite(redPin, HIGH);
}
digitalWrite(greenPin, LOW); // Grüne und blaue LEDs ausschalten
digitalWrite(bluePin, LOW);
}
break;
default:
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
break;
}
}
// Buzzer Alarm im Error-Zustand
void errorAlarm() {
static unsigned long lastErrorSoundTime = 0;
static const unsigned long errorSoundInterval = 500; // Zeitintervall zwischen den Tönen in Millisekunden
static const unsigned long errorSoundDuration = 50; // Dauer des Tons in Millisekunden
static bool isErrorSoundPlaying = false;
unsigned long currentTime = millis();
if (currentTime - lastErrorSoundTime >= errorSoundInterval) {
if (!isErrorSoundPlaying) {
tone(buzzerPin, 1000);
isErrorSoundPlaying = true;
} else {
noTone(buzzerPin);
isErrorSoundPlaying = false;
lastErrorSoundTime = currentTime + errorSoundDuration; // Dauer des Tons
}
}
}
// Buzzer Alarm im Info-Zustand
void infoAlarm() {
static unsigned long lastInfoSoundTime = 0;
static const unsigned long infoSoundInterval = 1000; // Zeitintervall zwischen den Tönen in Millisekunden
static const unsigned long infoSoundDuration = 50; // Dauer des Tons in Millisekunden
static bool isInfoSoundPlaying = false;
unsigned long currentTime = millis();
if (currentTime - lastInfoSoundTime >= infoSoundInterval) {
if (!isInfoSoundPlaying) {
tone(buzzerPin, 300);
isInfoSoundPlaying = true;
} else {
noTone(buzzerPin);
isInfoSoundPlaying = false;
lastInfoSoundTime = currentTime + infoSoundDuration; // Dauer des Tons
}
}
}
// Funktion zur Abstandsmessung
int getDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
int distance = duration * 0.034 / 2;
return distance;
}