Hey allemaal,
Ik ben bezig met het ontwikkelen van een solar tracker op basis van een simpele microcontroller (AT89S8252) en een RTC (PCF8563). Grofweg komt het erop neer dat de RTC via i2c de tijd doorgeeft aan de uC en die dan berekent waar de zon precies zit. Mijn solar tracker moet niet supersuperprecies zijn dus zocht ik naar een redelijk simpel algoritme op internet. Ik vond dit:
int Year;
int Month;
int Day;
float Hours;
float Minutes;
float Longitude = 3.7; //enter longitude here
float Latitude = 52; //enter latitude here
void sunPos(void){
float ZenithAngle;
float Azimuth;
float RightAscension;
float Declination;
float Parallax;
float ElevationAngle;
float ElapsedJulianDays;
float DecimalHours;
float EclipticLongitude;
float EclipticObliquity;
float dY;
float dX;
float JulianDate;
long int liAux1;
long int liAux2;
float MeanLongitude;
float MeanAnomaly;
float Omega;
float Sin_EclipticLongitude;
float GreenwichMeanSiderealTime;
float LocalMeanSiderealTime;
float LatitudeInRadians;
float HourAngle;
float Cos_Latitude;
float Sin_Latitude;
float Cos_HourAngle;
DecimalHours = Hours + (Minutes / 60.0);
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;
ElapsedJulianDays = JulianDate-2451545.0;
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);
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 );
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
}De code werkt prachtig als ik ze vanop mij computer run en wat waardes ingeef maar is véél te zwaar voor de microcontroller door alle float-types (denkik). Enig idee hoe dit efficienter te maken?
Als tijdelijke oplossing zijn we bezig met het inladen van waarden van dit algoritme in een EEPROM en dan zo verder te doen maar we zouden het liever met het algoritme doen.
Bedankt!
Pieter-Jan
Je kunt alle waarden met een bepaalde factor vermenigvuldigen zodat je alleen nog met gehele getallen werkt. Voor goniometrische zaken kun je lookup tables gebruiken, die kun je zo precies maken als jezelf wilt. (sinus in 10 stappen? Geen probleem!) Verder kun je dingen als sinussen en cosinussen mooi in 4 stukken 'breken' aangezien die symetrisch over 2 assen zijn.
Daarbij kun je nog eens constanten toevoegen aan de functies. Je solar tracker zal denk ik niet op een bootje de wereld rondgaan. Je kunt dus al een aantal dingen van te voren uitrekenen.
Op zich een leuk idee om het zo te doen, zelf zou ik een paar LDR's op de analoge ingangen van zo'n controller zetten en hem zelf de zon op laten zoeken. Dat is maar 20 regels code of zo.
Ja int gebruiken ipv float. 
Float is een 32-bits getal en dat gaat niet zo goed op een 8bit controller. Meeste(of allemaal?) kleine goedkope microcontroller hebben verder ook geen FPU, float is daarom vele malen langzamer dan int op een AT89S8252.
Je hoeft geen float te gebruiken, je kan int gebruiken met wat berekeningen erbij. Zelfs met die extra bekeringen is in int rekenen nog steeds vele malen sneller dan floats te gebruiken.
Hier is bijvoorbeeld wat uitleg te vinden, even wat google en je vind vast nog meer artikelen.
http://winavr.scienceprog.com/avr-gcc-tutorial/using-sprintf--function…
Stel dat je je paneel rond een as, evenwijdig aan de pool-as, zou laten draaien.
Hij zou dan op 21 maart en 23 september de zon precies volgen, als hij per uur 15 graden zou draaien.
Hoog zomer staat de zon 23,5 graden 'te hoog', en midden winter evenveel te laag. Dat levert een cosinusfout op, maar de cos van 23,5 graden is nog steeds 0,92 (dus praktisch 1). Op alle andere dagen is de fout nog minder.
Je hebt dus aan die éne draaias wel genoeg.
Je moet alleen bedenken dat je hem pal zuid laat staan, niet om 12 uur kloktijd, maar op het moment dat de zon ook zuid is. Dat hangt af van je lengtegraad, maar is een vaste correctie - afgezien van de 'tijdvereffening', maar die bedraagt 's zomers hoogstens 6 minuten.
Floats vervangen door ints kan niet altijd. En dus ook niet met dit soort berekeningen, dat heeft te maken met de dynamische range van ints en floats.
Maar met FETs oplossing (pool as) wordt het een stuk simpeler, heb je maar correcties op 1 as nodig.
Ben nog niet helemaal mee met de FLOAT naar INT conversie voor de 8051 structuren maar ik zal beginnen zoeken op google.
Ik ben niet op zoek naar een simepelere versie (1draaiaas ofzo) want het is vooral een project voor mijzelf om te leren werken met microcontrollers en C programmeren enzo. Waarschijnlijk ga ik enkel de sturing in 't echt uitvoeren maar het toestel zal nooit operationeel worden.
Is er geen manier om met pointers bv. altijd dezelfde registers te beschrijven en toch de float's te bewaren?
Heel erg bedankt iedereen!
[Bericht gewijzigd door Pieter-Jan op (12%)]
Omdat de berekening maar om de paar minuten nodig is, en als je genoeg geheugen hebt gewoon floats gebruiken. De berekening is traag, maar als het twee seconden duurt: so what.
Ik vraag me trouwens af of floats voldoende zijn, gezien de constantes in de code zou je doubles nodig hebben en ik weet niet of je C compiler die ook ondersteund.
Roland van Leusden
It's the rule that you live by and die for It's the one thing you can't deny Even though you don't know what the price is. It is justified.
Ik ben niet op zoek naar een simepelere versie (1draaiaas ofzo) want het is vooral een project voor mijzelf om te leren werken met microcontrollers en C programmeren enzo.
Neem een ARM, floats geen probleem en geheugen ook niet, daarnaast nauwelijks duurder dan een 8 bits uC:
stm32discovery boardje (32Bits 128Kb flash 8Kb ram) van ST
http://www.st.com/internet/evalboard/product/250863.jsp
Ondermeer te bestellen bij Farnell voor € 10,54 (excl BTW & verzenden) Er zit een programmer en debugger via USB al op, en ook standaard 12bits ADC en DAC met DMA.
Fabrikant: STMICROELECTRONICS
Ordercode: 1824325
Fabrikantnummer: STM32VLDISCOVERY
Op 4 december 2010 19:58:40 schreef JoWi:
Omdat de berekening maar om de paar minuten nodig is, en als je genoeg geheugen hebt gewoon floats gebruiken. De berekening is traag, maar als het twee seconden duurt: so what.Ik vraag me trouwens af of floats voldoende zijn, gezien de constantes in de code zou je doubles nodig hebben en ik weet niet of je C compiler die ook ondersteund.
Mijn ervaring met avrgcc is dat je bij wat grotere programma's icm floats tegen allerlei rare compilerfouten begint aan te lopen, en dat hetzelfde stuk code opeens niet meer compileert of niet-functionerende code genereert. Het kan wel, maar hou 't simpel.
Gatze
Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously
Ik werk zelf veel met bitshifting. Dus net zoveel << shiften tot je een groot genoeg resolutie hebt, aan het eind van de berekening weer hetzelfde aantal shifts terug shiften. Mocht het hiermee niet lukken, dan gebruik ik een lookup tabel die in de flash geprogrammeerd is.
Hoe lang duurt deze berekening trouwens ?