Zonnevolgsystemen

Tidak Ada

Golden Member

Ik heb in ieder geval die oude versies verzendbereid voor wie er naar wil kijken.

Rommelige werkplek? In de natuur is wanorde de meest stabiele toestand; de entropie is dan maximaal. Het handhaven van "orde" kost daarom altijd energie. ----> TUBE COLLECTORS ASSOCIATION - †
Lambiek

Special Member

Maar dat draait onder DOS zeker?

Als je haar maar goed zit, GROETEN LAMBIEK.
Tidak Ada

Golden Member

Nee, ook een windoosversie, maar de DOS versie zal makkelijker aan te passen zijn voor wie wil

Rommelige werkplek? In de natuur is wanorde de meest stabiele toestand; de entropie is dan maximaal. Het handhaven van "orde" kost daarom altijd energie. ----> TUBE COLLECTORS ASSOCIATION - †
Lambiek

Special Member

Wat is dat voor een bestand Tidak?, kun je dat hier plaatsen?

Als je haar maar goed zit, GROETEN LAMBIEK.

Dit kostte een paar uur, kun je hier iets mee?
De main functie kan zodra je de classe hebt getest in de prullenbak, samen met de "include stdio.h"

het resultaat (voor 2019-12-21, 12:22):

code:


SunriseDegrees: 58.15587
SunriseTime: 0.31985
SolarNoon: 0.48139
SunsetTime: 0.64294
SunsetDegrees: 301.84413
SolarElevationCorrectedForAtmRefraction: 13.94599
SolarAzimuthAngle: 191.52090

code:


#include <stdio.h>
#include <math.h>

class Solar {

public:
    Solar( double TimeZone, double Latitude, double Longitude );
    void setDateTime( long Year, long Month, long Day, long Hour, long Minute );
    void setDate( long Year, long Month, long Day );
    void setTime( long Hour, long Minute );
    double SolarElevationCorrectedForAtmRefraction( void );
    double SolarAzimuthAngle( void );
    double SunriseDegrees( void );
    double SunriseTime( void );
    double SunsetTime( void );
    double SolarNoon( void );
    double SunsetDegrees( void );
private:
    long GregorianToJulian( long Year, long Month, long Day );
    double DecimalDate( void );
    double DecimalTime( void );
    double JulianDay( void );
    double JulianCentury( void );
    double GeomMeanLongSun( void );
    double GeomMeanAnomSun( void );
    double EccentEarthOrbit( void ); 
    double MeanObliqEcliptic( void );
    double ObliqCorr( void );
    double SunDeclin( void );
    double VarY( void );
    double SunAppLong( void );
    double SunEqOfCtr( void );
    double SunTrueLong( void );
    double TrueSolarTime( void );
    double HourAngle( void );
    double SolarZenithAngle( void );
    double EqOfTime( void );
    double SolarElevationAngle( void );
    double ApproxAtmosphericRefraction( void );
    double radians( double );
    double degrees( double );
    double m_TimeZone;
    double m_Latitude;
    double m_Longitude;
    long m_Year;
    long m_Month;
    long m_Day;
    long m_Hour;
    long m_Minute;
};

double Solar::radians( double degrees) {
    return 3.141592654 * degrees / 180.0;
}

double Solar::degrees( double radians ) {
    return 180.0 * radians / 3.141592654;
}

Solar::Solar( double TimeZone, double Latitude, double Longitude ) {
    m_TimeZone  = TimeZone;
    m_Latitude  = Latitude;
    m_Longitude = Longitude;
}

double Solar::DecimalDate( void ) {  
    return (double) GregorianToJulian( m_Year, m_Month, m_Day );
}

long Solar::GregorianToJulian( long Year, long Month, long Day ) { // Dublin JD, epoch Dec 31, 1899  
    double Y = (double) Year;
    double M = (double) Month;
    double D = (double) Day;
    return (long) (1461.0*(Y+4800.0+(M-14.0)/12.0))/4.0+(367.0*(M-2.0-12.0*((M-14.0)/12.0)))/12.0-(3.0*((Y+4900.0+(M-14.0)/12.0)/100.0))/4.0+D-32075.0-2415020.0;
}

double Solar::DecimalTime( void ) { // DecimalTime (time past local midnight)
    return (double) ( m_Hour + ( m_Minute / 60.0 ) ) / 24.0;
}

void Solar::setDateTime( long Year, long Month, long Day, long Hour, long Minute ) {
    m_Year   = Year;
    m_Month  = Month;
    m_Day    = Day;
    m_Hour   = Hour;
    m_Minute = Minute;
}

void Solar::setDate( long Year, long Month, long Day ) {
    m_Year   = Year;
    m_Month  = Month;
    m_Day    = Day;
}

void Solar::setTime( long Hour, long Minute ) {
    m_Hour   = Hour;
    m_Minute = Minute;
}

double Solar::JulianDay( void ) {  
    return DecimalDate() + 2415018.5 + DecimalTime() - m_TimeZone / 24.0;
}

double Solar::JulianCentury( void ) {
    return ( JulianDay() - 2451545.0 ) / 36525.0;
}

double Solar::GeomMeanLongSun( void ) {
    return fmod( 280.46646 + JulianCentury() * (36000.76983 + JulianCentury() * 0.0003032 ), 360.0 );
}

double Solar::GeomMeanAnomSun( void ) {
    return 357.52911 + JulianCentury() * ( 35999.05029 - 0.0001537 * JulianCentury() );
}

double Solar::EccentEarthOrbit( void ) {
    return 0.016708634 - JulianCentury() * ( 0.000042037 + 0.0000001267 * JulianCentury() );
}

double Solar::MeanObliqEcliptic( void ) {
    return 23.0 + ( 26.0 + ( ( 21.448 - JulianCentury() * ( 46.815 + JulianCentury() * ( 0.00059 - JulianCentury() * 0.001813 ) ) ) ) / 60.0 ) / 60.0;
}

double Solar::ObliqCorr( void ) {
    return MeanObliqEcliptic() + 0.00256 * cos( radians( 125.04 - 1934.136 * JulianCentury() ) ); 
}

double Solar::SunDeclin( void ) {
    return degrees( asin( sin( radians( ObliqCorr() ) ) * sin( radians( SunAppLong() ) ) ) );
}

double Solar::VarY( void ) {
    return tan( radians( ObliqCorr() / 2.0 ) ) * tan( radians( ObliqCorr() / 2 ) );
}

double Solar::SunAppLong( void ) {
    return SunTrueLong() - 0.00569 - 0.00478 * sin( radians( 125.04 - 1934.136 * JulianCentury() ) );
}

double Solar::SunEqOfCtr( void ) {
    return sin( radians( GeomMeanAnomSun() ) ) * ( 1.914602 - JulianCentury() * ( 0.004817 + 0.000014 * JulianCentury() ) ) + sin( radians( 2.0 * GeomMeanAnomSun() ) ) * ( 0.019993 - 0.000101 * JulianCentury() ) + sin( radians( 3.0 * GeomMeanAnomSun() ) ) * 0.000289;
}

double Solar::SunTrueLong( void ) {
    return GeomMeanLongSun() + SunEqOfCtr();
}

double Solar::SunriseDegrees( void ) {
    return degrees( acos( cos( radians( 90.833 ) ) / ( cos( radians( m_Latitude ) ) * cos( radians( SunDeclin() ) ) ) - tan( radians( m_Latitude ) ) * tan( radians( SunDeclin() ) ) ) ); 
}
double Solar::SunsetDegrees( void ) {
    return 360.0 - SunriseDegrees(); 
}
double Solar::SunriseTime( void ) {
    return SolarNoon() - SunriseDegrees() * 4.0 / 1440.0;
}
double Solar::SunsetTime( void ) {
    return SolarNoon() + SunriseDegrees() * 4.0 / 1440.0;
}
double Solar::SolarNoon( void ) {
    return ( 720.0 - 4.0 * m_Longitude - EqOfTime() + m_TimeZone * 60.0 ) / 1440.0;
}

double Solar::TrueSolarTime( void ) {
    return fmod( DecimalTime() * 1440.0 + EqOfTime() + 4.0 * m_Longitude - 60.0 * m_TimeZone, 1440.0 );
}

double Solar::EqOfTime( void ) {
    return 4.0 * degrees( VarY() * sin( 2.0 * radians( GeomMeanLongSun() ) ) - 2.0 * EccentEarthOrbit() * sin( radians( GeomMeanAnomSun() ) ) + 4.0 * EccentEarthOrbit() * VarY() * sin( radians( GeomMeanAnomSun() ) ) * cos( 2.0 * radians( GeomMeanLongSun() ) ) - 0.5 * VarY() * VarY() * sin( 4.0 * radians( GeomMeanLongSun() ) ) - 1.25 * EccentEarthOrbit() * EccentEarthOrbit() * sin( 2.0 * radians( GeomMeanAnomSun() ) ) );
}

double Solar::HourAngle( void ) {
    double dTemp = TrueSolarTime() / 4.0;
    if( dTemp < 0 ) {
        return dTemp + 180.0;
    } else {
        return dTemp - 180.0;
    }
}

double Solar::SolarZenithAngle( void ) {
    return degrees( acos( sin( radians( m_Latitude ) ) * sin( radians( SunDeclin() ) ) + cos( radians( m_Latitude ) ) * cos( radians( SunDeclin() ) ) * cos( radians( HourAngle() ) ) ) );
}

double Solar::SolarElevationAngle( void ) {
    return 90.0 - SolarZenithAngle();
}

double Solar::ApproxAtmosphericRefraction( void ) {
    if( SolarElevationAngle() > 85.0 ) {
        return 0;
    } else if( SolarElevationAngle() > 5.0 ) {
        return ( 58.1 / tan( radians( SolarElevationAngle() ) ) - 0.07 / pow( tan( radians( SolarElevationAngle() ) ), 3 ) + 0.000086 / pow( tan( radians( SolarElevationAngle() ) ), 5.0 ) ) / 3600.0;
    } else if( SolarElevationAngle() > -0.575 ) {
        return ( 1735.0 + SolarElevationAngle() * ( -518.2 + SolarElevationAngle() * ( 103.4 + SolarElevationAngle() * ( -12.79 + SolarElevationAngle() * 0.711 ) ) ) ) / 3600.0;
    } else {
        return ( -20.772 / tan( radians( SolarElevationAngle() ) ) ) / 3600.0;
    }
}

double Solar::SolarElevationCorrectedForAtmRefraction( void ) {
    return SolarElevationAngle() + ApproxAtmosphericRefraction();
}

double Solar::SolarAzimuthAngle( void ) {
    if( HourAngle() > 0.0 ) {
        return fmod( degrees( acos( ( ( sin( radians( m_Latitude ) ) * cos( radians( SolarZenithAngle() ) ) ) - sin( radians( SunDeclin() ) ) ) / ( cos( radians( m_Latitude ) ) * sin( radians( SolarZenithAngle() ) ) ) ) ) + 180.0, 360.0 );
    } else {
        return fmod( 540.0 - degrees( acos( ( ( sin( radians( m_Latitude ) ) * cos( radians( SolarZenithAngle() ) ) ) - sin( radians( SunDeclin() ) ) ) / ( cos( radians( m_Latitude ) ) * sin( radians( SolarZenithAngle() ) ) ) ) ), 360.0 );
    }
}

int main() {
    // Zevenaar Lat 51.9374
    // Zevenaar Long 6.063
    // Zevenaar is precies GMT+0.48
    // Vanwege aansluiting met europa is wintertijd (GMT+1) 
    // Hier is zonnetijd nodig, dus niet zomertijd (GMT+2), de Oekraiense tijd die wij in de zomer hanteren. 
    Solar m_Solar( 0.0, 51.9374, 6.063 );
    m_Solar.setDateTime( 2019, 12, 21, 12, 22 );
    printf( "\nSunriseDegrees: %.5f", m_Solar.SunriseDegrees() );
    printf( "\nSunriseTime: %.5f", m_Solar.SunriseTime() );
    printf( "\nSolarNoon: %.5f", m_Solar.SolarNoon() );
    printf( "\nSunsetTime: %.5f", m_Solar.SunsetTime() );
    printf( "\nSunsetDegrees: %.5f", m_Solar.SunsetDegrees() );    
    printf( "\nSolarElevationCorrectedForAtmRefraction: %.5f", m_Solar.SolarElevationCorrectedForAtmRefraction() );
    printf( "\nSolarAzimuthAngle: %.5f", m_Solar.SolarAzimuthAngle() );
    printf( "\n");
    return 0;
}
reading can seriously damage your ignorance
Lambiek

Special Member

Op 18 april 2019 19:32:00 schreef hennep:
Dit kostte een paar uur, kun je hier iets mee?

Dat had nu ook weer niet nodig geweest, ik ging er van uit dat het een kant en klaar bestand was. Maar in ieder geval reuze bedankt. :) Ik hoop dat meer mensen hier iets aan hebben. :)

Heb je dit zelf gemaakt, of komt het ergens uit en heb je het naar VB omgezet?

Als je haar maar goed zit, GROETEN LAMBIEK.

Uiteraard komt het ergens vandaan. Ik ben niet zo slim dat ik dit even zelf uit de mouw schud.
https://www.esrl.noaa.gov/gmd/grad/solcalc/

Ik had al eerder naar een dergelijk probleem gekeken. Toen heb ik de zonsopgangs- en zonsondergangs-tijden bij het knmi gedownload en met een "solver" in excel geprobeerd om daar een formule mee te maken. Die functie wilde niet naar een oplossing convergeren, waarschjnlijk door die rare achtvormige baan.

Op deze pagina staan een paar spreadsheets:
https://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html

Ik heb de OpenOffice versie gebruikt en daarvan de formules in de cellen 1 op 1 overgezet naar C++ functies. Dat is de reden dat de methods in de class hierboven er zo merkwaardig uitzien (one-liners).

Er hoefden maar 4 functies echt aangepast te worden. power() in de spreadsheet naar pow() in c++ en die datum waar je zo maar mee kunt rekenen in een spreadsheet naar de "julian day", de juliaanse kalender.
En ik moest twee functies toevoegen om te converteren tussen graden en radialen.
Of zijn het radianen?
Indians -> indianen
radians -> radianen

Er kan nog veel aan verbeterd worden. Veel functies worden meerdere keren aangeroepen in een berekening. dat kan nog geoptimaliseerd worden. En voor gebruik in een microcontroller zou het handiger zijn om geen floating point variabelen te gebruiken. Dat vreet gelijk je hele geheugen op.
een long variabele of evt. een long long die je in duizensten laat rekenen doet het werk ook wel.
Maar ik heb nu even geen zin om alle rekenfuncties om te bouwen. Ik heb er al wel een aantal op de plank liggen omdat ik zoiets al eerder heb gedaan. Dat is een klus die ik misschien ga uitvoeren als ik de class zelf ga gebruiken :-)

reading can seriously damage your ignorance
Lambiek

Special Member

Op 19 april 2019 10:59:59 schreef hennep:
Uiteraard komt het ergens vandaan. Ik ben niet zo slim dat ik dit even zelf uit de mouw schud.]

Valt wel mee toch. :)

Die functie wilde niet naar een oplossing convergeren, waarschjnlijk door die rare achtvormige baan.

Daar komt bij mij waarschijnlijk ook die kleine afwijking vandaan als er de hele dag geen zon is.

Of zijn het radianen?
Indians -> indianen
radians -> radianen

Ik heb werkelijk geen idee. :)

Er kan nog veel aan verbeterd worden. Veel functies worden meerdere keren aangeroepen in een berekening.

Software is eigenlijk nooit klaar, iedere keer vind je wel weer iets dat anders kan.

In ieder geval bedankt voor de moeite, ik hoop dat meer mensen hier iets aan hebben. :)

Als je haar maar goed zit, GROETEN LAMBIEK.
Tidak Ada

Golden Member

Daarom is het ook Sof(t)ware :P

P.S.: Zijn het geen Indialen....?

[Bericht gewijzigd door Tidak Ada op vrijdag 19 april 2019 18:05:59 (37%)

Rommelige werkplek? In de natuur is wanorde de meest stabiele toestand; de entropie is dan maximaal. Het handhaven van "orde" kost daarom altijd energie. ----> TUBE COLLECTORS ASSOCIATION - &#8224;
Lambiek

Special Member

Op 19 april 2019 18:05:05 schreef Tidak Ada:
Daarom is het ook Sof(t)ware :P

Haha, dat kan kloppen.

Heb het programma gisteren weer uitgebreid met een paar drukknoppen voor de handbediening van oost naar west en andersom. Zo blijf je bezig toch. :)

Als je haar maar goed zit, GROETEN LAMBIEK.

Interessant om te zien dat de aandacht verplaatst is van een "dynamisch volgsysteem" met lichtsensoren naar een stuursysteem wat de zonnebaan gewoon uitrekent.
Eerlijk gezegd lijkt me dat dit ook beter zal werken omdat het niet in de war wordt gebracht door min of meer egaal bedekte luchten enz.

mel

Golden Member

Gewoon iedere dag de Kepler parameters laten downloaden, daar staat ook de Zon tussen :)

u=ir betekent niet :U bent ingenieur..
Lambiek

Special Member

Op 20 april 2019 11:19:03 schreef Leo-Bolier:
Interessant om te zien dat de aandacht verplaatst is van een "dynamisch volgsysteem" met lichtsensoren naar een stuursysteem wat de zonnebaan gewoon uitrekent.

Dat is best interessant ja. :)

Eerlijk gezegd lijkt me dat dit ook beter zal werken omdat het niet in de war wordt gebracht door min of meer egaal bedekte luchten enz.

Nou, dat valt reuze mee. Ik meet of er voldoende zon is of niet, dus bij geen of niet genoeg zon draait het gewoon op de RTC en staat dus niet te zoeken.

Op 20 april 2019 11:39:37 schreef mel:
Gewoon iedere dag de Kepler parameters laten downloaden, daar staat ook de Zon tussen :)

Maar dan zit je weer aan een PC vast of je moet iets van een raspberry pi in zetten.

Als je haar maar goed zit, GROETEN LAMBIEK.
Lambiek

Special Member

Dat is ook een idee, maar iedereen heeft niet zo'n sloot bij zijn huis. :) Misschien een idee voor op het IJsselmeer. :)

Als je haar maar goed zit, GROETEN LAMBIEK.

Op 20 april 2019 12:53:09 schreef Lambiek:
..Dat is best interessant ja. :) ...Maar dan zit je weer aan een PC vast of je moet iets van een raspberry pi in zetten.

Ja, dat advies had ik je op pagina 2 al gegeven. Zo moeilijk is het niet. Die library functie geeft je aan waar de zon staat, en daar draai je je motor naar toe. Geen idee of ie rekening met zomer/winter houdt, maar dat verschil lijkt me best verwaarloosbaar als het je om opbrengst gaat.
Een RPi inrichten is kinderspel.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Lambiek

Special Member

Op 22 april 2019 10:36:58 schreef flipflop:
Ja, dat advies had ik je op pagina 2 al gegeven.

Ja dat weet ik en daar is ook niets mis mee. :)

Zo moeilijk is het niet....Een RPi inrichten is kinderspel.

Ja ja, maar de leeftijd gaat toch ook een beetje mee spelen. Je gaat nieuwe dingen toch een beetje lastiger opslaan. Het is niet meer zoals vroeger, als ik toen een beetje door een handleiding bladerde wis ik het, maar tegenwoordig moet ik het toch wel helemaal gaan lezen. :)

Als je haar maar goed zit, GROETEN LAMBIEK.

Da's nou juist het mooie van RPi en Arduino (en afgeleiden), de instap is super simpel. "Kinderspel" betekend: ook easy voor bejaarden :-)
Maar nu hou ik erover op hoor.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Lambiek

Special Member

Ja ja, drijf er de spot maar mee. :)

Als je haar maar goed zit, GROETEN LAMBIEK.
Lambiek

Special Member

Dit kwam ik nog tegen op het net, zitten ook leuke oplossingen tussen.

http://www.redrok.com/electron.htm#led5s12v

Als je haar maar goed zit, GROETEN LAMBIEK.
Take care to get what you like or you will be forced to like what you get
Lambiek

Special Member

Dat is zeker een mooie oplossing, zit vernuftig in elkaar. Dit is niet iets voor zelfbouw, de panelen zijn hier speciaal voor gemaakt. Ben wel benieuwd wat zoiets opbrengt, de prijs valt me nog soort mee.

Heb even gekeken, brengt ongeveer 4000 kWh op in Nederland, Het gemiddelde verbruik van een gezin ligt tussen de 2500 en 4000 kWh denk.

Als je haar maar goed zit, GROETEN LAMBIEK.
Tidak Ada

Golden Member

Rommelige werkplek? In de natuur is wanorde de meest stabiele toestand; de entropie is dan maximaal. Het handhaven van "orde" kost daarom altijd energie. ----> TUBE COLLECTORS ASSOCIATION - &#8224;
Lambiek

Special Member

Oké, die heb ik even gemist dan. :) Maar ik vind het een mooie oplossing en het ziet er leuk uit.

Als je haar maar goed zit, GROETEN LAMBIEK.
Tidak Ada

Golden Member

Ik heb zelf een oud huis en voel er weinig voor om het te ontsieren met al die blauwe platen, maar als ik in een VINEX wijk zou wonen, zou ik er ook wel aan willen. "Ik vindt het niet eerlijk! (© Calimero)

Rommelige werkplek? In de natuur is wanorde de meest stabiele toestand; de entropie is dan maximaal. Het handhaven van "orde" kost daarom altijd energie. ----> TUBE COLLECTORS ASSOCIATION - &#8224;