Solar tracking sustav

Rasprava o AVR mikrokontrolerima, AVR projekti i drugo vezano za AVR...

Moderators: pedja089, stojke369, trax, InTheStillOfTheNight

Post Reply
energyman
Pocetnik na forumu
Pocetnik na forumu
Posts: 43
Joined: 11-11-2009, 11:56

Solar tracking sustav

Post by energyman »

Pozdrav forumaši,

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!
}
Glavna nedoumica u ovom kodu mi je, gdje su deklarirani pinovi tj PWM izlazi koji se spajaju na relay shield. Pošto ja ne korisitm servo motore nego obične DC motore. Koiko sam skužio, ovo smao ispisuje položaj trackera u konzoli.

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);
   }
  }
 }
 
 


        
                       
        
Svaka pomoč je dobrodošla :)
Post Reply