PIC Per Tutti, Energia Alternativa - Sistema di comando e controllo a basso costo
Webmaster - PinoTux
Inseguire il sole con i sistemi a fotoresistenza o fotodiodo possono funzionare, ma hanno dei problemini specialmente quando passano le nuvole...
A cosa può servire l'orologio nel PPTEA (REAL TIME CLOCK)? Visto che conosciamo l'ora e pure dove ci troviamo, nel caso possiamo ricavare le coordinate geografiche dal nostro navigatore o da quello di un amico, possiamo scrivere un algoritmo che ci indica tilt ed azimuth del sole.
Questo è un algoritmo di Tracking molto accurato e vi riporto il codice.
Avete capito dove voglio arrivare, basta tradurre questo codice in eabasic ed il gioco è fatto.
Questa è la discussione originale.
Questo è il file ".eab" dell' Inseguitore Solare.
Scarica il file (ZIP)
(26/12/2012 - Corretto bug sul codice alle righe 400-410)
CODICE:
// This file is available in electronic form at http://www.psa.es/sdg/sunpos.htm
#ifndef __SUNPOS_H #define __SUNPOS_H // Declaration of some constants #define pi 3.14159265358979323846 #define twopi (2*pi) #define rad (pi/180) #define dEarthMeanRadius 6371.01 // In km #define dAstronomicalUnit 149597890 // In km struct cTime { int iYear; int iMonth; int iDay; double dHours; double dMinutes; double dSeconds; }; struct cLocation { double dLongitude; double dLatitude; }; struct cSunCoordinates { double dZenithAngle; double dAzimuth; }; void sunpos(cTime udtTime, cLocation udtLocation, cSunCoordinates *udtSunCoordinates); #endif |
CODICE:
// This file is available in electronic form at http://www.psa.es/sdg/sunpos.htm #include "sunpos.h" #include <math.h> void sunpos(cTime udtTime,cLocation udtLocation, cSunCoordinates *udtSunCoordinates) { // Main variables double dElapsedJulianDays; double dDecimalHours; double dEclipticLongitude; double dEclipticObliquity; double dRightAscension; double dDeclination; // Auxiliary variables double dY; double dX; // Calculate difference in days between the current Julian Day // and JD 2451545.0, which is noon 1 January 2000 Universal Time { double dJulianDate; long int liAux1; long int liAux2; // Calculate time of the day in UT decimal hours dDecimalHours = udtTime.dHours + (udtTime.dMinutes + udtTime.dSeconds / 60.0 ) / 60.0; // Calculate current Julian Day liAux1 =(udtTime.iMonth-14)/12; liAux2=(1461*(udtTime.iYear + 4800 + liAux1))/4 + (367*(udtTime.iMonth - 2-12*liAux1))/12- (3*((udtTime.iYear + 4900 + liAux1)/100))/4+udtTime.iDay-32075; dJulianDate=(double)(liAux2)-0.5+dDecimalHours/24.0; // Calculate difference between current Julian Day and JD 2451545.0 dElapsedJulianDays = dJulianDate-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) { double dMeanLongitude; double dMeanAnomaly; double dOmega; dOmega=2.1429-0.0010394594*dElapsedJulianDays; dMeanLongitude = 4.8950630+ 0.017202791698*dElapsedJulianDays; // Radians dMeanAnomaly = 6.2400600+ 0.0172019699*dElapsedJulianDays; dEclipticLongitude = dMeanLongitude + 0.03341607*sin( dMeanAnomaly ) + 0.00034894*sin( 2*dMeanAnomaly )-0.0001134 -0.0000203*sin(dOmega); dEclipticObliquity = 0.4090928 - 6.2140e-9*dElapsedJulianDays +0.0000396*cos(dOmega); } // 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) { double dSin_EclipticLongitude; dSin_EclipticLongitude= sin( dEclipticLongitude ); dY = cos( dEclipticObliquity ) * dSin_EclipticLongitude; dX = cos( dEclipticLongitude ); dRightAscension = atan2( dY,dX ); if( dRightAscension < 0.0 ) dRightAscension = dRightAscension + twopi; dDeclination = asin( sin( dEclipticObliquity )*dSin_EclipticLongitude ); } // Calculate local coordinates ( azimuth and zenith angle ) in degrees { double dGreenwichMeanSiderealTime; double dLocalMeanSiderealTime; double dLatitudeInRadians; double dHourAngle; double dCos_Latitude; double dSin_Latitude; double dCos_HourAngle; double dParallax; dGreenwichMeanSiderealTime = 6.6974243242 + 0.0657098283*dElapsedJulianDays + dDecimalHours; dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime*15 + udtLocation.dLongitude)*rad; dHourAngle = dLocalMeanSiderealTime - dRightAscension; dLatitudeInRadians = udtLocation.dLatitude*rad; dCos_Latitude = cos( dLatitudeInRadians ); dSin_Latitude = sin( dLatitudeInRadians ); dCos_HourAngle= cos( dHourAngle ); udtSunCoordinates->dZenithAngle = (acos( dCos_Latitude*dCos_HourAngle *cos(dDeclination) + sin( dDeclination )*dSin_Latitude)); dY = -sin( dHourAngle ); dX = tan( dDeclination )*dCos_Latitude - dSin_Latitude*dCos_HourAngle; udtSunCoordinates->dAzimuth = atan2( dY, dX ); if ( udtSunCoordinates->dAzimuth < 0.0 ) udtSunCoordinates->dAzimuth = udtSunCoordinates->dAzimuth + twopi; udtSunCoordinates->dAzimuth = udtSunCoordinates->dAzimuth/rad; // Parallax Correction dParallax=(dEarthMeanRadius/dAstronomicalUnit) *sin(udtSunCoordinates->dZenithAngle); udtSunCoordinates->dZenithAngle=(udtSunCoordinates->dZenithAngle + dParallax)/rad; } } |
Visto che la V.2.8 è stata consegnata vi posto il codice che visualizza la posizione del SOLE.
In questa versione occorre avere il REAL TIME CLOCK, l'espansione di memoria, un display e tutto funziona automaticamente
Se non avete il display potete far uscire l'output su usb.
Occorre solo settare le coordinate (latitudine e longitudine Linea 130 e 140
Questo è il codice, impiega meno di un secondo a fare tutti i calcoli: bravo PPTEA...hehehe ^_^ .
Il codice può essere ottimizzato, ma considerate che rimane più della metà della memoria libera, sufficiente per fare qualsiasi cosa.
Un applicazione carina sarebbe quella di realizzare un orologio, sensore di temperatura, alba, tramonto e fasi lunari.
C'è qualche volontario?
100 MATH_PRECISION=18 ' AUMENTIAMO LA PRECISIONE DEL PPTEA 110 'Calcolo posizione Sole FINO AL BLOCCO CON VERSIONE PPTEA 2.8 O SUPERIORE 120 PRAGMA EXTERNAL_EEPROM 125 'USBOUT="START" 130 CONSTANT dLongitude=13.526507 140 CONSTANT dLatitude=45.813530 150 CONSTANT dEarthMeanRadius=6371.01 160 CONSTANT dAstronomicalUnit=149597890 170 ' ----- Calculate difference in days between the current Julian Day 180 ' and JD 2451545.0, which is noon 1 January 2000 Universal Time ----- 190 ' Calculate time of the day in UT decimal hours 200 'GG_MM_AA=DATE ' 210 'USBOUT="GIORNO MISURE:" & GG_MM_AA & chr(13) & chr(10) 220 'FDATE=4 230 'dDecimalHours =DATE/3600.0 ' 35608/3600.0 ' 240 FDATE=2 250 GG_MM_AA=DATE ' 260 LCDPOS=&H11 270 LCDWRITE= " PPTEA BOLLE" 280 LCDPOS=&H21 290 LCDWRITE= " SUN POSITION" 300 waits 2 301 LCDCLEAR 302 LCDPOS=&H24 303 FDATE=1 305 LCDWRITE= DATE 310 LCDPOS=&H11 320 LCDWRITE="DATE: "& GG_MM_AA 330 waits 2 340 LCDPOS=amp;H11 350 LCDWRITE= " Lat. Long. " 360 LCDPOS=&H21 370 LCDWRITE= "45.8135 13.5265" 380 waits 2 381 LCDCLEAR 382 LCDPOS=&H11 383 LCDWRITE="START REAL TIME" 384 LCDPOS=&H21 385 LCDWRITE=" ELABORATION" 386 waits 1 387 FDATE=4 388 dDecimalHours =DATE/3600.0 ' 35608/3600.0 ' 389 dDecimalHours-=1.0 'metto l'ora sul fuso giusto 390 iMonth=mid(GG_MM_AA,4,2) 400 liAux1=(iMonth-14)/12 410 iYear =right(GG_MM_AA,2)+2000 420 iDay=left(GG_MM_AA,2) 430 liAux2=((1461*(iYear + 4800 + liAux1))/4) 440 liAux2+=(367*(iMonth- 2-12*liAux1))/12 450 liAux2+= -1*(3*((iYear + 4900+ liAux1)/100))/4+iDay-32075 460 dJulianDate= liAux2 - 0.5 + dDecimalHours/24.0 470 ' Calculate difference between current Julian Day and JD 2451545.0 480 dElapsedJulianDays = dJulianDate-2451545.0 490 ' ----- Calculate ecliptic coordinates ----- 500 dOmega=2.1429-0.0010394594*dElapsedJulianDays 510 dMeanLongitude = 4.8950630+ 0.01720279169 * dElapsedJulianDays 'Radians 520 dMeanAnomaly = 6.2400600+ 0.0172019699 * dElapsedJulianDays 530 'NV= dMeanAnomaly 540 'GOSUB :NORMALIZZA_VALORE 550 NV1=SIN(dMeanAnomaly) 560 'NV= dMeanAnomaly*2 570 'GOSUB :NORMALIZZA_VALORE 580 NV2=SIN(dMeanAnomaly*2) 590 'NV= dOmega 600 'GOSUB :NORMALIZZA_VALORE 610 NV3=SIN(dOmega) 620 dEclipticLongitude = dMeanLongitude + 0.03341607*NV1+ 0.00034894*NV2-0.0001134 -0.0000203*NV3 630 'USBOUT= "dEclLon=" & dEclipticLongitude 640 'NV= dOmega 650 'GOSUB :NORMALIZZA_VALORE 660 NV1=COS(dOmega) 670 'USBOUT="COS="& NV1 680 dEclipticObliquity = 0.4090928 - (0.00000006214*dElapsedJulianDays)/10 +0.0000396*NV1 690 'USBOUT= " dEclObl=" & dEclipticObliquity 700 'Calculate celestial coordinates ( right ascension and declination ) 710 'in radians but without limiting the angle to be less than 2*Pi 720 'NV=dEclipticLongitude 730 'GOSUB :NORMALIZZA_VALORE 740 dSin_EclipticLongitude= sin( dEclipticLongitude ) 750 'NV=dEclipticObliquity 760 'GOSUB :NORMALIZZA_VALORE 770 dY = cos( dEclipticObliquity) * dSin_EclipticLongitude 780 'NV=dEclipticLongitude 790 'GOSUB :NORMALIZZA_VALORE 800 dX = cos(dEclipticLongitude) 810 NV2=DY 820 NV1=DX 830 GOSUB :ATAN2 840 dRightAscension = NV1 850 if dRightAscension >= 0.0 THEN 900 860 dRightAscension = dRightAscension + 2*PI 870 'NV=dEclipticObliquity 880 'GOSUB :NORMALIZZA_VALORE 890 dDeclination=sin(dEclipticObliquity)*dSin_EclipticLongitude 900 dDeclination = asin( dDeclination ) 910 'USBOUT= " dSinEcl=" & dSin_EclipticLongitude 920 'USBOUT= " dRigAsc=" & dRightAscension 930 'USBOUT= " dDecl=" & dDeclination 940 'Calculate local coordinates ( azimuth and zenith angle ) in degrees 950 dLocalMeanSiderealTime = 6.6974243242 + 0.0657098283 * dElapsedJulianDays + dDecimalHours 960 dLocalMeanSiderealTime= (dLocalMeanSiderealTime*15 + dLongitude)*PI/180 970 liAux1 = dLocalMeanSiderealTime - dRightAscension 'dHourAngle 980 'NV=liAux1 990 'GOSUB :NORMALIZZA_VALORE 1000 'liAux1=NV 1010 'USBOUT=" dHourAngle="& liAux1 1020 liAux2 = dLatitude * PI/180 'dLatitudeInRadians 1030 'USBOUT=" dLat="& liAux2 1040 NV1=cos( liAux2 ) 'dCos_Latitude 1050 'USBOUT=" dCos="& NV1 1060 NV2=sin( liAux2 ) 'dSin_Latitude 1070 'USBOUT=" dSin="& NV2 1080 NV= cos( liAux1 ) 'dCos_HourAngle 1090 'USBOUT=" dCosH="& NV 1100 iMonth=acos(NV1*NV*cos(dDeclination)+sin(dDeclination)*NV2) 'dZenithAngle 1110 'USBOUT=" dZen="& iMonth 1120 dY = -sin( liAux1 ) 1130 'USBOUT=" dY="& dy 1140 dX = tan( dDeclination )*NV1-NV2*NV 1150 'USBOUT=" dx="& dx 1160 NV2=DY 1170 NV1=DX 1180 GOSUB :ATAN2 1190 if NV1 > 0 then 1210 1200 NV1 += 2*PI 1210 NV1=NV1/(PI/180) 1212 LCDPOS=&H11 1213 FDATE=4 1215 if DATE mod 10 then :SALT 1216 LCDWRITE= " Azimuth Elevat"'& DATE 1217 GOTO 1220 1218 :SALT FDATE=1 1219 LCDWRITE= " TIME "& DATE 1220 USBOUT=" dAzim="& NV1 1230 LCDPOS=&H22 1240 LCDWRITE=left(NV1,6) 'LCDWRITE="Azimuth="& left(NV1,6) 1250 dParallax=dEarthMeanRadius/dAstronomicalUnit *sin(iMonth) 1260 'USBOUT=" dPar="& dParallax 1270 iMonth=(iMonth+ dParallax)/(PI/180) 'dZenithAngle 1280 USBOUT=" dZen="& iMonth &" " 1290 'LCDPOS=&H21 1299 iMonth=90.0-iMonth 1300 LCDWRITE=" "& left(iMonth,6) 'LCDWRITE="Zenith ="& left(iMonth,6) 1310 'NV= int((dDecimalHours-int(dDecimalHours))*60) 1320 'NV2= int(dDecimalHours *3600 - int(dDecimalHours) *3600 - NV*60) 1330 'MV3=right("0"&int(dDecimalHours),2) &":" & right("0"&NV,2) &":"&right("0"&NV2,2) 1340 'USBOUT=MV3 & chr(13) & chr(10) 1350 'LCDPOS=&H21 1360 'LCDWRITE=" SUNPOS " & MV3 1370 'dDecimalHours+=0.0166666666 1380 goto 387 1390 ':NORMALIZZA_VALORE 1400 'USBOUT=" NV1="& NV 1410 'NV= NV/ (2*PI) 1420 'USBOUT=" NV2="& NV 1430 'L= NV-INT(NV) 1440 'USBOUT=" L="& L 1450 'NV=L*2*PI+2*PI 1460 'USBOUT=" NV3="& NV 1470 RETURN 1480 :ATAN2 1490 IF NV1 > 0 Then 1540 1500 IF NV1 < 0 Then 1560 1510 IF NV2 = 0 Then 1610 1520 NV1= SGN(NV2) * pi / 2 1530 RETURN 1540 NV1= ATAN(NV2 / NV1) 1550 RETURN 1560 NV = SGN(NV2) 1570 NV3 = ABS(NV2 / NV1) 1580 NV3 = ATAN( NV3) 1590 NV1 = NV * (PI - NV3) 1600 RETURN 1610 NV1 = 0.0 1620 RETURN |
Si può notare che la funzione ATAN2 non esiste nel PPTEA e quindi è stata realizzata a livello di codice EAbasic.
[ Back to top ] [ Home ]