Hallo,
derzeit bin ich dabei eine Outdoor Wettersensor mit BME280 und Aku Solar Betrieb zu bauen.
Aufgabe :
Ein Wemos D1 mit BME280 soll alle 30 Minuten aufwachen , allerdings zu festen Uhrzeiten ( volle Stunde / halbe Stunde) , seine Daten an einen Server senden und anschliessend wieder schlafen gehen.
Mit einer festen Zeitangabe für den Deepsleep hat das natürlich nicht geklappt, die Zeit ist ziemlich schnell weggelaufen. Also holt sich der Wemos die aktuelle Uhrzeit von der Fritzbox ( NTP) und berechnet nach getaner Arbeit seine neue Schlafzeit. Ist die kleiner als eine Minute dann wird der nächste Zyklus übersprungen. Da das Ganze mit Aku und einer Solarzelle läuft sollte natürlich nicht unnötig oft aufgeweckt werden. Die im Server gespeicherten Daten enthalten die Zeit des Servers wann Daten angekommen sind, damit ich das kontrollieren kann.
Zudem hab ich festgestellt das die berechnete Zeit gundsätzlich etwa 5% zu kurz ist deshalb gibt es eine Anpassung dazu.
Innerhab der Wohnung hat das ziemlich genau geklappt , schwankte schon mal um ein paar Sekunden. Seit das Ding draussen steht schwankt es um +-15s. Das ganze läuft jetzt seit einer Woche in der Testphase. Heute hat nun die Sonne drauf geschienen, die gemessene Temperatur war auch etwa 35 Grad. Dabei wurde dann der Wemos mehr als 1minute zu früh wieder wach, hat seine Arbeit gemacht und natürlich ist er nach etwas mehr als einer Minute erneut wieder wach geworden.
Zusammengefasst
bei 10-25 Grad scheint die Deep Sleep Zeit für 1800s innerhalb +-15s (1%) zu passen + die 5% Grund-Anpassung.
bei 35 Grad war die Sleepzeit etwa 90s zu kurz. -> 5%
ich schliesse daraus das die Frequenz Temperatur abhängig ist, macht ja auch Sinn. höhere Temperatur -> höhere Frequenz = Sleepzeit zu kürzer. Nun meiner Frage ist das im normlen Bereich ? oder habe ich ein extrem schlechtes Stück erwischt. Zudem wird er womöglich im Winter dann in eine Winterschlaf verfallen und gar nicht mehr wach werden.
Damit wäre dann mein derzeitiges Konzept Banane.
Derzeit sehe ich als Lösung
Ich müsste also das Fenster grösser machen und 2-3 Minuten Abweichung zulassen.
kürzere Schalfzeiten, kontollieren ob die Zeit zum senden erreicht ist ... Würde ich aber wegen des Akus nur ungern machen. für ganze Hardware hab ich im Sleepmodus am Aku 0,5mA gemessen. Die gesamte Wachzeit beträgt etwa 6-7s . Das sollte also eigendllich auch im Winter ganz ohne Sonne für 6-8 Wochen, auch bei kaltem Aku, reichen. Muss ich halt dann mal sehen.
Hardware Wemos D1 , BME280
Stromversorgung Aku LIPO 18650 3,7V 2500mAh
Solarzelle 6V 100mA
Laderegler TP4056 mit Unterspannungsschutz
Step Up Wandler auf 5V
Akuspannung gemessen an A0 über zus.200KOhm (Messbereich 5,2V)
Gruß Heinz
hier noch der Sketch
/* Wetterdaten mit ESP und BME 280
Hardware Wemos D1 , BME280
Stromversorgung Aku LIPO 18650 3,7V 2500mAh
Solarzelle 6V 100mA
Laderegler TP4056, Step Up Wandler auf 5V
Akuspannung gemessen an A0 über zus.200KOhm (Messbereich 5,2V)
*/
#include <ESP8266WiFi.h>
#include <time.h>
#include <BME280I2C.h>
#include <Wire.h>
const char* ssid = "xxxx";
const char* password = "xxxx";
IPAddress staticIP(192, 168, 178, 10); // eigene PI
IPAddress gateway(192, 168, 178, 1); // Fritzbox Heimnetz
IPAddress subnet(255, 255, 255, 0);
const char*host = "192.168.178.10"; //server IP
//uint16_t localPort = 4211;
uint16_t hostPort = 4210; // Host Port
float temp, hum, pres, Vcc;
unsigned long altzeit;
int devAdress = 1;
int year;
byte month, day, hour, minute, second;
const uint16_t messcycle = 1800; // Messzyklus sekunden
uint16_t sleeptime = 0; // ESP deep Sleep Zeit
//ADC_MODE(ADC_VCC);
// BME settings
BME280I2C::Settings settings(
BME280::OSR_X1,
BME280::OSR_X1,
BME280::OSR_X1,
BME280::Mode_Forced,
BME280::StandbyTime_1000ms,
BME280::Filter_Off,
BME280::SpiEnable_False,
0x77 // I2C address. I2C specific.
);
BME280I2C bme(settings);
//---------------- Setup--------------
void setup() {
Serial.begin(115200);
Serial.println("wire");
// I2C Bus starten an pin D1=SCL u pin D2=SDA
Wire.begin();
delay(200);
while (!bme.begin()) {
Serial.println(F(" Kann BME 280 Sensor nicht finden"));
// Wenn keine Verbindung möglich beenden
calcnext();
ESP_sleep();
}
conectWIFI(); // einloggen
configTime(0, 0, "192.168.178.1"); // locale Fritzbox
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1); // locale Zeit einstellen mit Sommerzeit
Serial.print("Waiting for time ");
while (!time(nullptr)) {
Serial.print(".");
delay(1000);
}
delay(1000); // warten auf NTP Zeit
}
//-------------- Loop ----------------
void loop() {
if (WiFi.status() != WL_CONNECTED) {
conectWIFI();
delay(1000);
}
// if (millis() - altzeit >= sleeptime * 1000UL) {
altzeit = millis();
readtime(); // aktuelle Zeit lesen
messen(); // Messdaten holen
sendTCP(); // daten an Server senden
calcnext(); // nexte Weckzeit berechnen
ESP_sleep(); // ESP in sleepmodus
// }
}
//================= funktions ======================
void conectWIFI() {
WiFi.persistent(false); // daten nicht in EEprom
WiFi.mode(WIFI_STA);
Serial.printf("Connecting to %s ", ssid);
WiFi.config(staticIP, gateway, subnet);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println(" connected");
Serial.print("local IP:");
Serial.println(WiFi.localIP());
}
// ---------- messen -------------------------
void messen() {
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
bme.read(pres, temp, hum, tempUnit, presUnit);
// umrechnen auf Meereshöhe Luftruck wird immer auf Meereshöhe bezogen
// vereinfachte Rechnung 12.2mbar /100m mehr
// Wohnort liegt ca. auf 150m
pres = pres + 12.2 * 150 / 100;
temp = temp - 2.2; // Temp anpassen
Vcc = analogRead(A0) / 1024.0 * 5.20;// zus. 200KOhm Messbereich jetzt 5,2V
}
// -------------- send TCP -------------------------
void sendTCP() {
Serial.printf("connecting to %s %d \n", host, hostPort);
WiFiClient client;
if (!client.connect(host, hostPort)) {
Serial.println("connection failed");
delay(5000);
return;
}
Serial.println("sending data to server");
Serial.printf("%4d;%4.2f;%4.2f;%4.2f;%4.2f\n", devAdress, temp, hum, pres, Vcc);
client.printf("%4d;%4.2f;%4.2f;%4.2f;%4.2f", devAdress, temp, hum, pres, Vcc);
Serial.println("closing connection");
client.stop();
}
// ------------------Datum und zeit auslesen
void readtime() {
time_t now = time(nullptr);
struct tm*timeinfo;
time(&now);
timeinfo = localtime(&now);
year = 1900 + timeinfo->tm_year;
month = 1 + timeinfo->tm_mon;
day = timeinfo->tm_mday;
hour = timeinfo->tm_hour;
minute = timeinfo->tm_min;
second = timeinfo->tm_sec;
// Serial.printf("%02u-%02u-%4u\n", day, month, year);
Serial.printf("%02u:%02u:%02u \n", hour, minute, second);
if (year < 2000) { // das war nix Zeit fasch
ESP.restart();
}
}
//----------------- ESP sleep
void ESP_sleep() {
delay(500);// noch warten sonst fehlen Telegramme
// anpassung der esp Frequenz +5%
sleeptime = sleeptime + sleeptime * 5 / 100;
Serial.printf("gehe schlafen für %u s Laufzeit war %lu ms\n", sleeptime, millis());
WiFi.disconnect(true);
delay(1);
WiFi.mode(WIFI_OFF);
WiFi.forceSleepBegin ();
delay(1);
ESP.deepSleep(sleeptime * 1000000, WAKE_NO_RFCAL);
delay(1);
}
//----------------- Nexte weckzeit berechnen
void calcnext() {
uint16_t actsec = 0;
actsec = minute * 60 + second;
sleeptime = messcycle - actsec % messcycle;
// sleeptime = sleeptime - millis() / 1000; // Laufzeit abziehen
if (sleeptime < 60) {
sleeptime = messcycle + sleeptime;
}
Serial.printf("akt.Sekunde %u Messcycle %u Sleeptime %u \n", actsec, messcycle, sleeptime);
}