Solar Tracking

Hi,

I am trying to build a solar tracker system for the first time both single axis and dual axis.

And I was wondering that what micro controller / Audrino development kit should I use?

Plus can you share the code that used real time clock, azimuth and elevation angle to move the solar panels?

I have seen the following thread which is very informative but I want to use the code and idea given in the thread but it did not recommend any kit.

http://forum.arduino.cc/index.php?topic=22670.15

I used the following website to put together the Truth table

http://aa.usno.navy.mil/data/docs/AltAz.php

but unable to figure out that how to use this truth table to calculate how much should I tilt the solar panel.

Thanks

Erica

Here's a thought. Suppose you took two photoresistors and mounted them on an arm, say 6 " apart, and tilted them apart at the same angle (say 10 degrees off vertical). Then out in the sun, they would read the same (allowing for calibration) only when the arm was tilted exactly facing (meaning perpendicular) to the sun. When they didn't read the same, you could use the discrepancy to change the tilt of the arm, and the solar panels, to exactly face the sun. You could do the same for both east-west and north-south orientations, which would compensate for time of day, as well as time of year.

Good luck

Hi,

I am using Mega2560 board and programmed it with the following code that was posted on the following link . I am confused that the code does not have I/O pins defined or PWM or how the motor will know how much (angle) to move and stay there. Please advise! erica

/

/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() {
Serial.begin(9600);
}

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;
          JulianDate=(float)(liAux2)-0.5+DecimalHours/24.0;
          // 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;
          Omega=2.1429-0.0010394594*ElapsedJulianDays;
          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
                -0.0000203*sin(Omega);
          EclipticObliquity = 0.4090928 - 6.2140e-9*ElapsedJulianDays
                +0.0000396*cos(Omega);

    // 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 +
                0.0657098283*ElapsedJulianDays
                + 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
          Parallax=(EarthMeanRadius/AstronomicalUnit)
                *sin(ZenithAngle);
          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!
}

Have you built or purchased the actual the sun tracker positioning mechanism yet?

In order to write a program to control the sun tracker position, you will first have to define how the positioning is physically accomplished.

Erica:

Please go and read the instructions, then go back and modify your post to mark up the code as such so we can examine it comfortably and reliably.

Then post the essential diagrams and pictures of your equipment.

Hi,

The code that I attached below is calculating the Sun’s azimuth and elevation angle. Let’s say sun’s azimuth angle is 282 and elevation angle is 20 what will be the angle of the motor or the tilt of the motor. How can I calculate it and direct the motor to make the solar panel face the Sun? I will be using PWM but I do not know how to relate the PWM and the angle and tilt that motor will do to make the solar panel face the sun.

I will be using 1 Watt output solar panel.

There will be two systems one for single axis and the second one for dual axes.

//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() {
Serial.begin(9600);
}

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;
           JulianDate=(float)(liAux2)-0.5+DecimalHours/24.0;
           // 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;
           Omega=2.1429-0.0010394594*ElapsedJulianDays;
           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
                 -0.0000203*sin(Omega);
           EclipticObliquity = 0.4090928 - 6.2140e-9*ElapsedJulianDays
                 +0.0000396*cos(Omega);

     // 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 +
                 0.0657098283*ElapsedJulianDays
                 + 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
           Parallax=(EarthMeanRadius/AstronomicalUnit)
                 *sin(ZenithAngle);
           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!
}

That's better!

I guess, I fixed it

what will be the angle of the motor or the tilt of the motor.

You mean the platform, which you have not described. Without that description it is impossible to go any further with this.

Hi,

The platform is a DC motor (3V, 20mA) and a solar panel (1W). If this setup is not good then Can you specify the algorithm for a mechanical setup that you or worked with. I will try to understand it and replicate it.

Erica

You are still missing the mechanical description -- how will the motor physically orient the solar panel?

For that, you need a framework that holds the solar panel, and includes a motor that somehow sets the panel orientation. Next you need to analyze the motor and framework geometry so that the program can run the motor, in order to orient the panel in a given direction.

This single axis solar tracker is reasonably well described, with some documents that you can download.

Here is a second and a third idea. There are many other projects like these.

Hi,

The DC motor 'a rotor shaft is perpendicular to the ground and solar panel can be moved by the motor +/- 180 degrees. I attached the word document with this email. This is single axis control of the solar panel. Can this setup follows Sun? If yes then what will be the algorithm to do this?

The source code that I mention in my previous message determines elevation and azimuth of the Sun. I am guessing that this scheme requires two motors. Am I right? if yes then what will be the algorithm and where should I place the second motor?

Erica

Your setup should be able to track the sun position in azimuth, which is conventionally the horizontal angle from North. You already have a program that can calculate the solar azimuth. The panel can be set at a fixed angle for the average solar elevation.

Today, in my area, the sun rises at azimuth 109 degrees, and sets at 251 degrees.

I would set the motor/panel to face toward 109 degrees at sunrise and every 15 minutes or so, increment it the appropriate amount until at sunset, it is facing toward 251 degrees.

You haven't given enough information for us to determine how the program might steer your panel to face the correct azimuth.

Hi,

The last post did not accept the .docx forma.So, I am attaching again the document with.doc .

erica

Motor and Solar panel.doc (33.5 KB)

Sorry, that diagram doesn't help at all.

Hi, Can you suggest a mechanical system that can do what I want to do from amazon or some other distributor under 100 bucks? I will buy that system and try to control it using this code.

Right now what I have is a small solar panel that can be rotated by a DC motor. Please advise what other information you need!

From you earlier reply, it seems like the motor needs to follow the sun's azimuth only which will vary with time. You gave the following example,

"Today, in my area, the sun rises at azimuth 109 degrees, and sets at 251 degrees. face toward 109 degrees at sunrise and every 15 minutes or so, increment it the appropriate amount until at sunset, it is facing toward 251 degrees."

Does it mean that only need one motor to follow the sun and the motor will only move in one axis (horizontally)?

erica

It's similar to telescope tracking - you optimally want an equatorial mount on which the motor gearing acts with the panel or panels rotating around this. Such an arrangement can be time driven rather than tracking. To be really picky, the elevation of the panels would be adjusted every so often to match the season, whether manually or automatically.

Hi,

As you can see from my previous replies that I am a beginner. Please try to answer my questions if you can or want to in simple words because I get more confused when you mention things like equatorial mount etc.

I thought that I can track sun by its azimuth and elevation and might require two motors for this but seems likes that I can use one motor to do this but now how to mount the solar panel is also an issue. Its getting really complicated for my skill set.

erica :(

Forum members probably can't help you build the mechanical part, and there don't seem to be suitable motorized platforms for sale. I suggest you team up with someone who has mechanical skills.

Hi,

Can you send me the web link to the mechanical system that does what we are discussing or can you give a block diagram of the system?

The code that I attached in the previous replies can calculate the azimuth and elevation of the sun. I need to know what kind of mechanical system is required to do this. If you can refer me to some website or send me a block diagram.

I know that how to control a motor using Full H-bridge and pulse width modulation but I am just confused about what is the algorithm or scheme to make the motor work in a way that it follows the Sun's changing azimuth and elevation angles.

erica