Arduino 2-axis Servo Solar Tracker
Intro: Arduino 2-axis Servo Solar Tracker
What is a solar tracker?
A solar tracker can increase the efficiency of a solar panel by up to 100%! It does this by always keeping the panel perpendicular to the incoming rays of sunlight.
here's an equation to prove this:
P = AW sin θ
P = power generated by the solar panel
A = Area of the solar panel
W = is the solar constant, which is equal to 1340 watts per square meter
θ = the angle of the incoming light
Since sin(90) = 1 you get the best performance out of the panel when it is totally perpendicular.
Materials:
1 - Arduino Uno w/ ability to program it
1 - Breadboard
1 - 2 axis tracking mechanism (i used a magnifying mirror that swiveled up and down)
2 - 360 deg continuous rotation servos
1 - ball bearing tilt switch or similar
5 - 10k resistors
1 - 5V breadboard power supply
3 - cadmium sulfide light sensitive resistors
wires
solder
soldering iron
vice (optional)
A solar tracker can increase the efficiency of a solar panel by up to 100%! It does this by always keeping the panel perpendicular to the incoming rays of sunlight.
here's an equation to prove this:
P = AW sin θ
P = power generated by the solar panel
A = Area of the solar panel
W = is the solar constant, which is equal to 1340 watts per square meter
θ = the angle of the incoming light
Since sin(90) = 1 you get the best performance out of the panel when it is totally perpendicular.
Materials:
1 - Arduino Uno w/ ability to program it
1 - Breadboard
1 - 2 axis tracking mechanism (i used a magnifying mirror that swiveled up and down)
2 - 360 deg continuous rotation servos
1 - ball bearing tilt switch or similar
5 - 10k resistors
1 - 5V breadboard power supply
3 - cadmium sulfide light sensitive resistors
wires
solder
soldering iron
vice (optional)
STEP 1: The Y-axis
Depending on what you use as a tracking mechanism, yours might be a little different than mine.
I picked up a magnifying mirror from Shoppers normally used for shaving or applying makeup. It had a base and a swivel to tilt the mirror up and down.
I cut off one side of the swivel bracket and replaced it with a servo. I measured so that the shaft of the servo would line up with the swivel point of the mirror. I then had to drill a hole for the servo shaft to fit into.
I used hot glue and zip ties to secure the servo to the base and then the servo shaft inside the hole I had drilled.
I picked up a magnifying mirror from Shoppers normally used for shaving or applying makeup. It had a base and a swivel to tilt the mirror up and down.
I cut off one side of the swivel bracket and replaced it with a servo. I measured so that the shaft of the servo would line up with the swivel point of the mirror. I then had to drill a hole for the servo shaft to fit into.
I used hot glue and zip ties to secure the servo to the base and then the servo shaft inside the hole I had drilled.
STEP 2: The X-axis
I marked the approximate center of the base and drilled a hole large enough to screw the setscrew for the servo armature in. I then hot glued the armature to the underside of the base making sure not to get glue in the hole i drilled.
Once the glue was dry, I attached the servo and screwed in the setscrew.
Once the glue was dry, I attached the servo and screwed in the setscrew.
STEP 3: The Sensors
I used 3 light sensors and 1 tilt sensor. You can substitute LEDs or photo-transistors for the CDS cells, and/or mercury switches for the ball bearing tilt sensor but your code will have to reflect the change(s).
I soldered wires from a scrap ribbon cable to the leads of each light sensor and a 2 pin header on the opposite end to connect easily to the breadboard. Use electrical tape / heat shrink / liquid insulator on the bare parts of the wire so that they don't short out.
Once that's done, hot glue the sensors at equal intervals around the circumference of the mirror. I placed the sensors so that the flat collecting side of the sensor was parallel with the plane of the mirror and angled out from the center just slightly.
The tilt sensor that I found was a plastic box with 4 contacts running through it and a ball bearing inside. This sensor prevents the tracker from pointing at the ground and also gives the y-axis an end-stop.
Solder wires onto the 4 pins of the tilt sensor then glue it on the back side of the mirror with the leads running horizontally. With the mirror pointing straight upward, the BB should be resting on the 2 middle leads.
The image I have uploaded is similar but not exactly the same as the tilt sensor I have. The one I used has only 4 leads.
I soldered wires from a scrap ribbon cable to the leads of each light sensor and a 2 pin header on the opposite end to connect easily to the breadboard. Use electrical tape / heat shrink / liquid insulator on the bare parts of the wire so that they don't short out.
Once that's done, hot glue the sensors at equal intervals around the circumference of the mirror. I placed the sensors so that the flat collecting side of the sensor was parallel with the plane of the mirror and angled out from the center just slightly.
The tilt sensor that I found was a plastic box with 4 contacts running through it and a ball bearing inside. This sensor prevents the tracker from pointing at the ground and also gives the y-axis an end-stop.
Solder wires onto the 4 pins of the tilt sensor then glue it on the back side of the mirror with the leads running horizontally. With the mirror pointing straight upward, the BB should be resting on the 2 middle leads.
The image I have uploaded is similar but not exactly the same as the tilt sensor I have. The one I used has only 4 leads.
STEP 4: Wiring It Up
Take a look at the pics for the wiring diagram and schematic. (sorry about the confusing scheamtic, still learning Fritzing)
***EDIT (04/03/13)*** Changed the images to reflect the proper wiring and cleaned it up a bit.
***EDIT (04/03/13)*** Changed the images to reflect the proper wiring and cleaned it up a bit.
STEP 5: The Arduino Code
#define TILTL 2
#define TILTH 3
#define BOTTOM 2
#define TOPLEFT 0
#define TOPRIGHT 1
#include <Servo.h>
#include "math.h"
Servo hservo;
Servo vservo;
int tlsense;
int trsense;
int bsense;
int tavg;
int diff;
int spd;
int divisor;
int sensitivity;
int tiltl;
int tilth;
void setup () {
vservo.attach(9); // attaches the servo on pin 9 to the servo object
hservo.attach(10); // attaches the servo on pin 10 to the servo object
divisor = 10; // this controls the speed of the servo. lower number = higher speed
sensitivity = 5; // this controls the sensitivity of the tracker. lower number = higher sensitivity. if your tracker is constantly jittering back and forth increase the number
Serial.begin(19200); // open serial com
Serial.print("SolarTracker ready!");
pinMode(BOTTOM, INPUT); // set the inputs
pinMode(TOPLEFT, INPUT);
pinMode(TOPRIGHT, INPUT);
pinMode(TILTL, INPUT);
pinMode(TILTH, INPUT);
}
void loop () {
tiltl = digitalRead(TILTL); // read the tilt sensor
tilth = digitalRead(TILTH);
tlsense = analogRead(TOPLEFT); // read the light sensors
trsense = analogRead(TOPRIGHT);
bsense = analogRead(BOTTOM);
//bsense = bsense * 1.05; // I had to adjust the value of this sensor to make it more accurate. you might have to do the same but start by leaving it alone
tavg = (tlsense + trsense)/2; // get an average value for the top 2 sensors
diff = abs(tavg - bsense); // this judges how far the tracker must turn
spd = diff/divisor; // and adjusts the speed of the reaction accordingly
spd = max(spd, 1); // sets the minimum speed to 1
Serial.print("\nTOP: "); Serial.print(tavg, DEC); // print the sensor values to the serial com
Serial.print("\tBOTTOM:"); Serial.print(bsense, DEC);
Serial.print("\tLEFT:"); Serial.print(tlsense, DEC);
Serial.print("\tRIGHT:"); Serial.print(trsense, DEC);
if((tavg < bsense) && (diff > sensitivity) && (tiltl == LOW) && (tilth == LOW)){ // if the average value of the top sensors is smaller (more light) than the bottom sensor and the tilt sensor is in the correct range
vservo.write(90 - spd); // send servo command to turn upward plus add speed
Serial.print("\tState: "); Serial.print("UP!");
}else if((tavg < bsense) && (diff > sensitivity) && (tiltl == HIGH) && (tilth == LOW)){ // if the average value of the top sensors is smaller (more light) than the bottom sensor and the tilt sensor is in the correct range
vservo.write(90 - spd); // send servo command to turn upward plus add speed
Serial.print("\tState: "); Serial.print("UP!");
}else if((tavg > bsense) && (diff > sensitivity) && (tiltl == HIGH) && (tilth == LOW)){ // if the value of the bottom sensor is smaller (more light) than the average value of the top sensors and the tilt sensor is in the correct range
vservo.write(90 + spd); // send servo command to turn downward plus add speed
Serial.print("\tState: "); Serial.print("DOWN!");
}else if((tavg > bsense) && (diff > sensitivity) && (tiltl == LOW) && (tilth == HIGH)){ // if the value of the bottom sensor is smaller (more light) than the average value of the top sensors and the tilt sensor is in the correct range
vservo.write(90 + spd); // send servo command to turn downward plus add speed
Serial.print("\tState: "); Serial.print("DOWN!");
}else{ // for every other instance
vservo.write(90); // stop the y-axis motor
Serial.print("\tState: "); Serial.print("STOP!");
}
tlsense = analogRead(TOPLEFT); // read the top 2 sensors again because they have probably changed
trsense = analogRead(TOPRIGHT);
//trsense = trsense * 1.03; // again I had to adjust the value of one sensor to make the tracker more accurate
diff = abs(tlsense - trsense); // reset the diff variable for the new values
spd = diff/divisor; // and generate a speed accordingly
spd = max(spd, 1); // set the minimum speed to 1
if((tlsense < trsense) && (diff > sensitivity)){ // if the top left sensor value is smaller (more light) than the top right sensor
hservo.write(90 + spd); // send servo command to turn left
Serial.print("\tState: "); Serial.print("LEFT!");
}else if((tlsense > trsense) && (diff > sensitivity)){ // if the top left sensor value is larger (less light) than the top right sensor
hservo.write(90 - spd); // send servo command to turn right
Serial.print("\tState: "); Serial.print("RIGHT!");
}else{ // for every other instance
hservo.write(90); // stop the x-axis motor
Serial.print("\tState: "); Serial.print("STOP!");
}
delay(10); // delay 10ms
}
Arduino polls the sensors and reacts accordingly making sure never to tilt too far down or up. The difference in light determines how fast the tracker should react.
#define TILTH 3
#define BOTTOM 2
#define TOPLEFT 0
#define TOPRIGHT 1
#include <Servo.h>
#include "math.h"
Servo hservo;
Servo vservo;
int tlsense;
int trsense;
int bsense;
int tavg;
int diff;
int spd;
int divisor;
int sensitivity;
int tiltl;
int tilth;
void setup () {
vservo.attach(9); // attaches the servo on pin 9 to the servo object
hservo.attach(10); // attaches the servo on pin 10 to the servo object
divisor = 10; // this controls the speed of the servo. lower number = higher speed
sensitivity = 5; // this controls the sensitivity of the tracker. lower number = higher sensitivity. if your tracker is constantly jittering back and forth increase the number
Serial.begin(19200); // open serial com
Serial.print("SolarTracker ready!");
pinMode(BOTTOM, INPUT); // set the inputs
pinMode(TOPLEFT, INPUT);
pinMode(TOPRIGHT, INPUT);
pinMode(TILTL, INPUT);
pinMode(TILTH, INPUT);
}
void loop () {
tiltl = digitalRead(TILTL); // read the tilt sensor
tilth = digitalRead(TILTH);
tlsense = analogRead(TOPLEFT); // read the light sensors
trsense = analogRead(TOPRIGHT);
bsense = analogRead(BOTTOM);
//bsense = bsense * 1.05; // I had to adjust the value of this sensor to make it more accurate. you might have to do the same but start by leaving it alone
tavg = (tlsense + trsense)/2; // get an average value for the top 2 sensors
diff = abs(tavg - bsense); // this judges how far the tracker must turn
spd = diff/divisor; // and adjusts the speed of the reaction accordingly
spd = max(spd, 1); // sets the minimum speed to 1
Serial.print("\nTOP: "); Serial.print(tavg, DEC); // print the sensor values to the serial com
Serial.print("\tBOTTOM:"); Serial.print(bsense, DEC);
Serial.print("\tLEFT:"); Serial.print(tlsense, DEC);
Serial.print("\tRIGHT:"); Serial.print(trsense, DEC);
if((tavg < bsense) && (diff > sensitivity) && (tiltl == LOW) && (tilth == LOW)){ // if the average value of the top sensors is smaller (more light) than the bottom sensor and the tilt sensor is in the correct range
vservo.write(90 - spd); // send servo command to turn upward plus add speed
Serial.print("\tState: "); Serial.print("UP!");
}else if((tavg < bsense) && (diff > sensitivity) && (tiltl == HIGH) && (tilth == LOW)){ // if the average value of the top sensors is smaller (more light) than the bottom sensor and the tilt sensor is in the correct range
vservo.write(90 - spd); // send servo command to turn upward plus add speed
Serial.print("\tState: "); Serial.print("UP!");
}else if((tavg > bsense) && (diff > sensitivity) && (tiltl == HIGH) && (tilth == LOW)){ // if the value of the bottom sensor is smaller (more light) than the average value of the top sensors and the tilt sensor is in the correct range
vservo.write(90 + spd); // send servo command to turn downward plus add speed
Serial.print("\tState: "); Serial.print("DOWN!");
}else if((tavg > bsense) && (diff > sensitivity) && (tiltl == LOW) && (tilth == HIGH)){ // if the value of the bottom sensor is smaller (more light) than the average value of the top sensors and the tilt sensor is in the correct range
vservo.write(90 + spd); // send servo command to turn downward plus add speed
Serial.print("\tState: "); Serial.print("DOWN!");
}else{ // for every other instance
vservo.write(90); // stop the y-axis motor
Serial.print("\tState: "); Serial.print("STOP!");
}
tlsense = analogRead(TOPLEFT); // read the top 2 sensors again because they have probably changed
trsense = analogRead(TOPRIGHT);
//trsense = trsense * 1.03; // again I had to adjust the value of one sensor to make the tracker more accurate
diff = abs(tlsense - trsense); // reset the diff variable for the new values
spd = diff/divisor; // and generate a speed accordingly
spd = max(spd, 1); // set the minimum speed to 1
if((tlsense < trsense) && (diff > sensitivity)){ // if the top left sensor value is smaller (more light) than the top right sensor
hservo.write(90 + spd); // send servo command to turn left
Serial.print("\tState: "); Serial.print("LEFT!");
}else if((tlsense > trsense) && (diff > sensitivity)){ // if the top left sensor value is larger (less light) than the top right sensor
hservo.write(90 - spd); // send servo command to turn right
Serial.print("\tState: "); Serial.print("RIGHT!");
}else{ // for every other instance
hservo.write(90); // stop the x-axis motor
Serial.print("\tState: "); Serial.print("STOP!");
}
delay(10); // delay 10ms
}
Arduino polls the sensors and reacts accordingly making sure never to tilt too far down or up. The difference in light determines how fast the tracker should react.
STEP 6: The Vid
Ya i look tired, I work a lot. Wanafightaboutit?
36 Comments
VinithV 5 years ago
majid.nabil 8 years ago
good work
SwarnadeepP 8 years ago
Hi I am making this tracker and using same of your code but the horizontal axis is not moving .. Can you please help me ?
baspav 9 years ago
Hello. Trying to understand the sketch and translate the comments, I'm sorry, correct me if I'm wrong, but maybe here is the error:
}else if((tavg > bsense) && (diff > sensitivity) && (tiltl == HIGH) && (tilth == LOW)){ // if the value of the bottom sensor is smaller (more light) than the average value of the top sensors and the tilt sensor is in the correct range?
I think there should be
}else if((tavg > bsense) && (diff > sensitivity) && (tiltl == LOW) && (tilth == LOW)){ // if the value of the bottom sensor is smaller (more light) than the average value of the top sensors and the tilt sensor is in the correct range
ВасилийП 9 years ago
Dear Adam.
Two years ago I acquired a 10-Watt solar
panel, controller, battery. Two years this instrument
helps me in tourist trips. Naturally, the question arose about the tracker. I looked at many options on the Internet, and has collected this one:
https://www.youtube.com/watch?v=Rt4HZOsOwNQ by purchasing servo motors (where
they at 60 degrees), but the functionality was not good.
Since I
need two axis tracker, I stopped on Your wiring diagram, completely changing the mechanical part. I
purchased the Visduino UNO R3 and the breadboard
on Aliexpress. Previously on the market bought the photoresistors. I took the 10K resistors from a radio boards. Assembled circuit for half an hour.
Because with the Arduino I ran for
the first time and I don't know how to write sketches for the Arduino at all, I
just copied Your sketch, filled in the Arduino (detailed instructions how to
upload sketches to the
Arduino the Internet is full), hooked up to my 60-degree servos.It worked immediately.
BUT!!!
I have two
drivers UNL2003A and two stepper motors. So I would like to use
them in my scheme.
Since I don't know how to write
sketches, can I ask You to help me in changing Your sketch, so instead of servo
motors to connect stepper motors and show the scheme
of connection on the Arduino? I would be
very grateful.
Translated by Yandex.
aplavins 9 years ago
If you want to use stepper motors to control the tracker, I would recommend a STEP / DIRECTION style driver like this:
https://www.pololu.com/category/155/a4988-stepper-motor-driver-carriers-black-edition
There is some working code here:
http://www.cerebralmeltdown.com/2011/05/30/open-source-arduino-sun-trackingheliostat-program/#more-2866
ВасилийП 9 years ago
Thank you. But since I don't know enough English, I'm not able to program the Arduino, I want to know: can I connect two stepper motor whis drivers UNL2003A to the Arduino UNO R3; how to do it and to get changes in the sketch of Adam relative to the stepper motors. I do not in any way claim to the authorship of the sketch, when I'l publish the description, I will indicate the real authors of the sketch, but I need the actual version of the program. (although ideally have more requirements). If interested, I can throw on the mailbox.
Translated by Yandex.
PrayasB 9 years ago
y tilt sensors are used??/
PrayasB 9 years ago
dear admin
i want to know what is the role of tilt sensors?????
PrayasB 9 years ago
dear admin
i want to know what is the role of tilt sensors?????
jaykentchriss 9 years ago
Hi!... What about you will be adding a voltage and current sensors for the solar panel in your project?... it would be great if you will share to us your knowledge about coding. :)
jaykentchriss 9 years ago
good day!.. In your video, i see that there is no tilt sensor at the back of the mirror of your tracker... Where did you put your tilt sensor?... im just wondering... thanks... and also what if a mercury tilt sensor will be use?... how many mercury sensor will be used?... and can you send me the code please?.. i will really appreciate it.. Thanks :)
robinmitchell 11 years ago
jaykentchriss 9 years ago
hi robinmitchell... did you used a mercury tilt sensor in your project?.. how many mercury tilt sensor did you used? i had difficulty in modifying the code when i used a mercury tilt sensor.. can u send the code? pls?... i will really appreciate it... thanks :)
McAldo 10 years ago
dpmdmph 10 years ago
DaBlakus 10 years ago
How does it perform in low light levels, like say dusk or dawn ??
I have made up a 2 axis system which works well under "normal' sunshine but I'm having trouble when all sensors are returning similar levels ie. diffused light when cloudy.
I have the sensors enclosed in short tubes 2 face 'forward' with the 3rd facing backwards to detect if the array is not facing the sun.
aplavins 10 years ago
robinmitchell 11 years ago
I was successful at replicating your experiment!! thanks for sharing!!
I was wondering about how to scale this project up to be able to carry a load of 40-50 lbs on top easily. ie a stirling engine and a fresnel lens :
https://www.youtube.com/watch?v=20wQOZbHXvo
i found this servo set up that i think might be able to do the job but i thought i would ask u for your thoughts. if i can accomplish the same thing bu replacing it with this servo gearbox set up.
http://www.servocity.com/html/spg7950a-45_continuous_rotatio.html
thanks in advance for your time,
Robin
thanks in advance for you
Science Wizard 11 years ago