Hallo liebes Forum.
Aktuell habe ich das Problem das bei meiner kürzlich gebauten Wetterstation mit ESP32 und einem 4" SPI-Display mit ILI9488_DRIVER nach längerer Nutzung (Erst nach mehreren Tagen) ziemlich wilde Probleme mit der Anzeige bekomme. Meistens passiert das, wenn der ESP32 die Daten der Außenwetterstation empfängt gesendet und Empfangen wird mit einem HC-12 Modul, die Außenwetterstation läuft mit einem Attiny85. Das kuriose ist, wenn ich den ESP32 führ mehrere Sekunden vom Strom nehme und anschließend wieder einstecke verschwinden die Anzeigefehler nicht mehr. Hat da jemand eine Idee, wo noch der Wurm drinnen liegt?
Die Anzeige Fehler:
Der Code der Sendestation:
#include <Arduino.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <SoftwareSerial.h>
#include <dht22.h>
constexpr byte DHTPIN {2};
constexpr byte UNUSEDPINS[] {0, 1, 4};
SoftwareSerial hc12(4, 3); // TX = 4, RX = 3
dht22 dht;
constexpr byte WATCHDOG_WAKEUPS_TARGET {37}; // 8 * 7 = 56 seconds between each data collection
// watchdog ISR
ISR(WDT_vect)
{
// nothing to do here, just wake up
}
void enableWatchdog()
{
cli();
MCUSR &= ~(1 << WDRF);
WDTCR |= (1 << WDCE) | (1 << WDE);
WDTCR = 1 << WDP0 | 1 << WDP3;
WDTCR |= (1 << WDIE);
sei();
}
// function to go to sleep
void enterSleep(void) {
ADCSRA &= ~(1 << ADEN); // switch off ADC -320µA
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // SLEEP_MODE_PWR_DOWN for lowest power consumption.
sleep_enable();
sleep_mode();
sleep_disable();
}
void initADC0() {
// Read 1.1V reference as input with reference operating voltage vcc
// Reference Vcc and analog input = internal reference 1.1V
// Initialise ADC with REFS[2:0] is 0 = VCC as Ref, MUX[3:0] 1100 = Vbg as Input,
ADMUX = _BV(MUX3) | _BV(MUX2);
bitSet(ADCSRA, ADEN); // Enable
delay(100); // Wait until the reference has stabilized
// After activating the ADC, a "dummy readout" is recommended.
// In other words, a value is read and discarded to allow the ADC to "warm up"
ADCSRA |= _BV(ADSC); // Start conversion
while ((ADCSRA & _BV(ADSC))) { ; } // measure
(void)ADCW; // Discard dummy readout..
}
constexpr uint16_t INTERN {1120}; // determined per IC
constexpr uint32_t INTERNxRESOLUTION {INTERN * 1024UL};
float measurementVCC()
{
initADC0();
ADCSRA |= _BV(ADSC); // Start conversion
while ((ADCSRA & _BV(ADSC))) { ; } // measure
return static_cast<float>(INTERNxRESOLUTION / ADCW) / 1000;
}
void setup() {
hc12.begin(4800);
dht_init(&dht, DHTPIN);
// Set unused pins to INPUT_PULLUP to save power.
for (auto pin : UNUSEDPINS) { pinMode(pin, INPUT_PULLUP); }
// switch off ADC -320µA
ADCSRA &= ~(1 << ADEN);
delay(2000);
// enable the watchdog
enableWatchdog();
}
void loop()
{
float Temperatur;
float Luftfeuchtigkeit;
float vcc = measurementVCC();
char toSend[40]; // Increased buffer size to accommodate VCC data
if (dht_read_data(&dht, &Temperatur, &Luftfeuchtigkeit) == 1) {
char tempData[5];
char humData[5];
char vccData[5];
char trenner[] = ",";
// 4 is mininum width, 1 is precision; float value is copied onto buff
dtostrf(Temperatur, 4, 1, tempData);
dtostrf(Luftfeuchtigkeit, 2, 0, humData);
dtostrf(vcc, 1, 2, vccData); // Adjust precision as needed
strcpy(toSend, tempData);
strcat(toSend, trenner);
strcat(toSend, humData);
strcat(toSend, trenner);
strcat(toSend, vccData);
} else {
strcpy(toSend, "99.9,99,"); // Error
}
hc12.print(toSend); // Transmitting data with the HC12 transmitter
// deep sleep
for (uint8_t i = 0; i < WATCHDOG_WAKEUPS_TARGET; i++) { enterSleep(); }
}
Der Code der Basisstation:
/*****************************************************************************************
HC12 ---------------------------> G26>RX // G27>TX
RTC DS3231 ---------------------> G21>SDA // G22>SCL
TFT ILI9488 --------------------> G23>MOSI // G18>SCK // G4>RESET // G2>DC // G32>CS // G15>LED
DHT22 --------------------------> G25>DHT
BEWEGUNGSSENSOR ----------------> G12>PIR
******************************************************************************************/
#include <Wire.h>
#include "DHT.h"
#include <SoftwareSerial.h>
SoftwareSerial HC12Serial(26, 27);
#define DHTPIN 25
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#include "RTClib.h"
RTC_DS3231 rtc;
#include <TFT_eSPI.h>
#include <SPI.h>
TFT_eSPI tft = TFT_eSPI();
#include "GfxUi.h"
GfxUi ui = GfxUi(&tft);
#define AA_FONT_FONT1 "fonts/NirmalaUI-Bold-45"
#define AA_FONT_FONT2 "fonts/Calibri-Light-25"
#define AA_FONT_FONT3 "fonts/Calibri-25"
const int pirSensorPin = 33; // Pin, an dem der PIR-Sensor angeschlossen ist
const int ledPin = 15; // Pin für die LED
bool motionDetected = false;
unsigned long motionTimestamp = 0;
const unsigned long motionDuration = 15000; // 15 Sekunden
unsigned long lastSensorUpdateTime = 0;
const unsigned long sensorUpdateInterval = 120000; // 300000 = 5 minutes in milliseconds
void setup()
{
SPIFFS.begin();
HC12Serial.begin(4800);
Serial.begin(115200);
Wire.begin(SDA, SCL);
dht.begin();
rtc.begin();
pinMode(pirSensorPin, INPUT); // PIR-Sensor als Eingang konfigurieren
pinMode(ledPin, OUTPUT);
tft.init();
tft.setRotation(3
);
tft.fillScreen(TFT_WHITE);
tft.fillRect(6, 6, 468, 308, TFT_GOLD); // Darstellungsfläche
tft.fillRect(6, 102, 468, 6, TFT_WHITE); // Erster Querteiler
tft.fillRect(6, 204, 468, 6, TFT_WHITE); // Zweiter Querteiler
tft.fillRect(234, 102, 6, 234, TFT_WHITE); // Längsteiler
tft.setTextColor(TFT_BLACK);
tft.loadFont(AA_FONT_FONT3);
tft.drawString("Feuchtigkeit", 307, 123); // Außen
tft.drawString("Temperatur", 71, 123); // Außen
tft.drawString("Temperatur", 71, 225); // Innen
tft.drawString("Feuchtigkeit", 307, 225); // Innen
if (SPIFFS.exists("/bilder/OUT.jpg") == true)
ui.drawJpeg("/bilder/IN.jpg",244, 214+0); // Außen Feuchtigkeit
ui.drawJpeg("/bilder/OUT.jpg",244, 112+0); // Außen Feuchtigkeit
ui.drawJpeg("/bilder/OUT.jpg",11, 112+0); // Außen Temperatur
ui.drawJpeg("/bilder/IN.jpg",11, 212+0); // Innen Temperatur
lastSensorUpdateTime = millis(); // Initialize the update time
readAndPrintSensorData(); // Initial display of DHT sensor values
}
void loop()
{
if (HC12Serial.available())
{
String receivedData = HC12Serial.readString();
teileDaten(receivedData);
}
unsigned long currentMillis = millis();
int motionState = digitalRead(pirSensorPin); // PIR-Sensor abfragen
if (motionState == HIGH && !motionDetected)
{
digitalWrite(ledPin, HIGH); // LED einschalten // Bewegung erkannt
motionDetected = true; // Bewegung gesetzt
motionTimestamp = millis(); // Zeitstempel für die Bewegung speichern
}
if (motionDetected && (currentMillis - motionTimestamp >= motionDuration))
{
digitalWrite(ledPin, LOW); // LED ausschalten // Überprüfen, ob die Bewegungsdauer abgelaufen ist
motionDetected = false; // Zurücksetzen der Bewegungserkennung
}
if (currentMillis - lastSensorUpdateTime >= sensorUpdateInterval) // Sensordaten aktualisieren
readAndPrintSensorData(), lastSensorUpdateTime = currentMillis;
readAndPrintRTC();
}
void motionInterrupt()
{
motionDetected = true;
}
void teileDaten(String daten)
{
char *daten2 = new char[daten.length() + 1];
strcpy(daten2, daten.c_str());
char *Part0 = strtok(daten2, ","); // Für Temp
char *Part1 = strtok(NULL, ","); // Für Humidity
char *Part2 = strtok(NULL, ","); // Für VCC
// Überprüfung, ob alle Teile vorhanden sind
if (Part0 == NULL || Part1 == NULL || Part2 == NULL) {
Serial.println("Fehlerhafte Daten empfangen");
delete[] daten2;
return;
}
// Überprüfung der Temperatur auf unrealistische Werte
float tempValue = atof(Part0);
if (tempValue < -50 || tempValue > 50) {
Serial.println("Ungültige Temperatur empfangen");
delete[] daten2;
return;
}
// Überprüfung der Luftfeuchtigkeit auf unrealistische Werte
int humidityValue = atoi(Part1);
if (humidityValue < 0 || humidityValue > 100) {
Serial.println("Ungültige Luftfeuchtigkeit empfangen");
delete[] daten2;
return;
}
// Überprüfung des VCC-Werts auf unrealistische Werte
float vccValue = atof(Part2);
if (vccValue < 3 || vccValue > 5.0) {
Serial.println("Ungültiger VCC-Wert empfangen");
delete[] daten2;
return;
}
// Weitere Verarbeitung der Daten, da sie gültig sind
float maxVcc = 4.86; // Maximaler VCC-Wert
float minVcc = 3.3; // Minimaler VCC-Wert
int vccPercentage = int(((vccValue - minVcc) / (maxVcc - minVcc)) * 100); // Umrechnung des VCC-Werts in Prozent mit Berücksichtigung des Minimalwerts
vccPercentage = max(0, min(100, vccPercentage)); // Begrenzen des Prozentwert auf den Bereich von 0 bis 100
tft.loadFont(AA_FONT_FONT1);
tft.setTextColor(TFT_BLACK, TFT_WHITE);
tft.setTextPadding(tft.textWidth("88.8.88"));
String tempString = String(Part0);
if (tempString.toFloat() < 0) {
tempString = "-" + tempString.substring(1);
}
tft.drawString(tempString + " °C", 75, 157); // OUT Temp
tft.setTextPadding(tft.textWidth("888.88"));
tft.drawString(String(Part1) + " %", 327, 157); // OUT Humidity
tft.loadFont(AA_FONT_FONT2);
if (vccValue < 3.3) {
tft.setTextPadding(tft.textWidth("88888888888888."));
tft.setTextColor(TFT_BLACK, TFT_GOLD); // Text in Rot einfärben
tft.drawString("Battery is low:", 85, 70);
} else {
tft.setTextColor(TFT_BLACK, TFT_GOLD);
tft.setTextPadding(tft.textWidth("888888888888888."));
tft.drawString("Battery Voltage:", 85, 70);
}
tft.setTextColor(TFT_BLACK, TFT_GOLD);
tft.setTextPadding(tft.textWidth("8.88.8.888888"));
tft.drawString(String(Part2) + " V, " + String(vccPercentage) + "% ", 260, 70); // Beispielposition für VCC-Anzeige, anpassen nach Bedarf
tft.unloadFont();
tft.setTextPadding(0);
// Aufräumen
delete[] daten2;
}
void readAndPrintSensorData()
{
float Temperatur = dht.readTemperature();
float Luftfeuchtigkeit = dht.readHumidity();
tft.loadFont(AA_FONT_FONT1);
tft.setTextColor(TFT_BLACK, TFT_WHITE);
tft.setTextPadding(tft.textWidth("88.8.88"));
tft.drawString(String(Temperatur, 1) + " °C", 75, 265); // IN Temp
tft.setTextPadding(tft.textWidth("888.88"));
tft.drawString(String((int)Luftfeuchtigkeit) + " %", 327, 265); // IN Humidity
tft.unloadFont();
tft.setTextPadding(0);
}
void readAndPrintRTC()
{
DateTime now = rtc.now();
char dateDisplay[15];
char timeDisplay[15];
sprintf(dateDisplay, "%.1d.%.02d.%.2d", now.day(), now.month(), now.year());
if (millis() % 1000 < 500) // Uhrzeit Doppelpunkt im Sekundentakt blinken lassen
{
sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());
}
else
{
sprintf(timeDisplay, "%.02d %02d", now.hour(), now.minute());
}
tft.loadFont(AA_FONT_FONT1); // Datum
tft.setTextColor(TFT_BLACK, TFT_GOLD);
tft.setTextPadding(tft.textWidth("88.88.88"));
tft.drawString(String(dateDisplay), 200, 20);
tft.setTextColor(TFT_BLACK, TFT_GOLD);
tft.setTextPadding(tft.textWidth("88 88")); // Uhrzeit
tft.drawString(String(timeDisplay), 47, 20);
tft.unloadFont(); // Font entladen und TextPadding zurücksetzen
tft.setTextPadding(0);
}
Vielen dank für eure unterstützung