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.
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!
}
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!
}
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.
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.
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?
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, 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)?
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.
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.
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.
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.