Open Source Arduino Sun Tracking/Heliostat Program 15

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!

15 thoughts on “Open Source Arduino Sun Tracking/Heliostat Program

  • Bill Kichman

    The vertical axis IS a linear actuator, acting at an angle. Don’t know whether the movement creates a linear change along with the linear motion variable, that’s why I asked….

    • Gabriel Miller Post author

      Oh, well in that case you will need the linear actuator calculations. The movement is not a “linear change” when linear actuators are involved since the linear motion of the actuator has to be translated to an angle.

  • Bill Kichman

    Wait, just thought of something. Can I scrap all the leadscrew calcs, I mean are the move motor variables linear, coming from the solar position calc, can i just covert a variable to a motor on timed event or is there some trig still involved?

    • Gabriel Miller Post author

      If your machine doesn’t use linear actuators for its pan and tilt, then no, you don’t really need the leadscrew calcs. Of course, it won’t hurt anything to leave them there. If you don’t have them turned on in the settings, the code won’t even be uploaded to the Arduino, so it won’t take up unnecessary space if that’s what you are worried about. It’s entirely up to you I guess. :)

  • Bill Kichman

    It’s making more sense now. Looking at this, despite my newness to programming, it actually looks like a small and easy application. Limit switches, timed motor relay outputs, and a solar core position calculator.
    Oh, and an RTC. I am using the DP8573, which needs a ton of port pins (16) but I have a ton of them so might as well use them, a MEGA has plenty of spare IO pins anyhow. And setting up a graphics display since I have a bunch of surplus units, might as well boilerplate them for future projects. Can you tell me the approximate accuracy you cna get with your calculations in positioning, using your simplified lookup table? I mean can I expect a degree or 2 accuracy during the day if I get the motor movement distances correct overall?

  • Bill Kichman

    Thanks for the reply. Regarding files, I think i understand now, it isn;t clear how the Arduino IDE works (or doesn’t). I now know I need to put most of the example codes I find into the libraries subdirectory, and call them from there. Before I was dumping everything into a sketch directory for ease of use, and the IDE wasn.t finding them correctly, the compiler was stopping all over the place. So am I correct that I am to put the entire project like for others, into its own subdirectory in the libraries folder, then set up a sketch to call the appropriate files…and insert references as appropriate?

    • Gabriel Miller Post author

      In general, the programs your write from scratch don’t have to be in the library folder. It’s only if you want to access code from anywhere on your computer or from multiple different programs that putting it in the library folder makes the most sense.

      Files with ending in .h or .cpp need to be in the library folder while files ending in .pde ( or .ino for Arduino IDE 1.0 and beyond) can be opened from anywhere on your computer. If you can’t see these extension, do a quick search for “How to turn on file extensions” so that you can view them on your computer.

      You can have multiple sketch files that are all just part of one larger program, which is how I have it set up with the sun tracker program. In my case, the multiple sketch files were just the result of me organizing program using the “new tab” feature in the Arduino IDE.

  • Bill K

    I see multiple versions of your program, and am getting a bit confused. Knowing what I want to accomplish, which program do I need, and aside of the standard flash and wire libraries, what else is needed, file wise? I see stepper and AFMotor includes referenced, but I would be driving only a timed pin output for (4) relays, which will work fine. It takes about 2 minutes total for up/down motor travel and about 45 minutes motor travel east-west. Those 2 includes aren’t in the zip file, do I need them? I guess I could sit a couple hours and decipher the program but thought I could more quickly ask :-)
    Thanks much.

    • Bill K

      Additionally I see references to MoveMachine, Machine on, etc…where are thee functions? It appears you generated the .pde app as standalone, but at first glance there is lots missing? Maybe I am missing something.

      • Gabriel Miller Post author

        It doesn’t really matter which version you use in your case, but I would go with the one on this page just because there is a little less code to wade through. (Try to use the Arduino IDE 1.0 version if at all possible.)
        Both versions are mostly identical, but there are slight differences because they are set up to be used with slightly different circuits.

        The stepper.h library is built into the Arduino IDE, and the Adafruit library is something that only needs to be installed if you want to use the Adafruit driver board.

        In your case, you could just comment out everything related to stepper motors since you aren’t using them, or even just leave it in and don’t use the pins, it doesn’t really matter.

        When you first downloaded the program, you should have had several different files inside the main Arduino_SunTracker folder. If they don’t open automatically as a row of tabs at the top when you open just one of them, go ahead and click and open each one individually, and you can edit them from there.

        I am 98% percent certain that I left you a comment before on how you might do drive your motors, but it seems to have disappeared. Forgive me if I am repeating something that I already told you.

        Anyway, I think the easiest way for you to accomplish what you want to do is to go to the top of the functions.pde tab/file and just go ahead and comment out everything inside of the moveToPosition() function. Then I think the easiest thing to do would be to turn the altsteps and azsteps variables into the the number of revolutions each motor needs to take.
        Something like, altrev = altsteps/steps;, azrev=azsteps/steps;

        Then you would somehow have to figure out how long it takes your DC motors to turn one revolution and then I guess just multiply that number by azrev or altrev, and you will have the amount of time the motor needs to stay on to move the specified distance.
        Pseudo code might look something like this for one motor able to move one direction.

        digitalWrite(altMotorClockwiseRelay, HIGH);
        digitalWrite(altMotorClockwiseRelay, LOW);

        I guess the findLimit function would also need to be edited too for your set up.

        That’s what I can think of so far. I’d do it for you if I could, but I am very strapped for time right now. In any case, I don’t have the same set up as you, so you would have to do all of the testing anyway.

        It’s probably going to take some finagling to get this to work, but I’m sure that it would still more accurate than an optical system regardless.

  • Gabriel Miller Post author

    Settings #8 and #15 let you specify what the angles are for your limits switches. I have a page here where I try to explain it a little better.

    Basically, once the machine triggers a limit switch, it can say, “OK I know where I am now in relation to the sun, so I need to move the stepper motors X number of steps to point at the sun.”

    Does that answer your question?

  • Bill K

    Quick question: I own a large pair of solar trackers, which use photosensors…they are a PITA due to chasing clouds and not starting out in the correct easterly direction due to varying seasons….so I would like to implement your system. I already have the motors and limit switches installed, only need to implement the controller. But how does the system know where in the morning to find the sun? I mean there are almost 90 compass degrees difference between summer and winter sunrise location…how do you set the system up, using the eastern-most compass direction as the limit, then the system knows how much to move, but based on what? Where do you tell the system the actual compass limit switch setting so it knows at the start where to move to?

  • Khalid Khattak

    Dear Gabriel,
    I am really thankful to you for sharing your great work with us. Your website is my favourite, full of knowledge and detail. I am also Arduino fan and i found the solar panel sun tracking Arduino sketch you have posted.
    I am currently studying the code. You have it very well-commented out.. I have few questions:
    1- It is difficult for me to understand the ARRAY you have defined with FLASH_ARRAY(int, HourAngleArray,-601,..};
    How the above Array work? what are the values -601,-721 etc? and where did they come from?..the first element is ‘int’ what is this?

    Again thanks for sharing.
    Khalid Khattak

    • Gabriel Miller Post author

      Hi Khalid,

      The “FLASH_ARRAY(int, HourAngleArray,-601,..};” syntax belongs to a neat library named “Flash”. It basically just makes it a lot easier to write code that utilizes the Arduino’s program memory space. The full documentation for it can be found at the below link.

      An explanation for the values inside the array can be found at this link.
      The program there needs to be updated, and doesn’t even use the Flash.h library, but that does give an explanation for how and why the array was created.

      The “int” just says what type of variable is held in the array. In this case it is an integer. Explaining the different types of variables would be a very lengthy discussion, but they are explained quite well on the Arduino reference page under “Data Types”

Comments are closed.