Зарядная станция с автоматической ориентацией солнечных панелей

Источник:

Зарядная станция с автоматической ориентацией солнечных панелей

Прошлым летом я приобрел небольшой солнечный модуль. В инструкции по эксплуатации указано, что его следует ориентировать на юг с углом наклона 35°, чтобы заряжать аккумулятор на 3,7 В через модуль Solar Power Manager.
Однако, чтобы днем он всегда был направлен в сторону солнца, я решил попробовать построить полностью автоматический следящий механизм с помощью датчика освещенности и двух сервоприводов.

Как всегда, я действовал постепенно. Сначала протестировал датчик освещенности, затем сервоприводы. Затем было интересно наблюдать за взаимодействием компонентов при поиске самой яркой точки.
Самое важное было задокументировано здесь, и я надеюсь, что это вдохновит кого-нибудь на создание собственной версии.
Когда версия 1 с Arduino была готова и работала, я сразу же создал вторую версию с платой ESP32, с тем чтобы при переходе в спящий режим устройство потребляло меньше энергии и, таким образом, более эффективно заряжало аккумулятор.

Но как же измерить интенсивность света?
Наиболее эффективная длина волны для наиболее распространенных солнечных батарей лежит в видимом диапазоне спектра света. Световой поток в 1 люмен, падающий на площадь 1 м², освещает ее (в среднем) с интенсивностью 1 люкс.
Интенсивность освещенности – Википедия

Итак, сначала поиск подходящего датчика освещенности.

Оборудование 1: Измерение освещенности с помощью GY-30

Изображение

Плата расширения датчика освещенности GY-30 / BH1750FVI оснащена фотодиодом, способным улавливать большую часть видимого света в диапазоне примерно от 400 до 700 нм. Чем ярче свет, тем выше значение освещенности в люксах, выдаваемое 16-разрядным аналого-цифровым преобразователем. Плата может выполнять как непрерывные, так и единичные измерения. Управление осуществляется через интерфейс I2C, питание — от 3,3 до 5 В.
Технические характеристики датчика освещенности GY-30

Подключение, часть 1:

Изображение

Исходный код для теста датчика освещенности:

Первое измерение освещенности в люксах.

  1. #include "BH1750FVI.h"
  2.  
  3. BH1750FVI myLux(0x23);
  4. uint32_t lastUpdate = 0;
  5.  
  6. void setup()
  7. {
  8. Serial.begin(115200);
  9. Serial.println();
  10. Serial.print(__FILE__);// liefert den Pfad zur aktuellen Datei
  11. Serial.println();
  12.  
  13. Wire.begin(); // für arduino uno
  14. // Wire.begin(23,19); // für lolin32 lite an SDA (Serial Data): Pin 23 und SCL (Serial Clock): Pin 19
  15.  
  16. myLux.powerOn();
  17. myLux.setContHighRes(); // Für kontinuierliche Messung
  18. // myLux.setOnceHighRes();// Für einmalige Messung - Stromsparmodus
  19. }
  20.  
  21. void loop()
  22. {
  23. uint16_t interval = 100;
  24. if (millis() - lastUpdate >= interval)
  25. {
  26. lastUpdate += interval;
  27. float val = myLux.getLux();
  28. Serial.println(val, 1);
  29. }
  30. delay(1000);
  31. // myLux.setOnceHighRes();// Für einmalige Messung - Stromsparmodus
  32. }

Еще одним открытием стало то, что библиотека для датчика освещенности позволяет выполнять однократное измерение, чтобы впоследствии сэкономить энергию. Однако в таком случае при каждом новом измерении необходимо вводить myLux.setOnceHighRes();. Измерение с помощью USB-тестера напряжения не показало никаких изменений. Поэтому я пока оставил это без внимания.

Оборудование 2: Сервопривод MG996R
MG996R — это цифровой микросервопривод, известный своим применением в дистанционно управляемых роботах, вертолетах и самолетах.
Он оснащен металлической передачей для повышенной прочности и может поворачиваться в диапазоне около 180 градусов. Его положение можно регулировать с высокой точностью.
Благодаря своей низкой стоимости и простоте в обращении он пользуется популярностью у любителей-конструкторов, и, следовательно, у меня.
Технические характеристики сервопривода

Подключение, часть 2:

Изображение

Исходный код
Для начала — тест с одним сервоприводом:

  1. #include <Servo.h> //f&uuml;r Arduino Uno
  2.  
  3.  
  4. Servo servo; // Servo-Objekt erstellen f&uuml;r Arduino
  5.  
  6. const int servoPin = 9; // servo1 gelb unten horizontal an Pin 9
  7.  
  8. void setup() {
  9. servo.attach(servoPin); //
  10. }
  11.  
  12. void loop() {
  13. servo.write(0); // move MG996R's shaft to angle 0&deg;
  14. delay(1000); // wait for one second
  15. servo.write(45); // move MG996R's shaft to angle 45&deg;
  16. delay(1000); // wait for one second
  17. servo.write(90); // move MG996R's shaft to angle 90&deg;
  18. delay(1000); // wait for one second
  19. servo.write(135); // move MG996R's shaft to angle 135&deg;
  20. delay(1000); // wait for one second
  21. servo.write(180); // move MG996R's shaft to angle 180&deg;
  22. delay(1000); // wait for one second
  23. }

Теперь тест с двумя сервоприводами:

  1. #include <Servo.h>
  2.  
  3. Servo servo1; // der MG 996R servo1
  4. Servo servo2; // der MG 996R servo2
  5.  
  6. void setup() {
  7. servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  8. servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  9. }
  10.  
  11. void loop() {
  12. servo2.write(45); // move MG996R's shaft to angle 0&deg;
  13. delay(1000); // wait for one second
  14. servo1.write(45); // move MG996R's shaft to angle 45&deg;
  15. delay(1000); // wait for one second
  16. servo2.write(90); // move MG996R's shaft to angle 90&deg;
  17. delay(1000); // wait for one second
  18. servo1.write(90); // move MG996R's shaft to angle 135&deg;
  19. delay(1000); // wait for one second
  20. servo2.write(135); // move MG996R's shaft to angle 180&deg;
  21. delay(1000); // wait for one second
  22. servo1.write(135); // move MG996R's shaft to angle 180&deg;
  23. delay(1000); // wait for one second
  24. }

Третье испытание:
Датчик освещенности управляет сервоприводом, GY-30 и MG996r одновременно

Теперь датчик освещенности и оба сервопривода работают вместе для первоначального горизонтального сканирования с целью нахождения самой яркой точки.

Подключение, часть 3: 

Изображение

Исходный код для сканирования:

Тестовое сканирование самой яркой точки по горизонтали

  1. #include "BH1750FVI.h"
  2. #include <Servo.h>
  3.  
  4. BH1750FVI myLux(0x23);
  5. uint32_t lastUpdate = 0;
  6.  
  7. Servo servo1; // der MG996R servo1
  8. Servo servo2; // der MG996R servo2
  9.  
  10. void setup(){
  11. Wire.begin();
  12. myLux.powerOn();
  13. myLux.setContHighRes();
  14. servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  15. servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  16. }
  17.  
  18. void loop() {
  19. int maxLightIntensity = 0; // Maximal gemessene Lichtintensit&auml;t
  20. int maxAngle = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t
  21.  
  22. // Durchlaufe alle Winkel von 0 bis 180 Grad
  23. for(int angle = 0; angle <= 180; angle += 10){
  24. servo1.write(angle); // Drehe den Servo auf den aktuellen Winkel
  25. delay(200); // Warte einen Moment, damit sich der Servo drehen kann
  26.  
  27. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  28. if(lux > maxLightIntensity){
  29. maxLightIntensity = lux;
  30. maxAngle = angle;
  31. }
  32. }
  33.  
  34. // Drehe den Servo auf den Winkel mit der h&ouml;chsten Lichtintensit&auml;t
  35. servo1.write(maxAngle);
  36. delay(10000); // Warte einen Moment, bevor der n&auml;chste Durchlauf beginnt
  37. }

Тест сканирования самой яркой точки по горизонтали и вертикали

  1. #include "BH1750FVI.h"
  2. #include <Servo.h>
  3.  
  4. BH1750FVI myLux(0x23);
  5.  
  6. Servo servo1; // der MG 996R servo1
  7. Servo servo2; // der MG 996R servo2
  8.  
  9. void setup(){
  10. Serial.begin(115200);
  11. Serial.println();
  12. Serial.print(__FILE__);// liefert den Pfad zur aktuellen Datei
  13. Serial.println();
  14.  
  15. Wire.begin();
  16. myLux.powerOn();
  17. myLux.setContHighRes();
  18. servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  19. servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  20. servo1.write(90);
  21. servo2.write(90);
  22. }
  23.  
  24. void loop() {
  25. int maxLightIntensity1 = 0; // Maximal gemessene Lichtintensit&auml;t horizontal
  26. int maxAngle1 = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t horizontal
  27. int maxLightIntensity2 = 0; // Maximal gemessene Lichtintensit&auml;t vertikal
  28. int maxAngle2 = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t vertikal
  29.  
  30. // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal
  31. for(int angle1 = 0; angle1 <= 180; angle1 += 10){
  32. servo1.write(angle1); // Drehe den Servo auf den aktuellen Winkel
  33. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  34.  
  35. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  36. if(lux > maxLightIntensity1){
  37. maxLightIntensity1 = lux;
  38. maxAngle1 = angle1;
  39. Serial.print("MaxLux1: ");
  40. Serial.println(maxLightIntensity1, 1);
  41. Serial.print("Bester Winkel horizontal: ");
  42. Serial.println(maxAngle1, 1);
  43. }
  44. }
  45.  
  46. // Durchlaufe alle Winkel von 0 bis 180 Grad vertikal
  47. for(int angle2 = 20; angle2 <= 160; angle2 += 10){
  48. servo2.write(angle2); // Drehe den Servo auf den aktuellen Winkel
  49. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  50.  
  51. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  52. if(lux > maxLightIntensity2){
  53. maxLightIntensity2 = lux;
  54. maxAngle2 = angle2;
  55. Serial.print("MaxLux2: ");
  56. Serial.println(maxLightIntensity2, 1);
  57. Serial.print("Bester Winkel horizontal: ");
  58. Serial.println(maxAngle2, 1);
  59. }
  60. }
  61.  
  62. // Drehe den Servo auf den Winkel mit der h&ouml;chsten Lichtintensit&auml;t
  63. servo1.write(maxAngle1);
  64. servo2.write(maxAngle2);
  65. Serial.print("Bester Winkel 1 und 2 : ");
  66. Serial.print(maxAngle1, 1);
  67. Serial.print(" und ");
  68. Serial.println(maxAngle2, 1);
  69. delay(10000); // Warte einen Moment, bevor der n&auml;chste Durchlauf beginnt
  70. }

Чтобы обеспечить полное сканирование на 360 градусов с помощью 180-градусных сервоприводов, необходимо выполнить 3 цикла.

1-й проход: все углы от 0 до 180 градусов по горизонтали при 35 градусах по вертикали.
2-й проход: все углы от 0 до 180 градусов по горизонтали при 145 градусах по вертикали.
3-й проход: все углы от 0 до 180 градусов по вертикали с оптимальным значением по горизонтали.

  1. #include "BH1750FVI.h"
  2. #include <Servo.h>
  3.  
  4. BH1750FVI myLux(0x23);
  5.  
  6. Servo servo1; // der MG 996R servo1
  7. Servo servo2; // der MG 996R servo2
  8.  
  9. void setup(){
  10. Serial.begin(115200);
  11. Serial.println();
  12. Serial.print(__FILE__); // liefert den Pfad zur aktuellen Datei
  13. Serial.println();
  14.  
  15. Wire.begin();
  16. myLux.powerOn();
  17. myLux.setContHighRes(); // F&uuml;r kontinuierliche Messung
  18. servo1.attach(9); // servo1 gelb unten horizontal an Pin 9
  19. servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  20. servo1.write(90);
  21. servo2.write(90);
  22. }
  23.  
  24. void loop() {
  25. int maxLightIntensity1 = 0; // Maximal gemessene Lichtintensit&auml;t horizontal
  26. int maxAngle1 = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t horizontal
  27. int maxLightIntensity2 = 0; // Maximal gemessene Lichtintensit&auml;t vertikal
  28. int maxAngle2 = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t vertikal
  29.  
  30. // Durchlauf alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad
  31. servo2.write(35);
  32. for(int angle1 = 0; angle1 <= 180; angle1 += 10){
  33. servo1.write(angle1); // Drehe den Servo auf den aktuellen Winkel
  34. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  35.  
  36. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  37. if(lux > maxLightIntensity1){
  38. maxLightIntensity1 = lux;
  39. maxAngle1 = angle1;
  40. Serial.print("MaxLux1: ");
  41. Serial.println(maxLightIntensity1, 1);
  42. Serial.print("Bester Winkel horizontal: ");
  43. Serial.println(maxAngle1, 1);
  44. }
  45. }
  46.  
  47. // Durchlauf alle Winkel von 0 bis 180 Grad horizontal bei 145 Grad
  48. servo2.write(145);
  49. for(int angle1 = 180; angle1 >= 0; angle1 -= 10){
  50. servo1.write(angle1); // Drehe den Servo auf den aktuellen Winkel
  51. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  52.  
  53. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  54. if(lux > maxLightIntensity1){
  55. maxLightIntensity1 = lux;
  56. maxAngle1 = angle1;
  57. Serial.print("MaxLux1: ");
  58. Serial.println(maxLightIntensity1, 1);
  59. Serial.print("Bester Winkel horizontal: ");
  60. Serial.println(maxAngle1, 1);
  61. }
  62. }
  63. // Durchlauf alle Winkel von 0 bis 180 Grad vertikal mit bester Wert bei horizontal
  64. servo1.write(maxAngle1);
  65. for(int angle2 = 30; angle2 <= 150; angle2 += 10){
  66. servo2.write(angle2); // Drehe den Servo auf den aktuellen Winkel
  67. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  68.  
  69. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  70. if(lux > maxLightIntensity2){
  71. maxLightIntensity2 = lux;
  72. maxAngle2 = angle2;
  73. Serial.print("MaxLux2: ");
  74. Serial.println(maxLightIntensity2, 1);
  75. Serial.print("Bester Winkel horizontal: ");
  76. Serial.println(maxAngle2, 1);
  77. }
  78. }
  79.  
  80. // Drehe den Servo auf den Winkel mit der h&ouml;chsten Lichtintensit&auml;t
  81.  
  82. servo1.write(maxAngle1);
  83. servo2.write(maxAngle2);
  84. Serial.print("Bester Winkel 1 und 2 : ");
  85. Serial.print(maxAngle1, 1);
  86. Serial.print(" und ");
  87. Serial.println(maxAngle2, 1);
  88. delay(300000); // Warte 5 Minuten, bevor der n&auml;chste Durchlauf beginnt
  89. }

Попробуй ускорить процесс:
Сократи время измерения после обнаружения максимального значения. (В ходе длительного тестирования этот метод не всегда эффективен в зависимости от облачности)

  1. #include "BH1750FVI.h"
  2. #include <Servo.h>
  3.  
  4. BH1750FVI myLux(0x23);
  5.  
  6. Servo servo1; // der MG 996R servo1
  7. Servo servo2; // der MG 996R servo2
  8.  
  9. void setup(){
  10. Serial.begin(115200);
  11. Serial.println();
  12. Serial.print(__FILE__); // liefert den Pfad zur aktuellen Datei
  13. Serial.println();
  14.  
  15. Wire.begin();
  16. myLux.powerOn();
  17. myLux.setContHighRes();
  18. servo1.attach(9); // servo1 ist am Arduino an Pin 9
  19. servo2.attach(10); // orange servo2 oben vertikal an Pin 10
  20.  
  21. }
  22.  
  23. void loop() {
  24. int maxLightIntensity1 = 0; // Maximal gemessene Lichtintensit&auml;t horizontal
  25. int maxAngle1 = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t horizontal
  26. int maxLightIntensity2 = 0; // Maximal gemessene Lichtintensit&auml;t vertikal
  27. int maxAngle2 = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t vertikal
  28.  
  29. // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad
  30. servo2.write(35);
  31. for(int angle1 = 0; angle1 <= 180; angle1 += 10){
  32. servo1.write(angle1); // Drehe den Servo auf den aktuellen Winkel
  33. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  34.  
  35. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  36. if(lux > maxLightIntensity1){
  37. maxLightIntensity1 = lux;
  38. maxAngle1 = angle1;
  39. Serial.print("MaxLux1: ");
  40. Serial.println(maxLightIntensity1, 1);
  41. Serial.print("Bester Winkel horizontal: ");
  42. Serial.println(maxAngle1, 1);
  43. }
  44. else if(lux < maxLightIntensity1){ // Bei abnehmender Helligkeit, breche die Schleife ab
  45. break;
  46. }
  47. }
  48.  
  49. // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 120 Grad
  50. servo2.write(120);
  51. for(int angle1 = 180; angle1 >= 0; angle1 -= 10){
  52. servo1.write(angle1); // Drehe den Servo auf den aktuellen Winkel
  53. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  54.  
  55. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  56. if(lux > maxLightIntensity1){
  57. maxLightIntensity1 = lux;
  58. maxAngle1 = angle1;
  59. Serial.print("MaxLux1: ");
  60. Serial.println(maxLightIntensity1, 1);
  61. Serial.print("Bester Winkel horizontal: ");
  62. Serial.println(maxAngle1, 1);
  63. }
  64. else if(lux < maxLightIntensity1){ // Bei abnehmender Helligkeit, breche die Schleife ab
  65. break;
  66. }
  67. }
  68. // Durchlaufe alle Winkel von 0 bis 180 Grad vertikal
  69. servo1.write(maxAngle1);
  70. for(int angle2 = 30; angle2 <= 150; angle2 += 10){
  71. servo2.write(angle2); // Drehe den Servo auf den aktuellen Winkel
  72. delay(500); // Warte einen Moment, damit sich der Servo drehen kann
  73.  
  74. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  75. if(lux > maxLightIntensity2){
  76. maxLightIntensity2 = lux;
  77. maxAngle2 = angle2;
  78. Serial.print("MaxLux2: ");
  79. Serial.println(maxLightIntensity2, 1);
  80. Serial.print("Bester Winkel horizontal: ");
  81. Serial.println(maxAngle2, 1);
  82. }
  83. else if(lux < maxLightIntensity2){ // Bei abnehmender Helligkeit, breche die Schleife ab
  84. break;
  85. }
  86. }
  87.  
  88. // Drehe den Servo auf den Winkel mit der h&ouml;chsten Lichtintensit&auml;t
  89.  
  90. servo1.write(maxAngle1);
  91. servo2.write(maxAngle2);
  92. Serial.print("Bester Winkel 1 und 2 : ");
  93. Serial.print(maxAngle1, 1);
  94. Serial.print(" und ");
  95. Serial.println(maxAngle2, 1);
  96. delay(300000); // Warte 5 Minuten, bevor der n&auml;chste Durchlauf beginnt
  97. }

Пока что почти всё работает. В качестве текущей финальной версии я использую поиск оптимального угла в 3 прогонах.
Теперь осталось подключить Servo Power Manager и аккумулятор (схема подключения показана на Lolin32) — и можно приступать к измерению потребляемого тока. Потребление Arduino составляет 0,058 А·ч.

Версия на Arduino готова.

Вторая версия с платой ESP32 Lolin32 Lite

В этой второй версии я заменил плату Arduino на Lolin32 Lite. Я хочу провести более длительное тестирование, чтобы проверить, будет ли плата без проблем работать с сервомоторами, когда она переходит в спящий режим. Первые измерения показывают, что во время «сна» потребление снижается с 0,052 Ач до 0,008 Ач.

Подключение с Lolin32 Lite:

Изображение

Тест датчика освещенности:
Скетч для тестирования измерения освещенности идентичен версии для Arduino; необходимо лишь добавить в функцию setup строку wire.begin() с указанием номера вывода: SDA (последовательные данные) — на вывод 23, а SCL (последовательный такт) — на вывод 19.

Изображение

Исходный код теста сервопривода на Lolin32:

Вот скетч для второго теста сервопривода с использованием библиотеки esp32servo (версия 1.1.2) и для проверки, не затянут ли где-нибудь кабели или не мешают ли они.

  1. #include <Arduino.h>
  2. #include <ESP32Servo.h> // Die ESP32Servo-Bibliothek einbinden
  3.  
  4. const int servoPin1 = 5; // gelb servo 1 unten horizontal an Pin 5
  5. const int servoPin2 = 18; // orange servo 2 oben vertikal an Pin 18
  6.  
  7. Servo myServo1; // Servo1-Objekt erstellen
  8. Servo myServo2; // Servo2-Objekt erstellen
  9.  
  10. void setup() {
  11.  
  12. myServo1.attach(servoPin1);
  13. myServo2.attach(servoPin2);
  14. }
  15.  
  16. void loop() {
  17. myServo2.write(90); // Servo 2 auf 90 Grad (Mittelstellung) drehen
  18. delay(5000);
  19. myServo1.write(90); // Servo1 auf 90 Grad (Mittelstellung) drehen
  20. delay(5000); // 5 Sekunde warten
  21. myServo1.write(0);
  22. delay(5000);
  23. myServo1.write(180);
  24. delay(5000);
  25.  
  26. myServo2.write(30); // Servo 2 auf 30 Grad drehen
  27. delay(5000);
  28. myServo1.write(0);
  29. delay(5000);
  30. myServo1.write(90);
  31. delay(5000);
  32. myServo1.write(180);
  33. delay(5000);
  34.  
  35. myServo2.write(150); // Servo 2 auf 150 Grad drehen
  36. delay(5000);
  37. myServo1.write(0);
  38. delay(5000);
  39. myServo1.write(90);
  40. delay(5000);
  41. myServo1.write(180);
  42. delay(5000);
  43. }

Исходный код финальной версии от Lolin32:
Вот мой текущий финальный скетч с отключенной возможностью сокращения времени сканирования:

  1. #include "BH1750FVI.h"
  2. #include <Arduino.h>
  3. #include <ESP32Servo.h> // Die ESP32Servo-Bibliothek einbinden
  4.  
  5. const int servoPin1 = 5; // gelb servo1 unten horizental an Pin 5
  6. const int servoPin2 = 18; // orange servo2 oben vertikal an Pin 18
  7. BH1750FVI myLux(0x23);
  8.  
  9. Servo Servohorizontal; // Servo 1 Objekt erstellen
  10. Servo Servovertikal; // Servo 2 Objekt erstellen
  11.  
  12. void setup() {
  13. Serial.begin(115200);
  14. Serial.println();
  15. Serial.print(__FILE__); // liefert den Pfad zur aktuellen Datei
  16. Serial.println();
  17. Wire.begin(23, 19); // f&uuml;r lolin32 lite an SDA (Serial Data): Pin 23 und SCL (Serial Clock): Pin 19
  18. Servohorizontal.attach(servoPin1);
  19. Servovertikal.attach(servoPin2);
  20. myLux.powerOn();
  21. myLux.setContHighRes(); // F&uuml;r kontinuierliche Messung
  22. }
  23.  
  24. void loop() {
  25. int maxLichtstaerkehoriz = 0; // Maximal gemessene Lichtintensit&auml;t horizontal
  26. int maxWinkelHorizont = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t horizontal
  27. int maxLichtstaerkevert = 0; // Maximal gemessene Lichtintensit&auml;t vertikal
  28. int maxWinkelvertikal = 0; // Winkel mit der h&ouml;chsten Lichtintensit&auml;t vertikal
  29.  
  30. // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 35 Grad vertikal
  31. Servovertikal.write(25);
  32. for (int winkelhorizontal = 0; winkelhorizontal <= 180; winkelhorizontal += 10) {
  33. Servohorizontal.write(winkelhorizontal); // Drehe den Servo auf den aktuellen Winkel
  34. delay(100); // Warte einen Moment, damit sich der Servo drehen kann
  35.  
  36. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  37. if (lux > maxLichtstaerkehoriz) {
  38. maxLichtstaerkehoriz = lux;
  39. maxWinkelHorizont = winkelhorizontal;
  40. Serial.print("Schleife 1: ");
  41. Serial.print("MaxLux1: ");
  42. Serial.println(maxLichtstaerkehoriz, 1);
  43. Serial.print("Bester Winkel horizontal: ");
  44. Serial.println(maxWinkelHorizont, 1);
  45. delay(1000);
  46. }
  47. // else if (lux < maxLichtstaerkehoriz) { // Bei abnehmender Helligkeit, breche die Schleife ab
  48. // Serial.println("breche die Schleife 1 ab");
  49. // delay(1000);
  50. // break;
  51. // }
  52. }
  53.  
  54. // Durchlaufe alle Winkel von 0 bis 180 Grad horizontal bei 120 Grad
  55. Servovertikal.write(140);
  56. for (int winkelhorizontal = 180; winkelhorizontal >= 0; winkelhorizontal -= 10) {
  57. Servohorizontal.write(winkelhorizontal); // Drehe den Servo auf den aktuellen Winkel
  58. delay(100); // Warte einen Moment, damit sich der Servo drehen kann
  59.  
  60. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  61. if (lux > maxLichtstaerkehoriz) {
  62. maxLichtstaerkehoriz = lux;
  63. maxWinkelHorizont = winkelhorizontal;
  64. Serial.print("Schleife 2: ");
  65. Serial.print("MaxLux1: ");
  66. Serial.println(maxLichtstaerkehoriz, 1);
  67. Serial.print("Bester Winkel horizontal: ");
  68. Serial.println(maxWinkelHorizont, 1);
  69. delay(1000);
  70. }
  71. // else if (lux < maxLichtstaerkehoriz) {
  72. // Serial.println("breche die Schleife 2 ab");
  73. // delay(1000); // Bei abnehmender Helligkeit, breche die Schleife ab
  74. // break;
  75. // }
  76. }
  77. // Durchlaufe alle Winkel von 0 bis 180 Grad vertikal
  78. Servohorizontal.write(maxWinkelHorizont);
  79. for (int angle2 = 30; angle2 <= 150; angle2 += 10) {
  80. Servovertikal.write(angle2); // Drehe den Servo auf den aktuellen Winkel
  81. delay(100); // Warte einen Moment, damit sich der Servo drehen kann
  82.  
  83. uint16_t lux = myLux.getLux(); // Lese die Lichtintensit&auml;t
  84. if (lux > maxLichtstaerkevert) {
  85. maxLichtstaerkevert = lux;
  86. maxWinkelvertikal = angle2;
  87. Serial.print("Schleife 3: ");
  88. Serial.print("MaxLux2: ");
  89. Serial.println(maxLichtstaerkevert, 1);
  90. Serial.print("Bester Winkel horizontal: ");
  91. Serial.println(maxWinkelvertikal, 1);
  92. delay(1000);
  93. }
  94. // else if (lux < maxLichtstaerkevert) {
  95. // Serial.println("breche die Schleife 3 ab");
  96. // delay(1000); // Bei abnehmender Helligkeit, breche die Schleife ab // Bei abnehmender Helligkeit, breche die Schleife ab
  97. // break;
  98. // }
  99. }
  100.  
  101. // Drehe den Servo auf den Winkel mit der h&ouml;chsten Lichtintensit&auml;t
  102.  
  103. Servohorizontal.write(maxWinkelHorizont);
  104. Servovertikal.write(maxWinkelvertikal);
  105. Serial.print("Bester Winkel 1 und 2 : ");
  106. Serial.print(maxWinkelHorizont, 1);
  107. Serial.print(" und ");
  108. Serial.println(maxWinkelvertikal, 1);
  109. // Warte 5 Minuten, bevor der n&auml;chste Durchlauf beginnt
  110. // delay(300000);
  111. esp_sleep_enable_timer_wakeup(300 * 1000000); // Setze die Schlafdauer (5 Minuten = 300.000.000 Mikrosekunden)
  112. esp_deep_sleep_start(); // Betrete den Deep-Sleep-Modus. Manuell aufwecken mit Reset-Taste.
  113. }

Финальная зарядная станция:
Поскольку в прошлые выходные было два солнечных дня без дождя, в конце дня я смог зарядить с её помощью два смартфона через разъем USB-A (5 В / 1 А).

Что мне пока не понравилось, так это то, что аккумуляторный блок находится под воздействием солнца, и эта версия подходит только для использования в хорошую погоду.
На фотографии уже видна вторая тестовая версия опорной пластины с крышкой, к которой, вероятно, еще будут добавлены боковые стенки.

Изображение

Используемые библиотеки:
Для датчика освещенности с обеими платами микроконтроллера:
GitHub – RobTillaart/BH1750FVI_RT: библиотека Arduino для датчика освещенности BH1750FVI (GY-30)
Для сервопривода MG996r:
На Arduino Uno: Servo (установлена по умолчанию)
На Lolin32 Lite: esp32servo

Дополнительное оборудование:
Солнечная панель 3,5 Вт
Модуль управления солнечной энергией без аккумулятора 14500, так как емкость составляет всего 800 мАч
Аккумулятор LiPo 10000 мАч, 3,7 В с разъемом PH2.0A

Технические характеристики производителя:
Датчик освещенности GY-30
Сервопривод MG996R
Управление солнечной энергией: http://www.waveshare.com/wiki/Solar_Power_Manager

Расположение выводов Arduino:
Схема расположения выводов Arduino Uno Rev3 – Prilchen tüftelt
Расположение выводов Lolin32:
Схема расположения выводов ESP32 LOLIN32 (Lite) – Prilchen tüftelt

3D-печать:
Всего для печати требуется 5 деталей, базовая плата доступна для Arduino Uno и Lolin32 Lite.
Базовая платформа размером 20 x 20 см предоставляет дополнительное место для Solar Panel Manager и аккумулятора на 3,7 В.
Крепление для солнечной панели рассчитано на размер 13,5 x 16,5 см.
Печать выполнялась с использованием нити PETG.
Солнечная панель и MG996R_servo1 были склеены с помощью клея для ПВХ-U от Tangit. На PETG держится надежно!
Сервоприводы были закреплены прилагающимися винтами. Остальные детали — саморезами M2x4 и M2x10.

17:57
63
Нет комментариев. Ваш будет первым!

Ссылка появится после регистрации

Похожие модели

Настраиваемый кейс для батареек (магнитный)
Настраиваемый кейс для переноскиПодробнее
Кейс для аккумуляторов и MicroSD GoPro
Полностью закрытый кейс для переноскиПодробнее
держатель для LiFePo4 аккумуляторов
📁 держатель для 2-4 LiFePo4Подробнее
Powerbank из батарей 21700
📁 3D модель корпуса для пауэрбанка наПодробнее
Кейс для хранения батарей ( 21700, 18650, AA, AAA)
📁 Кейс для хранения батарей ( 21700Подробнее
Зарядник на 1х 18650 и TP4056
Недавно мне досталось несколькоПодробнее
Кейс для двух аккумуляторов 18650
Простой корпус для 18650 без лишнихПодробнее
Кейс для 8х 18650 батарей
Контейнер для аккумуляторов 18650 безПодробнее
Корпус для адаптера питания
📁 Корпус для преобразователя питания сПодробнее
Корпус для DC регулируемого источника
📁 Корпус для DC регулируемого источникаПодробнее
Портативный настольный источник питания
📁 Портативный настольный источникПодробнее
Зарядное устройство для часов Casio Tough Solar
С помощью этой конструкции я хотелПодробнее
Батарейный отсек для Baofeng под 18650
Обновление за сентябрь 2025 года: ПослеПодробнее
Источник питания на 40 000 мАч
Корпус для сборки источника питания наПодробнее
Корпус на магнитах с солн. батареей Meshtastic
# Магнитный автомобильный крепление LoRaПодробнее
Корпус для стационарной уличной ноды Meshtastic
Это стационарный узел, а не портативноеПодробнее
Герметичная коробка для размещения на мачте Meshtastic
Это закрытый корпус, предназначенный дляПодробнее
Meshtastic Солнечная нода с 10W панелью
Корпус для уличной ноды с солнечнойПодробнее
3D солнечный Meshtastic корпус
Материал: PETG, PC, ASA. КрепежныеПодробнее
Корпус для Meshtastic в виде скворечника
Вот солнечная панель, которую яПодробнее
Meshtastic солнечная нода, корпус/крепление
📁 Meshtastic солнечная нода, корпусПодробнее
Уличный узел Meshtastic с солнечной батареей
📁 Уличный узел Meshtastic с солнечнойПодробнее
Корпус для устройства Meshtastic с солнечной батареей
📁 Корпус для устройства Meshtastic сПодробнее
Уличный узел Promicro DIY с солнечной батареей
📁 3D модель корпуса для внешнего роутераПодробнее
Мештастик корпус для точки с солнечной батареей
📁 Meshtastic Мештастик кейс с солнечнойПодробнее
Бокс для репитера Meshtastic, Meshcore, Faketec
📁 Бокс для репитера Meshtastic, MeshcoreПодробнее
Корпус для Heltec T114 под батарею 21700
Этот корпус разработан для Heltec T114Подробнее
Meshtastic & MeshCore Солнечная нода
MESH-S — это солнечный узел MeshtasticПодробнее
Стационарный корпус для Meshcore
Для использования с комплектом RAK19003Подробнее
Посещая этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.