This project uses actuators to control a solar panel's position so that it points to the strongest light source. It works by sensing the light using 4 LDRs (Light Dependent Resistors); each LDR is connected to a resistor to form a voltage divider that is then connected to an Arduino's ADC input to read the voltage. If the voltage is high, then there's light on the LDR; if low, then there's low light on the LDR. The LDRs are placed in a four-quadrant configuration and have blinders placed next to each one to isolate the light going to them. In the code the Arduino averages the voltages of the top, bottom, right, and left quadrants to determine the intensity of light entering each quadrant. If the top quadrant has a greater voltage than the bottom, the panel will move up via servo; else, the panel will move down. If the right quadrant has a greater voltage than the left, the panel will move right via servo; else, the panel will move left. There is also a joystick where the user can manually control the solar panel to whatever position they desire.
This video shows off the manual control of the panel through a joystick and the automatic control of the panel through a strong light source.
#include <Servo.h> // use of servo library
Servo servo_up_down; // creating a seperate objects for each servo
Servo servo_left_right;
int TopLeftLdr = 0; // initializing LDR variables and setting them to zero initially
int TopRightLdr = 0;
int BottomLeftLdr = 0;
int BottomRightLdr = 0;
int servo_up_downLimitHigh = 180; // initializing and setting the degree limits for both servos
int servo_up_downLimitLow = 130;
int servoservo_left_rightLimitHigh = 150;
int servoservo_left_rightLimitLow = 30;
int servo_UD_read = 0; // initialing the variable that outputs the current angle of the up/down servo
int servo_LR_read = 0; // initialing the variable that outputs the current angle of the left/right servo
int xpin = A0; // intializing and setting the joystick x-axis pin to arduino pin A0
int ypin = A1; // intializing and setting the joystick y-axis pin to arduino pin A1
int xServoPos; // initializing and setting the variable that is used to control the posistion of up/down
int yServoPos;
int xval; // variable that will hold the analog values for the x posistion of the joystick
int yval; // variable that will hold the analog values for the y posistion of the joystick
int button; // variable that will hold the ouput state of the state
void setup(){
Serial.begin(9600); // serial monitor
servo_up_down.attach(10); // attaches up/down servo to pin 10
servo_left_right.attach(9); // attaches left/right servo to pin 9
servo_up_down.write(160); // initially posisting the up/down servo to 160 degrees
servo_left_right.write(90); // initially posisting the left/right servo to 90 degrees
pinMode(xpin,INPUT); // setting the joystick x-axis as an input
pinMode(ypin,INPUT); // setting the joystick y-axis as an input
pinMode(12,INPUT); // setting the switch as an input
}
void loop() {
button = digitalRead(12); // read the state of the switch and store it into the variable named button
while(button == 1){ // If the button is high then run joystick funtion
joystick(); // joystick function
button = digitalRead(12); // read button state
}
while(button == 0){ // If the button is low then run solar tracker funtion
solartracker(); // solar tracker function
button = digitalRead(12); // read button state
}
}
//solar tracker function
void solartracker (){
TopLeftLdr = analogRead(A2); // storing the analog values from the LDR's to the respective varaibles
TopRightLdr = analogRead(A3);
BottomLeftLdr = analogRead(A4);
BottomRightLdr = analogRead(A5);
int avgtop = ((TopLeftLdr + TopRightLdr)/2); // computing the averages of the top,bottom,left, and right LDR's, and storing them to their respective variables
int avgbottom = ((BottomLeftLdr + BottomRightLdr)/2);
int avgleft = ((TopLeftLdr + BottomLeftLdr)/2);
int avgright = ((TopRightLdr + BottomRightLdr)/2);
servo_UD_read = servo_up_down.read(); // storing the current posistion of the up/down servo to servo_UD_read
servo_LR_read = servo_left_right.read(); // storing the current posistion of the up/down servo to servo_UD_read
if (avgtop > avgbottom){ // if their is more light on the top than the bottom then ...
servo_up_down.write(servo_UD_read + 1); // increment servo up 1 degree
if (servo_UD_read > servo_up_downLimitHigh){ // if servo reaches its upper limit then stop the servo
servo_up_down.write(servo_up_downLimitHigh);
}
else if(avgtop - avgbottom < 20){ // if the average light of the top and bottom are close together then stop the servo
servo_up_down.write(servo_UD_read);
}
delay(10); //delay 10ms
}
else if (avgbottom > avgtop){ // if their is more light on the bottom than the top then ...
servo_up_down.write(servo_UD_read - 1); // increment servo down 1 degree
if(servo_UD_read < servo_up_downLimitLow){ // if servo reaches its lower limit then stop the servo
servo_up_down.write(servo_up_downLimitLow);
}
else if(avgbottom - avgtop < 20){ // if the average light of the bottom and top are close together than stop the servo
servo_up_down.write(servo_UD_read); // hold servos current posistion
}
delay(10); //delay 10ms
}
else{
servo_up_down.write(servo_UD_read); // hold servos current posistion
}
if (avgright > avgleft){ // if their is more light on the right than the left then ...
servo_left_right.write(servo_LR_read + 1); // increment servo right 1 degree
if (servo_LR_read > servoservo_left_rightLimitHigh){ // if servo reaches its right limit then stop the servo
servo_left_right.write(servoservo_left_rightLimitHigh);
}
else if(avgright - avgleft < 20){ // if the average light of the right and left are close together than stop the servo
servo_left_right.write(servo_LR_read); // hold servos current posistion
}
delay(10); //delay 10ms
}
else if (avgleft > avgright){ // if their is more light on the left than the right then ...
servo_left_right.write(servo_LR_read - 1); // increment servo left 1 degree
if(servo_LR_read < servoservo_left_rightLimitLow){ //// if servo reaches its left limit then stop the servo
servo_left_right.write(servoservo_left_rightLimitLow);
}
else if(avgleft - avgright < 20){ // if the average light of the right and left are close together than stop the servo
servo_left_right.write(servo_LR_read); // hold servos current posistion
}
delay(10); //delay 10ms
}
else{
servo_left_right.write(servo_LR_read); // hold servos current posistion
}
delay(50); //delay 50ms
}
// joystick function
void joystick(){
button = digitalRead(12); //read current state of button and store values into a variable called "button"
xval = analogRead(xpin); // read x posistion of joystick and store into a variable called "xval"
yval = analogRead(ypin); // read y posistion of joystick and store into a variable called "yval"
servo_UD_read = servo_up_down.read(); // storing the current posistion of the up/down servo to servo_UD_read
servo_LR_read = servo_left_right.read(); // storing the current posistion of the left/right servo to servo_LR_read
if(xval > 530){ // if joystick's x posistion is greater than the postion when stationary then...
servo_UD_read = servo_up_down.read(); // read current posistion of up/down servo
servo_up_down.write(servo_UD_read - 1); // increment up 1 degree
}
else if(xval < 515){ // if joystick's x posistion is less than the postion when stationary then...
servo_UD_read = servo_up_down.read(); //read current posistion of up/down servo
servo_up_down.write(servo_UD_read + 1); // increment down 1 degree
}
else if(yval > 515){ // if joystick's y posistion is greater than the postion when stationary then...
servo_LR_read = servo_left_right.read(); //read current posistion of left/right servo
servo_left_right.write(servo_LR_read - 1); // increment right 1 degree
}
else if(yval < 505){ // if joystick's x posistion is greater than the postion when stationary then...
servo_LR_read = servo_left_right.read(); //read current posistion of left/right servo
servo_left_right.write(servo_LR_read + 1); // increment left 1 degree
}
}