#include <Streaming.h> // https://github.com/janelia-arduino/Streaming.git
#include <DHT.h> // https://github.com/adafruit/DHT-sensor-library
#include <LiquidCrystal_I2C.h> // https://github.com/johnrickman/LiquidCrystal_I2C
#include <RTClib.h> // https://github.com/adafruit/RTClib
#include <SD.h>
//
// defines
//
#define SHOW_FILE_CONTENT // If not commented out, then display your file content on the serial console
//
// Global constants
//
constexpr byte DHTTYPE {DHT22};
constexpr byte DHTPIN_1 {6}; // Datenleitung für den DHT-Sensor 1 (inner)
constexpr byte DHTPIN_2 {5}; // Datenleitung für den DHT-Sensor 2 (außen)
constexpr byte LEDPIN_AUFZEICHNUNG {4};
constexpr byte RELAISPIN {2};
constexpr byte SIRENPIN {9};
constexpr byte CSPIN {10};
//
// Data definitions
//
enum DHTDescription : byte { inner, outer, end };
struct DHT22Data {
float temperature;
float humidity;
};
//
// Global variables/objects
//
char filename[] {"LOGGER00.CSV"};
bool isFileReadyForOpen {false};
RTC_DS1307 rtc; // RTC Clock Object
LiquidCrystal_I2C lcd(0x27, 20, 4); // LCD I2C Adresse 0x27 für 20 Zeichen und 4 Zeilen Darstellung
DHT dht[2] {
{DHTPIN_1, DHTTYPE},
{DHTPIN_2, DHTTYPE}
}; // Zwei DHT Sensoren initialisieren 0 inner 1 outer
//
// Functions
//
bool checkFilename(SDClass card, char *filename) {
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i / 10 + '0';
filename[7] = i % 10 + '0';
if (!card.exists(filename)) {
Serial.println(filename);
return true;
break;
}
}
return false;
}
void readDHT22Data(DHT sensor, DHT22Data &data) {
data.temperature = sensor.readTemperature();
data.humidity = sensor.readHumidity();
}
void Sensor(DHT22Data data, byte sensorNum) {
const char *location[] {"Innen", "Aussen", "x"};
if (sensorNum > DHTDescription::outer) { sensorNum = DHTDescription::end; }
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("SENSOR DHT"));
lcd.print(sensorNum + 1);
lcd.print(' ');
lcd.print(location[sensorNum]);
lcd.setCursor(0, 1);
lcd.print(F("TEMP"));
lcd.setCursor(0, 2);
lcd.print(F("LUFT"));
lcd.setCursor(7, 1); // neu
lcd.print(data.temperature);
lcd.setCursor(13, 1);
lcd.print('C');
lcd.setCursor(7, 2);
lcd.print(data.humidity);
lcd.setCursor(13, 2);
lcd.print('%');
delay(1000);
lcd.clear();
}
void Zeitschaltuhr_Uhr(DateTime &time) {
char dateFormat[11] {"DD.MM.YYYY"};
char timeFormat[9] {"hh:mm:ss"};
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("ZEIT : "));
lcd.print(time.toString(timeFormat));
lcd.setCursor(0, 1);
lcd.print(F("DATUM: "));
lcd.print(time.toString(dateFormat));
delay(1000);
lcd.clear();
}
bool Zeitschaltuhr_Hum(DHT22Data *data, bool isRelaisOn) {
constexpr byte minhum_on = 30;
constexpr byte maxhum_on = 38;
if (isnan(data[DHTDescription::inner].humidity) || (isnan(data[DHTDescription::outer].humidity))) { return false; }
if (data[DHTDescription::outer].humidity > minhum_on && (data[DHTDescription::outer].humidity < maxhum_on)) {
if (!isRelaisOn) {
digitalWrite(RELAISPIN, HIGH);
isRelaisOn = true;
delay(1000);
lcd.clear();
}
} else if (isRelaisOn) {
digitalWrite(RELAISPIN, LOW);
isRelaisOn = false;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("RELAY 01"));
if (!isRelaisOn) {
lcd.setCursor(0, 2);
lcd.print(F(" >>>> AUS-HUM"));
} else {
lcd.setCursor(0, 2);
lcd.print(F(" >>>> AN-HUM"));
}
delay(1000);
lcd.clear();
return isRelaisOn;
}
bool Zeitschaltuhr_Sig(DateTime &time, bool isSignalOn) {
byte hour = time.hour();
byte minute = time.minute();
if (hour == 23 && minute == 45 && !isSignalOn) {
Serial.println(F("Sirene an SIG"));
isSignalOn = true;
digitalWrite(SIRENPIN, HIGH); // 9
lcd.setCursor(0, 0);
lcd.print(F("SIRENE EIN"));
delay(1000);
lcd.clear();
}
if (hour == 23 && minute == 46 && isSignalOn) {
Serial.println(F("Sirene aus SIG"));
isSignalOn = false;
digitalWrite(SIRENPIN, LOW);
lcd.setCursor(0, 0);
lcd.print(F("SIRENE AUS"));
delay(1000);
lcd.clear();
}
return isSignalOn;
}
void Aufzeichnung(DateTime &time, const DHT22Data *data, bool signalFlag = false, bool relaisFlag = false) {
static unsigned long counter {0};
char dateFormat[11] {"DD.MM.YYYY"};
char timeFormat[9] {"hh:mm:ss"};
File myFile;
Print &fCout {myFile};
if (isFileReadyForOpen) {
myFile = SD.open(filename, FILE_WRITE);
if (!myFile) {
Serial.println(F("error opening file"));
return;
}
}
digitalWrite(LEDPIN_AUFZEICHNUNG, HIGH);
fCout << _WIDTHZ(++counter, 10) << ' ' << time.toString(dateFormat) << ' ' << time.toString(timeFormat) << ' '
<< F("Humidity I: ") << data[DHTDescription::inner].humidity << F("% A: ")
<< data[DHTDescription::outer].humidity << F("% Signal: ");
(signalFlag == true) ? fCout << F("EIN ") : fCout << F("AUS ");
fCout << "RELAIS: ";
(relaisFlag == true) ? fCout << F("EIN ") : fCout << F("AUS ");
fCout << endl;
myFile.close();
#ifdef SHOW_FILE_CONTENT
// re-open the file for reading:
myFile = SD.open(filename);
if (myFile) {
// read from the file until there's nothing else in it:
while (myFile.available()) { Serial.write(myFile.read()); }
// close the file:
myFile.close();
Serial.println(F("---"));
} else {
// if the file didn't open, print an error:
Serial.println(F("error opening file"));
}
#endif
lcd.setCursor(0, 0);
lcd.print(F("AUFZEICHNUNG:"));
delay(1000);
lcd.clear();
digitalWrite(LEDPIN_AUFZEICHNUNG, LOW);
}
//
// Main Program
//
void setup() {
Serial.begin(9600);
pinMode(RELAISPIN, OUTPUT);
pinMode(SIRENPIN, OUTPUT);
pinMode(LEDPIN_AUFZEICHNUNG, OUTPUT);
pinMode(CSPIN, OUTPUT);
lcd.init();
lcd.backlight();
dht[DHTDescription::inner].begin(); // Sensoren starten DHT22 I
dht[DHTDescription::outer].begin(); // Sensoren starten DHT22 A
if (!rtc.begin()) {
Serial.println(F("Couldn't find RTC"));
Serial.flush();
abort();
}
Serial.println(F("KARTE SUCHEN"));
delay(1000);
if (!SD.begin(CSPIN)) {
Serial.println(F("KARTE FEHLT"));
delay(1000);
return;
}
Serial.println(F("GEFUNDEN"));
isFileReadyForOpen = checkFilename(SD, filename);
if (!isFileReadyForOpen) {
Serial.println(F("The number of 100 files has been reached. No new file has been created!"));
while (1) {}
}
rtc.adjust(DateTime(2024, 9, 14, 23, 44, 45));
}
void loop() {
static DHT22Data envData[2];
static bool stateRelais {false};
static bool stateSignal {false};
DateTime now = rtc.now();
for (byte i = DHTDescription::inner; i < DHTDescription::end; ++i) {
readDHT22Data(dht[i], envData[i]);
Sensor(envData[i], i);
}
Zeitschaltuhr_Uhr(now);
stateRelais = Zeitschaltuhr_Hum(envData, stateRelais);
stateSignal = Zeitschaltuhr_Sig(now, stateSignal);
Aufzeichnung(now, envData, stateSignal, stateRelais);
}
Signal
Speichern
Innen
Außen