UPDATE: This program is the old version. Please visit this page for the new one.
On this page you will find a program for the Arduino which is capable of controlling various types of solar machines. For example, it can be applied to a dual* axis solar panel tracking system, a parabolic dish solar concentrator, or basically anything else you can think of which needs to point directly at the sun.
This program is also able to control a heliostat with multiple targets programmed into it, each available at the flick of a switch.
In fact, it is able to control all of these different types of solar machines simultaneously from just one single Arduino.
With this program, the position of the sun is actually calculated inside the Arduino (there is no trickery done with light sensors). This means that a minimum of power is used to orient the machine. Also, you won’t have to worry about your solar machine pointing in the wrong direction because of stray light.
By extending the number of outputs on the Arduino with shift registers, it is possible to control more solar machines with it than I can imagine anyone ever, practically, needing for a home DIY project.
At some point, the Arduino will run out of space since each machine’s settings uses some of it up. Depending on a variety of factors, the Arduino Duemilanove will be maxed out after about 10-12 machines are added.
Depending on what you are doing though, you might be able to trim off some of the code since you might not need it all. Also, I’m sure that there are probably ways to make the program more efficient and compact which I haven’t yet had the time to seek out.
On one final note, the Arduino Mega has 4x the space of the Arduino Duemilanove, so, if you do need more machines, that might be the route to take. You will, however, have to make some modifications to the code for it to work. I think the only thing you would have to do is change the various pin assignments, but I haven’t tried it yet since I don’t have an Arduino Mega.
Keep in mind that this program is still in its testing stages. It has been working for me thus far, but long term testing has only just begun. To put it simply, there are a lot of things that may or may not go wrong, so you might want to wait for me to do some more testing before you start an especially elaborate project based on this program. Of course, beta testers are most certainly welcome.
So far, the only person who really knows how it all works is me (I know, scary isn’t it). I’ve tried to document everything as best as I can, but there is still no way for me to address everything I would like to within my current time constraints. There should, however, be enough here so that it is much much easier for you to build you solar tracking project than it was for me.
If you make any mods to this program or build any machines which utilize this code, I would love to see them. The forum is the best place to post anything you might have. In particular, this thread has some of the more up to date information about this program such as ideas for future additions and bugs that you need to be aware of.
On one final note, should you find this program useful you might consider making a financial contribution through the PayPal link below to further not only its development but also the development of other solar-projects.
Both developing and documenting projects that are as complex as this one while also making them as accessible as possible takes up a good chunk of my free time. I’m not going to charge for it since I think that the world needs more solar-projects like this one, but, at the same time, extra cash does help speed up development time
So much to do, so little time.
Have Fun!
Gabriel Miller
*Notice that I said dual axis. The solar panel tracking systems you typically encounter on the web are single axis. Here’s a heads up to anyone trying to combine a single axis system with the duel axis Arduino controls on this page, it won’t work, but a lot of the code could still be made useful.
Download
UPDATE: This program is the old version. Please visit this page for the new one.
You can download the latest Arduino Sun Tracking/Heliostat Control program by clicking the link. Arduino Sun Tracker V0911.zip
Current Version (0.9.1.1)
The current version fixes a bug that caused the stepper motors to lose steps every time they updated the machine’s position. It also fixes a small error in the hour angle table which caused it to take up more space on the Arduino than it needed.
Old Versions
(0.9.1) This version fixes a mistake in the table which helps calculate the hour angle.
Arduino Sun Tracker V091.zip
Electronics
Check out the page Arduino Sun Tracking / Heliostat Electronics Control System for the electronics needed to control your solar machine.
In particular, you will need to have the DS1307 Real Time Clock setup on your Arduino with the correct time and date loaded onto it before you can start experimenting with the program.
Which Tab
When you open the program, you will see that it is a fairly large one after clicking on the different tabs.
The only tab you really need to worry about though is the one labeled “Arduino_SunTracker”. This is the only place where you absolutely must make changes so that you can customize it for both your location and situation.
![]()
Setting the Time and Date
Note: You won’t be able to set the time and date if you haven’t hooked up the DS1307 Real Time Clock yet. Check out the “Arduino Sun Tracking / Heliostat Electronics Control System” page for information on how to do it.
To set the correct time on the DS1307, first find the variables indicated in the picture below which are located in “void() setup”, towards the top(ish) of the sketch.
![]()
Change the numbers to match the current time. Make sure you use the 24hr clock, i.e. 13:00 instead of 1:00pm. Also, do not use daylight saving time. This means that you will have to set the time one hour earlier if daylight saving time is in effect. (That’s how it works in the U.S. anyway.)
Here is a link which shows the start and end date for daylight saving time around the world http://www.worldtimezone.com/daylight.html
It takes awhile to upload the sketch to the Arduino because of its large size. Setting the time about 40s ahead helps compensate for the delay.
Before clicking the upload button, make sure you remove the “//” preceding the setDateDs1307(…) text. Once that has been done, you can go ahead and start the upload.
After the upload is finished, put the “//” back in front of the setDateDs1307(…) text and hit the upload button again before doing anything else. Doing so will keep the time from defaulting back to the specified values every time the Arduino is reset.
After the second upload is finished, you should now see the current time and date displayed when you open the Serial Monitor.
If you see all zeros, however, then there is likely a loose connection between the Arduino and the DS1307. If that’s the case, check all of your connections and try again.
Setting your Location
At the very top of the Arduino sketch, you will see where to input your latitude, longitude, and time zone.
Check out the page “How to Find Your Latitude-Longitude Values and Convert them into Decimal Degrees” for information on finding your latitude and longitude.
If you don’t know it already, you can find your time zone value at this website http://www.worldtimezone.com/.
![]()
Make North be the Direction where the Azimuth Equals Zero
In the northern hemisphere, the sun’s path across the sky is mostly to the south. For various reasons, this is also the direction I chose to make the azimuth equal zero. If you are in the southern hemisphere though, the sun’s path across the sky is mostly to the north, so it will probably be easier for you if you make north as the direction where the azimuth equals zero degree.
To do so, just switch the 0 assigned to the northOrSouth variable to 180.
![]()
Setting the Hour the Machines Reset their Position
The hourReset variable specifies the time at which your solar machines will reset their position on the limit switches. You should choose an hour that occurs after nightfall for every day of the year.
![]()
Remember that daylight saving time is not used, so the hour the machines reset might be one hour off from the clocks in your home.
Stepper Motor Setup
You can customize the program to match your stepper motors where it says “#define STEPS 200″. If necessary, change the “200″ to match the number of steps for your stepper motors.
You can change the speed at which your stepper motors rotate by changing the “60″ in front of the stepperSpeed variable to either a higher or lower number.
![]()
Double Checking the Output for the Position of the Sun
If you open up the serial monitor after you have everything set up for your location, time, and date, you should see the correct altitude and azimuth displayed for the sun’s current position.
![]()
It wouldn’t be a bad idea to double check this output against another program that calculates the position of the sun to be certain that you have everything right. It can be very confusing to get everything set up correctly. Believe me, I know.
This one here seems to be pretty good. http://www.srrb.noaa.gov/highlights/sunrise/azel.html There are others out there too.
For this, the only thing we are interested in is the azimuth and altitude (aka elevation) calculations given by the above program.
The outputs given by each program won’t be exact, but they should be pretty close. You will have to subtract 180 degrees from the azimuth given at the link for it to match with the output from the Arduino program.
If they aren’t the same, double check everything and try to get it working correctly as there is really no point in continuing if it’s not.
One thing in particular that has thrown me off before is the usage of daylight saving time. Try setting one of the programs either an hour ahead or an hour behind to see if that at least gets the output to match.
Changing How Often the Machines Update Their Position
By default, I have the program set up so that the machines will update their position every five minutes. I chose a five minute span to help prolong the life of the relays (perhaps unnecessary) and also because a percentage of one step is lost for each stepper motor during each update. (This is explained further under the “Programming the Settings for each Sun Tracking Machine” section of this page.)
If you want to experiment with shorter increments of time, scroll down to about the top of the void loop() and you will find the if statement that controls how often the machines update their position.
You should see the code in the picture below. To make the machines update every three minutes, comment out the “if ( (minute2/5 == int(minute2/5)) || (firstRun == 0) ){” and un-comment the “if ( (minute2/3 == int(minute2/3)) || (firstRun == 0) ){” line below it.
To make the machines update every minute, comment out both of these lines along with the “}//END Update Every X Minutes” at the bottom of the code which calculates the position of the sun.
![]()
Adding More Machines
Here is a video which will show you how to add more solar machines. When you first download the program, only machine #1 is set up to run. You can use this code as a template for adding more machines.
You must repeat the procedure outlined in the video for every machine you want to control except, to add a third machine, you would replace the code indicated in the video with “Machine3″. For a fourth machine, you would use “Machine4″ and so on and so on.
Try watching the video in full screen mode so that you can see what’s going on better.
Setting the Targets when using a Heliostat
Here is a video which will show you how to setup different targets that are controlled electronically with switches. The code itself is mostly written already when you first download the program, but you will have to add some of it yourself to specify which target each heliostat machine points toward for every on/off combination of the three switches.
In the example video, I’m only using two heliostat machines, but more can be added.
Try watching the video in full screen mode so that you can see what’s going on better.
Programming the Settings for each Sun Tracking Machine
The moveMotors() function call (this is the same code that was copied and pasted in the “Adding More Machines” video above) contains all of the settings which can be customized for each individual solar machine.
It might look confusing, but it isn’t so bad if you take it step by step. I’ll go through it one setting at a time.
Setting #1 specifies whether your solar machine uses gears for its method of rotation or a lever arm leadscrew arrangement. The lever arm leadscrew arrangement is what I use, but it should be possible to use gears instead (I’ve spent a limited amount of time testing a solar machine with gears, so consider this feature to be even more “beta” than the others).
If you decide to use gears, a 200:1 gear ratio would be about the minimum I would recommend. The reason why is because you will lose part of 1 step every time the machine updates its position. For example, let’s pretend that it takes 10 steps to move the machine 1 degree. If the machine only ever updates 0.1 degree at a time, this would work out fine, but it doesn’t.
Assume instead that the same machine needed to rotate 0.15 degree, it would be able to successfully rotate 0.1 degree since that equals one step, but the other 0.05 degree would be lost.
Sometime in the future I might update the program to compensate for this loss, but, for now, it works fine just so long as there is a high enough gear ratio.
Setting #2 is straight forward. This setting allows you to either make your solar machine point directly at the sun or act as a heliostat.
Note: Settings #3-9 are basically the same as #10-16 except that one set is for the altitude rotation and the other is for the azimuth rotation.
Setting #3 specifies either the altitude’s gear ratio if your machine uses gears or the leadscrew’s turns per inch if your machine is using a lever arm leadscrew arrangement. The metric system should work here too just as long as it is used for everything.
Setting #4 is used to reverse the direction your stepper motors are spinning. It is easier to just replace the 1 with -1 (or -1 with 1) than it is to rewire your stepper motor.
Note: Settings 5-8 can be left as is if you machine does not use a lever arm leadscrew arrangement.
Setting #5 refers to “Length A” in the picture below.
Setting #6 refers to “Length B” in the picture below.
Note: the values for settings 5 and 6 can be reversed. It doesn’t matter which leg of the triangle is called length A and which is called length B.
Setting #7 Put the starting angle (when altitude = 0) of the altitude lever arm here. In the picture below, it is 90 degrees and I would suggest that you always just build your solar machines so that they all have a 90 degree angle between “Length A” and “Length B” when their altitude tilt is at zero degrees.
I would suggest the same basic idea for the azimuth setting as well except that “Length B” in the picture below would run parallel with geographic north and south while “Length A” would run parallel with east and west.
If you accidentally set up your solar machine incorrectly though, it can be easier to just change this setting in the program than to take it apart and realign everything, confusing though it may be.
![]()
Setting #8 specifies whether the altitude lever arm becomes more acute when it moves in the positive direction or more obtuse. Note: I’ve only really tested the acute setting with the Arduino Sun Tracker program and would also recommend that you always set up your solar machines to use the acute setting simply to make things more consistent.
Let me try and clarify this with a couple of pictures. If you look at the picture on the left below, you will see that the mirror has rotated up in the positive direction. In doing so, the triangle created by the end of leadscrew, mirror pivot, and stepper motor points has turned from the 90 degree triangle seen above into an acute triangle.
If you look at the picture on the right, however, you will see that the leadscrew attaches to the mirror on its opposite side. In this example, rotating the mirror in the positive direction will turn the triangle created by the end of leadscrew, mirror pivot, and stepper motor points into an obtuse triangle.
![]()
![]()
Essentially, the acute or obtuse option simply lets the Arduino Sun Tracker program know which side of the mirror the leadscrew attaches.
Setting #9 lets the Arduino Sun Tracker program know where the altitude limit switch is located. Make sure you don’t use zero for this value.
When you first plug in the Arduino and also when the machines reset themselves at night, the program will automatically move the stepper motors to try and find this limit switch. Once it is finally triggered, the program will then turn the machine 4 degrees away from the limit.
If you look under the functions tab and scroll all the way down to the bottom, you will find a function named findLimit(). This is the code that seeks out the limit switch.
![]()
Inside this function you will find two occurrences of the code you see in the picture below.
![]()
Every time the while loop repeats the stepper motor is told to take 10 steps. This will repeat up to 10,000 times before it gives up. This could be a problem if it occurs before the limit switch is reached. If your machine requires a lot of steps to rotate, you may need to change the 10000 in each while loop to a bigger number.
You will also need to change the “x=10001;” located a few lines below the start of each while loop to a number that is one number higher than the number you choose for the while loop.
Settings #10-16 are basically the same as settings #3-9, so I’m not going to repeat them. The only difference is that they control the azimuth rotation instead of the altitude rotation.
Setting #17 specifies the maximum possible azimuth rotation for your machine. Any value greater than this number is assumed to be outside the range of motion for your solar machine, and the Arduino Sun Tracker Program will stop moving it. This situation should typically occur late in the afternoon.
What Will Happen?
When the Arduino Sun Tracking / Heliostat Control Program runs, the following will occur.
When first started, the azimuth motor will seek out the limit switch. After it is triggered, the machine will move 4 degrees in the opposite direction so that the limit switch is no longer pressed down.
After the azimuth stepper motor is finished, the altitude stepper motor will do the same thing.
Note: As it is now, the altitude and azimuth stepper motors take turns when they move, but it is probably possible to synchronize them some how in the code, assuming it doesn’t take up too much space. Something to try in the future I suppose.
Assuming that the necessary azimuth* required of the solar machine is within its physical range, the machine will then move to either point at the sun or to reflect the light at the target. (*It doesn’t check to see if the altitude is within range.)
If the azimuth is out of range, early in the morning for example, the machine will wait until the sun moves into range before moving into position.
Once the reset is finished, the machine will update every five minutes (assuming you are using the default update time) until either the sun drops below the horizon or the required azimuth is out of the maximum range of the solar machine.
At this point, the machine will cease movement until it reaches the hour it is programmed to reset its position. It will then reset on the limit switches as it did in the beginning and wait until morning before resuming operations.
If you are using a heliostat and have switches set up and programmed so that you can change between different targets, the heliostat should move almost immediately (within about 7 seconds) to the selected target as soon as you change the combination of on and off for the switches.
This isn’t perfect yet however and it is possible, although rare, that the heliostat might move to a different programmed target before moving to the correct target. This happens because the Arduino might pick up the wrong combination of on and off for the switches as you are changing them. It won’t hurt anything, but it could be confusing if you weren’t expecting it.
It’s something that should be fixed for future versions.


Thanks Gabriel for naming ZininZelfdoen and Bernard, we are honoured!