moram za projekt na faksu napraviti tracking sustav. Odlucio sam se za ravoj na Arduino pločici jer mi izgleda kao najjednostavnije riješenje.
Guglao sam malo ali na kraju nisam postao ništa pametniji.
Dakle ovako vidio sam da neki to rade sa LDR otpornicima ali je preporuka da se njih izbjegava jer se vrlo često kvare pa ih nije preporučljivo koristiti. Drugi pak imaju foru sa RTC-om, koji im uvijek daje točno vrijeme i proračunava u kojem bi se položaju trebalo nalaziti sunce te tako okreču motore.
Primjer takvog koda je ovdje:
Code: Select all
//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!
}
Stvarno sam zbunjen i ne znam šta da radim. Našao sam i jedan drugi kod, koji mi je logičniji nego ovaj prvi. Tu vidim gdje su deklarirani pinovi za RTC, ali idalje mi nejde u glavu kako povezati PWM izlaze sa arduina na relay shiel kao što je npr ovaj http://img.dxcdn.com/productimages/sku_144762_2.jpg
Code: Select all
#include <EtherShield.h>
#include <Time.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include <DS1307RTC.h>
#include <math.h>
#include <AFMotor.h>
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x28};
static uint8_t myip[4] = {192,168,4,202};
static uint8_t gwip[4] = {192,168,4,1};
#define STATUS_BUFFER_SIZE 35
static char statusstr[STATUS_BUFFER_SIZE];
#define PORT 80
#define HOSTNAME "192.168.4.45"
static uint8_t websrvip[4] = {192,168,4,45};
#define HTTPPATH "/wr_az_el.php"
EtherShield es=EtherShield();
#define BUFFER_SIZE 800
static uint8_t buf[BUFFER_SIZE+1];
void browserresult_callback(uint8_t statuscode,uint16_t datapos){}
#define pi 3.14159265358979323846
#define twopi (2*pi)
#define rad (pi/180)
#define EarthMeanRadius 6371.01 // In km
#define AstronomicalUnit 149597890 // In km
LiquidCrystal lcd(4, 9, 7, 8, 5, 6);
AF_Stepper ElevStepper(200,1);
AF_Stepper AziStepper(200,2);
boolean nightTime;
int ElevInt = 0;
int AziInt = 0;
int ElevFrac = 0;
int AziFrac = 0;
int AziStep = 0;
int ElevStep = 0;
int AziPrevious = 0;
int ElevPrevious = 0;
int AziOneDegree = 10; // Enter number of steps to physically move your rig 1 degree Azimuth.
int ElevOneDegree = 20; // Enter number of steps to physically move your rig 1 degree Elevation.
float ElevationAngle;
float Azimuth;
float Longitude = -121.23486042022705; //enter longitude here
float Latitude = 44.224928297647466; //enter latitude here
void setup(){
es.ES_enc28j60Init(mymac);
es.ES_init_ip_arp_udp_tcp(mymac, myip, PORT);
es.ES_client_set_gwip(gwip);
es.ES_client_set_wwwip(websrvip);
lcd.begin (19,3);
Wire.begin();
// pinMode (18, OUTPUT); // +5v for LCD Backlight (analog1 (digital 18)
pinMode (17, OUTPUT); // +5v for DS1307 RTC on analog 2 (digital 17)
pinMode (16, OUTPUT); // Ground for DS1307 on analog 3 (digital 16)
digitalWrite (17, HIGH); // tell pin 17 to be +5v
digitalWrite (16, LOW); // tell pin 16 to be Ground
// digitalWrite (18, HIGH); // tell pin 18 to be +5v (for backlight)
setSyncProvider(RTC.get); // Get time from RTC
setSyncInterval(86400); // re-sync time with the RTC every ( ) seconds.
ElevStepper.setSpeed(100);
AziStepper.setSpeed(100);
lcd.setCursor(0,0);
lcd.print("Sun Position Tracker");
lcd.setCursor(0,1);
lcd.print(" Initializing..");
lcd.setCursor(0,2);
lcd.print(" Please wait.. ");
}
void sunPos(){
float dY;
float dX;
float ZenithAngle;
float RightAscension;
float Declination;
float Parallax;
float ElapsedJulianDays;
float DecimalHours;
float EclipticLongitude;
float EclipticObliquity;
// 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 = (hour() + minute() / 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
lcd.setCursor(0,0);
lcd.print("Sun Position Tracker");
lcd.setCursor(0,1);
if(hour() <10)
lcd.print("0");
lcd.print(hour());
lcd.print(":");
if(minute() <10)
lcd.print("0");
lcd.print(minute());
lcd.print(":");
if(second() <10)
lcd.print("0");
lcd.print(second());
lcd.print(" ");
lcd.print(month());
lcd.print("/");
lcd.print(day());
lcd.print("/");
lcd.print(year());
lcd.print(" ");
lcd.setCursor(0,2);
lcd.print("E: ");
lcd.print(ElevationAngle);
lcd.print(" A: ");
lcd.print(Azimuth);
ElevInt = ElevationAngle;
AziInt = Azimuth;
ElevFrac = (float)(ElevationAngle - (float)ElevInt + 0.005)*100.0;
AziFrac = (float) (Azimuth - (float)AziInt + 0.005)*100.0;
}
void stepperFunc() {
// Convert Azimuth and ElevationAngle to output to stepper motors
// NOTE!!! For the code below, you must manually calculate how many steps it takes
// to mechanically move your rig exactly 1 degree of physical motion. This is in variables above,
// as ElevOneDegree and AziOneDegree.
ElevStep = (ElevationAngle * ElevOneDegree);
AziStep = ((Azimuth / 2) * AziOneDegree);
if (ElevationAngle < 0){
nightTime = true;
lcd.setCursor(0,3);
lcd.print (" Parking All Panels ");
ElevStepper.step(((90-ElevationAngle)*ElevOneDegree),BACKWARD, DOUBLE); // Park the panel flat at night.
AziStepper.step(((Azimuth/4)*AziOneDegree),BACKWARD, DOUBLE);
}
while(nightTime){
ElevPrevious = 0; // Clear "previous" values
AziPrevious = 0;
lcd.setCursor(0,3);
lcd.print(" Night Time ");
sunPos(); //Run sunPos() to see when Elevation is above zero.
if (ElevationAngle > 0)
nightTime = false;
lcd.setCursor(0,2);
lcd.print("E: ");
lcd.print(ElevationAngle);
lcd.print(" A: ");
lcd.print(Azimuth);
delay(1000);
}
if ((ElevStep - ElevPrevious)<0) // After the solar noon, Elevation will be declining, so we have
ElevStepper.step(((ElevStep - ElevPrevious)*-1),BACKWARD, DOUBLE); // to invert the negative number to positive (* -1), and tell
else // the stepper to run BACKWARD.
ElevStepper.step((ElevStep - ElevPrevious),FORWARD, DOUBLE); // For the steppers, we want to only have motion if there has been
AziStepper.step((AziStep - AziPrevious),FORWARD, DOUBLE); // change. By subtracting the previous values from the current values,
// it will result in a 0 value, unless there is change.
lcd.setCursor(0,3);
lcd.print(" Day Time ");
ElevPrevious = ElevStep;
AziPrevious = AziStep;
}
void loop(){
static uint32_t timetosend;
uint16_t dat_p;
dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
if (dat_p == 0){
if (millis() - timetosend > 60000) // every 10 seconds
{
timetosend = millis();
sunPos();
stepperFunc();
sprintf( statusstr, "?el=%d.%.2d&az=%d.%.2d", ElevInt, ElevFrac, AziInt, AziFrac );
es.ES_client_browse_url(PSTR(HTTPPATH), statusstr, PSTR(HOSTNAME), &browserresult_callback);
}
}
}