#include <dht.h>
#include <LiquidCrystal_I2C.h>
#include <SdFat.h>
#include "RTClib.h"
// initalisieren von Konstanten
#define TEMP_PIN 5 // Wärmemesser
#define LED_PIN_GREEN 9 // Grüne LED
#define LED_PIN_YELLOW 6 // Gelbe LED
#define LED_PIN_RED 11 // Rote LED
#define I2C_ADDR 0x27 // Adresse für LCD
#define LCD_COLUMNS 20 // Anzahl Spalten
#define LCD_LINES 4 // Anzahl Zeilen
#define BUTTON_PIN 2 //Knopf
#define BUZZER_PIN A3 //Beeper / Lautsprecher
#define FEUCHT_PIN 3 //Feuchtemesser
#define MOTION_PIN 4 //Bewegungsmelder
#define SPI_SPEED SD_SCK_MHZ(4)
#define CS_PIN 10
#define SERIAL_BAUDRATE 115200
const int chipSelect = 4;
dht DHT;
dht feucht;
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
SdFat sd;
SdFile myFile;
RTC_DS1307 rtc;
char fileName[] = "wokwi.txt";
int sdPower = 3;
bool lcd_on = false; //
int last_Button_State = HIGH;
int suspend_Alarm = 0;
bool alarm = false;
int motion_State = LOW;
struct {
uint32_t total;
uint32_t ok;
uint32_t crc_error;
uint32_t time_out;
uint32_t connect;
uint32_t ack_l;
uint32_t ack_h;
uint32_t unknown;
} stat = { 0, 0, 0, 0, 0, 0, 0, 0};
char daysOfTheWeek[7][12] = {"Sonntach", "Montach", "Dienstach", "Mittwoch", "Donnerstach", "Freitach", "Samstach"};
// ausführen der Funktionen
void setup()
{ // Erstes und einmaliges Ausführen
initializeLeds();
initializeSd();
initializeMotion();
initializeButton();
initialize_Lcd();
initializeSerial();
initialize_Sd_Card();
}
void initializeSerial()
{
Serial.begin(SERIAL_BAUDRATE);
Serial.println(DHT_LIB_VERSION);
}
//Methode tone2
void Beep(int freq, int leng)
{
tone(BUZZER_PIN, freq, leng);
delay(leng/1.8);
}
void initializeButton()
{
// Button ansteuern
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void initializeMotion()
{
pinMode(MOTION_PIN, INPUT);
}
void initializeLeds()
{
// LEDs ansteuern
pinMode(LED_PIN_GREEN, OUTPUT);
pinMode(LED_PIN_YELLOW, OUTPUT);
pinMode(LED_PIN_RED, OUTPUT);
}
void initializeSd()
{
pinMode(sdPower,OUTPUT);
}
void initialize_Lcd()
{
// LCD ansteuern
lcd.init();
lcd.backlight();
}
void initialize_Sd_Card()
{
if (!sd.begin(CS_PIN, SPI_SPEED))
{
if (sd.card()->errorCode())
{
Serial.println("SD initialization failed.");
} else if (sd.vol()->fatType() == 0)
{
Serial.println("Can't find a valid FAT16/FAT32 partition.");
} else
{
Serial.println("Can't determine error type");
}
return;
}
Serial.println("Files on card:");
Serial.println(" Size Name");
sd.ls(LS_R | LS_SIZE);
File textFile2 = sd.open("wokwi.txt", FILE_WRITE);
if (textFile2)
{
textFile2.close();
} else
{
Serial.println("error opening wokwi.txt!");
}
File txtFile = sd.open("wokwi.txt");
if (txtFile)
{
while (txtFile.available())
{
Serial.write(txtFile.read());
}
txtFile.close();
}
if (! rtc.begin())
{
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
}
void loop()
{ // Regelmäßiges / wiederholtes Ausführen
// READ DATA
read_Temperature_sensor();
read_Humidity_Sensor();
uint32_t start = micros();
uint32_t stop = micros();
float t = DHT.temperature;
float h = feucht.humidity;
// BUTTON
int aktionsKnopf = digitalRead((BUTTON_PIN));
lcd_on = LCD_Screen_on(aktionsKnopf, lcd_on);
// LEDs
wetter(t, h);
// BUZZER
if (aktionsKnopf == LOW && alarm)
{
suspend_Alarm = 500;
}
if ((t>=70 && (suspend_Alarm == 0) || t<=-30) && (suspend_Alarm == 0) || (h>= 60) && (suspend_Alarm == 0))
{
tone(BUZZER_PIN, 80, 200);
alarm = true;
} else
{
alarm = false;
}
if (suspend_Alarm > 0 )
{
suspend_Alarm--;
Serial.println(suspend_Alarm);
}
//Bewegungsmelderchen
flitzi();
//Ührchen
clock();
}
void read_Temperature_sensor()
{
dht_Sensor_Error(DHT.read22(TEMP_PIN));
}
void read_Humidity_Sensor()
{
dht_Sensor_Error(feucht.read22(FEUCHT_PIN));
}
String clock()
{
DateTime now = rtc.now();
String time;
time += " ";
time += now.day();
time += '/';
time += now.month();
time += '/';
time += now.year();
time += " | ";
time += now.hour();
time += ':';
time += now.minute();
time += ':';
time += now.second();
return time;
}
void Motion_Log()
{
File textFile2 = sd.open("wokwi.txt", FILE_WRITE);
if (textFile2) {
Serial.println(clock());
textFile2.println(clock());
textFile2.close();
} else
{
Serial.println("error opening wokwi.txt!");
}
File txtFile = sd.open("wokwi.txt");
if (txtFile)
{
while (txtFile.available())
{
Serial.write(txtFile.read());
}
txtFile.close();
}
}
void tippse()
{
//SD-Kärtchen
digitalWrite(sdPower,HIGH);
sd.begin(chipSelect, SPI_HALF_SPEED);
myFile.open(fileName, O_RDWR | O_CREAT | O_AT_END);
Serial.println("Hallöle");
myFile.println("Hello World");
myFile.close();
// re-open the file for reading:
if (!myFile.open(fileName, O_READ))
{
sd.errorHalt("opening test.txt for read failed");
}
// read from the file until there's nothing else in it:
int data;
while ((data = myFile.read()) >= 0) Serial.write(data);
// close the file:
myFile.close();
digitalWrite(sdPower,LOW);
delay(1000);
}
void flitzi()
{
int val = digitalRead(MOTION_PIN); // read input value
if (val == HIGH)
{ // check if the input is HIGH
if (motion_State == LOW)
{
// we have just turned on
Serial.println("Motion detected!");
Motion_Log();
// We only want to print on the output change, not state
motion_State = HIGH;
}
} else
{
if (motion_State == HIGH)
{
// we have just turned of
Serial.println("Motion ended!");
// We only want to print on the output change, not state
motion_State = LOW;
}
}
}
void dht_Sensor_Error(int chk)
{
switch (chk)
{
case DHTLIB_OK:
stat.ok++;
/* Serial.print("OK,\t"); */
break;
case DHTLIB_ERROR_CHECKSUM:
stat.crc_error++;
Serial.print("Checksum error,\t");
break;
case DHTLIB_ERROR_TIMEOUT:
stat.time_out++;
Serial.print("Time out error,\t");
break;
case DHTLIB_ERROR_CONNECT:
stat.connect++;
Serial.print("Connect error,\t");
break;
case DHTLIB_ERROR_ACK_L:
stat.ack_l++;
Serial.print("Ack Low error,\t");
break;
case DHTLIB_ERROR_ACK_H:
stat.ack_h++;
Serial.print("Ack High error,\t");
break;
default:
stat.unknown++;
Serial.print("Unknown error,\t");
break;
}
}
void display_Data(float t, float h, uint32_t start, uint32_t stop)
{
Serial.print(h, 1);
Serial.print(",\t\t");
Serial.print(t, 1);
Serial.print(",\t\t");
Serial.print(stop - start);
Serial.println();
}
void summary()
{
Serial.println("\nTOT\tOK\tCRC\tTO\tCON\tACK_L\tACK_H\tUNK");
Serial.print(stat.total);
Serial.print("\t");
Serial.print(stat.ok);
Serial.print("\t");
Serial.print(stat.crc_error);
Serial.print("\t");
Serial.print(stat.time_out);
Serial.print("\t");
Serial.print(stat.connect);
Serial.print("\t");
Serial.print(stat.ack_l);
Serial.print("\t");
Serial.print(stat.ack_h);
Serial.print("\t");
Serial.print(stat.unknown);
Serial.println("\n");
}
bool LCD_Screen_on(int aktionsKnopf, bool lcd_on)
{
if (last_Button_State != aktionsKnopf)
{
last_Button_State = aktionsKnopf;
if (aktionsKnopf == LOW)
{
lcd_on = !lcd_on;
}
}
lcd.setCursor(0, 0);
if (lcd_on) {
lcd.print("Es sind: ");
lcd.setCursor(0, 1);
lcd.print(DHT.temperature);
lcd.print(" Grad C.");
lcd.setCursor(0, 2);
lcd.print("Die Humidity ist: ");
lcd.setCursor(0, 3);
lcd.print(feucht.humidity);
lcd.print(" %");
}
else
{
lcd.clear();
}
return lcd_on;
}
void LED_range(float t, float a, float b, int LED)
{
if (a > b)
{
float c = a;
b = a;
a = c;
}
if (t > a && t <= b)
{
LED_Color(LED);
}
}
void LED_Color(int LED)
{
analogWrite(LED_PIN_GREEN, 0);
analogWrite(LED_PIN_YELLOW, 0);
analogWrite(LED_PIN_RED, 0);
analogWrite(LED, 255);
}
void LED_on(float t)
{
LED_range(t, 5, 30, LED_PIN_GREEN);
LED_range(t, -5, 5, LED_PIN_YELLOW);
LED_range(t, 30, 50, LED_PIN_YELLOW);
LED_range(t, -40, -5, LED_PIN_RED);
LED_range(t, 50, 80, LED_PIN_RED);
}
void LED_on1(float h)
{
LED_range(h, 0, 40, LED_PIN_GREEN);
LED_range(h, 40, 60, LED_PIN_YELLOW);
LED_range(h, 60, 100, LED_PIN_RED);
}
void wetter(float t, float h)
{
analogWrite(LED_PIN_GREEN, 0);
analogWrite(LED_PIN_YELLOW, 0);
analogWrite(LED_PIN_RED, 0);
if ((t>=50 && t<=80) || (t<=-40 && t<=-5) || (h>= 60 && h<=100))
{
analogWrite(LED_PIN_RED, 255);
} else if ((t>30 && t<50) || (t> -5 && t<5) || (h>= 40 && h<=60))
{
analogWrite(LED_PIN_YELLOW, 255);
} else if ((t>=5 && h<=30) || (h>= 0 && h<=40))
{
analogWrite(LED_PIN_GREEN, 255);
}
}
//The Pink Panther
/* Beep(233,250);
Beep(246,450);
Beep(30000,250);
Beep(261,250);
Beep(261,1800);
Beep(261,900);
Beep(261,450);
Beep(30000,250);
Beep(233,250);
Beep(246,450);
Beep(30000,250);
Beep(261,250);
Beep(261,1800);
Beep(261,900);
Beep(261,450);
Beep(30000,250);
Beep(246,250);
Beep(246,450);
Beep(30000,250);
Beep(246,250);
Beep(220,1800);
Beep(220,900);
Beep(220,450);
Beep(30000,250);
Beep(233,250);
Beep(246,450);
Beep(30000,250);
Beep(261,250);
Beep(261,1800);
Beep(261,900);
Beep(261,450);
Beep(30000,450);
Beep(30000,675);
Beep(261,250);
Beep(261,450);
Beep(30000,675);
Beep(293,250);
Beep(329,450);
Beep(30000,675);
Beep(261,250);
Beep(261,675);
Beep(293,250);
Beep(329,675);
Beep(493,250);
Beep(392,675);
Beep(261,250);
Beep(329,675);
Beep(392,250);
Beep(369,900);
Beep(392,150);
Beep(349,150);
Beep(329,150);
Beep(261,150);
Beep(246,150);
Beep(261,150);
Beep(261,900);
Beep(30000,787);
Beep(261,250);
Beep(261,450);
Beep(30000,675);
Beep(293,250);
Beep(329,450);
Beep(30000,675);
Beep(261,250);
Beep(261,675);
Beep(293,250);
Beep(329,675);
Beep(493,250);
Beep(392,675);
Beep(261,250);
Beep(329,675);
Beep(587,250);
Beep(554,1800);
Beep(554,900);
Beep(30000,787);
Beep(277,250);
Beep(261,250);
Beep(261,450);
Beep(30000,675);
Beep(293,250);
Beep(329,450);
Beep(30000,675);
Beep(261,250);
Beep(261,675);
Beep(293,250);
Beep(329,675);
Beep(493,250);
Beep(392,675);
Beep(261,250);
Beep(329,675);
Beep(392,250);
Beep(369,900);
Beep(392,150);
Beep(349,150);
Beep(329,150);
Beep(261,150);
Beep(246,150);
Beep(261,150);
Beep(261,900);
Beep(30000,1350);
Beep(587,675);
Beep(523,250);
Beep(392,675);
Beep(349,250);
Beep(329,675);
Beep(261,250);
Beep(369,250);
Beep(349,675);
Beep(369,250);
Beep(349,675);
Beep(369,250);
Beep(349,675);
Beep(369,250);
Beep(349,675);
Beep(329,150);
Beep(261,150);
Beep(246,150);
Beep(261,450);
Beep(261,450);
Beep(261,900);
Beep(30000,900);
Beep(329,150);
Beep(261,150);
Beep(246,150);
Beep(261,450);
Beep(261,450);
Beep(261,900);
Beep(30000,900);
Beep(329,150);
Beep(261,150);
Beep(246,150);
Beep(261,450);
Beep(261,450);
Beep(261,900); */
//Alle meine Entchen
/* tone(BUZZER_PIN, 523, 500);
delay(500);
tone(BUZZER_PIN, 587,500);
delay(500);
tone(BUZZER_PIN, 659,500);
delay(500);
tone(BUZZER_PIN, 698,500);
delay(500);
tone(BUZZER_PIN, 784,800);
delay(800);
tone(BUZZER_PIN, 784,500);
delay(500);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 784,800);
delay(800);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 876,400);
delay(400);
tone(BUZZER_PIN, 784,800);
delay(800);
tone(BUZZER_PIN, 698,400);
delay(400);
tone(BUZZER_PIN, 698,400);
delay(400);
tone(BUZZER_PIN, 698,400);
delay(400);
tone(BUZZER_PIN, 698,400);
delay(400);
tone(BUZZER_PIN, 659,700);
delay(700);
tone(BUZZER_PIN, 659,500);
delay(500);
tone(BUZZER_PIN, 587,400);
delay(400);
tone(BUZZER_PIN, 587,400);
delay(400);
tone(BUZZER_PIN, 587,400);
delay(400);
tone(BUZZER_PIN, 587,400);
delay(400);
tone(BUZZER_PIN, 523,1000);
delay(1000); */
/* tone(BUZZER_PIN, 1000, 50);
delay(200);
tone(BUZZER_PIN, 750, 50);
delay(200);
tone(BUZZER_PIN, 500, 50);
delay(200);
tone(BUZZER_PIN, 250, 50);
delay(200);
tone(BUZZER_PIN, 500, 50);
delay(200);
tone(BUZZER_PIN, 750, 50);
delay(200);
tone(BUZZER_PIN, 1000, 50);
delay(200); */
/* tone(BUZZER_PIN, 450, 50);
delay(200);
tone(BUZZER_PIN, 500, 50);
delay(200); */