Солнечный трекер
Солнечный трекер - система, предназначенная для слежения за перемещением солнца, чтобы получить максимальный КПД от солнечных батарей.
Концепция трекера предельно проста - по двум датчикам контроллер заставляет серводвигатель поворачивать платформу с солнечной батареей в ту сторону, где больше света.
Домашний прототип рабочего трекера показан на фото ниже:
В проекте используется два датчика-фоторезистора, которые направлены в разные стороны от плоской поверхности на 45°, т.е. относительно друг-друга фоторезисторы сориентированы на 90°. На сами датчики надеты колпачки, чтобы поток света, падающий на них был узконаправленным.
В проекте используется контроллер Arduino. Контроллер периодически считывает значения с двух датчиков и сравнивает их. Если значения с датчиков одинаковы, значит панель наведена на солнце. В случае, если значение одного из датчиков отличается от другого, контроллер дает команду на серводвигатель для поворота платформы. Команда на серво работает до тех пор, пока значения с датчиков не сравняются.
Для предотвращения чрезмерного поворота платформы присутствуют программные лимиты поворота, которые в случае необходимости можно отключить. Также, в коде программы предусмотрена константа deadband, при разности с датчиков меньше значения этой константы, контроллер не будет давать команду на поворот серводвигателя. Т.о. предотвращается дергание платформы (джиттер).
Также, на всякий случай добавлено 2 переменные позволяющие сгладить значения от датчиков. Это помогает отфильтровать "выбросы" и шум.
В начальной секции программы описываются подключаемые библиотеки (в нашем случае servo.h), определяются пины и константы
#include//IO Pins int pinL = 5; //IO Pin левого фоторезистора int pinR = 4; //IO Pin правого фоторезистора int pinServo = 11; //PWM pin серво int leftValue = 0; //Значение левого фоторезистора int rightValue = 0; //Значение правого фоторезистора int error =0; //Разница между показаниями двух датчиков int errorAVG = 0; //Error Average - Rolling 2 Point int deadband = 10; //Мертвая зона (защита от джиттера) //Servo Stuff Servo hServo; //servo object int Position = 45; //Position to write out int minPos = 5; //Min позиция int maxPos = 150; //Max позиция float output = (maxPos - minPos) /2; //Initial output Position
В следующей части кода описывается функция Setup(). Данная функция выполняется только один раз при запуске программы или после сброса контроллера. Здесь вы можете вывести в Serial Monitor какие либо данные для отладки, или как в приведенном ниже примере сделать "прогон" серводвигателя по всей траектории до лимитов.
void setup() { Serial.begin(9600); hServo.attach(pinServo); //Set Servo to Centre for Alignment Purpose Serial.println("Перемещение к начальной позиции"); hServo.write(minPos); delay(5000); Serial.println("Перемещение к конечной позиции"); hServo.write(maxPos); delay(5000); Serial.println("Перемещение к средней точке"); hServo.write(output); delay(5000); Serial.println("Going Live................"); }
Финальная часть кода выполняется в циклической функции loop(). Здесь считываются значения с датчиков, производятся все расчеты и выдаются команды на серводвигатель.
void loop() { //Чтение значений с фоторезисторов leftValue = analogRead(pinL); rightValue = analogRead(pinR); Serial.print("L = "); Serial.print(leftValue); Serial.print(" | "); Serial.print("R = "); Serial.print(rightValue); Serial.print(" | "); Serial.print("E = "); Serial.print(error); Serial.print(" | "); Serial.print("Eavg = "); Serial.print(errorAVG); Serial.println(); //Расчет error = leftValue - rightValue; errorAVG = (errorAVG + error) / 2; float newOutput = output + getTravel(); if (newOutput > maxPos) { Serial.println("At Upper Limit"); newOutput = maxPos; } else { if (newOutput < minPos) { Serial.println("At Lower Limit"); newOutput = minPos; } } Serial.println("Writing output"); //Вывод команды управления серво hServo.write(newOutput); output = newOutput; } }
Также, в программе используется вспомогательная функция getTravel(), которая используется для вычисления, куда поворачивать серво - влево, вправо или вообще ничего не делать. Функция просто возвращает значение: 0 - ничего не происходит, -1 поворот влево, +1 поворот право.
int getTravel() { // -1 = Влево; +1 = Вправо if (errorAVG < (deadband * -1)) { return 1; } else { if (errorAVG > deadband) { return -1; } else { //Ничего не делаем return 0; } } }
Видео работы трекера:
Конечно, это простой солнечный трекер и может служить основой для более сложных устройств. К примеру можно сделать более лучшую фильтрацию входных переменных, добавить ПИД-регулирование, в схему добавить второй сервопривод для перемещения солнечной панели по вертикали и получения максимального КПД.
Оригинал статьи на английском языке (перевод Колтыков А.В.)