/* Usage Commando's over serial port: t12 to set day 12 M05 to set month 5 j12 to set year 2012 h14 to set hour 14 m30 to set minute 30 s00 to set secondes 00 dxx to set manual time to rtc L046.90 to set latitude 46.90 l007.41 to set longitude 7.41 U-2 to set time correction for ex. MESZ -2 = UTC */ #include #include #include #include #define pi 3.14159265358979323846 #define twopi (2*pi) #define rad (pi/180) #define EarthMeanRadius 6371.01 // In km #define AstronomicalUnit 149597890 // In km const int ledBetrieb = 2; const int ledAusrichtungOk = 3; const int ledPumpe = 4; const int K1 = 5; const int K23 = 6; const int K4 = 7; const int K5 = 8; const int dcf = 9; //http://www.elv.ch/dcf-empfangsmodul-dcf-2.html boolean Tag = true; boolean nacht = false; int neigungsWert = 20; boolean motorEle = false; boolean ausrichtungEle = false; boolean ausrichtungAzi = false; int abweichungElevation = 0; int abweichungAzimuth = 0; float vorlauf = 20; float ruecklauf = 20; float deltaTemp = 0; /********************************** Benutzerdefinierte Voreinstellungen *************************************************/ float abschaltTemperatur = 50; int nachtWinkel = 0; float Latitude = 46.905898; //enter latitude here float Longitude = 7.418046; //enter longitude here int mechanischePause = 8000; // Ruhezeit nach Ausrichtung der Motoren bis alle mechanischen Schwingungen vorbei sind /************************************************************************************************************************/ int dcfState = 0; int utc = -2; //difference back to UTC. MEZ - 1 (Winter), MESZ -2 (Summer) float ZenithAngle; float Azimuth; float RightAscension; float Declination; float Parallax; float ElevationAngle; float ElapsedJulianDays; float DecimalHours; float EclipticLongitude; float EclipticObliquity; int zeichen; int tag, monat, jahr, minuten, sekunde, x = 0; int azimuth = 20; int stunde = 12; int DCF77value = 0; // analog value from DCF77 module int DCF77data = 0; // 0 = low / 1 = high int DCF77start = 0; // start high in millis int DCF77tick = 0; // most recent in millis int DCF77signal[60]; // array of DCF77 values (http://en.wikipedia.org/wiki/DCF77#Time_code_interpretation) int DCF77count = 0; // count variable for array manipulation int DCF77dw = 0; // day of week translation (e.g. 1 = Monday) int HMC6352Address = 0x42; int slaveAddress; byte headingData[2]; int i, headingValue = 0; int startByte; char buffer[9]; time_t t; boolean check1, check2, check3, check4, check5, check6 = false; boolean zeitNichtGesetzt = true; /******************************** Funktion Vorlauf - und Ruecklauftemperatur messen *************************/ float temperatur(int ntc) { double sensorValue = analogRead(ntc); double Temp = log(((10240000/sensorValue) - 10000)); Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp)); Temp = Temp - 273.15; // Convert Kelvin to Celcius return(Temp); } /****************************************************************************************************/ void setup() { Serial.begin(9600); pinMode(ledBetrieb, OUTPUT); pinMode(ledAusrichtungOk, OUTPUT); pinMode(ledPumpe, OUTPUT); pinMode(K1, OUTPUT); pinMode(K23, OUTPUT); pinMode(K4, OUTPUT); pinMode(K5, OUTPUT); pinMode(dcf, INPUT); slaveAddress = HMC6352Address >> 1; Wire.begin(); } void compass() { //****************************** Kompass Azimuth ermitteln ***************************** Wire.beginTransmission(slaveAddress); Wire.write("A"); Wire.endTransmission(); delay(10); Wire.requestFrom(slaveAddress, 2); i = 0; while(Wire.available() && i < 2) { headingData[i] = Wire.read(); i++; } headingValue = headingData[0]*256 + headingData[1]; headingValue = headingValue / 10; Serial.print("Azimuth: "); Serial.println(headingValue); } void elevation() { //******************************** Accelerometer Elevation messen ************************* x = analogRead(3); int minValue = 367; //(1024/4.8)*1.63; //1.63 Volt entspricht 0, 0.0049 V pro Unit int maxValue = 460; //(1024/4.8)*1.95; //1.95 Volt entspricht 90, 0.0049 V pro Unit Serial.println(x); neigungsWert = map(x, minValue, maxValue, 0, 90); Serial.print("Elevation: "); Serial.println(neigungsWert); } void Zeit() { //************************************* Zeit ausgeben ************************************** t = now(); Serial.print(day(t)); Serial.print("."); Serial.print(month(t)); Serial.print("."); Serial.print(year(t)); Serial.print(" "); Serial.print(hour(t)); Serial.print(":"); Serial.print(minute(t)); Serial.print(":"); Serial.println(second(t)); } void sunPos(){ //**************************************** Sonnenposition errechnen ******************************* 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 = hour(t)+utc + (minute(t) / 60.0); // Calculate current Julian Day liAux1 =(month(t)-14)/12; liAux2=(1461*(year(t) + 4800 + liAux1))/4 + (367*(month(t) - 2-12*liAux1))/12- (3*((year(t) + 4900 + liAux1)/100))/4+day(t)-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; azimuth = int(Azimuth); // Parallax Correction Parallax=(EarthMeanRadius/AstronomicalUnit)*sin(ZenithAngle); ZenithAngle=(ZenithAngle + Parallax)/rad; ElevationAngle = (90-ZenithAngle); if (ElevationAngle < nachtWinkel) { nacht = true; Tag = false; } else { nacht = false; Tag = true; } } void zeiteinstellung () { //********************************* manuelle Zeiteinstellung ********************************** if (Serial.available() > 2) { startByte = Serial.read(); if ( startByte == 't') { for (int i=0; i < 2; i++ ) { buffer[i] = Serial.read(); } int tag10 = (buffer[0]-48)*10; int tag1 = buffer[1]-48; tag = tag10 + tag1; Serial.print("Tag: "); Serial.println(tag); } if ( startByte == 'M') { for (int i=0; i < 2; i++ ) { buffer[i] = Serial.read(); } int monat10 = (buffer[0]-48)*10; int monat1 = buffer[1]-48; monat = monat10 + monat1; Serial.print("Monat: "); Serial.println(monat); } if ( startByte == 'j') { for (int i=0; i < 2; i++ ) { buffer[i] = Serial.read(); } int jahr10 = (buffer[0]-48)*10; int jahr1 = buffer[1]-48; jahr = jahr10 + jahr1; jahr = jahr + 2000; Serial.print("Jahr: "); Serial.println(jahr); } if ( startByte == 'h') { for (int i=0; i < 2; i++ ) { buffer[i] = Serial.read(); } int stunde10 = (buffer[0]-48)*10; int stunde1 = buffer[1]-48; stunde = stunde10 + stunde1; Serial.print("Stunde: "); Serial.println(stunde); } if ( startByte == 'm') { for (int i=0; i < 2; i++ ) { buffer[i] = Serial.read(); } int minute10 = (buffer[0]-48)*10; int minute1 = buffer[1]-48; minuten = minute10 + minute1; Serial.print("Minute: "); Serial.println(minuten); } if ( startByte == 's') { for (int i=0; i < 2; i++ ) { buffer[i] = Serial.read(); } int sekunde10 = (buffer[0]-48)*10; int sekunde1 = buffer[1]-48; sekunde = sekunde10 + sekunde1; Serial.print("Sekunde: "); Serial.println(sekunde); } if ( startByte == 'd') { Serial.print(tag); Serial.print("."); Serial.print(monat); Serial.print("."); Serial.print(jahr); Serial.print(" "); Serial.print(stunde); Serial.print(":"); Serial.print(minuten); Serial.print(":"); Serial.println(sekunde); setTime(stunde,minuten,sekunde,tag,monat,jahr); } if ( startByte == 'L') { for (int i=0; i < 6; i++ ) { buffer[i] = Serial.read(); } int lat100 = (buffer[0]-48)*100; int lat10 = (buffer[1]-48)*10; int lat1 = (buffer[2]-48); float latk1 = (float)(buffer[4]-48) / 10.00; float latk2 = (float)(buffer[5]-48) / 100.00; Latitude = lat100 + lat10 + lat1 + latk1 + latk2; Serial.print("Latitude: "); Serial.println(Latitude); } if ( startByte == 'l') { for (int i=0; i < 6; i++ ) { buffer[i] = Serial.read(); } int lon100 = (buffer[0]-48)*100; int lon10 = (buffer[1]-48)*10; int lon1 = (buffer[2]-48); float lonk1 = (float)(buffer[4]-48)/10.00; float lonk2 = (float)(buffer[5]-48)/100.00; Longitude = lon100 + lon10 + lon1 + lonk1 + lonk2; Serial.print("Longitude: "); Serial.println(Longitude); } if ( startByte == 'U') { for (int i=0; i < 3; i++ ) { buffer[i] = Serial.read(); } if (buffer[0] == '-') { int utc10 = (buffer[1]-48)*10; int utc1 = (buffer[2]-48); utc = utc - (utc1 + utc10); } if (buffer[0] == '+') { int utc10 = (buffer[1]-48)*10; int utc1 = (buffer[2]-48); utc = utc + (utc1 + utc10); } Serial.print("UTC: "); Serial.println(utc); } } } void DCF () { //************************************************** DCF 77 ************************************** dcfState = digitalRead(dcf); if (dcfState == LOW) { digitalWrite(ledBetrieb, HIGH); if (DCF77data == 0) { DCF77start = millis(); if (DCF77start - DCF77tick > 1200) { displayTime(); for (DCF77count = 0; DCF77count < 60; DCF77count = DCF77count + 1) { DCF77signal[DCF77count] = 0; } DCF77count = 0; Serial.println(""); } else { if (DCF77start - DCF77tick > 850) { DCF77signal[DCF77count] = 0; } else { if (DCF77start - DCF77tick < 850) { if (DCF77start - DCF77tick > 650) { DCF77signal[DCF77count] = 1; } } } if (DCF77start - DCF77tick > 650) { DCF77count = DCF77count + 1; } } } DCF77data = 1; DCF77tick = millis(); } else { digitalWrite(ledBetrieb, LOW); DCF77data = 0; } } void displayTime() { Serial.println(""); Serial.println("-CYCLE---"); for (DCF77count = 0; DCF77count < 60; DCF77count = DCF77count + 1) { Serial.print(DCF77signal[DCF77count]); } Serial.println(""); Serial.print("M = "); Serial.println(DCF77signal[0]); Serial.print("R = "); Serial.println(DCF77signal[15]); Serial.print("A1 = "); Serial.println(DCF77signal[16]); Serial.print("Z1 = "); Serial.println(DCF77signal[17]); Serial.print("Z2 = "); Serial.println(DCF77signal[18]); Serial.print("A2 = "); Serial.println(DCF77signal[19]); Serial.print("S = "); Serial.println(DCF77signal[20]); DCF77dw = DCF77signal[42] * 1 + DCF77signal[43] * 2 + DCF77signal[44] * 4; Serial.print("DW = "); Serial.print(DCF77dw); int jahrDCF = (DCF77signal[50] * 1 + DCF77signal[51] * 2 + DCF77signal[52] * 4 + DCF77signal[53] * 8 + DCF77signal[54] * 10 + DCF77signal[55] * 20 + DCF77signal[56] * 40 + DCF77signal[57] * 80); Serial.print("YY = "); Serial.println(jahrDCF); if ((jahrDCF < 50)&&(jahrDCF > 11)) { jahr = jahrDCF + 2000; check1 = true; } else { check1 = false; } int tagDCF = (DCF77signal[36] * 1 + DCF77signal[37] * 2 + DCF77signal[38] * 4 + DCF77signal[39] * 8 + DCF77signal[40] * 10 + DCF77signal[41] * 20); Serial.print("DD = "); Serial.println(tagDCF); if ((tagDCF < 32)&&(tagDCF > 0) && (jahrDCF != 0)) { tag = tagDCF; check2 = true; } else { check2 = false; } int monatDCF = (DCF77signal[45] * 1 + DCF77signal[46] * 2 + DCF77signal[47] * 4 + DCF77signal[48] * 8 + DCF77signal[49] * 10); Serial.print("MM = "); Serial.println(monatDCF); if ((monatDCF < 13)&&(monatDCF > 0) && (jahrDCF != 0)) { monat = monatDCF; check3 = true; } else { check3 = false; } int stundeDCF = (DCF77signal[29] * 1 + DCF77signal[30] * 2 + DCF77signal[31] * 4 + DCF77signal[32] * 8 + DCF77signal[33] * 10 + DCF77signal[34] * 20); Serial.print("HH = "); Serial.println(stundeDCF); int stundenSumme = (DCF77signal[29] + DCF77signal[30] + DCF77signal[31] + DCF77signal[32] + DCF77signal[33] + DCF77signal[34]) % 2; if (stundenSumme != 0) { stundenSumme = 1; } else { stundenSumme = 0; } if ((stundeDCF < 25)&&(stundeDCF >= 0) && (jahrDCF != 0) && (stundenSumme == DCF77signal[35])) { stunde = stundeDCF; check4 = true; } else { check4 = false; } int minutenDCF = (DCF77signal[21] * 1 + DCF77signal[22] * 2 + DCF77signal[23] * 4 + DCF77signal[24] * 8 + DCF77signal[25] * 10 + DCF77signal[26] * 20 + DCF77signal[27] * 40); Serial.print("MM = "); Serial.println(minutenDCF); int minutenSumme = (DCF77signal[21] + DCF77signal[22] + DCF77signal[23] + DCF77signal[24] + DCF77signal[25] + DCF77signal[26] + DCF77signal[27]) % 2; if (minutenSumme != 0) { minutenSumme = 1; } else { minutenSumme = 0; } if ((minutenDCF < 61) && (minutenDCF >= 0) && (jahrDCF != 0) && (minutenSumme == DCF77signal[28])) { minuten = minutenDCF; check5 = true; } else { check5 = false; } int datumSumme = (DCF77signal[36] + DCF77signal[37] + DCF77signal[38] + DCF77signal[39] + DCF77signal[40] + DCF77signal[41] + DCF77signal[42] + DCF77signal[43] + DCF77signal[44] + DCF77signal[45] + DCF77signal[46] + DCF77signal[47] + DCF77signal[48] + DCF77signal[49] + DCF77signal[50] + DCF77signal[51] + DCF77signal[52] + DCF77signal[53] + DCF77signal[54] + DCF77signal[55] + DCF77signal[56] + DCF77signal[57]) % 2; if (datumSumme != 0) { datumSumme = 1; } else { datumSumme = 0; } if (datumSumme == DCF77signal[58]) { check6 = true; } else { check6 = false; } if (check1 && check2 && check3 && check4 && check5) { // && check6 setTime(stunde,minuten,sekunde,tag,monat,jahr); zeitNichtGesetzt = false; } else { zeitNichtGesetzt = true; } Serial.println("SS = 0"); if (DCF77signal[17] == 1) { Serial.println("CEST"); } if (DCF77signal[18] == 1) { Serial.println("CET"); } Serial.println("----------"); } void ZeitSync() { //************************** Zeitabgleich zu Mitternacht ***************************************** if ((hour(t) == 23) && ((minute(t)) == 59)) { zeitNichtGesetzt = true; } } void abweichungAzi () { abweichungAzimuth = azimuth - headingValue; } //***************************************************** Motoransteuerung ***************************************** void motorAzimuth () { if (8 < abweichungAzimuth) { while (2 < abweichungAzimuth) { digitalWrite(K23, HIGH); digitalWrite(K4, HIGH); digitalWrite(K1, LOW); ausrichtungAzi = false; statusAusrichtung(); compass(); abweichungAzi (); Serial.print("Azi zu gross. Differenz: "); Serial.println(abweichungAzimuth); delay(10); } digitalWrite(K1, HIGH); digitalWrite(K4, HIGH); digitalWrite(K23, HIGH); ausrichtungAzi = true; statusAusrichtung(); Serial.println("Azi nicht mehr zu gross"); delay(mechanischePause); } else if (-8 > abweichungAzimuth) { while (-2 > abweichungAzimuth) { digitalWrite(K23, LOW); digitalWrite(K4, HIGH); digitalWrite(K1, LOW); ausrichtungAzi = false; statusAusrichtung(); compass(); abweichungAzi(); Serial.print("Azi zu klein. Differenz: "); Serial.println(abweichungAzimuth); delay(10); } digitalWrite(K1, HIGH); digitalWrite(K4, HIGH); digitalWrite(K23, HIGH); ausrichtungAzi = true; statusAusrichtung(); Serial.println("Azi nicht mehr zu klein"); delay(mechanischePause); } else { digitalWrite(K1, HIGH); digitalWrite(K4, HIGH); digitalWrite(K23, HIGH); ausrichtungAzi = true; statusAusrichtung(); Serial.println("Azi zentriert"); } } void abweichungEle() { abweichungElevation = ElevationAngle - neigungsWert; } void motorElevation () { if (8 < abweichungElevation ) { while (2 < abweichungElevation ) { digitalWrite(K23, HIGH); digitalWrite(K4, LOW); digitalWrite(K1, LOW); motorEle = false; ausrichtungEle = false; statusAusrichtung(); elevation(); abweichungEle(); Serial.print("Ele zu klein. Differenz: "); Serial.println(abweichungElevation); } digitalWrite(K1, HIGH); digitalWrite(K4, HIGH); digitalWrite(K23, HIGH); motorEle = true; ausrichtungEle = true; statusAusrichtung(); Serial.println("Ele nicht mehr zu klein"); delay(mechanischePause); } else if (-8 > abweichungElevation) { while (-2 > abweichungElevation) { digitalWrite(K23, LOW); digitalWrite(K4, LOW); digitalWrite(K1, LOW); motorEle = false; ausrichtungEle = false; statusAusrichtung(); elevation(); abweichungEle(); Serial.print("Ele zu gross. Differenz: "); Serial.println(abweichungElevation); } digitalWrite(K1, HIGH); digitalWrite(K23, HIGH); digitalWrite(K4, HIGH); motorEle = true; ausrichtungEle = true; statusAusrichtung(); Serial.println("Ele nicht mehr zu gross"); delay(mechanischePause); } else { digitalWrite(K1, HIGH); digitalWrite(K23, HIGH); digitalWrite(K4, HIGH); motorEle = true; ausrichtungEle = true; statusAusrichtung(); Serial.println("Elevation zentriert"); } } void statusAusrichtung() { if ((ausrichtungEle && ausrichtungAzi)) { digitalWrite(ledAusrichtungOk, HIGH); } else { digitalWrite(ledAusrichtungOk, LOW); } } void pumpenBetrieb() { vorlauf = temperatur(0); ruecklauf = temperatur(1); if ((vorlauf > abschaltTemperatur) || (ruecklauf > abschaltTemperatur)) { digitalWrite(K5, LOW); notStellung(); } deltaTemp = ruecklauf - vorlauf; if (deltaTemp > 10) { digitalWrite(K5, LOW); //Serial.println("Pumpe: ein"); digitalWrite(ledPumpe, HIGH); } else { digitalWrite(K5, HIGH); //Serial.println("Pumpe: aus"); digitalWrite(ledPumpe, LOW); } } void notStellung () { if ((vorlauf > abschaltTemperatur) || (ruecklauf > abschaltTemperatur) || (zeitNichtGesetzt) || (nacht)) { while ((vorlauf > abschaltTemperatur) || (ruecklauf > abschaltTemperatur) || (zeitNichtGesetzt) || (nacht)) { digitalWrite(ledBetrieb, LOW); Serial.println("!!!!! Notstellung aktiv !!!!!!"); // Motor Azimuth auf 180 Grad, Motor Elevation auf 20 Grad stellen ElevationAngle = 20; elevation(); abweichungEle(); statusAusrichtung(); motorElevation(); azimuth = 180; compass(); abweichungAzi(); statusAusrichtung(); if (motorEle) { motorAzimuth(); } while (zeitNichtGesetzt) { DCF(); zeiteinstellung(); pumpenBetrieb(); } pumpenBetrieb(); sunPos(); if ((nacht)) { Serial.print("Fehler Nacht: errechnete Elevation "); Serial.println(ElevationAngle); } if (zeitNichtGesetzt) { Serial.println("Fehler Zeit: Keine Uhrzeit gesetzt"); } if (vorlauf > abschaltTemperatur) { Serial.println("Fehler Vorlauf: Temperatur Vorlauf zu heiss!"); } if (ruecklauf > abschaltTemperatur) { Serial.println("Fehler Ruecklauf: Temperatur Ruecklauf zu heiss!"); } pumpenBetrieb(); ZeitSync(); } } } void loop() { notStellung(); //Prüfen ob die Anlage in die Notstellung gesetzt werden muss ZeitSync(); //Zeitabgleich um Mitternacht vornehmen Zeit(); //Zeit weiterzählen sunPos(); //Azimuth und Elevation errechnen elevation(); //Elevation messen abweichungEle(); //Differenz Elevation ermitteln motorElevation(); //Elevation nachrichten compass(); //Azimuth messen abweichungAzi(); //Differenz Azimuth ermitteln statusAusrichtung(); //Ausrichtung kontrollieren if (motorEle) { //wenn Motor Elevation nicht in Betrieb ist, dann Motor Azimuth motorAzimuth(); } pumpenBetrieb(); //Temperatur messen & Pumpe steuern Serial.print("Azimuth soll: "); Serial.println(azimuth); Serial.print("Azimuth ist: "); Serial.println(headingValue); Serial.print("Elevation soll: "); Serial.println(ElevationAngle); Serial.print("Elevation ist: "); Serial.println(neigungsWert); Serial.print("Vorlauf = "); Serial.println(vorlauf); Serial.print("Ruecklauf = "); Serial.println(ruecklauf); delay(500); }