Projektvorstellung Womo-Monitor

Hallöchen zusammen,
ich weiss, ich weiss, es gibt den "Zeigt her eure geilen Projekte"-Thread. Ich möchte diesen Thread aber auch nutzen um Probleme zu diskutieren. Es gibt ja im Wohnmobilsektor alles zum kaufen was man sich vorstellt....aber die Preis sind jenseits von gut und Böse. Also was macht der geneigt Bastler: selber bauen. So kam auch dieses Projekt zustande. Erst mal zur Hardware:

  1. Herzstück ist ein Arduino Mega (vorallem wegen der seriellen Ports)
  2. Ein BME280 Sensor für Temperatur, Feuchtigkeit und Luftdruck (letzterer für die Wettervorhersage)
  3. Ein ADXL345 für die Ausrichtung des Wohnmobils
  4. Ein RTC DS3231
  5. Momentan noch 2 Nanos zur Simulation der beiden Solarladeregler
  6. Ein 7" Touchdisplay mit Shield

Künftig werden anstelle der beiden Nanos 2 Solarladeregler seriell verbunden. Die Wasserwerte und die Bordbatterie werden noch durch Zufallswerte simuliert. Bei der Bordbatteriemessung kommt ein Spannungsteiler zum Einsatz, und der Wasserstandsensor liefert bis 2.2 Volt und kann so direkt am Analogpin ausgemessen werden.

Bekannte BUGS (da bin ich noch am debuggen)

  1. Random Freezes
  2. Nach dem Neustart ist manchmal der Touchscreen noch aktiv und wechselt einfach auf die letzte gedrückte Position

Hier mal der Sketch zum ganzen Projekt (ich weiss es gibt da bestimmt Verbesserungspotential, und ich bin da auch offen für Vorschläge:

//#######################################################################
//# Wohnmobil-Monitor by Roland Kälin
//#
//# Dieses System ist ausgelegt für eine Auflösung vonn 800x480
//# Benutzt wird ein 7" Touch-Display mit einem SSD1963 Treiber
//# Touchtreiber ist ein TF5206
//#
//# Bekannte Bugs:
//# 1. Der Sketch friert manchmal ein. Ob der Watchdog das merkt wird sich zeigen
//# 2. Manchmal gibt es Random touches
//#
//#######################################################################

#define __DEBUG__
#ifdef __DEBUG__
#define DEBUG(x)  Serial.print (x)
#define DEBUGLN(x)  Serial.println (x)
#else
#define DEBUG(x)
#define DEBUGLN(x)
#endif



#include <SPI.h>
#include <Wire.h>
#include <UTFT.h>
#include <UTFT_Geometry.h>
#include <Adafruit_FT6206.h>
#include <ADXL345_WE.h> //Gyroskop Bibliothek
#include <EEPROM.h>
#include <BME280I2C.h>
#include "HardwareSerial.h"
#include "icons.h"
#include "victron.h"


// Template Funktion größten Wert aus Array ermitteln
template <typename T, size_t size> T maxRead(const T (&arr)[size]) {
  T maxValue {arr[0]};
  for (auto &value : arr) maxValue = max(maxValue, value);
  return maxValue;
}

// Template Funktion kleinsten Wert aus Array ermitteln
template <typename T, size_t size> T minRead(const T (&arr)[size]) {
  T minValue {arr[0]};
  for (auto &value : arr) minValue = min(minValue, value);
  return minValue;
}


//Display und Touch
Adafruit_FT6206 ts = Adafruit_FT6206();
#define TFT_CS 20
#define TFT_DC 21
UTFT tft(SSD1963_800, 38, 39, 40, 41); //(byte model, int RS, int WR, int CS, int RST, int SER)
UTFT_Geometry geo(&tft);
#define FT5206_WAKE 11
#define FT5206_INT   48
int displayY = tft.getDisplayXSize();
int displayX = tft.getDisplayYSize();
int splashCounter = 0;


//Schriftarten
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t arial_normal[];
extern uint8_t Inconsola[];
extern uint8_t UbuntuBold[];
extern uint8_t various_symbols[];
extern uint8_t Various_Symbols_32x32[];


//Touchscreen Offsets
int offsetX = 0;
int offsetY = 10;


//Programmversion
String Version = "1.4.2";


//Uhr
#include <RTClib.h> //Real Time Clock Bibliothek einbinden
RTC_DS1307 rtc; //Uhr benennen
#define RST_PIN -1 //Reset Pin nicht vorhanden --> also -1


//Colors
#define BLACK   0x0000
#define GREY    0x5555
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define DARKGREEN   0x05C0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define GOLD    0xDDC0
#define WHITE   0xFFFF
#define DARKGREY 0x10A2


//Temperatursensor
BME280I2C bme;
float temp(NAN), hum(NAN), pres(NAN), temp_alt, hum_alt, pres_alt;
float sealevelKorr;
float baro[100];
String tStamp[100];
int b, l1;
static uint32_t baroloop;
float maxValueb, minValueb;
long yPixel, yPixel1, yb, yb1;
int barostatus = 0;
float mosl = 867, moslEE;
float baroInterval = 0.6; //in minuten 14.4 enspricht 24 stunden - 7.2 entspricht 12 stunden - 0.6 entspricht 1 Stunde - 0.05 entspricht 5 Minuten
float hoehenkorrektur = 0;

//Uhrzeitvariablen
String Datumget;
String Uhrget;
String Tagnow;
String Wochentag;
String Datumget_alt;
String Uhrget_alt;
String Tagnow_alt;
String Wochentag_alt;
byte ControllerUhr = 0;
int tiStampMin, tiStampStd, tiStamp;

//Batterien
float Aufbaubatterie, Bordbatterie;

//Wasserstandvariablen
int Wasserstand;
float Wasser;

//Gauge Variablen
#define RED2RED 0
#define GREEN2GREEN  1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN  5
byte seg = 5; //5 // Segments are 5 degrees wide = 60 segments for 300 degrees
byte inc = 5; //10 // Draw segments every 5 degrees, increase to 10 for segmented ring


//Gyroskop
#define ADXL345_I2CADDR 0x53 // 0x1D if SDO = HIGH
ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR); //Name des Gyroskops
uint32_t runTime = -99999;       // time for next update


enum pageId {
  MENU,
  INFO,
  BATTERIE,
  WATER,
  INFO1,
  DISPLAYAUS,
  SOLAR,
  SOLAR1,
  WETTER,
  WETTERTREND,
  EINSTELL,
  EINSTELLFARBE,
  EINSTELLHOEHE,
  LEVEL,
  SPLASH,
  NEUSTART,
  TIMEOUT,
  WECHSELRICHTER,
};
unsigned int currentPage = MENU, oldPage = -1;

//Tonausgabe

int tonPin = 45;

//Solarvariablen
float SolarAmps, SolarAmps2, SolarVolts, BatAmps, BatVolts;
int SolarWatts;
String label200, label160, val200, val160;
String PID200, PID160;         //Produkt-ID
String FW200, FW160;          //Firmware Version
String SER200, SER160;         //Seriennummer
float V200, V160;          //[V]   Batteriespannung
float Ib200, Ib160;          //[mA]  Batterieladestrom
float VPV200, VPV160;        //[V] Solar-Panel Spannung
float PPV200, PPV160;        //[W] Solar-Panel Leistung
int CS200, CS160;          //Charger-Status 0=Aus, 2=Error, 3=Laden, 4=Entladen, 5=Batt V halten
String MPPT200, MPPT160;        //Unbekannter Wert
String OR200, OR160;          //Unbekannter Wert
int ERR200, ERR160;         //Error-Status 0=Kein Error, 2=Batt V zu hoch, 17=Temp zu hoch, 18=Überstrom, 19=Amp umgekehrt, 20=Ladezeitlimit abgelaufen, 21=Amp Sensor Fehler, 26=Anschlüsse überhitzt, 33=Solar V zu hoch, 34=Solar A zu hoch, 38=Input abgeschaltet, 116=WerkseinstellungenDatenVerloren, 117=Falsche Firmware, 119=Einstellungen falsch
float LOAD200, LOAD160;        //Lastausgang ON/OFF
float IL200, IL160;         //[mA] Lastausgang-Strom
float H19200, H19160;        //[kWh] Ertrag über die gesamte Lebensdauer des Gerätes
int H20200, H20160;        //[kWh] Ertrag Heute
int H21200, H21160;        //[W] Max-Leistung Heute
int H22200, H22160;        //[kWh] Ertrag Gestern
int H23200, H23160;        //[W] Max-Leistung Gestern
int HSDS200, HSDS160;            //[T] Anzahl Tage über die gesamte Lebensdauer des Gerätes
float tempfloat = 0.00;
int radius = 70;


//Einstellungen zum Nivelieren
float abwlr = 1.5; //winkelabweichung zum Keilen
float abwhv = 1.5;
float links = 0.0, rechts = 0.0, vorne = 0.0, hinten = 0.0;
float rad = 0.0174532925;

//Umrechnung RGB in 565
#define RGB565(r, g, b)    ((((r)& 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3))

//Farbeinstellungen
uint16_t Vorder, BtnTextf, Schriftf, Vorder_alt, BtnTextf_alt, Schriftf_alt;
int selRot, selGruen, selBlau, selRot_alt, selGruen_alt, selBlau_alt;
int  pixel_x_alt;    //Touch_getXY() updates global vars
int o = 0;
int n = 1;
int F = 0;
int rot, gruen, blau, fx, fy, cursx, rf, gf, bf;


//Systemreset
void(* resetFunc) (void) = 0;//declare reset function at address 0


//Bildschirm schwarz
unsigned int aus_ee;
long aus;
static uint32_t sekundenloop, timeoutloop;
int zahl[8], ki = 0, ka = 0;
int uebergabe = 0;


//Wechselrichter
bool wechselrichterStatus = false;


//Buttons
bool down = 0;
bool pressed = 0;
int ty, tx;


void setup(void)
{
  Serial.begin(9600);

  Serial1.begin(19200);
  Serial3.begin(19200);
  aus_ee = EEPROM[0];

  //Grundfarben definieren
  BtnTextf = 0xFFFF;
  Vorder = 0x0a2a;
  Schriftf = 0xf2f0;
  readeepromColor();
  fx = 100;//Position Farbbalken
  fy = 100;
  cursx = 0;

  tft.InitLCD();
  if (!ts.begin(40)) {
    DEBUGLN("Unable to start touchscreen.");
  }
  else {
    DEBUGLN("Touchscreen started.");
  }
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);
  pinMode     (FT5206_WAKE, INPUT);
  digitalWrite(FT5206_WAKE, HIGH );
  pinMode     (FT5206_INT, INPUT);
  tft.fillScr(0, 0, 0);
  tft.setFont(SmallFont);
  DEBUGLN("TFT initialized");


  //Uhr
#ifndef ESP8266 //Wenn ein ESP8266 angeschlossen ist
  while (!Serial); // auf den Seriellen Port warten. Dieser wird für natives USB benötigt
#endif
  delay(500);
  if (! rtc.begin())
  { //Wenn rtc.begin fehlschlägt
    DEBUGLN("Konnte die RTC nicht starten"); //Ausgabe auf den seriellen Monitor
    abort(); //abbrechen
  }
  delay(1000); //1 Sekunde warten
  if (! rtc.isrunning())
  { //Wenn RTC nicht läuft
    DEBUGLN("RTC läuft nicht, also müssen wir die Zeit einstellen");
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //Daten von Systemzeit holen
    // rtc.adjust(DateTime(2023, 6, 23, 18, 7, 30)); //Datum und Uhrzeit manuell eingeben (ohne anführende Nullen
  }
  // Wenn nur Zeit/Datum eingestellt werden muss
  //Serial.println("RTC läuft, aber wir müssen die Zeit einstellen");
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //Daten von Systemzeit holen
  // rtc.adjust(DateTime(2023, 6, 23, 18, 7, 30)); //Datum und Uhrzeit manuell eingeben (ohne anführende Nullen
  getUhrzeit();


  //Gyroskop abfragen
  if (!myAcc.init()) {
    DEBUGLN("ADXL345 not connected!");
  }
  //Korrekturfaktoren für das Gyroskop
  myAcc.setCorrFactors(-262.0, 279.0, -270.0, 275.0, -291.0, 214.0);

  //Gyroskop ausrichten
  delay(2000);
  myAcc.measureAngleOffsets();

  //Gyroskop Abtastrate
  myAcc.setDataRate(ADXL345_DATA_RATE_50);

  //Gyroskop Messbereich
  myAcc.setRange(ADXL345_RANGE_2G);


  // Temperatursensor starten
  while (!bme.begin())
  {
    DEBUGLN("Could not find BME280 sensor!");
    delay(1000);
  }
  switch (bme.chipModel())
  {
    case BME280::ChipModel_BME280:
      DEBUGLN("Found BME280 sensor! Success.");
      break;
    default:
      DEBUGLN("Found UNKNOWN sensor! Error!");
  }

  //Wire starten
  Wire.begin();
  Wire.setClock(400000L);

  //Wasserstand holen
  getWasser();


  currentPage = SPLASH;
  sekundenloop = millis();
  baroloop = millis();
  timeoutloop = millis();
  wechselrichterStatus = 1;
  label200 = "0";
  label160 = "0";
  b = 99;
  tx = 0;
  ty = 0;
  down = 0;
  watchdogSetup();
  DEBUGLN("Setup komplett");
}

void loop(void)
{
  //DEBUG("Timeout: ");
  //DEBUGLN((millis() / 10000) - (timeoutloop / 10000));
  if (millis() - baroloop > baroInterval * 60000)
  {
    DEBUGLN("Baroloop");
    getBaroTrend();
    baroloop = millis();
  }
  if ((millis() / 10000) - (timeoutloop / 10000)  < aus_ee)
  {
    DEBUG("Timeoutloop: ");
    DEBUGLN((millis() / 10000) - (timeoutloop / 10000));
    switch (currentPage)
    {
      case WETTERTREND:
        DEBUGLN("Case Wettertrend");
        if (currentPage != oldPage)     drawWetterTrendScreen();
        zbp(WETTER);
        hbp();
        break;

      case SPLASH:
        DEBUGLN("Case Splash");
        if (currentPage != oldPage) drawSplashScreen();
        // getSolar200();
        // getSolar160();
        splashCounter++;
        if (splashCounter == 100)
        {
          down = 0;
          currentPage = MENU;
        }
        sekundenloop = millis();
        break;

      case MENU: //Menu page
        DEBUGLN("Case Menu");
        if (currentPage != oldPage)   drawMenuScreen();
        getTouched();
        if ((down == 1) and (tx > 250 - 250) and (ty > 100 - 60) and (tx < 250 + 250 / 2) and (ty < 100 + 60 / 2))
        {
          currentPage = WATER;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 100 - 60) and (tx < 550 + 250 / 2) and (ty < 100 + 60 / 2))
        {
          currentPage = LEVEL;
          down = 0;
        }
        if ((down == 1) and (tx > 250 - 250) and (ty > 205 - 60) and (tx < 250 + 250 / 2) and (ty < 205 + 60 / 2))
        {
          currentPage = BATTERIE;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 205 - 60) and (tx < 550 + 250 / 2) and (ty < 205 + 60 / 2))
        {
          currentPage = WETTER;
          down = 0;
        }
        if ((down == 1) and (tx > 250 - 250) and (ty > 310 - 60) and (tx < 250 + 250 / 2) and (ty < 310 + 60 / 2))
        {
          currentPage = SOLAR;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 310 - 60) and (tx < 550 + 250 / 2) and (ty < 310 + 60 / 2))
        {
          currentPage = WECHSELRICHTER;
          down = 0;
        }
        ibp();
        sbp();
        abp();
        break;

      case WATER: //Wasserstand
        DEBUGLN("Case Wasser");
        if (currentPage != oldPage)   drawWaterScreen();
        updateWater();
        hbp();
        break;

      case LEVEL:
        DEBUGLN("Case Level");
        if (currentPage != oldPage)   drawLevelScreen();
        getLevel();
        hbp();
        break;

      case SOLAR: //Solar 160W
        DEBUGLN("Case Solar");
        if (currentPage != oldPage)   drawSolarScreen();
        hbp();
        vbp(SOLAR1);
        break;

      case SOLAR1: //Solar 200 W
        DEBUGLN("Case Solar1");
        if (currentPage != oldPage)   drawSolar1Screen();
        updateSolarWerte();
        hbp();
        zbp(SOLAR);
        break;

      case WETTER:
        DEBUGLN("Case Wetter");
        if (currentPage != oldPage)
        {
          getTemperatur();
          getUhrzeit();
          drawWetterScreen();
        }
        updateUhrzeit();
        updateTemperatur();
        hbp();

        vbp(WETTERTREND);
        break;

      case INFO:
        DEBUGLN("Case Info");
        if (currentPage != oldPage) drawInfoScreen();
        if (down == 1)
        {
          currentPage = MENU;
          down = 0;
        }
        break;

      case EINSTELL:
        DEBUGLN("Case Einstell");
        //DEBUG("Down: ");
        //DEBUGLN(down);
        if (currentPage != oldPage) drawEinstellScreen();
        if ((down == 1) and (tx > 250 - 250) and (ty > 100 - 60) and (tx < 250 + 250 / 2) and (ty < 100 + 60 / 2))
        {
          currentPage = NEUSTART;
          down = 0;
        }
        if ((down == 1) and (tx > 250 - 250) and (ty > 205 - 60) and (tx < 250 + 250 / 2) and (ty < 205 + 60 / 2))
        {
          currentPage = TIMEOUT;
          down = 0;
        }
        if ((down == 1) and (tx > 250 - 250) and (ty > 310 - 60) and (tx < 250 + 250 / 2) and (ty < 310 + 60 / 2))
        {
          currentPage = EINSTELLFARBE;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 100 - 60) and (tx < 550 + 250 / 2) and (ty < 100 + 60 / 2))
        {
          currentPage = EINSTELLHOEHE;
          down = 0;
        }
        hbp();
        break;

      case EINSTELLFARBE:
        DEBUGLN("Case Einstellfarbe");
        if (currentPage != oldPage) drawEinstellFarbeScreen();
        Farbenwahl();
        zbp(EINSTELL);
        hbp();
        break;

      case EINSTELLHOEHE:
        DEBUGLN("Case Einstellhoehe");
        if (currentPage != oldPage) drawEinstellHoeheScreen();
        Hoehenwahl();
        zbp(EINSTELL);
        hbp();
        break;

      case BATTERIE:
        DEBUGLN("Case Batterie");
        if (currentPage != oldPage)   drawBatterieScreen();
        updateBatterie();
        hbp();
        break;

      case NEUSTART: //System zurücksetzen
        DEBUG("Case Neustart");
        if (currentPage != oldPage)   drawResetScreen();
        if ((down == 1) and (tx > 140) and (ty > displayY - 42) and (tx < 260) and (ty < displayY - 2))
        {
          down = 0;
          resetFunc();
        }
        if ((down == 1) and (tx > 560) and (ty > displayY - 42) and (tx < 680) and (ty < displayY - 2))
        {
          currentPage = EINSTELL;
          down = 0;
        }
        break;

      case DISPLAYAUS:
        DEBUG("Case Displayaus");
        if (currentPage != oldPage)drawDisplayAusScreen();
        tx = 0;
        ty = 0;
        if (ts.touched())
        {
          digitalWrite(8, HIGH);
          down = 0;
          delay(500);
        }
        break;

      case TIMEOUT:
        DEBUG("Case Timeout");
        if (currentPage != oldPage)drawTimeoutScreen();
        tft.setColor(Schriftf);
        tft.setBackColor(0x0000);
        tft.setFont(BigFont);
        if ((down == 1) and (tx > 480) and (ty > displayY - 42) and (tx < 600) and (ty < displayY - 2))
        {
          down = 0;
          if (aus_ee < 60)
          {
            tft.print("   ", 350, 70);
            tft.print("                                     ", 20, 90);
          }
          aus_ee = aus_ee + 1;
          tft.printNumI(aus_ee * 10, 350, 70);
          if (aus_ee >= 60)
          {
            aus_ee = 60;
            tft.print("Mehr als 10 Minuten macht keinen Sinn", 20, 90);
            tft.print(aus_ee * 10, 350, 70);
          }
          delay(300);
        }

        if ((down == 1) and (tx > 200) and (ty > displayY - 42) and (tx < 320) and (ty < displayY - 2))
        {
          down = 0;
          if (aus_ee > 0)
          {
            tft.print("   ", 350, 70);
            tft.print("                                     ", 20, 90);
          }
          aus_ee = aus_ee - 1;
          tft.printNumI(aus_ee * 10, 350, 70);
          if (aus_ee  <= 12)
          {
            aus_ee = 12;
            tft.print("Weniger als 2 Minuten ist nicht erlaubt", 20, 90);
            tft.printNumI(aus_ee * 10, 350, 70);
          }
          delay(300);
        }

        if ((down == 1) and (tx > 340) and (ty > displayY - 42) and (tx < 460) and (ty < displayY - 2))
        {
          down = 0;
          EEPROM.update(0, aus_ee);
          delay(10);
          currentPage = EINSTELL;
        }
        hbp();
        break;

      case WECHSELRICHTER:
        DEBUGLN("Case Wechselrichter");
        if (currentPage != oldPage)drawWechselrichterScreen();
        getTouched();
        if ((down == 1) and (tx > 540) and (ty > 230) and (tx < 660) and (ty < 270))
        {
          if (wechselrichterStatus == 0)
          {
            wechselrichterStatus = 1;
            drawSwitch(50, 100, 300, 20, Vorder, wechselrichterStatus);
            pressed = 0;
          }
        }

        if ((down == 1) and (tx > 140) and (ty > 230) and (tx < 260) and (ty < 270))
        {
          if ((wechselrichterStatus == 1))
          {
            wechselrichterStatus = 0;
            drawSwitch(50, 100, 300, 20, Vorder, wechselrichterStatus);
            pressed = 0;
          }
        }
        hbp();
        break;
    }
    if (oldPage == currentPage)
    {
      getTouched();
      if (down == 1 and digitalRead(8) == LOW)
      {
        DEBUGLN("Dsiplay ist aus und wartet auf touch");
        timeoutloop = millis();
        down = 0;
        digitalWrite(8, HIGH);
        delay(500);
      }
    }
  }
  else if (((millis() / 10000) - (timeoutloop / 10000)  > aus_ee - 1) and (digitalRead(8) == HIGH))
  {
    DEBUGLN("Dsiplay wird ausgeschalten durch timer");
    down = 0;
    digitalWrite(8, LOW);
  }
  else if (((millis() / 10000) - (timeoutloop / 10000)  > aus_ee - 1) and (digitalRead(8) == LOW))
  {
    DEBUGLN("Display wurde ausgeschalten durch timer und wartet auf touch");
    DEBUG("Timeoutloop Display ist aus: ");
    DEBUGLN((millis() / 10000) - (timeoutloop / 10000));
    DEBUG("CurrentPage: ");
    DEBUGLN(currentPage);

    if (ts.touched() and digitalRead(8) == LOW)
    {
      timeoutloop = millis();
      down = 0;
      digitalWrite(8, HIGH);
      delay(500);
    }
  }
  asm("WDR");
  //DEBUGLN("Watchdog Reset");
}


/************************************************************************************
  Screens gestalten
************************************************************************************/
void drawWechselrichterScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Wechselrichter",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  drawSwitch(50, 100, 300, 20, Vorder, wechselrichterStatus);
  tft.setColor(Schriftf);
  tft.print("Aus", 0, 100 - tft.getFontYsize() / 2);
  tft.print("Ein", 355, 100 - tft.getFontYsize() / 2);
  Button(600, 250, 120, 40, Vorder, BtnTextf, "AN", UbuntuBold);
  Button(200, 250, 120, 40, Vorder, BtnTextf, "AUS", UbuntuBold);
  showHome();
  oldPage = currentPage;
}


void drawSplashScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Vorder);
  tft.drawBitmap(displayX / 2 - 250, displayY / 2 - 65, 250, 65, rimor, 2);
  oldPage = currentPage;
}


void drawTimeoutScreen()
{
  down = 0;
  aus_ee = EEPROM[0];
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Timeout fur das Display",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  tft.print ("Timeout in Sekunden: ", 20, 70);
  tft.printNumI(aus_ee * 10, 350, 70);
  Button(260, displayY - 22, 120, 40, Vorder, BtnTextf, "-10", UbuntuBold);
  Button(540, displayY - 22, 120, 40, Vorder, BtnTextf, "+10", UbuntuBold);
  Button(displayX / 2, displayY - 22, 120, 40, Vorder, BtnTextf, "OK", UbuntuBold);
  showHome();
  oldPage = currentPage;
}


void drawDisplayAusScreen()
{
  down = 0;
  digitalWrite(8, LOW);
  oldPage = currentPage;
}


void drawMenuScreen()
{
  down = 0;
  tx = 0;
  ty = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Womo - Monitor",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  // Button
  tft.setColor(Vorder);
  Button(250, 100, 250, 60, Vorder, BtnTextf, "Wasser", UbuntuBold);
  Button(550, 100, 250, 60, Vorder, BtnTextf, "Level", UbuntuBold);
  Button(250, 205, 250, 60, Vorder, BtnTextf, "Batterie", UbuntuBold);
  Button(550, 205, 250, 60, Vorder, BtnTextf, "Wetter", UbuntuBold);
  Button(250, 310, 250, 60, Vorder, BtnTextf, "Solar", UbuntuBold);
  Button(550, 310, 250, 60, Vorder, BtnTextf, "Strom", UbuntuBold);
  showInfo();
  showSet();
  showAus();
  oldPage = currentPage;
}


void drawBatterieScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Ladezustand Batterien",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  updateBatterie();
  showHome();
  oldPage = currentPage;
}


void drawSolarScreen()//Solar gesamt
{
  radius = 120;
  down = 0;
  for (int r = 0; r < 10; r++)
  {
    getSolar200();
    getSolar160();
  }
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Solarleistung gesamt",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);

  //Volts
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  String bText = String((VPV200 + VPV160) / 2);
  int laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, displayX / 4 - laengeText - 50, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("V", displayX / 4 + laengeText - 50, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter((VPV200 + VPV160) / 2, 12, 45, displayX / 4 - radius - 50, displayY / 2 - radius, radius, RED2GREEN  );

  //Amps
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  bText = String((PPV200 + PPV160) / (VPV200 + VPV160) / 2);
  laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, displayX / 2 - laengeText, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("A", displayX / 2 + laengeText, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter((PPV200 + PPV160) / (VPV200 + VPV160) / 2, 0, 20, displayX / 2 - radius, displayY / 2 - radius, radius, RED2GREEN  );

  //Watts
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  bText = String((PPV200 + PPV160), 0);
  laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, displayX / 4 * 3 - laengeText + 50, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("W", displayX / 4 * 3 + laengeText + 50, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter(PPV200 + PPV160, 1, 360, displayX / 4 * 3 - radius + 50, displayY / 2 - radius, radius, RED2GREEN  );

  showHome();
  showVor();
  oldPage = currentPage;
}


void drawSolar1Screen()
{
  down = 0;
  getSolar200();
  getSolar160();
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Solarwerte",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  tft.print("Bat. Spannung: ", 20, 50);
  tft.printNumF(V200, 2, 360, 50);
  tft.print(" V", 470, 50);
  tft.print("Ladestrom: ", 20, 100);
  tft.printNumF(Ib200 + Ib160, 2, 360, 100);
  tft.print(" A", 470, 100);
  tft.print("Tot. Ertrag: ", 20, 150);
  tft.printNumF(H19200 + H19160, 2, 360, 150);
  tft.print(" kWh", 470, 150);
  tft.print("Ertrag heute: ", 20, 200);
  tft.printNumF(H20200 + H20160, 2, 360, 200);
  tft.print(" Wh", 470, 200);
  tft.print("max Leistung heute: ", 20, 250);
  tft.printNumF(H21200 + H21160, 2, 360, 250);
  tft.print(" W", 470, 250);
  tft.print("Ertrag gestern: ", 20, 300);
  tft.printNumF(H22200 + H22160, 2, 360, 300);
  tft.print(" Wh", 470, 300);
  tft.print("max Leistung gestern: ", 20, 350);
  tft.printNumF(H23200 + H23160, 2, 360, 350);
  tft.print(" W", 470, 350);
  showHome();
  showVor();
  showZuruck();
  oldPage = currentPage;
}


void drawWaterScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Frischwasser",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  randomSeed(millis());
  Wasserstand = random(0, 220);
  getWasser();
  showHome();
  oldPage = currentPage;
}


void drawLevelScreen()
{
  down = 0;
  tft.fillScr(0x0000);
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Nivelierung",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  getLevel();
  tft.setColor(WHITE);
  tft.drawRect(10, 100, 70, 120);
  tft.drawRect(10, 250, 70, 270);
  tft.drawRect(300, 100, 360, 120);
  tft.drawRect(300, 250, 360, 270);
  tft.drawLine(40, 120, 40, 175);
  tft.drawLine(40, 195, 40, 250);
  tft.drawCircle(40, 185, 10);
  tft.drawLine(330, 120, 330, 250);
  tft.drawLine(50, 185, 330, 185);
  showHome();
  oldPage = currentPage;
}


void drawInfoScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Informationen",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  tft.print("Dieses System wurde in muhevoller", 25, 80);
  tft.fillRect(412, 80, 414, 82);
  tft.fillRect(418, 80, 420, 82);
  tft.print("Kleinstarbeit und mit viel Zeit", 25, 105);
  tft.print("von Roland zusammengekloppelt.", 25, 130);
  tft.fillRect(396, 130, 398, 132);
  tft.fillRect(402, 130, 404, 132);
  tft.print("Bei Fragen gerne melden.", 25, 155);
  tft.print("Tel: +41 79 XXX XX XX", 25, 205);
  tft.print("email: rxxxxxxxxx@gmail.com", 25, 230);
  tft.print("Programmversion: ", 25, 280);
  tft.print(Version, 300, 280);
  down = 0;
  oldPage = currentPage;
}


void drawEinstellScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Einstellungen",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  Button(250, 100, 250, 60, Vorder, BtnTextf, "Neustart", UbuntuBold);
  Button(250, 205, 250, 60, Vorder, BtnTextf, "Display", UbuntuBold);
  Button(250, 310, 250, 60, Vorder, BtnTextf, "Farben", UbuntuBold);
  Button(550, 100, 250, 60, Vorder, BtnTextf, "Hoehe", UbuntuBold);
  showHome();
  oldPage = currentPage;
}


void drawEinstellFarbeScreen()
{
  down = 0;
  tft.clrScr();
  Button(50, fy + 25, 50, 50, Vorder, BtnTextf, "-", UbuntuBold);
  Button(406, fy + 25, 50, 50, Vorder, BtnTextf, "+", UbuntuBold);
  Button(50, fy + 125, 50, 50, Vorder, BtnTextf, "-", UbuntuBold);
  Button(406, fy + 125, 50, 50, Vorder, BtnTextf, "+", UbuntuBold);
  Button(50, fy + 225, 50, 50, Vorder, BtnTextf, "-", UbuntuBold);
  Button(406, fy + 225, 50, 50, Vorder, BtnTextf, "+", UbuntuBold);
  Button(650, fy + 25, 250, 50, Vorder, BtnTextf, "Hauptfarbe", UbuntuBold);
  Button(650, fy + 125, 250, 50, Vorder, BtnTextf, "Textfarbe", UbuntuBold);
  Button(650, fy + 325, 250, 50, Vorder, BtnTextf, "Reset", UbuntuBold);
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.setColor(Schriftf);
  tft.drawRoundRect(525, fy + 200, 775, fy + 250);
  tft.print("Farbeinstellungen",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  farben();
  showHome();
  showZuruck();
  oldPage = currentPage;
}


void drawEinstellHoeheScreen()
{
  moslEE = EEPROM.read(10);
  if (EEPROM.read(9) > 0)
  {
    mosl = moslEE * 20 + 10;
  }
  else
  {
    mosl = moslEE * 20;
  }
  down = 0;
  tft.clrScr();
  Button(50, 125, 50, 50, Vorder, BtnTextf, "-", UbuntuBold);
  Button(406, 125, 50, 50, Vorder, BtnTextf, "+", UbuntuBold);
  Button(650, 125, 250, 50, Vorder, BtnTextf, "Speichern", UbuntuBold);
  tft.setFont(UbuntuBold);
  tft.setColor(Schriftf);
  String bText = String (mosl, 0);
  bText = " " + bText + " m.u.M.";
  int laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, 225 - laengeText, 100 + tft.getFontYsize() / 2);
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.setColor(Schriftf);
  tft.print("Hoeheneinstellung",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  showHome();
  showZuruck();
  oldPage = currentPage;
}


void drawWetterScreen()
{
  down = 0;
  tft.clrScr();
  tft.setFont(BigFont);
  tft.print("Heute ist: ", 50, 50);
  tft.print(Wochentag, 330, 50);
  tft.print(Datumget, 330, 75);
  tft.print(Uhrget, 330, 100);
  Uhrget_alt = Uhrget;
  Datumget_alt = Datumget;
  Tagnow_alt = Tagnow;
  tft.setFont(BigFont);
  tft.print("Temperatur:          ", 50, 150);
  tft.printNumF(temp, 1, 361, 150);
  tft.print(" C ", 440, 150);
  tft.print("Luftfeuchtigkeit:    ", 50, 175);
  tft.printNumF(hum, 1, 361, 175);
  tft.print(" % ", 440, 175);
  tft.print("Luftdruck: ", 50, 200);
  tft.printNumF(pres / 100 + sealevelKorr +  hoehenkorrektur, 2, 329, 200);
  tft.print(" hpa ", 440, 200);
  //DEBUG("Press Sealevel: ");
  //DEBUGLN(pres / 100 +  hoehenkorrektur + sealevelKorr);
  //DEBUG("Press: ");
  //DEBUGLN(pres / 100 +  hoehenkorrektur);
  if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 75 and (pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 105)
  {
    tft.print("Tendenz: Regen", 50, 250);
  }
  else if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 106 and (pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 112)
  {
    tft.print("Tendenz: Wechselhaft", 50, 250);
  }
  else if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 113 and (pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 129)
  {
    tft.print("Tendenz: Schoen", 50, 250);
  }
  else if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 130)
  {

    tft.print("Tendenz: Trocken", 50, 250);
  }
  showHome();
  showVor();
  oldPage = currentPage;
}


////////////////////////////////////////////////////////////////////
//WetterTrend
////////////////////////////////////////////////////////////////////
void drawWetterTrendScreen()
{
  down = 0;
  for (int l1 = 0; l1 < (sizeof(baro) / sizeof(baro[0])); l1++)
  {
    maxValueb = maxRead(baro);
    minValueb = minRead(baro);
  }
  tft.clrScr();
  tft.setColor(Vorder);
  tft.setFont(SmallFont);
  tft.drawLine(59, 50, 59, 350);
  tft.drawLine(59, 350, 761, 350);
  tft.printNumF(maxValueb / 1, 2, 0, 50 - (tft.getFontYsize() / 2));
  tft.printNumF(minValueb / 1, 2, 0, 350 - (tft.getFontYsize() / 2));
  int calc = 0;
  //DEBUG("Timestamp: ");
  //DEBUGLN(tiStamp);
  DateTime now = rtc.now(); //Daten auslesen
  tiStampStd = now.hour();
  tiStampMin = now.minute();
  tiStamp = tiStampStd * 60 + tiStampMin + (11 * baroInterval);
  for (int posi = 10; posi >= 1; posi--)
  {
    if ((tiStamp -  10 * baroInterval) < 60) tiStamp = tiStamp + 1440;
    tiStamp = tiStamp -  11 * baroInterval;
    //DEBUG("TimeSchtamp: ");
    //DEBUGLN(tiStamp);
    //DEBUG("Calc: ");
    //DEBUGLN(calc);
    tiStampStd = tiStamp / 60;
    tiStampMin = tiStamp - (tiStampStd * 60);
    //DEBUG("Std: ");
    //DEBUGLN(tiStampStd);
    String Std, Min, Stempel;
    if (tiStampStd < 10)
    {
      Std = String(tiStampStd);
      Std = "0" + Std;
    }
    else if (tiStampStd == 24)
    {
      Std = "00";
    }
    else
    {
      Std = String(tiStampStd);
    }
    if (tiStampMin < 10)
    {
      Min = String(tiStampMin);
      Min = "0" + Min;
    }
    else
    {
      Min = String(tiStampMin);
    }
    Stempel = (Std + ":" + Min);
    tft.print(Stempel, (59 - tft.getFontYsize() / 2) + (posi - 1) * 77, 400, 270);
    //DEBUG("Timestamp: ");
    //DEBUG(tiStampStd);
    //DEBUG(" : ");
    //DEBUGLN(tiStampMin);

    calc++;
  }
  l1 = 0;
  while (l1 < 99)
  {
    yb = baro[l1];
    yPixel = map(yb, minValueb, maxValueb, 349, 50);
    yb1 = baro[l1 + 1];
    yPixel1 = map(yb1, minValueb, maxValueb, 349, 50);
    tft.setColor(Schriftf);
    tft.drawLine(l1 * 7 + 60, yPixel, l1 * 7 + 67, yPixel1);
    l1++;
  }
  showHome();
  showZuruck();
  oldPage = currentPage;
}


void drawResetScreen()
{
  down = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Neustart",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  tft.setFont(BigFont);
  tft.print("Bei einem Neustart des Systems", 25, 70);
  tft.print("werden alle Parameter neu geladen.", 25, 95);
  tft.print("Das Fahrzeug muss dabei ganz", 25, 120);
  tft.print("gerade stehen, da der Niveausensor", 25, 145);
  tft.print("dabei neu kalibriert wird.", 25, 170);
  tft.print("Neu starten ? ", 25, 220);
  Button(200, displayY - 42, 120, 40, Vorder, BtnTextf, "JA", UbuntuBold);
  Button(600, displayY - 42, 120, 40, Vorder, BtnTextf, "NEIN", UbuntuBold);
  oldPage = currentPage;
}


/************************************************************************************
  Zusätzliche Funktionen
*************************************************************************************/

//#######################################################
//Fest platzierte Buttons
//#######################################################
void showHome()//Home Button anzeigen
{
  Button(70, displayY - 22, 120, 40, Vorder, WHITE, "Home", UbuntuBold);
}


void hbp() //home Button pressed
{
  getTouched();
  if (down == 1)
  {
    if ((tx > 10) and (ty > displayY - 42) and (tx < 130) and (ty < displayY - 2))
    {
      currentPage = MENU;
      down = 0;
    }
  }
}


void showVor()//Vorwärts Button anzeigen
{
  Button(465, displayY - 22, 120, 40, Vorder, WHITE, "S", Various_Symbols_32x32);
}


void vbp(unsigned int Page) //Vorwärts Button gedrückt
{
  getTouched();
  if (down == 1)
  {
    if ((tx > 405) and (ty > displayY - 42) and (tx < 525) and (ty < displayY - 2))
    {
      currentPage = Page;
      down = 0;
    }
  }
}

void showZuruck()//Zurück Button anzeigen
{
  Button(335, displayY - 22, 120, 40, Vorder, WHITE, "R", Various_Symbols_32x32);
}


void zbp(unsigned int Page) //Zurück Button pressed
{
  getTouched();
  if (down == 1)
  {
    if ((tx > 275) and (ty > displayY - 42) and (tx < 355) and (ty < displayY - 2))
    {
      currentPage = Page;
      down = 0;
    }
  }
}

void showAus() //Display aus
{
  Button(displayX - 26, displayY - 27, 50, 50, Vorder, BtnTextf, "l", Various_Symbols_32x32);
}

void abp() //Info Button gedrückt
{
  getTouched();
  if (down == 1)
  {
    if ((tx < displayX - 1) and (ty > displayY - 42) and (tx > displayX - 51) and (ty < displayY - 2))
    {
      down = 0;
      digitalWrite(8, LOW);
      delay(500);
      timeoutloop = millis();
    }
  }
}

void showInfo()//info Button anzeigen
{
  Button(displayX - 26, 26, 50, 50, Vorder, WHITE , "i", UbuntuBold);
}


void ibp() //Info Button gedrückt
{
  getTouched();
  if (down == 1)
  {
    if ((tx < displayX - 1) and (ty > 1) and (tx > displayX - 51) and (ty < 51))
    {
      currentPage = INFO;
      down = 0;
    }
  }
}

void showSet()//Settings Button anzeigen
{
  Button(displayX - 86, 26, 50, 50, Vorder, WHITE, "s", Various_Symbols_32x32);
}


void sbp() //Settings Button gedrückt
{
  getTouched();
  if (down == 1)
  {
    if ((tx < displayX - 61) and (ty > 1) and (tx > displayX - 101) and (ty < 51))
    {
      currentPage = EINSTELL;
      down = 0;
    }
  }
}


//##############################################
//#Uhrzeit auslesen
//##############################################
void getUhrzeit()
{
  vbp(WETTERTREND);
  hbp();
  DateTime now = rtc.now(); //Daten auslesen
  char buf1[] = " DDD"; //Wochentag in buf2[] schreiben
  Tagnow = (now.toString(buf1)); //Wochentag als String übergeben an tagnow
  //Überprüfung welcher Wochentag ist, und diesen dann ausgeschrieben an Display senden mit Zeilenumbruch
  if (Tagnow == " Sam") Wochentag = "Samstag";
  else if (Tagnow == " Son") Wochentag = "Sonntag";
  else if (Tagnow == " Mon") Wochentag = "Montag ";
  else if (Tagnow == " Die") Wochentag = "Dienstag";
  else if (Tagnow == " Mit") Wochentag = "Mittwoch";
  else if (Tagnow == " Don") Wochentag = "Donnerstag";
  else if (Tagnow == " Fre") Wochentag = "Freitag   ";
  //Überprüfung fertig
  char buf2[] = "DD.MM.YYYY";
  Datumget = (now.toString(buf2));
  char buf3[] = "hh:mm";
  Uhrget = (now.toString(buf3)); //Aktuelle Uhrzeit in oledreset schreiben
  DEBUG("tiStamp: ");
  DEBUGLN(tiStamp);
}


//##############################################
//#Uhrzeit aktualisieren
//##############################################
void updateUhrzeit()
{
  getUhrzeit();
  if (Uhrget != Uhrget_alt or Datumget != Datumget_alt or Tagnow != Tagnow_alt)
  {
    tft.setFont(BigFont);
    tft.print(Wochentag, 330, 50);
    tft.print(Datumget, 330, 75);
    tft.print(Uhrget, 330, 100);
    Uhrget_alt = Uhrget;
    Datumget_alt = Datumget;
    Tagnow_alt = Tagnow;
  }
}


//##############################################
//#Temperatursensor auswerten
//##############################################
void getTemperatur()
{
  BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
  BME280::PresUnit presUnit(BME280::PresUnit_Pa);
  bme.read(pres, temp, hum, tempUnit, presUnit);
  sealevelKorr = (1013.25 * pow((1 - 6.5 * mosl / (288150)), 5.255));
  sealevelKorr = 1013.25 - sealevelKorr;

}

//##############################################
//#Temperatursensor updaten
//##############################################
void updateTemperatur()
{
  getTemperatur();
  tft.setFont(BigFont);
  if (pres != pres_alt)
  {
    tft.printNumF(pres / 100 + sealevelKorr +  hoehenkorrektur, 2, 329, 200);
    // tft.print("hpa", 440, 200);
    pres_alt = pres / 100 + sealevelKorr +  hoehenkorrektur;
  }
  if ((temp) != (temp_alt, 0))
  {
    tft.printNumF(temp, 1, 361, 150);
    temp_alt = (temp);
  }
  if ((hum, 0) / 100 != (hum_alt, 0))
  {
    tft.printNumF(hum, 1, 361, 175);
    tft.print("Luftdruck : ", 50, 200);
    hum_alt = (hum, 0) / 100;
  }
  if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 74)
  {
    tft.print("Tendenz : Sturm", 50, 250);
  }
  if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 75 and (pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 105)
  {
    tft.print("Tendenz : Regen", 50, 250);
  }
  if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 106 and (pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 112)
  {
    tft.print("Tendenz : Wechselhaft", 50, 250);
  }
  if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 113 and (pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) <= 129)
  {
    tft.print("Tendenz : Schoen", 50, 250);
  }
  if ((pres / 100 +  hoehenkorrektur + sealevelKorr) - (pres / 100 - hoehenkorrektur) >= 130)
  {
    tft.print("Tendenz : Trocken", 50, 250);
  }
}


//##############################################
//#Vorläufige Werte für diverse Sensoren
//##############################################

void getWasser()
{
  Wasserstand = (Wasserstand / 100 * 45.45);
}

void updateWater()
{
  if (Wasserstand < 100)
  {
    Wasserstand++;
    int radius = 180;
    ringMeter(Wasserstand, 0, 100,  displayX / 2 - radius,  displayY / 2 - radius, radius, 5);
    tft.setFont(UbuntuBold);
    tft.setColor(Schriftf);
    String Wasser = String(Wasserstand);
    int laengeText = (Wasser.length() * tft.getFontXsize() / 2);
    tft.print(Wasser, displayX / 2 - laengeText , displayY / 2 - tft.getFontYsize() / 2);
    tft.print("% ", displayX / 2 + laengeText, displayY / 2 - tft.getFontYsize() / 2);
  }
}


void getBordbatterie()
{
  randomSeed(millis());
  Bordbatterie = random(1200, 1400);
}


//#######################################################
//Ringmeter
//#######################################################

int ringMeter(int value, int vmin, int vmax, int x, int y, int r, byte scheme)
{
  x += r; y += r;   // Calculate coords of centre of ring
  int w = r / 4;    // Width of outer ring is 1/4 of radius
  int angle = 150;  // Half the sweep angle of meter (300 degrees)
  int text_colour = 0; // To hold the text colour
  int v = map(value, vmin, vmax, -angle, angle); // Map the value to an angle v

  // Draw colour blocks every inc degrees
  for (int i = -angle; i < angle; i += inc) {

    // Choose colour from scheme
    int colour = 0;
    switch (scheme) {
      case 0: colour = RED; break; // Fixed colour
      case 1: colour = GREEN; break; // Fixed colour
      case 2: colour = BLUE; break; // Fixed colour
      case 3: colour = rainbow(map(i, -angle, angle, 0, 127)); break; // Full spectrum blue to red
      case 4: colour = rainbow(map(i, -angle, angle, 63, 127)); break; // 0x07e0  to red (high temperature etc)
      case 5: colour = rainbow(map(i, -angle, angle, 127, 63)); break; // Red to 0x07e0  (low battery etc)
      default: colour = BLUE; break; // Fixed colour
    }

    // Calculate pair of coordinates for segment start
    float sx = cos((i - 90) * 0.0174532925);
    float sy = sin((i - 90) * 0.0174532925);
    uint16_t x0 = sx * (r - w) + x;
    uint16_t y0 = sy * (r - w) + y;
    uint16_t x1 = sx * r + x;
    uint16_t y1 = sy * r + y;

    // Calculate pair of coordinates for segment end
    float sx2 = cos((i + seg - 90) * 0.0174532925);
    float sy2 = sin((i + seg - 90) * 0.0174532925);
    int x2 = sx2 * (r - w) + x;
    int y2 = sy2 * (r - w) + y;
    int x3 = sx2 * r + x;
    int y3 = sy2 * r + y;

    if (i < v) { // Fill in coloured segments with 2 triangles
      tft.setColor(colour);
      geo.fillTriangle(x0, y0, x1, y1, x2, y2);
      geo.fillTriangle(x1, y1, x2, y2, x3, y3);
      text_colour = colour; // Save the last colour drawn
    }
    else // Fill in blank segments
    {
      tft.setColor(DARKGREY);
      geo.fillTriangle(x0, y0, x1, y1, x2, y2);
      geo.fillTriangle(x1, y1, x2, y2, x3, y3);
    }
  }
}


// #########################################################################
// Return a 16 bit rainbow colour
// #########################################################################
unsigned int rainbow(byte value)
{
  // Value is expected to be in range 0-127
  // The value is converted to a spectrum colour from 0 = blue through to 127 = red
  byte red = 0; // Red is the top 5 bits of a 16 bit colour value
  byte green  = 0;// 0x07e0  is the middle 6 bits
  byte blue = 0; // Blue is the bottom 5 bits
  byte quadrant = value / 32;
  if (quadrant == 0) {
    blue = 31;
    green  = 2 * (value % 32);
    red = 0;
  }
  if (quadrant == 1) {
    blue = 31 - (value % 32);
    green  = 63;
    red = 0;
  }
  if (quadrant == 2) {
    blue = 0;
    green  = 63;
    red = value % 32;
  }
  if (quadrant == 3) {
    blue = 0;
    green  = 63 - 2 * (value % 32);
    red = 31;
  }
  return (red << 11) + (green  << 5) + blue;
}


//#######################################################
//Nivelierung
//#######################################################
void getLevel()
{
  xyzFloat corrAngles = myAcc.getCorrAngles();
  tft.setColor(0x07e0);
  tft.fillCircle(400, 185, 50);
  tft.setColor(0x0000);
  tft.drawCircle(400, 185, 10);
  tft.setColor(0xFFFF);
  tft.drawCircle(400, 185, 51);
  tft.setFont(BigFont);

  //Variablen für Berechnungen definieren
  int Achsabstand = 410;
  int Radstand = 165;

  //Links Keile
  if (corrAngles.x > abwlr and corrAngles.y<abwhv and corrAngles.y> abwhv * -1)
  {
    if (corrAngles.x > 10 and corrAngles.y<abwhv and corrAngles.y> abwhv * -1)
    {
      corrAngles.x = 10;
    }
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Links ", 70, 320);
    links = (sin(corrAngles.x * rad)) * Radstand;
    tft.printNumF(links, 1, 70, 350);
    tft.print(" cm             ", 110, 350);
    tft.setColor(RED);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(GREEN);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(RED);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(GREEN);
    tft.fillRect(11, 251, 69, 269);
  }

  //Rechts Keile
  if (corrAngles.x < abwlr * -1 and corrAngles.y<abwhv and corrAngles.y> abwhv * -1)
  {
    if (corrAngles.x < -10 and corrAngles.y<abwhv and corrAngles.y> abwhv * -1)
    {
      corrAngles.x = -10;
    }
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Rechts ", 70, 320);
    rechts = (sin(corrAngles.x * -1 * rad)) * Radstand;
    tft.printNumF(rechts, 1, 70, 350);
    tft.print(" cm             ", 110, 350);
    tft.setColor(GREEN);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(RED);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(GREEN);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(RED);
    tft.fillRect(11, 251, 69, 269);
  }

  //Vorne Keile
  if (corrAngles.y < abwhv * -1 and corrAngles.x<abwlr and corrAngles.x> abwlr * -1)
  {
    if (corrAngles.y < - 10 and corrAngles.x<abwlr and corrAngles.x> abwlr * -1)
    {
      corrAngles.y = -10;
    }
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Vorne ", 70, 320);
    vorne = (sin(corrAngles.y * -1 * rad)) * Achsabstand;
    tft.printNumF(vorne, 1, 70, 350);
    tft.print(" cm             ", 110, 350);
    tft.setColor(RED);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(RED);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(GREEN);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(GREEN);
    tft.fillRect(11, 251, 69, 269);
  }

  //Hinten Keile
  if (corrAngles.y > abwhv and corrAngles.x<abwlr and corrAngles.x> abwlr * -1)
  {
    if (corrAngles.y > 10 and corrAngles.x<abwlr and corrAngles.x> abwlr * -1)
    {
      corrAngles.y = 10;
    }
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Hinten ", 70, 320);
    hinten = (sin(corrAngles.y * rad)) * Achsabstand;
    tft.printNumF(hinten, 1, 70, 350);
    tft.print(" cm             ", 110, 350);
    tft.setColor(GREEN);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(GREEN);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(RED);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(RED);
    tft.fillRect(11, 251, 69, 269);
  }

  //Hinten Links Keile
  if (corrAngles.x > abwlr and corrAngles.y > abwhv)
  {
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Hinten Links ca. ", 70, 320);
    hinten = (sin(corrAngles.y * rad)) * Achsabstand;
    links = (sin(corrAngles.x * rad)) * Radstand;
    if (hinten < links)tft.printNumF(links, 1, 70, 350);
    if (hinten > links)tft.printNumF(hinten, 1, 70, 350);
    tft.print(" cm  ", 110, 350);
    tft.setColor(GREEN);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(GREEN);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(RED);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(GREEN);
    tft.fillRect(11, 251, 69, 269);
  }

  //Hinten Rechts Keile
  if (corrAngles.x < abwlr * -1 and corrAngles.y > abwhv)
  {
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Hinten Rechts ca. ", 70, 320);
    hinten = (sin(corrAngles.y * rad)) * Achsabstand;
    rechts = (sin(corrAngles.x * -1 * rad)) * Radstand;
    if (hinten < rechts)tft.printNumF(links, 1, 70, 350);
    if (hinten > rechts)tft.printNumF(hinten, 1, 70, 350);
    tft.print(" cm  ", 110, 350);
    tft.setColor(GREEN);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(GREEN);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(GREEN);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(RED);
    tft.fillRect(11, 251, 69, 269);
  }

  //Vorne Links Keile
  if (corrAngles.x > abwlr and corrAngles.y < abwhv * -1)
  {
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Vorne Links ca. ", 70, 320);
    vorne = (sin(corrAngles.y * -1 * rad)) * Achsabstand;
    links = (sin(corrAngles.x * rad)) * Radstand;
    if (vorne < links)tft.printNumF(links, 1, 70, 350);
    if (vorne > links)tft.printNumF(vorne, 1, 70, 350);
    tft.print(" cm  ", 110, 350);
    tft.setColor(RED);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(GREEN);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(GREEN);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(GREEN);
    tft.fillRect(11, 251, 69, 269);
  }

  //Vorne Rechts Keile
  if (corrAngles.x < abwlr * -1 and corrAngles.y < abwhv * -1)
  {
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("Vorne Rechts ca. ", 70, 320);
    vorne = (sin(corrAngles.y * -1 * rad)) * Achsabstand;
    rechts = (sin(corrAngles.x * -1 * rad)) * Radstand;
    if (vorne < rechts)tft.printNumF(links, 1, 70, 350);
    if (vorne > rechts)tft.printNumF(hinten, 1, 70, 350);
    tft.print(" cm  ", 110, 350);
    tft.setColor(GREEN);
    tft.fillRect(301, 101, 359, 119);
    tft.setColor(RED);
    tft.fillRect(301, 251, 359, 269);
    tft.setColor(GREEN);
    tft.fillRect(11, 101, 69, 119);
    tft.setColor(GREEN);
    tft.fillRect(11, 251, 69, 269);
  }
  if ((corrAngles.x < abwlr and corrAngles.x > abwlr * -1) and (corrAngles.y  < abwhv and corrAngles.y  > abwhv * -1))
  {
    tft.setColor(RED);
    tft.fillCircle(400 + corrAngles.y * 4, 185 + corrAngles.x * 4, 5);
    tft.print("                                  ", 70, 350);
    tft.print("                                  ", 70, 320);
    tft.setColor(GREEN);
    tft.fillRect(11, 101, 69, 119);
    tft.fillRect(11, 251, 69, 269);
    tft.fillRect(301, 101, 359, 119);
    tft.fillRect(301, 251, 359, 269);
  }
}

//##############################################
//#Farbenbalken anzeigen
//##############################################
void farben()
{
  tft.setColor(0xFFFF);
  tft.drawRect(fx - 1, fy - 1, fx + 256, fy + 51);
  tft.drawRect(fx - 1, fy + 99, fx + 256, fy + 151);
  tft.drawRect(fx - 1, fy + 199, fx + 256, fy + 251);
  cursx = 0;
  for (rot = 0; rot < 255; rot++)
  {
    tft.setColor(rot, 0, 0);
    tft.fillRect(fx + cursx, fy, fx + cursx + 1, fy + 50);
    cursx++;
  }
  cursx = 0;
  for (gruen = 0; gruen < 255; gruen++)
  {
    tft.setColor(0, gruen, 0);
    tft.fillRect(fx + cursx, fy + 100, fx + cursx + 1, fy + 150);
    cursx++;
  }
  cursx = 0;
  for (blau = 0; blau < 255; blau++)
  {
    tft.setColor(0, 0, blau);
    tft.fillRect(fx + cursx, fy + 200, fx + cursx + 1, fy + 250);
    cursx++;
  }
  tx = 127;
  ty = fy + 5;
  readeepromColor();
  tft.setColor(WHITE);
  tft.setFont(Various_Symbols_32x32);
  tft.print("P", fx - tft.getFontXsize() / 2 + selRot, fy - 2 - tft.getFontYsize());
  tft.print("P", fx - tft.getFontXsize() / 2 + selGruen, fy + 98 - tft.getFontYsize());
  tft.print("P", fx - tft.getFontXsize() / 2 + selBlau, fy + 198 - tft.getFontYsize());
  tft.setColor(selRot, selGruen, selBlau);
  tft.fillRoundRect(526, fy + 201, 774, fy + 249);
}


//##############################################
//#Farben von Touchscreen
//##############################################
void Farbenwahl()
{
  //Rot
  if ((down == 1) and (tx >= 25) and (ty >= fy) and (tx <= 75 - 25) and (ty <= fy + 50)) //rotminus
  {
    down = 0;
    if (selRot > 0)
    {
      tft.setFont(Various_Symbols_32x32);
      tft.setColor(0x0000);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selRot, fy - 2 - tft.getFontYsize());
      selRot = selRot - 2;
      tft.setColor(WHITE);
      if (selRot <= 0)selRot = 0;
      tft.print("P", fx - (tft.getFontXsize() / 2) + selRot, fy - 2 - tft.getFontYsize());
      tft.setColor(selRot, selGruen, selBlau);
      tft.fillRoundRect(526, fy + 201, 774, fy + 249);
    }
  }
  if ((down == 1) and (tx >= 381) and (ty >= fy) and (tx <= 431 - 25) and (ty <= fy + 50)) //rotplus
  {
    down = 0;
    if (selRot < 255)
    {
      tft.setColor(0x0000);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selRot, fy - 2 - tft.getFontYsize());
      selRot = selRot + 2;
      if (selRot >= 255)selRot = 255;
      tft.setColor(WHITE);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selRot, fy - 2 - tft.getFontYsize());
      tft.setColor(selRot, selGruen, selBlau);
      tft.fillRoundRect(526, fy + 201, 774, fy + 249);
    }
  }

  //Gruen
  if ((down == 1) and (tx >= 25) and (ty >= fy + 100) and (tx <= 75 - 25) and (ty <= fy + 150)) //gruenminus
  {
    down = 0;
    if (selGruen > 0)
    {
      tft.setFont(Various_Symbols_32x32);
      tft.setColor(0x0000);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selGruen, fy + 98 - tft.getFontYsize());
      selGruen = selGruen - 2;
      if (selGruen <= 0)selGruen = 0;
      tft.setColor(WHITE);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selGruen, fy + 98 - tft.getFontYsize());
      tft.setColor(selRot, selGruen, selBlau);
      tft.fillRoundRect(526, fy + 201, 774, fy + 249);
    }
  }
  if ((down == 1) and (tx >= 381) and (ty >= fy + 100) and (tx <= 431 - 25) and (ty <= fy + 150)) //gruenplus
  {
    down = 0;
    if (selGruen < 255)
    {
      tft.setColor(0x0000);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selGruen, fy + 98 - tft.getFontYsize());
      selGruen = selGruen + 2;
      if (selGruen >= 255)selGruen = 255;
      tft.setColor(WHITE);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selGruen, fy + 98 - tft.getFontYsize());
      tft.setColor(selRot, selGruen, selBlau);
      tft.fillRoundRect(526, fy + 201, 774, fy + 249);
    }
  }

  //Blau
  if ((down == 1) and (tx >= 25) and (ty >= fy + 200) and (tx <= 75 - 25) and (ty <= fy + 250)) //rotminus
  {
    down = 0;
    if (selBlau > 0)
    {
      tft.setFont(Various_Symbols_32x32);
      tft.setColor(0x0000);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selBlau, fy + 198 - tft.getFontYsize());
      selBlau = selBlau - 2;
      if (selBlau <= 0)selBlau = 0;
      tft.setColor(WHITE);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selBlau, fy + 198 - tft.getFontYsize());
      tft.setColor(selRot, selGruen, selBlau);
      tft.fillRoundRect(526, fy + 201, 774, fy + 249);
    }
  }
  if ((down == 1) and (tx >= 381) and (ty >= fy + 200) and (tx <= 431 - 25) and (ty <= fy + 250)) //Blauplus
  {
    down = 0;
    if (selBlau < 255)
    {
      tft.setColor(0x0000);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selBlau, fy + 198 - tft.getFontYsize());
      selBlau = selBlau + 2;
      if (selBlau >= 255)selBlau = 255;
      tft.setColor(WHITE);
      tft.print("P", fx - (tft.getFontXsize() / 2) + selBlau, fy + 198 - tft.getFontYsize());
      tft.setColor(selRot, selGruen, selBlau);
      tft.fillRoundRect(526, fy + 201, 774, fy + 249);
    }
  }

  if ((down == 1) and (tx >= 525) and (ty >= fy) and (tx <= 775) and (ty <= fy + 50)) //Vorder
  {
    down = 0;
    Button(650, fy + 25, 250, 50, Vorder, BtnTextf, "Set", UbuntuBold);
    delay(1000);
    Button(650, fy + 25, 250, 50, Vorder, BtnTextf, "Hauptfarbe", UbuntuBold);
    Vorder = RGB565(selRot, selGruen, selBlau);
    EEPROM.update(1, selRot);
    EEPROM.update(2, selGruen);
    EEPROM.update(3, selBlau);
  }
  if ((down == 1) and (tx >= 525) and (ty >= fy + 100) and (tx <= 775) and (ty <= fy + 150)) //Schrift
  {
    down = 0;
    Button(650, fy + 125, 250, 50, Vorder, BtnTextf, "Set", UbuntuBold);
    delay(1000);
    Button(650, fy + 125, 250, 50, Vorder, BtnTextf, "Textfarbe", UbuntuBold);
    Schriftf = RGB565(selRot, selGruen, selBlau);
    EEPROM.update(4, selRot);
    EEPROM.update(5, selGruen);
    EEPROM.update(6, selBlau);
  }
  if ((down == 1) and (tx >= 525) and (ty >= fy + 300) and (tx <= 775) and (ty <= fy + 350)) //Reset
  {
    down = 0;
    tft.setColor(0x0000);
    tft.print("P", fx - (tft.getFontXsize() / 2) + selRot, fy - 2 - tft.getFontYsize());
    tft.print("P", fx - (tft.getFontXsize() / 2) + selGruen, fy + 98 - tft.getFontYsize());
    tft.print("P", fx - (tft.getFontXsize() / 2) + selBlau, fy + 198 - tft.getFontYsize());

    selRot = 255 / 2;
    selGruen = 255 / 2;
    selBlau = 255 / 2;

    tft.setColor(WHITE);
    tft.print("P", fx - (tft.getFontXsize() / 2) + selRot, fy - 2 - tft.getFontYsize());
    tft.print("P", fx - (tft.getFontXsize() / 2) + selGruen, fy + 98 - tft.getFontYsize());
    tft.print("P", fx - (tft.getFontXsize() / 2) + selBlau, fy + 198 - tft.getFontYsize());

    tft.setColor(selRot, selGruen, selBlau);
    tft.fillRoundRect(526, fy + 201, 774, fy + 249);
  }
}

void Hoehenwahl()
{
  if ( mosl <= 0)  mosl = 1;
  if ( mosl >= 5000) mosl = 5000;
  //Höhe korrigieren
  if ((down == 1) and (tx >= 25) and (ty >= 75) and (tx <= 75) and (ty <= 125)) //Höhe minus
  {
    down = 0;
    if ( mosl > 0)
    {
      mosl = mosl - 10;
      //DEBUGLN(mosl);
      if ( mosl <= 0) mosl = 1;
      tft.setFont(UbuntuBold);
      tft.setColor(Schriftf);
      String bText = String(mosl, 0);
      bText = " " + bText + " m.u.M.";
      int laengeText = bText.length() * tft.getFontXsize() / 2;
      tft.print(bText, 225 - laengeText, 100 + tft.getFontYsize() / 2);
      delay(250);
    }
  }
  if ((down == 1) and (tx >= 381) and (ty >= 75) and (tx <= 431) and (ty <= fy + 125)) //Hoehe plus
  {
    down = 0;
    if ( mosl < 5000)
    {
      mosl = mosl + 10;
      if ( mosl >= 5000) mosl = 5000;
      tft.setFont(UbuntuBold);
      tft.setColor(Schriftf);
      String bText = String(mosl, 0);
      bText = " " + bText + " m.u.M.";
      int laengeText = bText.length() * tft.getFontXsize() / 2;
      tft.print(bText, 225 - laengeText, 100 + tft.getFontYsize() / 2);
      delay(250);
    }
  }
  if ((down == 1) and (tx >= 525) and (ty >= 75) and (tx <= 775) and (ty <= 125)) //Vorder
  {
    down = 0;
    Button(650, 125, 250, 50, Vorder, BtnTextf, "Set", UbuntuBold);
    delay(1000);
    Button(650, 125, 250, 50, Vorder, BtnTextf, "Speichern", UbuntuBold);
    //DEBUG("Mosl: ");
    //DEBUGLN(mosl);
    moslEE = mosl / 20;
    int moslEEvergleich = mosl / 20;
    //DEBUG("MoslEE: ");
    //DEBUGLN(moslEE);
    //DEBUG("MoslEEvergleich: "); DEBUGLN(moslEEvergleich);
    if (moslEEvergleich < moslEE)
    {
      EEPROM.update(9, 1);
      EEPROM.update(10, moslEE);
    }
    else
    {
      EEPROM.update(9, 0);
      EEPROM.update(10, moslEE);
    }
  }
}


void readeepromColor()
{
  selRot = EEPROM.read(4);
  selGruen = EEPROM.read(5);
  selBlau = EEPROM.read(6);
  Schriftf = RGB565(selRot, selGruen, selBlau);
  selRot = EEPROM.read(1);
  selGruen = EEPROM.read(2);
  selBlau = EEPROM.read(3);
  Vorder = RGB565(selRot, selGruen, selBlau);

}

void drawSlider(int x, int y, int slideLength,  int sliderWidth, int sliderHeight, int color, int bordercolor)
{
  tft.setColor(color);
  tft.drawRect(x - sliderWidth / 2 - 1, y - sliderHeight / 2 - 1, slideLength + sliderWidth / 2 + 1 + x, sliderHeight + 2 + y);
  tft.fillRect(x - sliderWidth / 2 + 1 / 2, y - sliderHeight / 2 + 1 / 2, sliderWidth - 2, sliderHeight - 2);
  tft.setColor(bordercolor);
  tft.drawRect(x - sliderWidth / 2, y - sliderHeight / 2, sliderWidth, sliderHeight);
}


void drawSwitch (int x, int y, int swLength, int swWidth, int color, int swStatus)
{
  if (swStatus == 0)
  {
    tft.setColor(Vorder);
    tft.drawRoundRect(x, y - swWidth / 2, swLength + x, swWidth / 2 + y);
    tft.fillRoundRect(x + 2, y - swWidth / 2 + 2, x + swLength / 5, swWidth / 2 + y - 2);
    tft.setColor(0x0000);
    tft.fillRoundRect(x + swLength - swLength / 5, y - swWidth / 2 + 2, x + swLength - 2, swWidth / 2 + y - 2);
  }
  if (swStatus == 1)
  {
    tft.setColor(Vorder);
    tft.drawRoundRect(x, y - swWidth / 2, swLength + x, swWidth / 2 + y);
    tft.fillRoundRect(x + swLength - swLength / 5, y - swWidth / 2 + 2, x + swLength - 2, swWidth / 2 + y - 2);
    tft.setColor(0x0000);
    tft.fillRoundRect(x + 2, y - swWidth / 2 + 2, x + swLength / 5, swWidth / 2 + y - 2);
  }
}


void Wechselrichter()
{
  if ((wechselrichterStatus = true))
    wechselrichterStatus = false;
  else if ((wechselrichterStatus = false))
    wechselrichterStatus = true;
}


void showSolar200()
{
  Serial.println("------ -200W------");
  Serial.print("Produkt ID : ");
  Serial.println(PID200);
  Serial.print("Firmware : ");
  Serial.println(FW200);
  Serial.print("Serien#: ");
  Serial.println(SER200);
  Serial.print("Betteriespannung : ");
  Serial.print(V200);
  Serial.println(" V");
  Serial.print("Batterie Ladestrom : ");
  Serial.print(Ib200);
  Serial.println(" A");
  Serial.print("Solarspannung : ");
  Serial.print(VPV200);
  Serial.println(" V");
  Serial.print("Solarleistung : ");
  Serial.print(PPV200);
  Serial.println(" W");
  Serial.print("Ladestatus : ");
  Serial.print(CS200);
  Serial.println(" -> 0 = Aus, 2 = Err, 3 = Lad, 4 = Entl, 5 = halten");
  Serial.print("MPPT : ");
  Serial.println(MPPT200);
  Serial.print("OR : ");
  Serial.println(OR200);
  Serial.print("Error : ");
  Serial.print(ERR200);
  Serial.println(" -> 0 = OK, 2 = Batt V zu hoch, 17 = Temp zu hoch, 18 = Überstrom, 21 = Amp Sensor Fehler, 33 = Solar V zu hoch, 34 = Solar A zu hoch");
  Serial.print("Lastausgang : ");
  Serial.println(LOAD200);
  Serial.print("Lastausgang Strom : ");
  Serial.print(IL200);
  Serial.println(" A");
  Serial.print("Ertrag gesamt : ");
  Serial.print(H19200);
  Serial.println(" kWh");
  Serial.print("Ertrag heute : ");
  Serial.print(H20200);
  Serial.println(" Wh");
  Serial.print("Maximalleistung heute : ");
  Serial.print(H21200);
  Serial.println(" W");
  Serial.print("Leistung gestern : ");
  Serial.print(H22200);
  Serial.println(" Wh");
  Serial.print("Maximalleistung gestern : ");
  Serial.print(H23200);
  Serial.println(" W");
  Serial.print("HSDS : ");
  Serial.println(HSDS200);
}

void showSolar160()
{
  Serial.println("------ -160W------");
  Serial.print("Produkt ID : ");
  Serial.println(PID160);
  Serial.print("Firmware : ");
  Serial.println(FW160);
  Serial.print("Serien#: ");
  Serial.println(SER160);
  Serial.print("Betteriespannung : ");
  Serial.print(V160);
  Serial.println(" V");
  Serial.print("Batterie Ladestrom : ");
  Serial.print(Ib160);
  Serial.println(" A");
  Serial.print("Solarspannung : ");
  Serial.print(VPV160);
  Serial.println(" V");
  Serial.print("Solarleistung : ");
  Serial.print(PPV160);
  Serial.println(" W");
  Serial.print("Ladestatus : ");
  Serial.print(CS160);
  Serial.println(" -> 0 = Aus, 2 = Err, 3 = Lad, 4 = Entl, 5 = halten");
  Serial.print("MPPT : ");
  Serial.println(MPPT160);
  Serial.print("OR : ");
  Serial.println(OR160);
  Serial.print("Error : ");
  Serial.print(ERR160);
  Serial.println(" -> 0 = OK, 2 = Batt V zu hoch, 17 = Temp zu hoch, 18 = Überstrom, 21 = Amp Sensor Fehler, 33 = Solar V zu hoch, 34 = Solar A zu hoch");
  Serial.print("Lastausgang : ");
  Serial.println(LOAD160);
  Serial.print("Lastausgang Strom : ");
  Serial.print(IL160);
  Serial.println(" A");
  Serial.print("Ertrag gesamt : ");
  Serial.print(H19160);
  Serial.println(" kWh");
  Serial.print("Ertrag heute : ");
  Serial.print(H20160);
  Serial.println(" Wh");
  Serial.print("Maximalleistung heute : ");
  Serial.print(H21160);
  Serial.println(" W");
  Serial.print("Leistung gestern : ");
  Serial.print(H22160);
  Serial.println(" Wh");
  Serial.print("Maximalleistung gestern : ");
  Serial.print(H23160);
  Serial.println(" W");
  Serial.print("HSDS : ");
  Serial.println(HSDS160);
}


void getSolar200()
{
  if (Serial1.available() > 10) {
    label200 = Serial1.readStringUntil('\t');
    val200 = Serial1.readStringUntil('\r\r\n');
    if (label200 == "PID") {
      PID200 = val200;
    } else if (label200 == "FW") {
      FW200 = val200;
    } else if (label200 == "SER#") {
      SER200 = val200;
    } else if (label200 == "V") {
      float temp = val200.toFloat();
      temp = temp / 1000;
      V200 = temp;
    } else if (label200 == "I") {
      float temp = val200.toFloat();
      temp = temp / 10000;
      Ib200 = val200.toFloat();
    } else if (label200 == "VPV") {
      float temp = val200.toFloat();
      temp = temp / 1000;
      VPV200 = temp;
    } else if (label200 == "PPV") {
      PPV200 = val200.toFloat();
    } else if (label200 == "CS") {
      CS200 = val200.toInt();
    } else if (label200 == "MPPT") {
      MPPT200 = val200;
    } else if (label200 == "OR") {
      OR200 = val200;
    } else if (label200 == "ERR") {
      ERR200 = val200.toInt();
    } else if (label200 == "LOAD") {
      LOAD200 = val200.toFloat();
    } else if (label200 == "IL") {
      IL200 = val200.toFloat();
    } else if (label200 == "H19") {
      int temp = val200.toInt();
      temp = temp / 10;
      H19200 = temp;
    } else if (label200 == "H20") {
      int temp = val200.toInt();
      temp = temp / 10;
      H20200 = temp;
    } else if (label200 == "H21") {
      float temp = val200.toFloat();
      temp = temp / 1000;
      H21200 = val200.toInt();
    } else if (label200 == "H22") {
      int temp = val200.toInt();
      temp = temp / 10;
      H22200 = temp;
    } else if (label200 == "H23") {
      float temp = val200.toFloat();
      temp = temp / 1000;
      H23200 = val200.toInt();
    } else if (label200 == "HSDS") {
      float temp = val200.toFloat();
      temp = temp / 100;
      HSDS200 = val200.toInt();
    }
  }
}


void getSolar160()
{
  if (Serial1.available() > 10) {
    label160 = Serial1.readStringUntil('\t');
    val160 = Serial1.readStringUntil('\r\r\n');
    if (label160 == "PID") {
      PID160 = val160;
    } else if (label160 == "FW") {
      FW160 = val160;
    } else if (label160 == "SER#") {
      SER160 = val160;
    } else if (label160 == "V") {
      float temp = val160.toFloat();
      temp = temp / 1000;
      V160 = temp;
    } else if (label160 == "I") {
      float temp = val160.toFloat();
      temp = temp / 10000;
      Ib160 = val160.toFloat();
    } else if (label160 == "VPV") {
      float temp = val160.toFloat();
      temp = temp / 1000;
      VPV160 = temp;
    } else if (label160 == "PPV") {
      PPV160 = val160.toFloat();
    } else if (label160 == "CS") {
      CS160 = val160.toInt();
    } else if (label160 == "MPPT") {
      MPPT160 = val160;
    } else if (label160 == "OR") {
      OR160 = val160;
    } else if (label160 == "ERR") {
      ERR160 = val160.toInt();
    } else if (label160 == "LOAD") {
      LOAD160 = val160.toFloat();
    } else if (label160 == "IL") {
      IL160 = val160.toFloat();
    } else if (label160 == "H19") {
      int temp = val160.toInt();
      temp = temp / 10;
      H19160 = temp;
    } else if (label160 == "H20") {
      int temp = val160.toInt();
      temp = temp / 10;
      H20160 = temp;
    } else if (label160 == "H21") {
      float temp = val160.toFloat();
      temp = temp / 1000;
      H21160 = val160.toInt();
    } else if (label160 == "H22") {
      int temp = val160.toInt();
      temp = temp / 10;
      H22160 = temp;
    } else if (label160 == "H23") {
      float temp = val160.toFloat();
      temp = temp / 1000;
      H23160 = val160.toInt();
    } else if (label160 == "HSDS") {
      float temp = val160.toFloat();
      temp = temp / 100;
      HSDS160 = val160.toInt();
    }
  }
}


void updateSolarWerte()
{
  for (int r = 0; r < 5; r++)
  {
    getSolar200();
    getSolar160();
  }
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.printNumF(V200, 2, 360, 50);
  tft.printNumF(Ib200 + Ib160, 2, 360, 100);
  tft.printNumF(H19200 + H19160, 0, 360, 150);
  tft.printNumF(H20200 + H20160, 0, 360, 200);
  tft.printNumF(H21200 + H21160, 0, 360, 250);
  tft.printNumF(H22200 + H22160, 0, 360, 300);
  tft.printNumF(H23200 + H23160, 0, 360, 350);
  hbp();
  label200 = "0";
  label160 = "0";
}


void updateSolarScreen()
{
  for (int r = 0; r < 200; r++)
  {
    getSolar200();
    getSolar160();
  }

  //Volts
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  String bText = String((VPV200 + VPV160) / 2);
  int laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, displayX / 4 - laengeText - 50, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("V", displayX / 4 + laengeText - 50, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter((VPV200 + VPV160) / 2, 12, 45, displayX / 4 - radius - 50, displayY / 2 - radius, radius, RED2GREEN  );

  //Amps
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  bText = String((PPV200 + PPV160) / (VPV200 + VPV160) / 2);
  laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, displayX / 2 - laengeText, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("A", displayX / 2 + laengeText, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter((PPV200 + PPV160) / (VPV200 + VPV160) / 2, 0, 20, displayX / 2 - radius, displayY / 2 - radius, radius, RED2GREEN  );

  //Watts
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  bText = String((PPV200 + PPV160), 0);
  laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print(bText, displayX / 4 * 3 - laengeText + 50, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("W", displayX / 4 * 3 + laengeText + 50, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter(PPV200 + PPV160, 1, 360, displayX / 4 * 3 - radius + 50, displayY / 2 - radius, radius, RED2GREEN  );
  label200 = "0";
  label160 = "0";
}


void updateBatterie()
{
  getBordbatterie();
  getSolar200();
  int radius = 150;
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  String bText = "Aufbaubatterie";
  int laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print("Aufbaubatterie", displayX / 4 - laengeText, 50);
  String V200text = String(V200);
  laengeText = (V200text.length() * tft.getFontXsize() / 2);
  tft.print(V200text, displayX / 4 - laengeText, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("V", displayX / 4 + laengeText, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter(V200, 11.6, 14.4, displayX / 4 - radius, displayY / 2 - radius, radius, RED2GREEN  );
  //Bordbatterie
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  bText = "Bordbatterie";
  laengeText = bText.length() * tft.getFontXsize() / 2;
  tft.print("Bordbatterie", displayX / 4 * 3 - laengeText, 50);
  String Bordtext = String(Bordbatterie / 100);
  laengeText = (Bordtext.length() * tft.getFontXsize() / 2);
  tft.print(Bordtext, displayX / 4 * 3 - laengeText, displayY / 2 - tft.getFontYsize() / 2);
  tft.print("V", displayX / 4 * 3 + laengeText, displayY / 2 - tft.getFontYsize() / 2);
  ringMeter(Bordbatterie, 1100, 1500, displayX / 4 * 3 - radius, displayY / 2 - radius, radius, RED2GREEN  );
  label200 = "0";
}


void getBaroTrend()
{
  BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
  BME280::PresUnit presUnit(BME280::PresUnit_Pa);
  if (b == 99)
  {
    bme.read(pres, temp, hum, tempUnit, presUnit);
    sealevelKorr = (1013.25 * pow((1 - 6.5 * mosl / (288150)), 5.255));
    sealevelKorr = 1013.25 - sealevelKorr;
    //DEBUG("SLK+99: "); DEBUGLN(sealevelKorr);
    baro[b] = pres / 100 + sealevelKorr;
    //DEBUG("Baro+99: "); DEBUGLN(baro[b]);
    b--;
  }
  if ((b >= 0) and (b < 99))
  {
    baro[b] = baro[b + 1];
    bme.read(pres, temp, hum, tempUnit, presUnit);
    sealevelKorr = (1013.25 * pow((1 - 6.5 * mosl / (288150)), 5.255));
    sealevelKorr = 1013.25 - sealevelKorr;
    //DEBUG("SLK: "); DEBUGLN(sealevelKorr);
    baro[b + 1] = pres / 100 + sealevelKorr;
    //DEBUG("Baro: "); DEBUGLN(baro[b] + 1);
    b--;
  }
  else
  {
    for (int Fifo = 0; Fifo < 99; Fifo++)
    {
      baro[Fifo] = baro[Fifo + 1];
    }
    bme.read(pres, temp, hum, tempUnit, presUnit);
    baro[99] = pres + 9840;

  }
}


void getTouched()
{
  // See if there's any  touch data for us
  if (ts.touched())
  {
    // Retrieve a point
    TS_Point p = ts.getPoint();
    down = 1;
    //DEBUG("touch down: ");
    //DEBUGLN(down);
    ty = p.y - offsetY;
    tx = p.x;
    //DEBUG("tx: ");
    //DEBUGLN(tx);
    //DEBUG("ty: ");
    //DEBUGLN(ty);
    timeoutloop = millis();
  }
}


void Button(int x, int y, int btnX, int btnY, int colorF, int colorS, String btnText, uint8_t *Schrift)
{
  tft.setColor(colorF);
  tft.fillRoundRect(x - btnX / 2, y - btnY / 2, x + btnX / 2, y + btnY / 2);
  tft.setColor(WHITE);
  tft.drawRoundRect(x - btnX / 2, y - btnY / 2, x + btnX / 2, y + btnY / 2);
  tft.setColor(colorS);
  tft.setBackColor(colorF);
  tft.setFont(Schrift);
  int textlength, textheight, laenge;
  laenge = btnText.length();
  textlength = tft.getFontXsize() * laenge;
  textheight = tft.getFontYsize();
  tft.print(btnText, x - textlength / 2, y - textheight / 2 + 2);
  tft.setBackColor(0x0000);
  tx = 0;
  ty = 0;

}

void watchdogSetup(void)
{
  cli(); // disable all interrupts
  asm("WDR"); // watchdog reset
  Serial.println("Watchdog setup complete");
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = (1 << WDE) | (1 << WDP3) | (1 << WDP0); // 4s / no interrupt, system reset
  sei();
}

Dann noch das Fritzing Schema:

und ein paar Eindrücke:












Nun denn, lasset die Diskusion beginnen. Ich bin auch für kreative Vorschläge was dieDarstellung betrifft offen. Der Nivelierungsbildschirm gefällt mir noch nicht wirklich.
Als Amateur habe ich natürlich vieles nach der Holzhackermethode programmiert, aber soweit läuft alles. Die Nivelierfunktion ist sehr umfangreich, da fehlt mir aber noch das know-how um das abzukürzen. Und ja, ich habs grad gesehen, da ist wohl ein Hund über den Screen gelaufen.

1 Like

Nach ausgiebigen Tests war wohl eine fehlerhafte Programmierung der Bildschirm-Timeoutfunktion der Übeltäter für die Freezes.
Falls noch jemand eine Idee hat, wie ich die Touches mit der letzten Position nach dem Neustart hinbekomme, wäre ich froh um einen Gedankenanstoss. Mittlerweile habe ich allerdings die Hardware in Verdacht. Vielleicht könnte eine Touchabfrage beim Splashscreen helfen (oder auch nicht). Wenn jemand Lust hat, und den Sketch mal durchsehen möchte und Ideen zum Vereinfachen hat, dann gerne. Auch wenn jemand etwas sieht, was längerfristig Probleme bereiten könnte, bitte melden. Könnte zum Beispiel der Überlauf der millis ein Problem werden? Denke ich zwar nicht, lasse mich aber gerne eines Besseren belehren. Das könnte ja dann mit einem Neustart vor dem Überlauf abgefangen werden.

Du hast ganz, ganz viele "magic numbers" benutzt. Die solltest du durch Konstanten mit sinnvollen Namen ersetzen.

die kann ich nicht durch konstanten ersetzen, weil die nicht konstant sind.
in diesem Beispiel ist displayX-26,26 die x und Y Position des Buttons (und zwar der Mittelpunkt) 50,50 dann halt die Grösse

-26, 26, 50, 50 sind doch aber konstant, wenn du es so schreibst.

Wenn du es variable halten willst, nutze Variablen. Aber keine Magic Numbers, die konstant sind.

Hallo

Variablen mögen es sehr gerne, wenn sie einen Namen, in der Form einer technischen Bezeichnung, erhalten.

Für die Variable spielt es keine Rolle, ob der gespeicherte Wert veränderbar oder konstant ist.

in diesem Falle ja. diese Zahlen werden an die Funktion übergeben. Beim nächsten Button sind die wieder anders (siehe unten die Funktion)

ja das weiss ich. Was macht es aber für einen Sinn, dass ich der Variabel erst einen Wert zuweisen muss, nur damit ich diesen wert dann an die Funktion übergeben kann. Das spricht dann ja völlig gegen die Funktion an sich, und würde den Code unnötig vergrössern.
oder verstehe ich da etwas falsch?
Das würde dann ja so aussehen, und das für jeden Button:

posX=26;
posY=26;
sizeX=50;
sizeY=50;
Button(displayX - posX, posY, SizeX, sizeY, Vorder, WHITE , "i", UbuntuBold);

Das macht für mich jetzt nicht so Sinn

Spätestens hier sollte Klar sein, dass die Zahlen gar nicht so magisch sind-

void Button(int x, int y, int btnX, int btnY, int colorF, int colorS, String btnText, uint8_t *Schrift)
{
  tft.setColor(colorF);
  tft.fillRoundRect(x - btnX / 2, y - btnY / 2, x + btnX / 2, y + btnY / 2);
  tft.setColor(WHITE);
  tft.drawRoundRect(x - btnX / 2, y - btnY / 2, x + btnX / 2, y + btnY / 2);
  tft.setColor(colorS);
  tft.setBackColor(colorF);
  tft.setFont(Schrift);
  int textlength, textheight, laenge;
  laenge = btnText.length();
  textlength = tft.getFontXsize() * laenge;
  textheight = tft.getFontYsize();
  tft.print(btnText, x - textlength / 2, y - textheight / 2 + 2);
  tft.setBackColor(0x0000);
  tx = 0;
  ty = 0;

}

Ich denke du hast das Problem der Magic Numbers nicht richtig verstanden. Und warum man dies meiden sollte.

Das kann durchaus sein. Kanns Du es mir dann bitte erklären?

Ein Beispiel:
Du machst ein Menü:

void drawMenuScreen()
{
  down = 0;
  tx = 0;
  ty = 0;
  tft.clrScr();
  tft.setColor(Schriftf);
  tft.setBackColor(0x0000);
  tft.setFont(BigFont);
  tft.print("Womo - Monitor",  20, 5);
  tft.drawLine(0, 34,  displayX * 0.6, 34);
  // Button
  tft.setColor(Vorder);
  Button(250, 100, 250, 60, Vorder, BtnTextf, "Wasser", UbuntuBold);
  Button(550, 100, 250, 60, Vorder, BtnTextf, "Level", UbuntuBold);
  Button(250, 205, 250, 60, Vorder, BtnTextf, "Batterie", UbuntuBold);
  Button(550, 205, 250, 60, Vorder, BtnTextf, "Wetter", UbuntuBold);
  Button(250, 310, 250, 60, Vorder, BtnTextf, "Solar", UbuntuBold);
  Button(550, 310, 250, 60, Vorder, BtnTextf, "Strom", UbuntuBold);
  showInfo();
  showSet();
  showAus();
  oldPage = currentPage;
}

und die gleiche Zahlen hast in deiner Button Auswertung:

      case MENU: //Menu page
        DEBUGLN("Case Menu");
        if (currentPage != oldPage)   drawMenuScreen();
        getTouched();
        if ((down == 1) and (tx > 250 - 250) and (ty > 100 - 60) and (tx < 250 + 250 / 2) and (ty < 100 + 60 / 2))
        {
          currentPage = WATER;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 100 - 60) and (tx < 550 + 250 / 2) and (ty < 100 + 60 / 2))
        {
          currentPage = LEVEL;
          down = 0;
        }
        if ((down == 1) and (tx > 250 - 250) and (ty > 205 - 60) and (tx < 250 + 250 / 2) and (ty < 205 + 60 / 2))
        {
          currentPage = BATTERIE;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 205 - 60) and (tx < 550 + 250 / 2) and (ty < 205 + 60 / 2))
        {
          currentPage = WETTER;
          down = 0;
        }
        if ((down == 1) and (tx > 250 - 250) and (ty > 310 - 60) and (tx < 250 + 250 / 2) and (ty < 310 + 60 / 2))
        {
          currentPage = SOLAR;
          down = 0;
        }
        if ((down == 1) and (tx > 550 - 250) and (ty > 310 - 60) and (tx < 550 + 250 / 2) and (ty < 310 + 60 / 2))
        {
          currentPage = WECHSELRICHTER;
          down = 0;
        }

an deiner Stelle würde ich mir ansehen,
was so einen Button ausmacht, (z.B. xStart, xEnd, yStart, yEnd, labelText, zielwert)
eine Struktur dafür definieren
einmal zentral die Werte definieren
und dann immer wieder verwenden.

die linken Buttons um 5px nach links verschieben?
Kein Problem - eine Variable ändern und die Buttons und die Touchauswertung ändern sich mit.

Danke für die Erklärung. So ist mir natürlich klar, was ihr meint. Man muss immer daran denken beide Werte zu ändern. Dann muss ich mich mal in Strukturen einlesen. Damit habe ich mich bis jetzt noch gar nicht auseinandergesetzt

Strukturen helfen Ordnung in deine Variablen zu bringen.
Schaus dir an.

Was mir sonst noch auffällt:
du verwendest 62 mal den Variablentyp int

  • checke jeden einzelne int und überlege dir:
  • braucht diese Variable einen Bereich von -32,768 .. 32,767?
  • reicht vieleicht eine 1 byte Variable?

Und auch die Variante in unsigned

unsigned int currentPage = MENU, oldPage = -1;

Wirst du wirklich mehr als 256 Menüs machen und peilst die 64000 an?

wobei man hier wohl besser die Enumeration zu einer scoped enum macht und dann diesen Variablen auch diesen Typ gibt

Weiters:
Lies nach zum Arduino F-Makro und wende es an.

1 Like
struct Button
{
  int btnXPos;
  int btnYPos;
  int btnXSize;
  int btnYSize;
  int btnTextColor;
  int btnFillColor;
  String btnText;
uint8_t *Schrift;
};

Button Menu =
{
  500,
  250,
  250,
  50,
  0xFFFF,
  Vorder,
  "Menu",
  arial_bold
};

Kommt das so etwa hin vom Grundgedanken?
Da müsste ich dann eine Funktion zum Anzeigen haben, und eine zum Abfragen. Ist das so richtig?

void showBtn(struct Button btnName)
{
  nt xStart, yStart, xEnd, yEnd;
  xStart = btnName.btnXPos - btnName.btnXSize / 2;
  yStart = btnName.btnYPos - btnName.btnYSize / 2;
  xEnd = btnName.btnXPos + btnName.btnXSize / 2;
  yEnd = btnName.btnYPos + btnName.btnYSize / 2;
  tft.setColor(btnName.btnFillcolor);
  tft.fillRoundRect(xStart, yStart, xEnd, yEnd);
  tft.setColor(btnName.btnTextColor);
  tft.drawRoundRect(xStart, yStart, xEnd, yEnd);
  tft.setColor(btnName.btnTextColor);
  tft.setBackColor(btnName.btnFillColor);
  tft.setFont(btnName.Schrift);
  int textlength, textheight, laenge;
  laenge = btnName.btnText.length(); //evtl zwischenschritt nötig
  textlength = tft.getFontXsize() * laenge;
  textheight = tft.getFontYsize();
  tft.print(btnName.btnText, btnName.btnXPos - textlength / 2, btnName.btnYPos - textheight / 2 + 2);
  tft.setBackColor(0x0000);
  tx = 0;
  ty = 0;
}

void checkBtn(struct Button btnName)
{
  int xStart, yStart, xEnd, yEnd;
  xStart = btnName.btnXPos - btnName.btnXSize / 2;
  yStart = btnName.btnYPos - btnName.btnYSize / 2;
  xEnd = btnName.btnXPos + btnName.btnXSize / 2;
  yEnd = btnName.btnYPos + btnName.btnYSize / 2;
  if (tx > xStart) and (ty > yStart) and (tx < yEnd) and (ty < yEnd))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

Würde das so funktionieren?

aufrufen dann so?

If (checkBtn(Menu) == 1)
{
  //code hier
}

Dass man einen enum Wert in einer Ganzzahl-Variablen speichern kann, stammt noch aus den ersten Tagen von C. Sollte man möglichst nicht ausnutzen, sondern den zugehörigen Variablen auch den Datentyp enum geben.
In diesem Fall eventuell die enum um einen Wert UNDEF (statt -1) erweitern.
Wenn man dann noch enum class verwendet, hilft einem der Compiler, es richtig zu machen.

Noch ne Baustelle :grimacing:

Das hast du so gewollt
:wink:

ja natürlich...aber doch bitte nicht alle auf einmal :rofl:
Momentan funktioniert das ganze ja. Es ist allerdings für Aussenstehende tatsächlich schwierig den Sketch nachzuvollziehen. Das ist aus meiner Sicht natürlich anders, weil ich ja die einzelnen Zusammenhänge kenne. Aber jetzt wird nacheinander der Sketch verbessert und wo es geht auch vereinfacht, und "sicher" gemacht. Bis jetzt hat mein Wachhund nicht wirklich etwas zu tun.

1 Like

bezüglich Grundgedanke --> ja.

na jetzt wird es interessant. Wenn du soweit bist gleich der nächste Holzhammer,
mach aus der Struktur eine Klasse,
mach den Konstruktor public:,
und gib die Funktionen gleich als Member Functions in die Klasse.

DANN reicht ein nettes

menu.showBtn() 

und voila: der Menübutton wird angezeigt.

übrigens:
Strukturnamen, Klassennamen --> Großanfangen
konkrete Instanzen einer Struktur/Klasse wie eine variable mit kleinbuchstaben beginnen.

Button menu {
  500,
  250,
  250,
  50,
  0xFFFF,
  Vorder,
  "Menu",
  arial_bold
};

Jetzt überforderst du mich ein bisschen. Kannst Du mir das an einem Beispiel erklären mit der Klasse und Member dingens?

dann wäre die abfrage dann:
menu.checkBtn()?
und wie erfahre ich dann, ob der menu-button tatsächlich gedrückt wurde?

ichweissnichtwiemanstreichenkann:
wenn wir dann schon gerade dabei sind: Um die Übersichtlichkeit zu behalten, kann ich das Struct in einem separaten .h file machen und dann per #include einbinden?

so sieht das .h file aus

/**************************************************************************************
keywords

btn wasser
btn level
btn batterie
btn wetter
btn solar
btn strom
btn gohome
btn info
btn vor
btn zuruck
btn displayaus
btn settings
btn setneustart
btn setdisplay
btn setfarben
btn sethoehe
btn rotminus
btn rotplus
btn gruenminus
btn gruenplus
btn blauminus
btn blauplus
btn hauptfarbe
btn textfarbe
btn resetfarbe
btn hoeheminus
btn hoeheplus
btn hoehespeichern
btn resetja
btn resetnein
**************************************************************/

struct btn
{
  int btnXPos;
  int btnYPos;
  int btnXSize;
  int btnYSize;
  int btnTextColor;
  int btnFillColor;
  String btnText;
  uint8_t *Schrift;
};

btn wasser =
{
  250,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Wasser",
  UbuntuBold
};

btn level =
{
  550,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Level",
  UbuntuBold
};

btn batterie =
{
  250,
  205,
  250,
  60,
  0xFFFF,
  Vorder,
  "Batterie",
  UbuntuBold
};

btn wetter =
{
  550,
  205,
  250,
  60,
  0xFFFF,
  Vorder,
  "Wetter",
  UbuntuBold
};

btn solar =
{
  250,
  310,
  250,
  60,
  0xFFFF,
  Vorder,
  "Solar",
  UbuntuBold
};

btn strom =
{
  550,
  310,
  250,
  60,
  0xFFFF,
  Vorder,
  "Strom",
  UbuntuBold
};


btn gohome =
{
  70,
  displayY - 22,
  120,
  40,
  0xFFFF,
  Vorder,
  "Home",
  UbuntuBold
};

btn info =
{
  displayX - 26,
  26,
  50,
  50,
  0xFFFF,
  Vorder,
  "i",
  UbuntuBold
};

btn vor =
{
  465,
  displayY - 22,
  120,
  40,
  0xFFFF,
  Vorder,
  "S",
  Various_Symbols_32x32
};

btn zuruck =
{
  335,
  displayY - 22,
  120,
  40,
  0xFFFF,
  Vorder,
  "R",
  Various_Symbols_32x32
};

btn displayaus =
{
  displayX - 26,
  displayY - 27,
  50,
  50,
  0xFFFF,
  Vorder,
  "l",
  Various_Symbols_32x32
};

btn settings =
{
  displayX - 86,
  26,
  50,
  50,
  0xFFFF,
  Vorder,
  "s",
  Various_Symbols_32x32
};

btn setneustart =
{
  250,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Neustart",
  UbuntuBold
};

btn setdisplay =
{
  250,
  205,
  250,
  60,
  0xFFFF,
  Vorder,
  "Display",
  UbuntuBold
};

btn setfarben =
{
  250,
  310,
  250,
  60,
  0xFFFF,
  Vorder,
  "Farben",
  UbuntuBold
};

btn sethoehe =
{
  550,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Hoehe",
  UbuntuBold
};

btn rotminus =
{
  50,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

btn rotplus =
{
  406,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

btn gruenminus =
{
  50,
  225,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

btn gruenplus =
{
  406,
  225,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

btn blauminus =
{
  50,
  325,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

btn blauplus =
{
  406,
  325,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

btn hauptfarbe =
{
  650,
  125,
  250,
  50,
  0xFFFF,
  Vorder,
  "Hauptfarbe",
  UbuntuBold
};

btn textfarbe =
{
  650,
  225,
  250,
  50,
  0xFFFF,
  Vorder,
  "Textfarbe",
  UbuntuBold
};

btn resetfarbe =
{
  650,
  425,
  250,
  50,
  0xFFFF,
  Vorder,
  "Reset",
  UbuntuBold
};

btn hoeheminus =
{
  50,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

btn hoeheplus =
{
  406,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

btn hoehespeichern =
{
  650,
  125,
  250,
  50,
  0xFFFF,
  Vorder,
  "Speichern",
  UbuntuBold
};

btn resetja =
{
  200,
  displayY - 42,
  120,
  40,
  0xFFFF,
  Vorder,
  "JA",
  UbuntuBold
};

btn resetnein =
{
  600,
  displayY - 42,
  120,
  40,
  0xFFFF,
  Vorder,
  "NEIN",
  UbuntuBold,
};

anzeigen funktioniert schonmal :partying_face:
was allerdings nicht funktioniert: die Füllfarbe wird nicht vom Hauptsketch übernommen. Wie kann ich das lösen? die variabel "Vorder" als Füllfarbe an buttons.h übergeben?

die checkBtn Funktion funktioniert auch mal.....jetzt kann es weiter gehen

bool checkBtn(struct btn btnName)
{
  getTouched();
  int xStart, yStart, xEnd, yEnd;
  xStart = btnName.btnXPos - btnName.btnXSize / 2;
  yStart = btnName.btnYPos - btnName.btnYSize / 2;
  xEnd = btnName.btnXPos + btnName.btnXSize / 2;
  yEnd = btnName.btnYPos + btnName.btnYSize / 2;
  if ((tx > xStart) && (ty > yStart) && (tx < xEnd) && (ty < yEnd))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

naja, ein "Beispiel" mit deinen Codefetzen ist nicht so einfach.
Aber das sollte dir mal eine Idee geben:

struct_to_class - Wokwi ESP32, STM32, Arduino Simulator

/*
    https://forum.arduino.cc/t/projektvorstellung-womo-monitor/1162849/20
    - mach mal ein struct
    - mach mal eine class aus dem struct
    - mach mal eine member function

    2023-08-30 by noiasca

*/

uint16_t Vorder, BtnTextf, Schriftf, Vorder_alt, BtnTextf_alt, Schriftf_alt;
int displayY ;
int displayX ;
int ty, tx;
bool down = 0;
bool pressed = 0;
// unbekanntes aus irgendwelchen Libraries
int UbuntuBold;
int Various_Symbols_32x32;

#include "definitions.h"

// nur Simuluation
const uint8_t levelPin = 2;
const uint8_t wasserPin = 3;

void simu() {
  pinMode(wasserPin, INPUT_PULLUP);
  pinMode(levelPin, INPUT_PULLUP);
}

// Simulation Touchscreen
void getTouched() {
  if (digitalRead(levelPin) == LOW) {
    tx = level.btnXPos + 2;
    ty = level.btnYPos + 2;
    down = 1;
  }
  else if (digitalRead(wasserPin) == LOW) {
    tx = wasser.btnXPos + 2;
    ty = wasser.btnYPos + 2;
    down = 1;
  }
  else {
    tx = 0;
    ty = 0;
    down = 0;
  }
}

void setup() {
  Serial.begin(115200);
  simu();
}

void loop() {
  if (level.checkBtn()) Serial.println(F("level pressed"));
  if (wasser.checkBtn()) Serial.println(F("wasser pressed"));
}

definitions.h


extern void getTouched();

class Btn {
  public:
    int btnXPos;
    int btnYPos;
    int btnXSize;
    int btnYSize;
    int btnTextColor;
    int btnFillColor;
    String btnText;
    uint8_t *Schrift;

    bool checkBtn() {
      getTouched();
      int xStart, yStart, xEnd, yEnd;
      xStart = btnXPos - btnXSize / 2;
      yStart = btnYPos - btnYSize / 2;
      xEnd = btnXPos + btnXSize / 2;
      yEnd = btnYPos + btnYSize / 2;
      if ((tx > xStart) && (ty > yStart) && (tx < xEnd) && (ty < yEnd))
      {
        return 1;
      }
      else
      {
        return 0;
      }
    }
};

Btn wasser =
{
  250,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Wasser",
  UbuntuBold
};

Btn level =
{
  550,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Level",
  UbuntuBold
};

Btn batterie =
{
  250,
  205,
  250,
  60,
  0xFFFF,
  Vorder,
  "Batterie",
  UbuntuBold
};

Btn wetter =
{
  550,
  205,
  250,
  60,
  0xFFFF,
  Vorder,
  "Wetter",
  UbuntuBold
};

Btn solar =
{
  250,
  310,
  250,
  60,
  0xFFFF,
  Vorder,
  "Solar",
  UbuntuBold
};

Btn strom =
{
  550,
  310,
  250,
  60,
  0xFFFF,
  Vorder,
  "Strom",
  UbuntuBold
};


Btn gohome =
{
  70,
  displayY - 22,
  120,
  40,
  0xFFFF,
  Vorder,
  "Home",
  UbuntuBold
};

Btn info =
{
  displayX - 26,
  26,
  50,
  50,
  0xFFFF,
  Vorder,
  "i",
  UbuntuBold
};

Btn vor =
{
  465,
  displayY - 22,
  120,
  40,
  0xFFFF,
  Vorder,
  "S",
  Various_Symbols_32x32
};

Btn zuruck =
{
  335,
  displayY - 22,
  120,
  40,
  0xFFFF,
  Vorder,
  "R",
  Various_Symbols_32x32
};

Btn displayaus =
{
  displayX - 26,
  displayY - 27,
  50,
  50,
  0xFFFF,
  Vorder,
  "l",
  Various_Symbols_32x32
};

Btn settings =
{
  displayX - 86,
  26,
  50,
  50,
  0xFFFF,
  Vorder,
  "s",
  Various_Symbols_32x32
};

Btn setneustart =
{
  250,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Neustart",
  UbuntuBold
};

Btn setdisplay =
{
  250,
  205,
  250,
  60,
  0xFFFF,
  Vorder,
  "Display",
  UbuntuBold
};

Btn setfarben =
{
  250,
  310,
  250,
  60,
  0xFFFF,
  Vorder,
  "Farben",
  UbuntuBold
};

Btn sethoehe =
{
  550,
  100,
  250,
  60,
  0xFFFF,
  Vorder,
  "Hoehe",
  UbuntuBold
};

Btn rotminus =
{
  50,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

Btn rotplus =
{
  406,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

Btn gruenminus =
{
  50,
  225,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

Btn gruenplus =
{
  406,
  225,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

Btn blauminus =
{
  50,
  325,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

Btn blauplus =
{
  406,
  325,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

Btn hauptfarbe =
{
  650,
  125,
  250,
  50,
  0xFFFF,
  Vorder,
  "Hauptfarbe",
  UbuntuBold
};

Btn textfarbe =
{
  650,
  225,
  250,
  50,
  0xFFFF,
  Vorder,
  "Textfarbe",
  UbuntuBold
};

Btn resetfarbe =
{
  650,
  425,
  250,
  50,
  0xFFFF,
  Vorder,
  "Reset",
  UbuntuBold
};

Btn hoeheminus =
{
  50,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "-",
  UbuntuBold
};

Btn hoeheplus =
{
  406,
  125,
  50,
  50,
  0xFFFF,
  Vorder,
  "+",
  UbuntuBold
};

Btn hoehespeichern =
{
  650,
  125,
  250,
  50,
  0xFFFF,
  Vorder,
  "Speichern",
  UbuntuBold
};

Btn resetja =
{
  200,
  displayY - 42,
  120,
  40,
  0xFFFF,
  Vorder,
  "JA",
  UbuntuBold
};

Btn resetnein =
{
  600,
  displayY - 42,
  120,
  40,
  0xFFFF,
  Vorder,
  "NEIN",
  UbuntuBold,
};
1 Like