/*
Sonnenstandberechnung und Solartracking,
jetzt mit Arduino-Motor-Shield Rev3.
und Nextion 5.0-Zoll-touch-Display.
Läuft nicht auf dem Arduino-UNO.
Wg. erhöhtem Speicherbedarf ist ein Arduino Mega erforderlich.
Positionsangaben für Ort: Rönkhausen.
Version 3.5, M. Schulte, 15. Januar 2023.
Achtung: Vin max. 7.5 Volt.
Änderung: Servo map-Funktion entfällt.
Neu: LED-Ampel (rot, gelb, grün) konfiguriert:
Ampel: rote LED = Rückwärtslauf, grüne LED = Vorwärtslauf, gelb = Zielposition erreicht, gelb blinkend = schneller Rückwärtslauf.
Änderung: diverse Anpassungen, u.a.Definition Sonnenuntergang (Elevation <= -2).
Azimut-Ist (azimutHall): map-Funktionen neu kalbriert (Ost 252, Süd 488, West 738)
Änderung: neue Variablen: mvOst, mvSued, mvWest
*/

#include <TimeLib.h>
#include <DTutils.h>
#include <Time.h>
#include <Servo.h>
#include <Stepper.h>                                            // Include the Stepper library
#include <Wire.h>
#include <DS3231.h>

#define RTC_I2C_ADDRESS 0x68                                    // I2C Adresse des RTC DS3231
#define pwmA 3
#define pwmB 11
#define dirA 12
#define dirB 13

const int stepsPerRevolution = 200;                             // Define number of steps per revolution

RTCDateTime dt;
DS3231 clock;
Servo servo2;                                                   // Servomotor für Elevation
Stepper myStepper = Stepper(stepsPerRevolution, dirA, dirB);    // Initialize the stepper library on the motor shield


void setup() {

Serial2.begin(9600);
pinMode(pwmA, OUTPUT);                                          // Set the PWM and brake pins so that the direction pins can be used to control the motor:
pinMode(pwmB, OUTPUT);
digitalWrite(pwmA, HIGH);
digitalWrite(pwmB, HIGH);
myStepper.setSpeed(80);                   // Set the motor speed (RPMs)

pinMode(A2, INPUT);                       // Hall-Sensor
pinMode(A15, INPUT);                      // PV-Panel
pinMode(4, OUTPUT);                       // grüne LED, Anschluss an D4
pinMode(6, OUTPUT);                       // gelbe LED, Anschluss an D6
pinMode(7, OUTPUT);                       // rote LED, Anschluss an D7

servo2.attach(5);
servo2.write(3);                          // Servo senkrechte Grundstellung

clock.begin();                            // Starte RTC Uhr

// clock.setDateTime(2022, 11, 26, 19, 57, 30);                // Hier Datum und aktuelle Uhrzeit (MEZ) setzen, danach auskommentieren und sketch neu laden

// Alle Daten des Displays leeren (refresh)

Serial2.print("ref=page0.t0.txt"); // refresh Seite 0 Textfeld 0
endNextionCommand();
Serial2.print("ref=page0.t1.txt"); // refresh Seite 0 Textfeld 1
endNextionCommand();
Serial2.print("ref=page0.t2.txt"); // refresh Seite 0 Textfeld 2
endNextionCommand();
Serial2.print("ref=page0.t3.txt"); // refresh Seite 0 Textfeld 3
endNextionCommand();
Serial2.print("ref=page0.t4.txt"); // refresh Seite 0 Textfeld 4
endNextionCommand();

Serial2.print("ref=page1.t0.txt"); // refresh Seite 1 Textfeld 0
endNextionCommand();
Serial2.print("ref=page1.t1.txt"); // refresh Seite 1 Textfeld 1
endNextionCommand();
Serial2.print("ref=page1.t2.txt"); // refresh Seite 1 Textfeld 2
endNextionCommand();
Serial2.print("ref=page1.t3.txt"); // refresh Seite 1 Textfeld 3
endNextionCommand();
Serial2.print("ref=page1.t4.txt"); // refresh Seite 1 Textfeld 4
endNextionCommand();
Serial2.print("ref=page1.t5.txt"); // refresh Seite 1 Textfeld 5
endNextionCommand();
Serial2.print("ref=page1.t6.txt"); // refresh Seite 1 Textfeld 6
endNextionCommand();

Serial2.print("ref=page2.t0.txt"); // refresh Seite 2 Textfeld 0
endNextionCommand();
Serial2.print("ref=page2.t1.txt"); // refresh Seite 2 Textfeld 1
endNextionCommand();
Serial2.print("ref=page2.t2.txt"); // refresh Seite 2 Textfeld 2
endNextionCommand();
Serial2.print("ref=page2.t3.txt"); // refresh Seite 2 Textfeld 3
endNextionCommand();
Serial2.print("ref=page2.t4.txt"); // refresh Seite 2 Textfeld 4
endNextionCommand();
Serial2.print("ref=page2.t5.txt"); // refresh Seite 2 Textfeld 5
endNextionCommand();
Serial2.print("ref=page2.t6.txt"); // refresh Seite 2 Textfeld 6
endNextionCommand();

Serial2.print("ref=page3.t0.txt"); // refresh Seite 3 Textfeld 0
endNextionCommand();
Serial2.print("ref=page3.t1.txt"); // refresh Seite 3 Textfeld 1
endNextionCommand();
Serial2.print("ref=page3.t2.txt"); // refresh Seite 3 Textfeld 2
endNextionCommand();
}


// Beginn der Schleife

void loop() {

const int stepsV = 16;                               // Anzahl steps Vorwärtslauf, ca. +0.5°
const int stepsR = -16;                              // Anzahl steps Rückwärtslauf, ca. -0.5°
const int stepsSR = -500;                            // Anzahl steps schneller Rücklauf, ca. -15°

dt = clock.getDateTime();                            // Zeitwert holen von RTC Echtzeituhr

String hour = clock.dateFormat("H", dt);
String minute = clock.dateFormat("i", dt);
String year = clock.dateFormat("z", dt);
String second = clock.dateFormat("s", dt);

int Jahr = (dt.year);
int Monat = (dt.month);
int Tag = (dt.day);
float Stunde = hour.toInt();
float Minute = minute.toInt();
float Sekunde = second.toInt();

int yearday = DayOfYear(Jahr, Monat, Tag);

// Kalibrierung Hall-Sensor

int mvOst = 252;
int mvSued = 488;                                   // 06.12.22, neu kalibriert
int mvWest = 738;

float Elevation;
float elevation;
float Aufgang;
float Untergang;
float Deklination;
float AzS;
float Zeitgleichung;
float Zeitdifferenz;
float AufgangOrtszeit;
float UntergangOrtszeit;
float Tageslaenge;
float Refraktion;
float MEZ;                                          // Mitteleuropäische Zeit
float MOZ;                                          // Mittlere Ortszeit
float WOZ;                                          // Wahre Ortszeit
float ZeitSeitMittag;

const float pi = 3.14159265;
const float kwert = pi / 180;
const float latitude = 51.222191;
const float longitude = 7.954169;
const float B = latitude * kwert;                                                  // geogr. Breite in Radians
const float h = -(50.0 / 60.0) * kwert;                                            // Höhe des Sonnenmittelpunkts bei Aufgang
const int Zeitzone = 1;                                                            // Zeitzone Greenwich + 1 (z.B. Berlin)

int Grenzwert;
int AzI;
int sensorValue;                                                                   // Analoger Ist-Wert (Hall-Sensor)
int i2;

MEZ = Stunde + Minute / 60 + Sekunde / 3600;                                       // Mitteleuropäische Zeit

Zeitgleichung = BerechneZeitgleichung (yearday);                                   // Aufruf der Funktion: BerechneZeitgleichung
ZeitSeitMittag = MEZ + longitude / 15.0 - Zeitzone - 12 + Zeitgleichung;           // Berechne ZeitSeitMittag
Deklination = BerechneDeklination (yearday);                                       // Aufruf der Funktion: BerechneDeklination
Zeitdifferenz = BerechneZeitdifferenz (h, pi, latitude, kwert, Deklination);       // Aufruf der Funktion: BerechneZeitdifferenz
AzS = SunAngles(Deklination, B, kwert, pi, ZeitSeitMittag, Elevation);             // Aufruf der Funktion: SunAngles
Tageslaenge = BerechneTageslaenge (Zeitdifferenz, Zeitgleichung, longitude, Zeitzone, Aufgang, Untergang);    // Aufruf der Funktion: BerechneTageslaenge

Elevation = Elevation / kwert;
Deklination = Deklination / kwert;

MOZ = MEZ - (-longitude / 15) - 1;                                                 // Berechne Mittlere Ortszeit aus MEZ
WOZ = MOZ + Zeitgleichung;                                                         // Berechne Wahre Ortszeit

int WOZdez = (int)WOZ;
int WOZmin = (WOZ - WOZdez) * 60;

int MOZdez = (int)MOZ;
int MOZmin = (MOZ - MOZdez) * 60;

int StdL = (int)Tageslaenge;
int MinL = (int)((Tageslaenge - StdL) * 60);

int StdA = (int)Aufgang;
int MinA = (int)((Aufgang - StdA) * 60);

int StdU = (int)Untergang;
int MinU = (int)((Untergang - StdU) * 60);

if (StdL >= 7 && StdL < 9) {
Grenzwert = 135;
}; // Grenzwerte für Rücklaufposition
if (StdL >= 9 && StdL < 10) {
Grenzwert = 120;
}; // abhängig von der Tageslänge (nur Stunde)
if (StdL >= 10 && StdL < 11) {
Grenzwert = 104;
};
if (StdL >= 11 && StdL < 13) {
Grenzwert = 90;
};
if (StdL >= 13 && StdL < 14) {
Grenzwert = 75;
};
if (StdL >= 14 && StdL < 15) {
Grenzwert = 60;
};
if (StdL >= 15 && StdL < 17) {
Grenzwert = 45;
};

sensorValue = analogRead(A2);                                        // Auslesen Hall-Sensor an Pin A2

AzI = MotorenSteuerung (AzS, Elevation, sensorValue, Grenzwert, stepsV, stepsR, stepsSR, mvOst, mvSued, mvWest); // Aufruf der Funktion: MotorenSteuerung


// Für Anzeige Windrichtung, abhängig von der Position des Drehtellers

const char* windrichtung[16] = {"Nord", "NNO", "NO", "ONO", "Ost", "OSO", "SO", "SSO", "Sued", "SSW", "SW", "WSW", "West", "WNW", "NW", "NNW"};

int i1 = Windrichtung(AzI, AzS, i2);                                 // Aufruf Funktion: Windrichtung
String wr1 = windrichtung[i1];
String wr2 = windrichtung[i2];

// 5-Volt-Solarpanel

const int analogPin = A15;
float pvmod = analogRead(analogPin);
float Volt = Solarspannung (pvmod);                                  // Aufruf Funktion: Solarspannung
float Prozent = Volt / 4.75 * 100;

// für Anzeige: Stunden, Minuten, Deklination

int Std = (int)Tageslaenge;
int Min = (int)((Tageslaenge - Std) * 60);


// Ausgabe auf Nextion-Display 5.0""

// Seite 0: Home

Serial2.print("page0.t0.txt=\"");
Serial2.print("Nextion-Solartracker-Projekt");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page0.t0.txt");
endNextionCommand();

Serial2.print("page0.t1.txt=\"");
Serial2.print("Version 3.5 vom 15.01.2023");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page0.t1.txt");
endNextionCommand();

Serial2.print("page0.t2.txt=\"");
Serial2.print("Dr. Michael Schulte");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page0.t2.txt");
endNextionCommand();

Serial2.print("page0.t3.txt=\"");
Serial2.print("http://wetterstation.mi-schu.de");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page0.t5.txt");
endNextionCommand();

Serial2.print("page0.t4.txt=\"");
Serial2.print("E-Mail: wetter.roenkhausen@gmx.de");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page0.t4.txt");
endNextionCommand();

// Seite 1: Time

Serial2.print("page1.t0.txt=\"");
Serial2.print(clock.dateFormat(" d. M. Y H:i:s", dt));
Serial2.print(" MEZ");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page1.t0.txt");
endNextionCommand();

Serial2.print("page1.t1.txt=\"");
if (WOZmin >= 0 && WOZmin < 10) {
Serial2.print(" Wahre Ortszeit: " + String (WOZdez) + ":" + "0" + String (WOZmin) + " h");
}
else
{ Serial2.print(" Wahre Ortszeit: " + String (WOZdez) + ":" + String (WOZmin) + " h");
}
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page1.t1.txt");
endNextionCommand();

Serial2.print("page1.t2.txt=\"");
if (MOZmin >= 0 && MOZmin < 10) {
Serial2.print(" Mittlere Ortszeit: " + String (MOZdez) + ":" + "0" + String (MOZmin) + " h");
}
else
{ Serial2.print(" Mittlere Ortszeit: " + String (MOZdez) + ":" + String (MOZmin) + " h");
}
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page1.t2.txt");
endNextionCommand();

Serial2.print("page1.t3.txt=\"");
Serial2.print(" Tag im Jahr: " + String(yearday));
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page0.t3.txt");
endNextionCommand();

Serial2.print("page1.t4.txt=\"");
if (MinA >= 0 && MinA < 10) {
Serial2.print(" Sonnenaufgang: " + String (StdA) + ":" + "0" + String (MinA) + " h");
}
else
{ Serial2.print(" Sonnenaufgang: " + String (StdA) + ":" + String (MinA) + " h");
}
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page1.t4.txt");
endNextionCommand();

Serial2.print("page1.t5.txt=\"");
if (MinU >= 0 && MinU < 10) {
Serial2.println(" Sonnenuntergang: " + String (StdU) + ":" + "0" + String (MinU) + " h");
}
else
{ Serial2.println(" Sonnenuntergang: " + String (StdU) + ":" + String (MinU) + " h");
}
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page1.t5.txt");
endNextionCommand();

Serial2.print("page1.t6.txt=\"");
if (MinL >= 0 && MinL < 10) {
Serial2.print(" Tageslaenge: " + String (StdL) + ":" + "0" + String (MinL) + " h");
}
else
{ Serial2.print(" Tageslaenge: " + String (StdL) + ":" + String (MinL) + " h");
}
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page1.t6.txt");
endNextionCommand();

// Seite 2: Data

Serial2.print("page2.t0.txt=\"");
Serial2.print(clock.dateFormat(" d. M. Y H:i:s", dt));
Serial2.print(" MEZ");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t0.txt");
endNextionCommand();

Serial2.print("page2.t1.txt=\"");
Serial2.print(" Azimut-Soll: " + String(AzS) + " Grd " + "(" + String(wr2) + ")");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t1.txt");
endNextionCommand();

Serial2.print("page2.t2.txt=\"");
Serial2.print(" Azimut-Ist (Panel): " + String(AzI) + ".00 Grd " + "(" + String(wr1) + ")");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t2.txt");
endNextionCommand();

Serial2.print("page2.t3.txt=\"");
Serial2.print(" Elevation: " + String(Elevation) + " Grd");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref = page2.t3.txt");
endNextionCommand();

Serial2.print("page2.t4.txt=\"");
Serial2.print(" Deklination: " + String(Deklination) + " Grd");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t4.txt");
endNextionCommand();

Serial2.print("page2.t5.txt=\"");
Serial2.print(" Zeitgleichung: " + String(Zeitgleichung * 60) + " min");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t5.txt");
endNextionCommand();

Serial2.print("page2.t6.txt=\"");
Serial2.print(" Solarspannung: " + String(Volt) + " V " + "(" + String (int (Prozent)) + "% Vmax" + ")");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t6.txt");
endNextionCommand();

// Seite 3: Sun

Serial2.print("page3.t0.txt=\"");
Serial2.print(" Azimut-Soll: " + String(AzS) + " Grd");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref = page3.t5.txt");
endNextionCommand();

Serial2.print("page3.t1.txt=\"");
Serial2.print(" Azimut-Ist: " + String(AzI) + "      Grd");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t2.txt");
endNextionCommand();

Serial2.print("page3.t2.txt=\"");
Serial2.print(" Elevation:    " + String(Elevation) + "    Grd");
Serial2.write('"');
endNextionCommand();
Serial2.print("ref=page2.t5.txt");
endNextionCommand();
}


void endNextionCommand()
{
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);
}


// Funktion: Windrichtung

int Windrichtung (float AzI, float AzS, int &i2) {
int i1;
if (AzI >= 0 && AzI < 11) {
i1 = 0;
}
if (AzS >= 0 && AzS < 11) {
i2 = 0;
}
if (AzI >= 11 && AzI < 34) {
i1 = 1;
}
if (AzS >= 11 && AzS < 34) {
i2 = 1;
}
if (AzI >= 34 && AzI < 56) {
i1 = 2;
}
if (AzS >= 34 && AzS < 56) {
i2 = 2;
}
if (AzI >= 56 && AzI < 79) {
i1 = 3;
}
if (AzS >= 56 && AzS < 79) {
i2 = 3;
}
if (AzI >= 79 && AzI < 101) {
i1 = 4;
}
if (AzS >= 79 && AzS < 101) {
i2 = 4;
}
if (AzI >= 101 && AzI < 124) {
i1 = 5;
}
if (AzS >= 101 && AzS < 124) {
i2 = 5;
}
if (AzI >= 124 && AzI < 146) {
i1 = 6;
}
if (AzS >= 124 && AzS < 146) {
i2 = 6;
}
if (AzI >= 146 && AzI < 169) {
i1 = 7;
}
if (AzS >= 146 && AzS < 169) {
i2 = 7;
}
if (AzI >= 169 && AzI < 191) {
i1 = 8;
}
if (AzS >= 169 && AzS < 191) {
i2 = 8;
}
if (AzI >= 191 && AzI < 214) {
i1 = 9;
}
if (AzS >= 191 && AzS < 214) {
i2 = 9;
}
if (AzI >= 214 && AzI < 236) {
i1 = 10;
}
if (AzS >= 214 && AzS < 236) {
i2 = 10;
}
if (AzI >= 236 && AzI < 259) {
i1 = 11;
}
if (AzS >= 236 && AzS < 259) {
i2 = 11;
}
if (AzI >= 259 && AzI < 281) {
i1 = 12;
}
if (AzS >= 259 && AzS < 281) {
i2 = 12;
}
if (AzI >= 281 && AzI < 304) {
i1 = 13;
}
if (AzS >= 281 && AzS < 304) {
i2 = 13;
}
if (AzI >= 304 && AzI < 326) {
i1 = 14;
}
if (AzS >= 304 && AzS < 326) {
i2 = 14;
}
if (AzI >= 326 && AzI < 349) {
i1 = 15;
}
if (AzS >= 326 && AzS < 349) {
i2 = 15;
}
return i1;
}


// Funktion: SunAngles für die Berechnung von Azimut und Elevation

float SunAngles (float Deklination, float B, float kwert, float pi, float ZeitSeitMittag, float & Elevation) {
float DK = Deklination;
float cosdec = cos(DK);
float sindec = sin(DK);
float lha = ZeitSeitMittag * (1.0027379 - 1 / 365.25) * 15 * kwert;
float coslha = cos(lha);
float sinlha = sin(lha);
float coslat = cos(B);
float sinlat = sin(B);
float N = -cosdec * sinlha;
float D = sindec * coslat - cosdec * coslha * sinlat;
Elevation = asin(sindec * sinlat + cosdec * coslha * coslat);                  // Höhe des Sonnenmittelpunktes über dem Horizont
float AzS = atan2(N, D);
if (AzS < 0) {
AzS += 2 * pi;
}
return (AzS / kwert);
}


// Funktion: BerechneZeitgleichung

float BerechneZeitgleichung (int yearday) {
float Zeitgleichung = -0.170869921174742 * sin(0.0336997028793971 * yearday + 0.465419984181394) - 0.129890681040717 * sin(0.0178674832556871 * yearday - 0.167936777524864);
return Zeitgleichung;
}


// Funktion: BerechneDeklination

float BerechneDeklination(int yearday) {
float Deklination = 0.409526325277017 * sin(0.0169060504029192 * (yearday - 80.0856919827619));
return Deklination;
}


// Funktion: BerechneZeitdifferenz

float BerechneZeitdifferenz(float h, float pi, float latitude, float kwert, float Deklination) {
float Zeitdifferenz;
Zeitdifferenz = 12 * acos((sin(h) - sin(latitude * kwert) * sin(Deklination)) / (cos(latitude * kwert) * cos(Deklination))) / pi;
return Zeitdifferenz;
}


// Funktion: BerechneTageslaenge

float BerechneTageslaenge (float Zeitdifferenz, float Zeitgleichung, float longitude, int Zeitzone, float & Aufgang, float & Untergang) {
float AufgangOrtszeit = 12 - Zeitdifferenz - Zeitgleichung;
float UntergangOrtszeit = 12 + Zeitdifferenz - Zeitgleichung;
Aufgang = AufgangOrtszeit - longitude / 15 + Zeitzone;
Untergang = UntergangOrtszeit - longitude / 15 + Zeitzone;
float Tageslaenge = Untergang - Aufgang;
return Tageslaenge;
}


// Funktion: MotorenSteuerung, Ansteuerung von Steppermotor und Servo

int MotorenSteuerung (float AzS, float Elevation, int sensorValue, int Grenzwert, const int stepsV, const int stepsR, const int stepsSR, const int mvOst, const int mvSued, const int mvWest)
{
float AzI;
constrain(Elevation, 0, 120);                                        // Begrenzung des Servo-Wertebereichs

if (sensorValue >= 0 && sensorValue < mvSued) {
AzI = map(sensorValue, mvOst, mvSued, 90, 180);                      // 03.12.22, neu kalibriert: Skalierung der Hall-Sensorwerte in Gradwerte 90-180 Grad
}
if (sensorValue >= mvSued && sensorValue <= 900) {
AzI = map(sensorValue, mvSued, mvWest, 180, 270);                    // 03.12.22, neu kalibriert: Skalierung der Hall-Sensorwerte in Gradwerte 180-270 Grad
}
constrain(AzI, 40, 320);                                             // Begrenzung des Azimut-Soll-Wertebereichs
if (Elevation > -2) {                                                // Solange Elevation > 0 --> Sonne steht über dem Horizont
servo2.write(Elevation - 3);                                         // Schreiben der Servoposition (Nachführung)


if ((int)AzI < (int)AzS) {                                           // Azimut-Nachführung: Wenn Hall-Sensorwert kleiner als Azimut, dann:
digitalWrite(pwmA, HIGH);                                            // Stepper Strom an
digitalWrite(pwmB, HIGH);                                            // Stepper Strom an
digitalWrite(4, HIGH);                                               // LED grün an
myStepper.step(stepsV);                                              // Step one revolution in one direction
delay (500);
digitalWrite(4, LOW);                                                // LED grün aus
digitalWrite(7, LOW);                                                // LED rot aus
digitalWrite(6, LOW);                                                // LED gelb aus
digitalWrite(pwmA, LOW);                                             // Stepper stromlos schalten
digitalWrite(pwmB, LOW);                                             // Stepper stromlos schalten
}
if ((int)AzI > (int)AzS) {                                           // Azimut-Nachführung: Wenn Hall-Sensorwert grösser als Azimut, dann:
digitalWrite(pwmA, HIGH);                                            // Stepper Strom an
digitalWrite(pwmB, HIGH);                                            // Stepper Strom an
servo2.write(Elevation - 3);                                         // Schreiben der Servoposition (Nachführung)
digitalWrite(7, HIGH);                                               // LED rot an
digitalWrite(6, LOW);                                                // LED gelb aus
myStepper.step(stepsR);                                              // Step one revolution in one direction
delay (500);
digitalWrite(7, LOW);                                                // LED rot aus
digitalWrite(4, LOW);                                                // LED grün aus
digitalWrite(pwmA, LOW);                                             // Stepper stromlos schalten
digitalWrite(pwmB, LOW);                                             // Stepper stromlos schalten
}
}
else {                                                               // Sonne ist untergegangen --> Rückführung auf Anfangsposition
if (Elevation <= -2 && (AzI - 2) >= Grenzwert) {                     // Azimut-Rückführung: Wenn Elevation < -1 (Sonne ist vollständig untergegangen), dann:
delay(500);
digitalWrite(pwmA, HIGH);
digitalWrite(pwmB, HIGH);
digitalWrite(6, HIGH);                                               // LED gelb an
myStepper.step(stepsSR);                                             // Step one revolution in one direction
delay (500);
digitalWrite(6, LOW);                                                // LED gelb aus
delay(500);
digitalWrite(6, HIGH);                                               // LED gelb an
delay(500);
digitalWrite(6, LOW);                                                // LED gelb aus
delay(500);
digitalWrite(6, HIGH);                                               // LED gelb an
delay (500);
digitalWrite(6, LOW);                                                // LED gelb aus
delay(500);
digitalWrite(6, HIGH);                                               // LED gelb an
delay (500);
digitalWrite(6, LOW);                                                // LED gelb aus
digitalWrite(pwmA, LOW);                                             // Stepper stromlos schalten
digitalWrite(pwmB, LOW);                                             // Stepper stromlos schalten
delay(500);
}
}
if (int(AzI) == int(AzS)) {                                          // Stepper aus gelbe LED an beim Erreichen der Zielposition (AzI == AzS)
digitalWrite(6, HIGH);
digitalWrite(pwmA, LOW);                                             // Stepper stromlos schalten
digitalWrite(pwmB, LOW);                                             // Stepper stromlos schalten
}
return AzI;                                                          // Rückgabewert: AzimutIst
}


// Funktion: Solarspannung

float Solarspannung(float pvmod)                                     // Funktion: Solarspannung
{
float Volt;
Volt = pvmod / 1023 * 4.75;                                          // Umrechnung Analogwert in Spannungswert (Volt)
return Volt;
}