Open Source Arduino Sun Tracking/Heliostat Program

Subscribe to my Feed!


UPDATE: The program / documentation on this page is horribly out of date. I’m currently working to re-write the “official” documentation, but until I finish you can find the most up to date stuff on this page on this site’s forum.

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 any other type of machine which points 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. You also won’t have to worry about your 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 Duemilanove will run out of space since each machine’s settings uses some of it up, but you would probably need an entire field filled with them before that happens. And if you need even more machines, you could, of course, always just upgrade to the Arduino Mega. :)

Keep in mind that this program is still in its testing stages. At the time of this writing, I have about 10 months of experience using this program, and thus far think I’ve worked through its biggest bugs. To put it simply though, there are a lot of things that may or may not go wrong, so you should be wary if you want start an especially elaborate project based on this program. That said, beta testers are most certainly welcome.

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.

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 and programs.

Both developing and documenting projects that are as complex as this one while also making them as universal 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 projects like this one, but, at the same time, extra cash does help speed up development time. ;)


*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 dual axis Arduino controls on this page, it won’t work straight out of the box, but a lot of the code could still be made useful.


UPDATE: 12/18/2012 The program / documentation on this page is horribly out of date. I’m currently working to re-write the “official” documentation, but until I finish you can find the most up to date stuff on this page on this site’s forum.

UPDATE: 1/09/12

Ver. 0.9.6 fixes a bug in the code which caused the altitude and azimuth of the heliostat to be calculated incorrectly for certain inputted angles. The entire “heliostat angle” algorithm was rewritten and tested throughly inside a computer simulation, so it should be good to go.

You can download the latest Arduino Sun Tracking/Heliostat Control program by clicking the link Arduino_SunTracker_V096. You will also need to download and install the “Flash” library which can be found on this site. Move it to your Arduino libraries folder before attempting to use the Sun Tracking/Heliostat program.

Arduino IDE 1.0 Code

Note: Arduino IDE 1.0.1 is not yet supported. Use the Previous 1.0 IDE when using this program.

(Update: V0.9.7 can be downloaded on the forums at this link.)

If you have updated the Arduino IDE to 1.0, you will need to use this program instead of the one above. Arduino_SunTracker_V096_Arduino1 (Alternatively, you can also download an older version of the IDE and just use the above program)

Also, make sure you download and install the latest version of the flash.h library (which has now been made compatible with the Arduino 1.0 IDE) before trying to upload this program. Here is the link.

Two Wire Step and Direction Driver Board Code

On the page Single Machine Sun Tracking / Heliostat Electronics you will find code which utilizes the more common two wire step and direction type of driver boards. The code on the page your currently at does have a two wire stepper motor driver board setting, but this is different than the step and direction type. If you try to use the two wire setting with the code on this page on a step and direction driver board, you will likely get unpredictable results.


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.

Note: I have noticed that all of these tabs don’t always show up when I open them on different computers. The downloaded zip file should contain several files with the same names as those on the tabs in the picture below. You can always open and edit these files individually if needed.

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 in the “void() setup” function located about two thirds of the way down from the top of the page.


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 where I live anyway.)

Here is a link which shows the start and end date for daylight saving time around the world

It takes awhile to upload the sketch to the Arduino because of its large size. Setting the time ahead by several seconds 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, there is likely a loose connection between the Arduino and the DS1307. 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.

You can find your time zone value at this website


Make North 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. (This hasn’t been throughly tested by anyone that I know of)

To do so, just switch the 0 assigned to the northOrSouth variable to 180.


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. 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.

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 depending on whether or not it is in affect.

Stepper Motor Setup

The settings for customizing the stepper motor setup are as shown in the picture below. It is all rather straight forward, and the included comments should be enough to get you going.

Programming the Settings for each Sun Tracking Machine

Setting #0 specifies whether your solar machine uses gears for its method of rotation or a linear actuator arrangement.

Setting #1 allows you to either make your solar machine point directly at the sun or act as a heliostat.

Setting #2 specifies either the altitude’s gear ratio if your machine uses gears or the linear actuator’s turns per inch depending on Setting #0. Note: the metric system should work here too just as long as it is used for everything else too.

Setting #3 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: Put 0 for settings 4-7 if using a gear reduction system as they are unused.

Setting #4 refers to “Length A” in the picture below.

Setting #5 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 #6 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.

heliostat setup

Setting #7 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 #8 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.

Note: The limit switches for both the altitude and azimuth should be positioned in such a way that the machine is ready for the morning sunrise after it resets.

Settings #9-15 are basically the same as settings #2-8, so I’m not going to repeat them. The only difference is that they control the azimuth movement instead of the altitude movement.

Setting #16 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 would typically occur late in the afternoon.

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 three minutes. I personally chose a three minute span to help prolong the mechanical life of my relays.

If you want to experiment with shorter increments of time, scroll down to the void loop() and inside 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 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. Other time increments are possible by writing different if statements.


Adding Machines

When first downloaded, the program is setup to control just one machine. Adding more is easy, especially if all of your machines are identical. First, specify the number of machines that you want to setup with the “numberOfMachines” variable.

You can then add more machines just by copying and pasting the first line as many times as needed. Below shows the code when first downloaded.

For these examples, we will assume that we have identical machines with wormgears as their gear reduction system.

Here is an example with two machines.

Here is one with three.

This pattern continues for every machine you wish to control. Remember to include the comma between every {…}, but do not include one after the last set.

Although the settings for each machine are identical in this example, they could have each been completely unique if needed.


Setting the Targets when using a Heliostat

If you go to the “TargetControl” tab / file, you will find where to put code for switching between different targets when using a heliostat. It has been commented out, but I have included the code I used for controlling the targets with switches as one possible example.

The bottom of the tab has the following code, which is an example of assigning a target with and altitude and azimuth of zero to machine number one.

MachineTargetAlt[0] = 0;
MachineTargetAz[0]  = 0;

The “0” between the square brackets lets the program know which machine to assign the target to.

If I had two machines and wanted to assign a target to the second one, I would use this code.
MachineTargetAlt[1] = 1;
MachineTargetAz[1]  = 5.2;

Notice that machine 1 has an index of 0 and machine 2 has an index of 1. Subtract one from the machine’s number to place its target in the correct location in the MachineTargetAlt and MachineTargetAz arrays.

The “targetsUsed” variable must be changed to a new number whenever the state of the target(s) is changed. This lets the program know that the heliostat should update its position immediately. Without it, you will have to wait until the sun’s position is updated, which could take several minutes.


What Will Happen?

When the Arduino Sun Tracking / Heliostat Control Program runs, the following will occur:


1. When the program first begins, the azimuth motor will seek out the limit switch (which should be located in the morning position). After it is triggered, the machine will move 4 degrees in the opposite direction so that the limit switch is no longer activated.

2. After the azimuth stepper motor is finished, the altitude stepper motor will do the same thing.

Moving into Position

3. 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. (*There is currently no 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.

Note 1: The azimuth and altitude motors take turns when they move. First the azimuth, then the altitude.
Note 2: If your machine takes a long time to reset itself, it may appear as though it has fallen behind the sun when it finishes moving into position. Try waiting a few minutes for the sun’s position to be updated inside the program. Once it does, it should then move to the correct position.

Moving Throughout the Day

4. Once the machine is in position it will update every three 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.

5. 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.

Subscribe to my Feed!