Солнечный трекер - система, предназначенная для слежения за перемещением солнца, чтобы получить максимальный КПД от солнечных батарей.
Концепция трекера предельно проста - по двум датчикам контроллер заставляет серводвигатель поворачивать платформу с солнечной батареей в ту сторону, где больше света.
Домашний прототип рабочего трекера показан на фото ниже:
В проекте используется два датчика-фоторезистора, которые направлены в разные стороны от плоской поверхности на 45°, т.е. относительно друг-друга фоторезисторы сориентированы на 90°. На сами датчики надеты колпачки, чтобы поток света, падающий на них был узконаправленным.
В проекте используется контроллер Arduino. Контроллер периодически считывает значения с двух датчиков и сравнивает их. Если значения с датчиков одинаковы, значит панель наведена на солнце. В случае, если значение одного из датчиков отличается от другого, контроллер дает команду на серводвигатель для поворота платформы. Команда на серво работает до тех пор, пока значения с датчиков не сравняются.
Для предотвращения чрезмерного поворота платформы присутствуют программные лимиты поворота, которые в случае необходимости можно отключить. Также, в коде программы предусмотрена константа deadband, при разности с датчиков меньше значения этой константы, контроллер не будет давать команду на поворот серводвигателя. Т.о. предотвращается дергание платформы (джиттер).
Также, на всякий случай добавлено 2 переменные позволяющие сгладить значения от датчиков. Это помогает отфильтровать "выбросы" и шум.
Скетчи для Arduino
В начальной секции программы описываются подключаемые библиотеки (в нашем случае 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................"
);
}
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;
}
}
int
getTravel()
{
// -1 = Влево; +1 = Вправо
if
(errorAVG < (deadband * -1))
{
return
1;
}
else
{
if
(errorAVG > deadband)
{
return
-1;
}
else
{
//Ничего не делаем
return
0;
}
}
}