Sonnen Tracker Arduino

An der Hardware möchte ich eigentlich nichts ändern, da nach langen hin und her es endlich gut funktioniert.

Deshalb kann mir die idee, ihn drehen zu lassen, wenn es lange "grau" ist. Wenn dann die Sonne kommt wird es erkannt.

@my_xy_projekt
Ich habe jetzt mal eine Sperre ebenfalls für die andere Achse eingefügt:

// Forensketch - Sonnentracker Arduino
// basiert auf: https://forum.arduino.cc/t/sonnen-tracker-arduino/859643/137
// noch keine Endlösung - kompiliert fehler und warnungsfrei 10.08.2022

// Begin Variablen Wind
bool windAusgeloest = false;
const byte anemometerPin = 2;  //Definierter Interrupt Pin (2 oder 3 beim Arduino Uno)
volatile unsigned long windCounter;
float Windgeschwindigkeit;

const unsigned long messZeit = 2000; //Messzeit in ms
const byte windSchwelle = 25; // km/h
const byte sturmSchwelle = 35; // km/h
const unsigned long umlaufZeit = 10000; // 10 Sekunden
byte umlaufMerker[umlaufZeit / messZeit]; // Anzahl der benötigten Elemente des Array errechnet sich aus den Zeiten
// End Variablen Wind

// Begin Variablen SolarPanel
unsigned int OL, OR, UL, UR = 0;
unsigned int OL2, OR2 = 0;
unsigned int GWO, GWU, GWL, GWR = 0;
unsigned int LFix, RFix = 0;
unsigned int DVERT, DHORIZ = 0;
unsigned int RL2Vergleich = 0;
bool Endschalter1VEVSStatus = false;
bool Endschalter2VEHSStatus = false;
bool Endschalter2VEOOEStatus = false;
bool Endschalter3HEVSStatus = false;
bool Endschalter4HEHSStatus = false;
bool Endschalter4HEHOEStatus = false;

// Sonnen Verfolgung Vertikal und Horizontal v10.6 vom 25.10.2021

const byte Endschalter1VEVS = 3; // Vertikal Endschalter vorne, schließer
const byte Endschalter2VEHS = 4; // Vertikal Endschalter hinten, schließer
const byte Endschalter2VEOOE = 5; // Vertikal Endschalter hinten, öffner

const byte Relais1pin = 6; // Relais 1 für Vertikale Achse, Zylinder ausfahren
const byte Relais2pin = 7; // Relais 2 für Vertikale Achse, Zylinder einfahren

const byte Endschalter3HEVS = 8; // Horizontal Endschalter vorne, schließer
const byte Endschalter4HEHS = 9; // Horizontal Endschalter hinten, schließer
const byte Endschalter4HEHOE = 10; // Horizontal Endschalter hinten, öffner

const byte Relais3pin = 11; // Relais 3 für Horizontal Achse, Zylinder ausfahren
const byte Relais4pin = 12; // Relais 4 für Horizontal Achse, Zylinder einfahren

// LDR Stiftverbindungen am Analogpin, LDR5528, GL5528, 0,5-200kOhm, 5mm
const byte LDRol = A0; // LDR oben links
const byte LDRor = A1; // LDR oben rechts
const byte LDRul = A2; // LDR unten links
const byte LDRur = A3; // LDR unten rechts
const byte LDRol2 = A4; // LDR oben links 2
const byte LDRor2 = A5; // LDR oben rechts 2

// Feste Werte
const unsigned int START = 300; // Wert ab wann das Programm wieder Startet (jeder Einzelner LDR)
const unsigned int TOLV = 145; // Wert, ab wann die Position Veretikal geändert werden soll (Toleranz)
const unsigned int TOLHA = 125; // Wert, ab wann die Position Horizontal geändert werden soll, Zylinder ausfahren (Toleranz)
const unsigned int TOLHE = 550; // Wert, ab wann die Position Horizontal geändert werden soll, Zylinder einfahren (Toleranz)
const unsigned int ENDEV = 10; // Wert zum Beenden der Ausrichtung Vertikal
const unsigned int ENDEH = 20; // Wert zum Beenden der Ausrichtung Horizontal
const unsigned int NACHT = 55; // Wert ab wann die Linearmotoren in Startposition fahren (Progamm bei Dunkelheit beendet, jeder Einzelner LDR)
const unsigned int HFix = 45; // Wert zum Abgleichen der LDR oben links, LDR oben links 2 und LDR oben rechts, LDR oben rechts 2
// End Variablen SolarPanel


void setup ()
{
  // Setup Wind
  pinMode(anemometerPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(anemometerPin), countup, RISING);
  Windmessung(messZeit);
  // Setup Solar
  pinMode(Endschalter1VEVS, INPUT); // Pin Modus definieren, Eingang, schließer
  pinMode(Endschalter2VEHS, INPUT); // Pin Modus definieren, Eingang, schließer
  pinMode(Endschalter2VEOOE, INPUT); // Pin Modus definieren, Eingang, öffner
  pinMode(Relais1pin, OUTPUT); // Pin Modus definieren, Ausgang
  pinMode(Relais2pin, OUTPUT); // Pin Modus definieren, Ausgang
  pinMode(Endschalter3HEVS, INPUT); // Pin Modus definieren, Eingang, schließer
  pinMode(Endschalter4HEHS, INPUT); // Pin Modus definieren, Eingang, schließer
  pinMode(Endschalter4HEHOE, INPUT); // Pin Modus definieren, Eingang, öffner
  pinMode(Relais3pin, OUTPUT); // Pin Modus definieren, Ausgang
  pinMode(Relais4pin, OUTPUT); // Pin Modus definieren, Ausgang
  Serial.begin(57600); // Serielle Schnittstelle initialisieren
}

void loop ()
{
  readPanelSensors();
  getWindSensors();
  // Ausrichtung bei Helligkeit, Wert "START"
  if ((OL > START) && (OR > START) && (UL > START) && (UR > START) && (OL2 > START) && (OR2 > START) && windAusgeloest == false)// LDR's alle über "START"
  {
    if ((sperrev() == false))
    {
      if (DVERT > TOLV) // "DVERT" größer "TOLV" Wert und Wind den Schwellwert nicht erreicht hat
      {
        // Vertikalachse ausrichten, Linearmotor 3000N 200mm
        if ((GWO < GWU) && ((Endschalter2VEHSStatus == LOW) || (Endschalter2VEOOEStatus == HIGH))) // Oben heller wie unten, Endschalter 2 schließer und öffner nicht betätigt
        {
          digitalWrite(Relais1pin, HIGH); // Zylinder ausfahren
          digitalWrite(Relais2pin, LOW); // Relais2 deaktivieren
        }
        else if ((GWO > GWU) && (Endschalter1VEVSStatus == LOW)) // Oben dunkler wie unten, Endschalter 1 schließer nicht betätigt ist
        {
          digitalWrite(Relais1pin, LOW); // Relais1 deaktivieren
          digitalWrite(Relais2pin, HIGH); // Zylinder einfahren
        }
      }
    }

    // Vertikalachse ausrichten abgeschlossen und die Relais 1 und 2 deaktivieren
    if (DVERT <= ENDEV) // Oben und unten gleich hell sind oder eine max. Differnz von "ENDEV" haben
    {
      digitalWrite(Relais1pin, LOW); // Relais1 deaktivieren
      digitalWrite(Relais2pin, LOW); // Relais2 deaktivieren
    }
    else if (((Endschalter2VEHSStatus == HIGH) || (Endschalter2VEOOEStatus == LOW)) && (digitalRead(Relais1pin) == HIGH) && (digitalRead(Relais2pin) == LOW)) // Endschalter 2 schließer und öffner betätigt, Relais 1 betätigt und Relais 2 aus
    {
      digitalWrite(Relais1pin, LOW); // Relais1 deaktivieren
      digitalWrite(Relais2pin, LOW); // Relais2 deaktivieren
    }
    else if ((Endschalter1VEVSStatus == HIGH) && (digitalRead(Relais1pin) == LOW) && (digitalRead(Relais2pin) == HIGH)) // Endschalter 1 schließer betätigt, Relais 1 aus und Relais 2 betätigt ist
    {
      digitalWrite(Relais1pin, LOW); // Relais1 deaktivieren
      digitalWrite(Relais2pin, LOW); // Relais2 deaktivieren
    }

    // Horizontalachse ausrichten, Linearmotor 3000N 100mm
    if (sperreh() == false) // "DHORIZ" größer "TOLH" Wert und die Sperre Horizontal inaktiv ist
    {
      if ((DHORIZ > TOLHA) && (GWL > GWR) && (LFix <= HFix)  && ((Endschalter4HEHSStatus == LOW) || (Endschalter4HEHOEStatus == HIGH))) // Differenz größer als Tolerenanz ausfahren und Rechts heller wie links, Endschalter 4 schließer und öffner nicht betätigt
      {
        digitalWrite(Relais3pin, HIGH); // Zylinder ausfahren
        digitalWrite(Relais4pin, LOW); // Relais4 deaktivieren
      }
      else if ((DHORIZ > TOLHE) && (GWL < GWR) && (RFix <= HFix) && (Endschalter3HEVSStatus == LOW)) // Differenz größer als Tolerenanz einfahren und Rechts dunkler wie links, Endschalter 3 schließer nicht betätigt
      {
        digitalWrite(Relais3pin, LOW); // Relais3 deaktivieren
        digitalWrite(Relais4pin, HIGH); // Zylinder einfahren
      }
    }

    // Horizontalachse ausrichten abgeschlossen und die Relais 3 und 4 deaktivieren
    if (DHORIZ <= ENDEH || (RL2Vergleich <= (ENDEH / 2))) // Oben und unten gleich hell sind oder eine max. Differnz von "ENDEH" haben
    {
      digitalWrite(Relais3pin, LOW); // Relais3 deaktivieren
      digitalWrite(Relais4pin, LOW); // Relais4 deaktivieren
    }
    else if (((Endschalter4HEHSStatus == HIGH) || (Endschalter4HEHOEStatus == LOW)) && (digitalRead(Relais3pin) == HIGH) && (digitalRead(Relais4pin) == LOW)) // Endschalter 4 schließer und öffner betätigt, Relais 3 betätigt und Relais 4 aus
    {
      digitalWrite(Relais3pin, LOW); // Relais3 deaktivieren
      digitalWrite(Relais4pin, LOW); // Relais4 deaktivieren
    }
    else if ((Endschalter3HEVSStatus == HIGH) && (digitalRead(Relais3pin) == LOW) && (digitalRead(Relais4pin) == HIGH)) // Endschalter 3 schließer betätigt, Relais 3 aus und Relais 4 betätigt ist
    {
      digitalWrite(Relais3pin, LOW); // Relais3 deaktivieren
      digitalWrite(Relais4pin, LOW); // Relais4 deaktivieren
    }
  }

  // Grundstellung
  // bei Dunkelheit, Wert "NACHT"
  // oder bei Wind
  if (((OL < NACHT) && (OR < NACHT) && (UL < NACHT) && (UR < NACHT)) // LDR's alle unter "NACHT"
      || windAusgeloest)
  {
    if (!Endschalter1VEVSStatus)// Endschalter 1 schließer nicht betätigt, fährt die Vertikalachse in die Startposition
    {
      digitalWrite(Relais1pin, LOW); // Relais1 deaktivieren
      digitalWrite(Relais2pin, HIGH); // Zylinder einfahren, Vertikal
    }
    else
    {
      digitalWrite(Relais1pin, LOW); // Relais1 deaktivieren
      digitalWrite(Relais2pin, LOW); // Relais2 deaktivieren
    }
    if (!windAusgeloest)
    {
      if (!Endschalter3HEVSStatus) // Endschalter 3 schließer nicht betätigt, fährt die Horizontalachse in die Startposition
      {
        digitalWrite(Relais3pin, LOW); // Relais3 deaktivieren
        digitalWrite(Relais4pin, HIGH); // Zylinder einfahren, Horizontal
      }
      else
      {
        digitalWrite(Relais3pin, LOW); // Relais3 deaktivieren
        digitalWrite(Relais4pin, LOW); // Relais4 deaktivieren
      }
    }
  }
  serialMonitor();
}

void getWindSensors()
{
  //Ausgabe der Windwerte
  static unsigned long lastprint;
  static unsigned long lastausloeser = 0;
  const unsigned long sperrZeit = 1000UL * 60 * 15; // Wind Sperrzeit 15 Min.
  if (millis() - lastprint >= messZeit)
  {
    lastprint = millis();
    Serial.print(F("15. Windgeschwindigkeit: "));
    Serial.print(Windgeschwindigkeit); // Ausgabe der Windgeschwindigkeit in Km/h
    Serial.println(F(" Km/h"));
  }
  Windmessung(messZeit);
  if (Auswertung(umlaufZeit))
  {
    Serial.println(F("Wind ausgelöst"));
    // Hier merken, das ausgelöst wurde:
    windAusgeloest = true;
    lastausloeser = millis();
    Serial.println(F("Auslöser gemerkt"));
  }
  if (windAusgeloest)
  {
    if (millis() - lastausloeser >= sperrZeit)
    {
      windAusgeloest = false;
      Serial.println(F("Ausloeser geloescht"));
    }
  }
}

bool Auswertung(unsigned long intervall)
{
  static unsigned long lastmillis = 0;
  unsigned int wind = 0;
  unsigned int sturm = 0;
  bool ausloeser = false;
  if (millis() - lastmillis >= intervall)
  {
    Serial.println(F("Werte durchzaehlen:"));
    for (byte i = 0; i < sizeof(umlaufMerker); i++)
    {
      if (umlaufMerker[i] >= windSchwelle) wind++;
      if (umlaufMerker[i] >= sturmSchwelle) sturm++;
      Serial.print(umlaufMerker[i]);
      Serial.print(F("\t"));
    }
    Serial.println();
    lastmillis = millis();
  }
  if ((wind >= 3) || (sturm >= 2))
  {
    ausloeser = true;
  }
  return ausloeser;
}

void Windmessung(unsigned long intervall) // Initalisierung und Berechnung für die Windgeschwindigkeit
{
  static unsigned long lastMessung = 0;
  static unsigned int elementeZaehler = 0;
  if (millis() - lastMessung >= intervall)
  {
    detachInterrupt(digitalPinToInterrupt(anemometerPin));
    Serial.println(windCounter);
    Windgeschwindigkeit = (float)(windCounter * 1.2) / (float)((millis() - lastMessung) / 1000);
    windCounter = 0;
    lastMessung = millis();
    attachInterrupt(digitalPinToInterrupt(anemometerPin), countup, RISING);
    umlaufMerker[elementeZaehler] = (int)Windgeschwindigkeit;
    elementeZaehler++;
    if (elementeZaehler > (sizeof(umlaufMerker))) elementeZaehler = 0;
  }
}

void countup() // Zähler für die Impulse des Reed Kontakt
{
  windCounter++;
}

void readPanelSensors()
{
  OL = analogRead (0) * 1.0; // Oben links, Faktor 1.0 anpassen, wenn die Widerstände sehr unterschiedlich sind
  OR = analogRead (1) * 1.0; // Oben rechts, Faktor 1.0 anpassen, wenn die Widerstände sehr unterschiedlich sind
  UL = analogRead (2) * 1.0; // Unten links, Faktor 1.0 anpassen, wenn die Widerstände sehr unterschiedlich sind
  UR = analogRead (3) * 1.0; // Unten rechts, Faktor 1.0 anpassen, wenn die Widerstände sehr unterschiedlich sind
  OL2 = analogRead (4) * 1.0; // Oben links 2, Faktor 1.0 anpassen, wenn die Widerstände sehr unterschiedlich sind
  OR2 = analogRead (5) * 1.0; // Oben rechts 2, Faktor 1.0 anpassen, wenn die Widerstände sehr unterschiedlich sind
  GWO = (OL + OR); // Gesamtwert oben
  GWU = (UL + UR); // Gesamtwert unten
  GWL = (OL + UL); // Gesamtwert links
  GWR = (OR + UR); // Gesamtwert rechts
  LFix = abs((int)OL - (int)OL2); // Oben links - oben  links 2, immer Positiv setzen
  RFix = abs((int)OR - (int)OR2); // Unten rechts - unten rechts 2, immer Positiv setzen
  RL2Vergleich = abs(OR2) - abs(OL2); // Vergleich von LDR2 oben rechts und links, immer Positiv setzen
  DVERT = abs((int)GWO - (int)GWU); // Überprüfen der Diffirenz zwischen oben und unten, Vertikal, immer Positiv setzen
  DHORIZ = abs((int)GWL - (int)GWR); // Überprüfen der Diffirenz zwischen links und rechts, Horizontal, immer Positiv setzen
  Endschalter1VEVSStatus = digitalRead(Endschalter1VEVS); // Zustand des Endschalter Vertikal vorne, schließer
  Endschalter2VEHSStatus = digitalRead(Endschalter2VEHS); // Zustand des Endschalter Vertikal hinten, schließer
  Endschalter2VEOOEStatus = digitalRead(Endschalter2VEOOE); // Zustand des Endschalter Vertikal hinten, öffner
  Endschalter3HEVSStatus = digitalRead(Endschalter3HEVS); // Zustand des Endschalter Horizontal vorne, schließer
  Endschalter4HEHSStatus = digitalRead(Endschalter4HEHS); // Zustand des Endschalter Horizontal hinten, schließer
  Endschalter4HEHOEStatus = digitalRead(Endschalter4HEHOE); // Zustand des Endschalter Horizontal hinten, öffner
}

bool sperrev() // Sperre Vertikal
{
  static bool sperrev = false;
  const unsigned long sperrzeit = 1000UL * 60 * 5; // Sperrzeit von 5min.
  static unsigned long sperrStart = millis();
  static bool lastZustand[2] = {HIGH, HIGH};
  uint8_t relaisPin[2] = {Relais1pin, Relais2pin};

  if (!sperrev)                                           // Keine Sperre aktiv
    for (byte b = 0; b < 2; b++)
    {
      if (lastZustand[b] != !digitalRead(relaisPin[b]))  // Letzter Zustand weicht vom aktuellen ab
      {
        sperrStart = millis();
        lastZustand[b] = !lastZustand[b];
        sperrev = true;
      }
    }
  if (millis() - sperrStart > sperrzeit) sperrev = false;
  return sperrev;
}

bool sperreh() // Sperre Horizontal
{
  static bool sperreh = false;
  const unsigned long sperrzeit = 1000UL * 60 * 5; // Sperrzeit von 5min.
  static unsigned long sperrStart = millis();
  static bool lastZustand[2] = {HIGH, HIGH};
  uint8_t relaisPin[2] = {Relais3pin, Relais4pin};

  if (!sperreh)                                           // Keine Sperre aktiv
    for (byte b = 0; b < 2; b++)
    {
      if (lastZustand[b] != !digitalRead(relaisPin[b]))  // Letzter Zustand weicht vom aktuellen ab
      {
        sperrStart = millis();
        lastZustand[b] = !lastZustand[b];
        sperreh = true;
      }
    }
  if (millis() - sperrStart > sperrzeit) sperreh = false;
  return sperreh;
}

void serialMonitor()
{
  // Die 4 LDR Werte, Berechnung der Helligkeitswerte, Relais und die Endschalterzustände zu Testzwecken an den PC übertragen
  static unsigned long lastprint;
  if (millis() - lastprint > 10000) // Testausgabe alle 10s
  {
    lastprint = millis();
    Serial.print(F("1. LDRol:")); Serial.print(OL); // LDR oben links
    Serial.print(F(" LDRor:")); Serial.println(OR); // LDR oben rechts
    Serial.print(F("2. LDRul:")); Serial.print(UL); // LDR unten links
    Serial.print(F(" LDRur:")); Serial.println(UR); // LDR unten rechts
    Serial.print(F("3. LDRol2:")); Serial.print(OL2); // LDR oben links 2
    Serial.print(F(" LDRor2:")); Serial.println(OR2); // LDR oben rechts 2
    Serial.print(F("4. GWO:")); Serial.print(GWO); // Gesamtwert oben
    Serial.print(F(" GWU:")); Serial.println(GWU); // Gesamtwert unten
    Serial.print(F("5. GWL:")); Serial.print(GWL); // Gesamtwert links
    Serial.print(F(" GWR:")); Serial.println(GWR); // Gesamtwert rechts
    Serial.print(F("6. Diff O & U:")); Serial.print(DVERT); // Diffirenze zwischen oben und unten
    Serial.print(F(" Diff L & R:")); Serial.println(DHORIZ); // Diffirenze zwischen links und rechts
    Serial.print(F("7. LDR links Fix:")); Serial.print(LFix); // Diffirenze zwischen links und links 2
    Serial.print(F(" LDR rechts Fix:")); Serial.println(RFix); // Diffirenze zwischen rechts und rechts 2
    Serial.print(F("8. Relais 1:")); Serial.print(digitalRead(Relais1pin)); // Zustand Relais 1
    Serial.print(F(" Relais 2:")); Serial.println(digitalRead(Relais2pin)); // Zustand Relais 1
    Serial.print(F("9. Relais 3:")); Serial.print(digitalRead(Relais3pin)); // Zustand Relais 1
    Serial.print(F(" Relais 4:")); Serial.println(digitalRead(Relais4pin)); // Zustand Relais 1
    Serial.print(F("10. Endschalter1VEVS:")); Serial.println(Endschalter1VEVSStatus); // Endschalter 1 schließer
    Serial.print(F("11. Endschalter2VEHS:")); Serial.print(Endschalter2VEHSStatus); // Endschalter 2 schließer
    Serial.print(F(" Endschalter2VEOOE:")); Serial.println(Endschalter2VEOOEStatus); // Endschalter 2 öffner
    Serial.print(F("12. Endschalter3HEVS:")); Serial.println(Endschalter3HEVSStatus); // Endschalter 3 schließer
    Serial.print(F("13. Endschalter4HEHS:")); Serial.print(Endschalter4HEHSStatus); // Endschalter 4 schließer
    Serial.print(F(" Endschalter4HEHOE:")); Serial.println(Endschalter4HEHOEStatus); // Endschalter 4 öffner
    Serial.print(F("14. Sturm Ausgelöst:")); Serial.println(windAusgeloest); // Sturm aufgelöst
  }
}

Mal eine Frage kann ich den Wertedurchzähler einfach so anpassen, das er noch geht, aber nicht per Serial ausgegeben wird?

  if (millis() - lastmillis >= intervall)
  {
    // Serial.println(F("Werte durchzaehlen:")); // Serielle Ausgabe deaktiviert
    for (byte i = 0; i < sizeof(umlaufMerker); i++)
    {
      if (umlaufMerker[i] >= windSchwelle) wind++;
      if (umlaufMerker[i] >= sturmSchwelle) sturm++;
      // Serial.print(umlaufMerker[i]);  // Serielle Ausgabe deaktiviert
      // Serial.print(F("\t"));  // Serielle Ausgabe deaktiviert
    }
    // Serial.println(); // Serielle Ausgabe deaktiviert
    lastmillis = millis();
  }

Ich möchte es mal so testen, ob die Serielle übertragung aus diesem Thema dann ohne Probleme geht: