ESP32: Ladestation mit automatischer Solarpanel-Ausrichtung

Im letzten Sommer habe ich mir ein kleines Solarmodul zugelegt. In der Gebrauchsanleitung steht, es sollte nach Süden und mit einem Neigungswinkel von 35% ausrichten werden, um über einen einen Solar Power Manager Modul ein 3,7 Volt Akku zu laden.
Um es jedoch tagsüber immer in Richtung Sonne auszurichten, dachte ich mir, probiere doch mal mit einem Lux-Sensor und zwei Servos, das zu automatisieren.


Wie immer habe ich mich Schritt für Schritt vorgetastet. Erst den Lichtsensor getestet, dann die Servo Motoren. Spannend war dann das Zusammenspiel der Komponenten, um den hellsten Punkt ausfindig zu machen.
Das wichtigste wurde hier dokumentiert und ich hoffe es inspiriert den ein oder anderen, sich seine eigene Version nachzubauen.
Als die Version 1 mit einem Arduino fertig gestellt war und funktionierte, habe ich gleich eine zweite Version mit einem ESP32 Board erstellt, mit der Absicht, das wenn es in den Sleep Modus gebracht wird, weniger Strom verbraucht wird und somit das Aufladen des Akku effizienter ausführt.

Wie kann ich jetzt aber Licht messen?
Die effizienteste Wellenlänge für die gängigsten Solarzellen liegt im sichtbaren Bereich des Lichtspektrums. Ein Lichtstrom von 1 Lumen, der auf eine Fläche von 1 m2 trifft, beleuchtet diese (gemittelt) mit 1 Lux.
Beleuchtungsstärke – Wikipedia

Somit zuerst die Suche nach einem brauchbaren Lichtsensor.


Hardware 1: Licht Messung mit dem GY-30

Das Lichtsensor-Breakout-Board GY-30 / BH1750FVI hat eine Fotodiode die einen großen Teil des sichtbarem Licht von ca. 400 – 700 nm erfassen kann. Um so heller das Licht scheint, um so höher ist der vom 16 Bit analog digital Wandler ausgegebene Lux-Wert. Es kann Dauer oder Einzelmessungen ausführen. Angesprochen wird es über I2C und wird mit 3,3 Volt bis 5 Volt Spannung versorgt.
Datenblatt Lichtsensor GY-30

Verdrahtung Teil 1:

Quellcode für Lichtsensor Test:

Erste Licht-Messung in Lux.

#include "BH1750FVI.h"

BH1750FVI myLux(0x23);
uint32_t lastUpdate = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.print(__FILE__);// liefert den Pfad zur aktuellen Datei
  Serial.println();

  Wire.begin();   // für arduino uno
  // Wire.begin(23,19);   // für lolin32 lite an SDA (Serial Data): Pin 23 und SCL (Serial Clock): Pin 19

  myLux.powerOn();
  myLux.setContHighRes();  // Für kontinuierliche Messung
  // myLux.setOnceHighRes();// Für einmalige Messung - Stromsparmodus
}

void loop()
{
  uint16_t interval = 100;
  if (millis() - lastUpdate >= interval)
  {
    lastUpdate += interval;
    float val = myLux.getLux();
    Serial.println(val, 1);
  }
delay(1000);
// myLux.setOnceHighRes();// Für einmalige Messung - Stromsparmodus
}

Eine weitere Erkenntnis war, das die Bibliothek für den Lichtsensor die Möglichkeit bietet, auch einmalige Messung auszuführen, um danach Strom zu sparen. Somit muss dann aber auch immer bei jeder Neumessung myLux.setOnceHighRes(); eingetragen werden. Eine Messung mit dem USB-Spannungsprüfer zeigte aber keine Veränderung. Somit habe ich das erst mal vernachlässigt.


Hardware 2: Der Servo MG996R
Der MG996R ist ein digitaler Mikroservomotor, der für seine Verwendung in ferngesteuerten Robotern, Hubschraubern und Flugzeugen bekannt ist.
Er verfügt über ein Metallgetriebe für erhöhte Haltbarkeit und kann sich in einem Bereich von etwa 180 Grad drehen. Seine Position kann mit hoher Genauigkeit gesteuert werden.
Aufgrund seiner geringen Kosten und einfachen Handhabung ist er bei Bastlern und somit bei mir beliebt.
Datenblatt des Servo

Verdrahtung Teil 2:

Quellcode
Erstmal ein Test mit nur einen Servo:

#include <Servo.h> //für Arduino Uno


Servo servo; // Servo-Objekt erstellen für Arduino

const int servoPin = 9; // servo1 gelb unten horizontal an Pin 9

void setup() {
  servo.attach(servoPin); // 
}

void loop() {
  servo.write(0); // move MG996R's shaft to angle 0°
  delay(1000); // wait for one second
  servo.write(45); // move MG996R's shaft to angle 45°
  delay(1000); // wait for one second 
  servo.write(90); // move MG996R's shaft to angle 90°
  delay(1000); // wait for one second
  servo.write(135); // move MG996R's shaft to angle 135°
  delay(1000); // wait for one second
  servo.write(180); // move MG996R's shaft to angle 180°
  delay(1000); // wait for one second
}

Nun der Test mit zwei Servo´s:

#include <Servo.h> 

Servo servo1; // der MG 996R servo1
Servo servo2; // der MG 996R servo2

void setup() {
  servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  servo2.attach(10); // orange servo2 oben vertikal an Pin 10
}

void loop() {
  servo2.write(45); // move MG996R's shaft to angle 0°
  delay(1000); // wait for one second
  servo1.write(45); // move MG996R's shaft to angle 45°
  delay(1000); // wait for one second 
  servo2.write(90); // move MG996R's shaft to angle 90°
  delay(1000); // wait for one second
  servo1.write(90); // move MG996R's shaft to angle 135°
  delay(1000); // wait for one second
  servo2.write(135); // move MG996R's shaft to angle 180°
  delay(1000); // wait for one second
  servo1.write(135); // move MG996R's shaft to angle 180°
  delay(1000); // wait for one second
}


Dritter Test:
Lichtsensor steuert Servo, GY-30 und MG996r zusammen

Nun Lichtsensor und beide Servo´s zusammen, für erste horizontale Abtastung, um den hellsten Punkt zu finden.

Verdrahtung Teil 3:

Quellcodes für Abtastung:

Test Abtastung hellster Punkt horizontal

#include "BH1750FVI.h"
#include <Servo.h>

BH1750FVI myLux(0x23);
uint32_t lastUpdate = 0;

Servo servo1; // der MG996R servo1
Servo servo2; // der MG996R servo2

void setup(){
  Wire.begin();
  myLux.powerOn();
  myLux.setContHighRes();
  servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  servo2.attach(10); // orange servo2 oben vertikal an Pin 10
}

void loop() {
  int maxLightIntensity = 0;  // Maximal gemessene Lichtintensität
  int maxAngle = 0;  // Winkel mit der höchsten Lichtintensität

  // Durchlaufe alle Winkel von 0 bis 180 Grad
  for(int angle = 0; angle <= 180; angle += 10){
    servo1.write(angle);  // Drehe den Servo auf den aktuellen Winkel
    delay(200);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity){
      maxLightIntensity = lux;
      maxAngle = angle;
    }
  }

  // Drehe den Servo auf den Winkel mit der höchsten Lichtintensität
  servo1.write(maxAngle);
  delay(10000);  // Warte einen Moment, bevor der nächste Durchlauf beginnt
}

Test Abtastung hellster Punkt horizontal und vertikal

#include "BH1750FVI.h"
#include <Servo.h>

BH1750FVI myLux(0x23);

Servo servo1; // der MG 996R servo1
Servo servo2; // der MG 996R servo2

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print(__FILE__);// liefert den Pfad zur aktuellen Datei
  Serial.println();

  Wire.begin();
  myLux.powerOn();
  myLux.setContHighRes();
  servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  servo1.write(90);
  servo2.write(90);
}

void loop() {
  int maxLightIntensity1 = 0;  // Maximal gemessene Lichtintensität horizontal
  int maxAngle1 = 0;  // Winkel mit der höchsten Lichtintensität horizontal
  int maxLightIntensity2 = 0;  // Maximal gemessene Lichtintensität vertikal
  int maxAngle2 = 0;  // Winkel mit der höchsten Lichtintensität vertikal

  // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal
  for(int angle1 = 0; angle1 <= 180; angle1 += 10){
    servo1.write(angle1);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity1){
      maxLightIntensity1 = lux;
      maxAngle1 = angle1;
      Serial.print("MaxLux1: ");
      Serial.println(maxLightIntensity1, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle1, 1);
    }
  }

    // Durchlaufe alle Winkel von 0 bis 180 Grad vertikal
  for(int angle2 = 20; angle2 <= 160; angle2 += 10){
    servo2.write(angle2);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity2){
      maxLightIntensity2 = lux;
      maxAngle2 = angle2;
      Serial.print("MaxLux2: ");
      Serial.println(maxLightIntensity2, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle2, 1);
    }
  }

  // Drehe den Servo auf den Winkel mit der höchsten Lichtintensität
  servo1.write(maxAngle1);
  servo2.write(maxAngle2);
  Serial.print("Bester Winkel 1 und 2 : ");
  Serial.print(maxAngle1, 1);
  Serial.print(" und ");
  Serial.println(maxAngle2, 1);
  delay(10000);  // Warte einen Moment, bevor der nächste Durchlauf beginnt
}

Um bei den 180 Grad Servo´s auch eine 360 Grad rundum Abtastung zu erlangen, nun 3 Durchläufe.

1. Durchlauf alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad vertikal
2. Durchlauf alle Winkel von 0 bis 180 Grad horizontal bei 145 Grad vertikal
3. Durchlauf alle Winkel von 0 bis 180 Grad vertikal mit bester Wert bei horizontal

#include "BH1750FVI.h"
#include <Servo.h>

BH1750FVI myLux(0x23);

Servo servo1; // der MG 996R servo1
Servo servo2; // der MG 996R servo2

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print(__FILE__); // liefert den Pfad zur aktuellen Datei
  Serial.println();

  Wire.begin();
  myLux.powerOn();
  myLux.setContHighRes(); // Für kontinuierliche Messung
  servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  servo1.write(90);
  servo2.write(90);
}

void loop() {
  int maxLightIntensity1 = 0;  // Maximal gemessene Lichtintensität horizontal
  int maxAngle1 = 0;  // Winkel mit der höchsten Lichtintensität horizontal
  int maxLightIntensity2 = 0;  // Maximal gemessene Lichtintensität vertikal
  int maxAngle2 = 0;  // Winkel mit der höchsten Lichtintensität vertikal

  // Durchlauf alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad
   servo2.write(35);
  for(int angle1 = 0; angle1 <= 180; angle1 += 10){
    servo1.write(angle1);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity1){
      maxLightIntensity1 = lux;
      maxAngle1 = angle1;
      Serial.print("MaxLux1: ");
      Serial.println(maxLightIntensity1, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle1, 1);
    }
  }

// Durchlauf alle Winkel von 0 bis 180 Grad horizontal bei 145 Grad
   servo2.write(145);
  for(int angle1 = 180; angle1 >= 0; angle1 -= 10){
    servo1.write(angle1);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity1){
      maxLightIntensity1 = lux;
      maxAngle1 = angle1;
      Serial.print("MaxLux1: ");
      Serial.println(maxLightIntensity1, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle1, 1);
    }
  }
    // Durchlauf alle Winkel von 0 bis 180 Grad vertikal mit bester Wert bei horizontal
    servo1.write(maxAngle1);
  for(int angle2 = 30; angle2 <= 150; angle2 += 10){
    servo2.write(angle2);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity2){
      maxLightIntensity2 = lux;
      maxAngle2 = angle2;
      Serial.print("MaxLux2: ");
      Serial.println(maxLightIntensity2, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle2, 1);
    }
  }

  // Drehe den Servo auf den Winkel mit der höchsten Lichtintensität
 
  servo1.write(maxAngle1);
  servo2.write(maxAngle2);
  Serial.print("Bester Winkel 1 und 2 : ");
  Serial.print(maxAngle1, 1);
  Serial.print(" und ");
  Serial.println(maxAngle2, 1);
  delay(300000);  // Warte 5 Minuten, bevor der nächste Durchlauf beginnt
}

Versuch den Vorgang zu Beschleunigen:
Verkürzung der Messung wenn maximaler Wert gefunden. (Im Langzeit Test je nach Bewölkung nicht so erfolgreich)

#include "BH1750FVI.h"
#include <Servo.h>

BH1750FVI myLux(0x23);

Servo servo1; // der MG 996R servo1
Servo servo2; // der MG 996R servo2

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print(__FILE__); // liefert den Pfad zur aktuellen Datei
  Serial.println();

  Wire.begin();
  myLux.powerOn();
  myLux.setContHighRes();
  servo1.attach(9); // servo1 ist am Arduino an Pin 9
  servo2.attach(10); // orange servo2 oben vertikal an Pin 10

}

void loop() {
  int maxLightIntensity1 = 0;  // Maximal gemessene Lichtintensität horizontal
  int maxAngle1 = 0;  // Winkel mit der höchsten Lichtintensität horizontal
  int maxLightIntensity2 = 0;  // Maximal gemessene Lichtintensität vertikal
  int maxAngle2 = 0;  // Winkel mit der höchsten Lichtintensität vertikal

  // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad
   servo2.write(35);
  for(int angle1 = 0; angle1 <= 180; angle1 += 10){
    servo1.write(angle1);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity1){
      maxLightIntensity1 = lux;
      maxAngle1 = angle1;
      Serial.print("MaxLux1: ");
      Serial.println(maxLightIntensity1, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle1, 1);
    }
    else if(lux < maxLightIntensity1){        // Bei abnehmender Helligkeit, breche die Schleife ab
        break;
        }
  }

// Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 120 Grad
   servo2.write(120);
  for(int angle1 = 180; angle1 >= 0; angle1 -= 10){
    servo1.write(angle1);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity1){
      maxLightIntensity1 = lux;
      maxAngle1 = angle1;
      Serial.print("MaxLux1: ");
      Serial.println(maxLightIntensity1, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle1, 1);
    }
    else if(lux < maxLightIntensity1){        // Bei abnehmender Helligkeit, breche die Schleife ab
        break;
        }
  }
    // Durchlaufe alle Winkel von 0 bis 180 Grad vertikal
    servo1.write(maxAngle1);
  for(int angle2 = 30; angle2 <= 150; angle2 += 10){
    servo2.write(angle2);  // Drehe den Servo auf den aktuellen Winkel
    delay(500);  // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if(lux > maxLightIntensity2){
      maxLightIntensity2 = lux;
      maxAngle2 = angle2;
      Serial.print("MaxLux2: ");
      Serial.println(maxLightIntensity2, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxAngle2, 1);
    }
    else if(lux < maxLightIntensity2){        // Bei abnehmender Helligkeit, breche die Schleife ab
        break;
        }
  }

  // Drehe den Servo auf den Winkel mit der höchsten Lichtintensität
 
  servo1.write(maxAngle1);
  servo2.write(maxAngle2);
  Serial.print("Bester Winkel 1 und 2 : ");
  Serial.print(maxAngle1, 1);
  Serial.print(" und ");
  Serial.println(maxAngle2, 1);
  delay(300000);  // Warte 5 Minuten, bevor der nächste Durchlauf beginnt
}

Soweit hat nun fast alles funktioniert. Als derzeit finale Version nehme ich die Suche nach besten Winkel in 3 Durchläufen.
Jetzt noch den Servo Power Manager und das Akku angeschlossen (Verdrahtung bei Lolin32 zu sehen) und los geht es mit dem Strom anzapfen. Arduino Eigenverbrach liegt bei 0,058Ah.

Fertig ist die Arduino Version


Zweite Version mit ESP32 Board Lolin32 Lite

In dieser zweiten Version habe ich das Arduino Board gegen einen Lolin32 Lite ausgetauscht. Ich will mal in einen längeren Test prüfen, ob wenn das Board in den Sleep Modus gebracht wird, problemlos mit den Servo Motoren läuft. Erste Messungen zeigen das in der „Schlafenszeit“ der Verbrauch von 0,052Ah auf 0,008Ah.

Verdrahtung mit Lolin32 Lite:

Lichtsensor Test:
Den Sketch zum testen der Licht Messung, ist identisch zur Arduino Version, es muss lediglich die Zeile wire.begin() in der Setup mit Pin-Nummer für SDA (Serial Data) an Pin 23 und SCL (Serial Clock) an Pin 19 ergänzt werden.

Quellcode Servo Test am Lolin32:

Hier der Sketch für den zweiten Servotest mit Library esp32servo (Version 1.1.2) und zur Prüfung ob irgend ein Kabel zu stramm oder im Weg ist.

#include <Arduino.h>
#include <ESP32Servo.h> // Die ESP32Servo-Bibliothek einbinden

const int servoPin1 = 5; // gelb servo 1 unten horizontal an Pin 5
const int servoPin2 = 18; // orange servo 2 oben vertikal an Pin 18

Servo myServo1; // Servo1-Objekt erstellen
Servo myServo2; // Servo2-Objekt erstellen

void setup() {
    
    myServo1.attach(servoPin1); 
    myServo2.attach(servoPin2);
}

void loop() {
    myServo2.write(90); // Servo 2 auf 90 Grad (Mittelstellung) drehen
    delay(5000);
    myServo1.write(90); // Servo1 auf 90 Grad (Mittelstellung) drehen
    delay(5000); // 5 Sekunde warten
    myServo1.write(0);
    delay(5000);
    myServo1.write(180);
    delay(5000);

    myServo2.write(30); // Servo 2 auf 30 Grad drehen
    delay(5000);
    myServo1.write(0);
    delay(5000); 
    myServo1.write(90);
    delay(5000);
    myServo1.write(180);
    delay(5000);

    myServo2.write(150); // Servo 2 auf 150 Grad drehen
    delay(5000);
    myServo1.write(0);
    delay(5000); 
    myServo1.write(90);
    delay(5000);
    myServo1.write(180);
    delay(5000);
}

Quellcode finale Version beim Lolin32:
Hier mein aktueller finaler Sketch mit deaktivierter Möglichkeit den Scanablauf zu verkürzen:

#include "BH1750FVI.h"
#include <Arduino.h>
#include <ESP32Servo.h>  // Die ESP32Servo-Bibliothek einbinden
 
const int servoPin1 = 5;   // gelb servo1 unten horizental an Pin 5
const int servoPin2 = 18;  // orange servo2 oben vertikal an Pin 18
BH1750FVI myLux(0x23);

Servo Servohorizontal;  // Servo 1 Objekt erstellen
Servo Servovertikal;    // Servo 2 Objekt erstellen

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.print(__FILE__);  // liefert den Pfad zur aktuellen Datei
  Serial.println();
  Wire.begin(23, 19);  // für lolin32 lite an SDA (Serial Data): Pin 23 und SCL (Serial Clock): Pin 19
  Servohorizontal.attach(servoPin1);
  Servovertikal.attach(servoPin2);
  myLux.powerOn();
  myLux.setContHighRes(); // Für kontinuierliche Messung
}

void loop() {
  int maxLichtstaerkehoriz = 0;  // Maximal gemessene Lichtintensität horizontal
  int maxWinkelHorizont = 0;     // Winkel mit der höchsten Lichtintensität horizontal
  int maxLichtstaerkevert = 0;   // Maximal gemessene Lichtintensität vertikal
  int maxWinkelvertikal = 0;     // Winkel mit der höchsten Lichtintensität vertikal

  // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad vertikal
  Servovertikal.write(25);
  for (int winkelhorizontal = 0; winkelhorizontal <= 180; winkelhorizontal += 10) {
    Servohorizontal.write(winkelhorizontal);  // Drehe den Servo auf den aktuellen Winkel
    delay(100);                               // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if (lux > maxLichtstaerkehoriz) {
      maxLichtstaerkehoriz = lux;
      maxWinkelHorizont = winkelhorizontal;
      Serial.print("Schleife 1: ");
      Serial.print("MaxLux1: ");
      Serial.println(maxLichtstaerkehoriz, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxWinkelHorizont, 1);
      delay(1000);
    }
    //  else if (lux < maxLichtstaerkehoriz) {  // Bei abnehmender Helligkeit, breche die Schleife ab
    //  Serial.println("breche die Schleife 1 ab");
    //   delay(1000);
    //     break;
    //   }
  }

  // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 120 Grad
  Servovertikal.write(140);
  for (int winkelhorizontal = 180; winkelhorizontal >= 0; winkelhorizontal -= 10) {
    Servohorizontal.write(winkelhorizontal);  // Drehe den Servo auf den aktuellen Winkel
    delay(100);                               // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if (lux > maxLichtstaerkehoriz) {
      maxLichtstaerkehoriz = lux;
      maxWinkelHorizont = winkelhorizontal;
      Serial.print("Schleife 2: ");
      Serial.print("MaxLux1: ");
      Serial.println(maxLichtstaerkehoriz, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxWinkelHorizont, 1);
      delay(1000);
    }
    //   else if (lux < maxLichtstaerkehoriz) {
    //     Serial.println("breche die Schleife 2 ab");
    //   delay(1000); // Bei abnehmender Helligkeit, breche die Schleife ab
    //     break;
    //    }
  }
  // Durchlaufe alle Winkel von 0 bis 180 Grad vertikal
  Servohorizontal.write(maxWinkelHorizont);
  for (int angle2 = 30; angle2 <= 150; angle2 += 10) {
    Servovertikal.write(angle2);  // Drehe den Servo auf den aktuellen Winkel
    delay(100);                   // Warte einen Moment, damit sich der Servo drehen kann

    uint16_t lux = myLux.getLux();  // Lese die Lichtintensität
    if (lux > maxLichtstaerkevert) {
      maxLichtstaerkevert = lux;
      maxWinkelvertikal = angle2;
      Serial.print("Schleife 3: ");
      Serial.print("MaxLux2: ");
      Serial.println(maxLichtstaerkevert, 1);
      Serial.print("Bester Winkel horizontal: ");
      Serial.println(maxWinkelvertikal, 1);
      delay(1000);
    }
    //    else if (lux < maxLichtstaerkevert) {
    //      Serial.println("breche die Schleife 3 ab");
    //   delay(1000); // Bei abnehmender Helligkeit, breche die Schleife ab // Bei abnehmender Helligkeit, breche die Schleife ab
    //     break;
    //     }
  }

  // Drehe den Servo auf den Winkel mit der höchsten Lichtintensität

  Servohorizontal.write(maxWinkelHorizont);
  Servovertikal.write(maxWinkelvertikal);
  Serial.print("Bester Winkel 1 und 2 : ");
  Serial.print(maxWinkelHorizont, 1);
  Serial.print(" und ");
  Serial.println(maxWinkelvertikal, 1);
  // Warte 5 Minuten, bevor der nächste Durchlauf beginnt
  // delay(300000);
  esp_sleep_enable_timer_wakeup(300 * 1000000);  // Setze die Schlafdauer (5 Minuten = 300.000.000 Mikrosekunden)
  esp_deep_sleep_start();                       // Betrete den Deep-Sleep-Modus. Manuell aufwecken mit Reset-Taste.
}

Finale Ladestation:
Da letztes Wochenende zwei regenfreie und sonnige Tage hatte, konnte ich am Ende des Tages zwei Smartphones über den USB A Anschluss (5V / 1A) damit aufladen.

Was mir noch nicht gefallen hatte, das das Akku Pack der Sonne ausgesetzt ist und diese Version nur eine Schönwetter Lösung ist.
Auf den Bild ist schon mal eine zweite Test Version einer Grundplatte mit Deckel zu sehen, diese wird wohl noch Seitenwände bekommen.

Verwendete Bibliotheken:
Für Licht-Sensor mit beiden Microcontroller Boards:
GitHub – RobTillaart/BH1750FVI_RT: Arduino library for BH1750FVI (GY-30) Lux sensor
Für Servo MG996r:
An einem Arduino Uno: Servo (Ist standardmäßig installiert)
An dem Lolin32 Lite: esp32servo

Weitere Hardware:
Solar Panel 3,5 Watt
Solar Power Management Module ohne 14500 Akku da nur 800mAh
Akku LiPo 10000mA 3,7 Volt mit Stecker PH2.0A

Hersteller Datenblätter:
Lichtsensor GY-30
Servo MG996R
Solar Power Manager: http://www.waveshare.com/wiki/Solar_Power_Manager

Pin Belegung Arduino:
Belegungsplan Arduino Uno Rev3 – Prilchen tüftelt
Pin Belegung Lolin32:
Belegungsplan ESP32 LOLIN32 (Lite) – Prilchen tüftelt

3D-Druck:
Insgesamt gibt es 5 Teile zum Drucken, die Grundplatte gibt es für Arduino Uno und Lolin32 Lite.
Die Grundplattform 20 x 20 cm bietet zusätzlich Platz für einen Solar Panel Manager und einer 3,7 Volt Akku.
Die Solar Panel Halterung ist für ein Größe von 13,5 x 16,5cm ausgelegt.
Gedruckt wurde mit PETG Filament.
Solar Panel und MG996R_servo1 wurden mit PVC-U Kleber von Tangit zusammen geklebt. Hält bei PETG unwiederbringlich zusammen!
Die Servo´s wurden mit den beiliegenden Schrauben verschraubt. Sonstige Teile mit M2x4 und M2x10 selbstschneidenden Schrauben

3D Druckformen für Solar Panel Tracker by Prilchen


Video:

, , ,