Repository navigation
Expand file tree
/
Copy pathmain.cpp
More file actions
230 lines (201 loc) · 10.1 KB
/
Copy pathmain.cpp
File metadata and controls
230 lines (201 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// --- Anschlussschema für Wemos D1 Mini ---
//
// Dieses Schema zeigt, wie die Komponenten an Ihren Wemos D1 Mini angeschlossen werden.
// Beachten Sie, dass die D-Pins auf dem Wemos D1 Mini nicht direkt den GPIO-Nummern entsprechen.
//
// | Komponente | Pin der Komponente | An ESP8266 Pin (GPIO-Nummer) | Wemos D1 Mini Pin-Label |
// | :------------------- | :----------------- | :--------------------------- | :-------------------------- |
// | Alle Komponenten | VCC | 3V3 | 3V3 |
// | Alle Komponenten | GND | GND | GND |
// | | | | |
// | DHT22 Sensor | Data (Signal) | GPIO16 | D0 |
// | | | | |
// | RTC-Modul (I2C) | SDA | GPIO4 | D2 |
// | RTC-Modul (I2C) | SCL | GPIO5 | D1 |
// | | | | |
// | Micro SD-Modul | SCK | GPIO14 | D5 |
// | Micro SD-Modul | MOSI | GPIO13 | D7 |
// | Micro SD-Modul | MISO | GPIO12 | D6 |
// | Micro SD-Modul | CS | GPIO15 | D8 |
// --------------------------------------------------------------------------------------------------
#include <Wire.h> // Erforderlich für I2C-Kommunikation (RTC)
#include <SimpleDHT.h> // Bibliothek für den DHT-Sensor (SimpleDHT)
#include <RTClib.h> // Bibliothek für Real-Time Clock (RTC) Module
#include <SPI.h> // Erforderlich für SPI-Kommunikation (SD-Karte)
#include <SD.h> // Erforderlich für SD-Karten-Operationen
#include <fcntl.h> // Für FILE_APPEND Flags (benötigt für einige SD-Karten-Operationen)
// Libraries for Wi-Fi and NTP
#include <ESP8266WiFi.h> // Erforderlich für WLAN-Konnektivität
#include <NTPClient.h> // Erforderlich für NTP-Zeitabfrage
#include <WiFiUdp.h> // Erforderlich für NTPClient
#ifndef FILE_APPEND
#define FILE_APPEND (O_WRITE | O_CREAT | O_APPEND) // Definiert FILE_APPEND für SD-Karte
#endif
// --- Pin-Konfiguration ---
// DHT22 Sensor
#define DHTPIN 16 // GPIO16 (D0 auf dem Wemos D1 Mini) für den DHT22 Datenpin
// SD-Karten-Modul (SPI)
// Standard-SPI-Pins auf dem Wemos D1 Mini:
// SCK: GPIO14 (D5)
// MISO: GPIO12 (D6)
// MOSI: GPIO13 (D7)
#define SD_CS 15 // GPIO15 (D8 auf dem Wemos D1 Mini) für SD-Karten-Chip-Select
// --- WLAN-Konfiguration ---
const char* ssid = "SSID"; // <<--- CHANGE THIS TO YOUR WIFI SSID
const char* password = "PASSWORD"; // <<--- CHANGE THIS TO YOUR WIFI PASSWORD
// --- NTP Konfiguration ---
// Set UTC offset to 0 for Coordinated Universal Time (UTC)
const long utcOffsetInSeconds = 0; // Always use UTC
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds, 60000); // NTP server, UTC offset, update interval (ms)
// --- Instanzen ---
SimpleDHT22 dht22(DHTPIN); // Initialisiert den DHT22-Sensor mit der SimpleDHT-Bibliothek
RTC_DS3231 rtc; // Initialisiert das RTC-Modul
bool rtcInitialized = false; // Flag, um zu prüfen, ob RTC erfolgreich initialisiert wurde
bool wifiConnected = false; // Flag, um den WLAN-Verbindungsstatus zu verfolgen
// --- Haupt-Setup-Funktion ---
void setup() {
Serial.begin(115200); // Startet die serielle Kommunikation für Debugging
// I2C-Bus für RTC initialisieren
// Auf Wemos D1 Mini: D1 ist GPIO5 (SCL), D2 ist GPIO4 (SDA)
Wire.begin(4, 5); // SDA = GPIO4 (D2), SCL = GPIO5 (D1)
Wire.setClock(400000); // I2C-Taktfrequenz auf 400 kHz für schnellere Updates einstellen
// --- Boot-Meldungen (nur seriell) ---
Serial.println("Starting...");
delay(1000);
Serial.println("Hello, World!");
delay(2000);
// --- RTC-Initialisierung ---
Serial.println("Init RTC...");
if (!rtc.begin()) {
Serial.println("Konnte RTC nicht finden");
} else {
rtcInitialized = true;
Serial.println("RTC gefunden.");
if (rtc.lostPower()) {
Serial.println("RTC hat Strom verloren, wird die Uhrzeit aus NTP aktualisieren (UTC)!");
}
}
delay(1000); // RTC-Status für 1 Sekunde anzeigen
// --- WLAN-Verbindung herstellen ---
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) { // Try for about 10 seconds (20 * 500ms)
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
wifiConnected = true;
Serial.println("\nWiFi connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// --- NTP-Client initialisieren und Zeit synchronisieren ---
Serial.println("Synchronizing time with NTP server (UTC)...");
timeClient.begin();
if (timeClient.forceUpdate()) { // Attempt to get time immediately
unsigned long epochTime = timeClient.getEpochTime();
DateTime ntpTime(epochTime); // This is already UTC because utcOffsetInSeconds is 0
if (rtcInitialized) {
// Only update RTC if the current RTC time is significantly different or lost power
DateTime rtcNow = rtc.now(); // This is the RTC's current time, which we want to be UTC
// Check if RTC time is very old (e.g., before 2020) or differs by more than 5 minutes
// Cast to long to avoid ambiguity with abs() function
if (rtcNow.year() < 2020 || abs((long)rtcNow.unixtime() - (long)ntpTime.unixtime()) > 300) {
rtc.adjust(ntpTime); // Set RTC to the UTC time from NTP
Serial.println("RTC time updated from NTP (UTC).");
} else {
Serial.println("RTC time is accurate (UTC), no update needed from NTP.");
}
}
} else {
Serial.println("Failed to get time from NTP server.");
}
} else {
Serial.println("\nFailed to connect to WiFi.");
}
delay(1000);
// --- SD-Karten-Initialisierung ---
Serial.println("Init SD Card..."); // Prägnante Nachricht
// SPI-Bus für SD-Karte initialisieren
SPI.begin();
if (!SD.begin(SD_CS)) { // SD_CS-Definition verwenden
Serial.println("SD-Karten-Initialisierung fehlgeschlagen!");
// Hier kein Return, damit andere Teile des Setups fortgesetzt werden können, auch wenn SD fehlschlägt
} else {
Serial.println("SD-Karte initialisiert.");
// Prüfen, ob log.csv existiert, wenn nicht, erstellen und Header schreiben
if (!SD.exists("/log.csv")) {
File logFile = SD.open("/log.csv", FILE_WRITE);
if (logFile) {
logFile.println("timestamp_utc,temperature_c,humidity_pct"); // Changed header to reflect UTC
logFile.close();
Serial.println("log.csv mit Header erstellt.");
} else {
Serial.println("Fehler beim Erstellen von log.csv");
}
} else {
Serial.println("log.csv existiert bereits.");
}
}
delay(1000); // SD-Status für 1 Sekunde anzeigen
Serial.println("Setup abgeschlossen. Starte Sensor, Uhrzeit und SD-Protokollierung.");
}
// --- Haupt-Loop-Funktion ---
void loop() {
// DHT22 benötigt mindestens 2 Sekunden zwischen den Messungen (SimpleDHT empfiehlt 2.5s)
delay(2500); // Verzögerung von 2.5 Sekunden, wie von SimpleDHT für DHT22 empfohlen
float temperature = 0; // Variable zum Speichern der Temperatur
float humidity = 0; // Variable zum Speichern der Luftfeuchtigkeit
// Daten vom DHT22-Sensor lesen
int err = dht22.read2(&temperature, &humidity, NULL);
// Aktuelle Uhrzeit von der RTC abrufen
String timestamp = "No Time";
if (rtcInitialized) {
DateTime now = rtc.now(); // This will be UTC if the RTC was synced to UTC
char timeBuffer[20]; // Puffergröße für vollständige Datums-Zeit-Zeichenkette erhöht
// Format: YYYY-MM-DD HH:MM:SS
// This format will now represent UTC time.
snprintf(timeBuffer, sizeof(timeBuffer), "%04d-%02d-%02d %02d:%02d:%02d",
now.year(), now.month(), now.day(),
now.hour(), now.minute(), now.second());
timestamp = String(timeBuffer);
}
// Prüfen, ob der DHT-Lesevorgang erfolgreich war
if (err != SimpleDHTErrSuccess) {
Serial.print("Lesen des DHT22 fehlgeschlagen, Fehler=");
Serial.println(err);
return; // Den Rest der Schleife überspringen und erneut versuchen
}
// --- Daten auf SD-Karte protokollieren ---
File logFile = SD.open("/log.csv", FILE_APPEND); // File und FILE_APPEND für SD.h-Bibliothek verwenden
if (logFile) {
logFile.printf("%s,%.2f,%.2f\n", timestamp.c_str(), temperature, humidity);
logFile.close();
Serial.println("Daten auf SD-Karte protokolliert (UTC)."); // Added (UTC) for clarity
} else {
Serial.println("SD-Karten-Schreibvorgang fehlgeschlagen!");
}
// Ergebnisse auf dem seriellen Monitor ausgeben
Serial.print("Time (UTC): "); // Added (UTC) for clarity
Serial.print(timestamp);
Serial.print(" | Temp: ");
Serial.print(temperature);
Serial.print(" °C | Humidity: ");
Serial.print(humidity);
Serial.println(" %");
// Periodically update NTP time to keep the RTC accurate
if (wifiConnected) {
timeClient.update(); // Updates the NTP time if the interval has passed
DateTime ntpTime(timeClient.getEpochTime()); // This is UTC
DateTime rtcNow = rtc.now(); // This should also be UTC
// Check if RTC time significantly differs from NTP time (e.g., more than 1 minute difference)
// Cast to long to avoid ambiguity with abs() function
if (abs((long)rtcNow.unixtime() - (long)ntpTime.unixtime()) > 60) {
Serial.println("RTC time significantly drifted, updating from NTP (UTC)."); // Added (UTC) for clarity
rtc.adjust(ntpTime); // Set RTC to the UTC time from NTP
}
}
}