Go Down

Topic: Arduino solar tracker (Read 70847 times) previous topic - next topic


See previous discussion...



Hello world !

You can see my develop of Sun Tracking system

In the next post I give you the address.




You can see my sun tracking develop at:


Thank you


Hi Guys,
I'm new to this forum, and new to solar tracking, but plan to build something myself.  I've looked at various approaches online, and many use sensors. I have an idea of how to do it, but cannot see any reference to this approach on any websites, so maybe it would not work.  Anyway, I wanted to put it out there and ask for feedback. So the idea is to just adjust the position of the panel to maximize the current going to the battery.  The current can be measured across an inexpensive shunt resistor. The Arduino would turn the control motor in the direction that causes the current to increase, and stop once the current starts to go down. It sounds pretty simple.  Am I missing something?
Feedback most welcome.


The remark about wear and tear on the LDRs out in the sun's damaging rays, and all weathers set me thinking...

a) In ANYTHING you design that will be outdoors, design it for easy replacement of damaged parts. They WILL need replacing... sooner than you hope!

b) Are LDRs the way to go? Probably... but I wondered if maybe temperature sensors embedded in small blocks of black epoxy might do just as well, and be more robust?

c) Of course, while I would be the first to applaud anyone wanting to have fun creating a solar tracker... how cool! (I've wanted to build one for years).... if I just wanted my solar panels oriented correctly, I would put my faith in Mr Newton. The geometries of the earth's relationship to the sun are entirely predictable, and a program can be written to point the panels in the right direction without any light sensors. Sorry to be a bore. Do remember on BIG advantage of the track-by-light-sensor approach, though: It doesn't need an accurately set RTC (time of day clock) to work.

d) A KISS point: You really only need the expense, complexity, etc, etc needed to "tip" the panels left and right around one axis of rotation day by day.... to track the sun across the sky. You may want to mount everything on a second axis of rotation to compensate for the sun's height above the horizon at noon, to compensate for the seasonal variation in that axis... but this adjustment can be done manually with whatever you want to use during your routine servicing of the panels. The rate of change in this axis is slow.


I too have been thinking of how to track the sun to gather that extra 30% of energy, but the cost of most commercial solutions has exceeded the cost of installing 30% more solar modules...
I'm very new to the world of Arduino, and from the few forum threads on the subject, the popular method seems to track light levels to determine the position of "Ol' Sol" visually.
The downside I see with this methodology is that it is difficult to allow for all the variations and possible scenarios that the solar array may face, and have to algorithmically respond to.  
For example, will the tracker (in the examples given) properly handle  if a thunderstorm blows in mid-day ?  In other words, all of a sudden there is no bright spot in the sky; what will it do ?  I suppose it will stay put, because the two or three light sensors will "see" the same light level, am I right ?
Next, what happens at sundown ?  How does it know whan to go back towards the east and wait for sunrise ?  Without a sense of time (ie, with an RTC) I'm not convinced it will find the sun in the morning, mostly because the sun will literally be behind the light sensors.

With respect to razorbud's and tkbyd's comments about using lat/long information  to determine azimuth and elevation of the sun in real time, I think this is a great idea.  It solves a lot of problems in terms of where the sun is, regardless of time or weather.  It's not the simplest (no KISS here) but

The big question is: has anyone done this, to calculate the sun's azimuth ?    

I've read and looked at ve9qrp's qrptracker project, and how he uses keplerian elements and Plan13 formulas.  I'm hoping someone has some information to share on how to do this, to save from re-inventing any wheels.

Thanks to all in advance for any assistance...


Jul 12, 2010, 09:35 pm Last Edit: Jul 12, 2010, 09:36 pm by retrolefty Reason: 1
I think the best simplest solution is to utilize a simple RTC/Calendar to drive a stepper motor gear drive at a constant sidereal rate for a single axis right ascension movement.

If you research telescope clock drives using polar mounts you will see that it's pretty simple, accurate and reliable. You may need to manual adjust the azimuth angle manually every month or so to optimize performance. The RTC/Calendar could also handle the skewing command to reposition to each sunrise from look up table in your program.


Mowcius has the answer!


Sun tracker code for you :)
Attach to a RTC and tell it your co-ordinates and it'll throw out sun position  ;)



Dec 28, 2010, 12:35 am Last Edit: Dec 28, 2010, 12:36 am by joeinbend Reason: 1
Great thread guys! Mowcius -- I read the info on your personal web site for the sun position tracking and was salivating, but only to find the links to the .pde's are broken! Are you still providing this sample code?


Yeah, annoying aint it.

Hopefully moving my website soon and sorting it out.

Anyway, here's some static code
Code: [Select]
//Sun Position Calculation
//Provides sun position (relative) from static variables

#include <math.h>
#define pi    3.14159265358979323846
#define twopi (2*pi)
#define rad   (pi/180)
#define EarthMeanRadius     6371.01      // In km
#define AstronomicalUnit    149597890      // In km

//Input Variables --------------------- TIME HAS TO BE IN UT (UNIVERSAL TIME)! NO TIME ZONES OR SUMMER TIMES --------
//My last modifications were probably at this time on this date!
     int Year = 2010; //year
     int Month = 7; //month
     int Day = 3; //day
     float Hours = 16; //hour
     float Minutes = 38; //minutes

     float Longitude = 1.2967; //enter longitude here
     float Latitude = 1.5465; //enter latitude here

//Program Variables
     float ZenithAngle;
     float Azimuth;
       float RightAscension;
     float Declination;
       float Parallax;
       float ElevationAngle;

     float ElapsedJulianDays;
     float DecimalHours;
     float EclipticLongitude;
     float EclipticObliquity;

void setup() {

void sunPos(){

     // Auxiliary variables
     float dY;
     float dX;

     // Calculate difference in days between the current Julian Day
     // and JD 2451545.0, which is noon 1 January 2000 Universal Time

           float JulianDate;
           long int liAux1;
           long int liAux2;
           // Calculate time of the day in UT decimal hours
           DecimalHours = Hours + (Minutes / 60.0);
           // Calculate current Julian Day
           liAux1 =(Month-14)/12;
           liAux2=(1461*(Year + 4800 + liAux1))/4 + (367*(Month
                 - 2-12*liAux1))/12- (3*((Year + 4900
           + liAux1)/100))/4+Day-32075;
           // Calculate difference between current Julian Day and JD 2451545.0
           ElapsedJulianDays = JulianDate-2451545.0;

     // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
     // ecliptic in radians but without limiting the angle to be less than 2*Pi
     // (i.e., the result may be greater than 2*Pi)

           float MeanLongitude;
           float MeanAnomaly;
           float Omega;
           MeanLongitude = 4.8950630+ 0.017202791698*ElapsedJulianDays; // Radians
           MeanAnomaly = 6.2400600+ 0.0172019699*ElapsedJulianDays;
           EclipticLongitude = MeanLongitude + 0.03341607*sin( MeanAnomaly )
                 + 0.00034894*sin( 2*MeanAnomaly )-0.0001134
           EclipticObliquity = 0.4090928 - 6.2140e-9*ElapsedJulianDays

     // Calculate celestial coordinates ( right ascension and declination ) in radians
     // but without limiting the angle to be less than 2*Pi (i.e., the result may be
     // greater than 2*Pi)

           float Sin_EclipticLongitude;
           Sin_EclipticLongitude= sin( EclipticLongitude );
           dY = cos( EclipticObliquity ) * Sin_EclipticLongitude;
           dX = cos( EclipticLongitude );
           RightAscension = atan2( dY,dX );
           if( RightAscension < 0.0 ) RightAscension = RightAscension + twopi;
           Declination = asin( sin( EclipticObliquity )*Sin_EclipticLongitude );

     // Calculate local coordinates ( azimuth and zenith angle ) in degrees

           float GreenwichMeanSiderealTime;
           float LocalMeanSiderealTime;
           float LatitudeInRadians;
           float HourAngle;
           float Cos_Latitude;
           float Sin_Latitude;
           float Cos_HourAngle;
           GreenwichMeanSiderealTime = 6.6974243242 +
                 + DecimalHours;
           LocalMeanSiderealTime = (GreenwichMeanSiderealTime*15
                 + Longitude)*rad;
           HourAngle = LocalMeanSiderealTime - RightAscension;
           LatitudeInRadians = Latitude*rad;
           Cos_Latitude = cos( LatitudeInRadians );
           Sin_Latitude = sin( LatitudeInRadians );
           Cos_HourAngle= cos( HourAngle );
           ZenithAngle = (acos( Cos_Latitude*Cos_HourAngle
                 *cos(Declination) + sin( Declination )*Sin_Latitude));
           dY = -sin( HourAngle );
           dX = tan( Declination )*Cos_Latitude - Sin_Latitude*Cos_HourAngle;
           Azimuth = atan2( dY, dX );
           if ( Azimuth < 0.0 )
             Azimuth = Azimuth + twopi;
           Azimuth = Azimuth/rad;
           // Parallax Correction
           ZenithAngle=(ZenithAngle //Zenith angle is from the top of the visible sky (thanks breaksbassbleeps)
                 + Parallax)/rad;
               ElevationAngle = (90-ZenithAngle); //Retrieve useful elevation angle from Zenith angle

void loop(){
 sunPos(); //Run sun position calculations
 Serial.print("Elevation Angle:  ");
 Serial.println(ElevationAngle, 0); //Print Elevation (Vertical) with no decimal places as accuracy is not really great enough
 Serial.print("Azimuth:  ");
 Serial.println(Azimuth, 0); //Print Azimuth (Horizontal) with no decimal places
 if(ElevationAngle < 0)
 Serial.println("The sun has set. Get some sleep!");
 while(1){} //Stop - Values aren't going to have changed anyway as they are currently static variables!

Should work fine.



Dec 28, 2010, 07:19 pm Last Edit: Dec 28, 2010, 07:22 pm by joeinbend Reason: 1
Thanks Mowcius, this is great!
I have what is probably a really uneducated, lame question: It seems to get this to work in my area, all I need is to swap in my lat/long, is that correct? If so, I tried that, and I must be doing this wrong:

In my area, (Redmond, OR, USA), my decimal lat/long comes up as:
Latitude: 44.2727778
Longitude: -121.1727778

When plugging that in, I see the serial port reads a negative elevation angle, and azimuth 239, and says 'The sun has set...."

Can you point me in the right direction?
I feel guilty asking someone who as written such detailed complex code, for something like this :(

EDIT:: Sorry!! Disregard. I had lat/long switched in the code. I guess I was right that it was a lame question :) Thanks again for this fantastic code!


I feel guilty asking someone who as written such detailed complex code, for something like this

EDIT:: Sorry!! Disregard. I had lat/long switched in the code. I guess I was right that it was a lame question  Thanks again for this fantastic code!

I feel slightly guilty every time someone writes something like that as I merely took it and modified it slightly for the arduino.

Yeah I think it'd confusing how it is written with the lat and long. People always seem to stick them in the wrong way round :P



Have you done any further work with integrating this with a GPS for the clock and lat/long? (I saw you talking about this in another thread by chance, and figured the two projects were related)


I integrated it with a RTC (DS1307) for the time. I don't have a GPS at the moment so I can't do it with that.

It's easy enough :)

I'd love to use a compass and a GPS some time to make an automatic system that will track the sun anywhere without any values being programmed in.

Something I am going to using it for in the next month is for part of a lamp I am doing. Because I know when the sun has set, I can adjust lighting accordingly in the evening. Then there's no chance of sticking something on top of an LDR by accident and making the light turn on in the middle of the day when it's still light :)



Hi Mowcius

It seems that a lot of people using your sun tracker code.
Your code is great! Many thanks!!

I am working still on my solar concentrating power system.
The full code for it is done, at the moment I am waiting for some mechanical parts from italy.
With these parts I would be able to finish my project till spring.

I tested your code with a libelium gps module and it works everywhere!

Please visit my website under http://www.andres.li/
The website is written in german...under "Steuerung" you can see how arduino is working with the gps module.


Go Up