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: