//Υπολογισμός θέσης του ήλιου //Δίνει την θέση του ήλιου στον ουρανό σε μοίρες όσο αφορά το ύψος και την ανατολή-δύση #include <Timer.h> //Timer Library Timer t; //defines t as a timer #define pi 3.14159265358979323846 //Το π #define rad (pi/180) //Για την μετατροπή ακτίνια=μοίρες*(π/180) #define DS1307_ADDR_R 0xd1 //rtc i2c address for reading #define DS1307_ADDR_W 0xd0 //rtc i2c address for writing #define _sda_pin A4 //i2c data line arduino pin #define _scl_pin A5 //i2c clock line arduino pin #define REG_SEC 0x00 //rtc second register address #define REG_MIN 0x01 //rtc minute register address #define REG_HOUR 0x02 //rtc hour register address #define REG_DOW 0x03 //rtc day of week register address #define REG_DATE 0x04 //rtc date register address #define REG_MON 0x05 //rtc month register address #define REG_YEAR 0x06 //rtc year register address #define ELEV_UP_POT_LIMIT 0x08 //rtc elevetion potensiometer upper limit ram register #define ELEV_DOWN_POT_LIMIT 0x09 //rtc elevetion potensiometer down limit ram register #define AZIM_EAST_POT_LIMIT 0x0a //rtc elevetion potensiometer east limit ram register #define AZIM_WEST_POT_LIMIT 0x0b //rtc elevetion potensiometer west limit ram register #define REG_DST 0x0c //rtc DST winter-summer ram register (0=Winter, 1=Summer) //-------------------------------------------------------------// #define elev_UP 2 //output pin for relay elevation UP #define elev_DOWN 3 //output pin for relay elevation DOWN #define azim_EAST 4 //output pin for relay azimuth EAST #define azim_WEST 5 //output pin for relay azimuth WEST //--------------------------------------------------------// #define but_UP 6 //input pin for button elevation UP #define but_DOWN 7 //input pin for button elevation DOWN #define but_EAST 8 //input pin for button azimuth EAST #define but_WEST 9 //input pin for button azimuth WEST //---------------------------------------------------------// #define limit_UP 10 //input pin for limit switch elevation UP #define limit_DOWN 11 //input pin for limit switch elevation DOWN #define limit_EAST 12 //input pin for limit switch azimuth EAST #define limit_WEST 13 //input pin for limit switch azimuth WEST #define limits_LED A0 //Led for indicating that one or more limit switches in activated #define auto_man A1 //input pin for auto/manual switch #define elev_pot A2 //Analog input pin for elevation pontensiometer #define azim_pot A3 //Analog input pin for azimuth pontensiometer //----------The mechanical limits in degrees of tracker-------------------// //-----------they depend from the tracker construction--------------------// #define UP_LIMIT_DEG 90 //elevation up limit of tracker #define DOWN_LIMIT_DEG 30 //elevation down limit of tracker #define EAST_LIMIT_DEG 120 //azimuth east limit of tracker #define WEST_LIMIT_DEG 240 //azimuth west limit of tracker #define SOUTH_DEG 180 //degrees of south //----------------------------------------------------------------// //Εισαγωγή Μεταβλητών //Η ημερομηνία και η ώρα την διαβάζει απο το RTC (Real Time Clock) μέσω I2C //υπολογίζεται με αλγοριθμο αν είναι καλοκαιρινή ώρα DST(Daylight Saving Time) int date; //Ημέρα int month; //Μήνας int year; //Χρονιά float hour; //Ώρα float minute; //Λεπτά byte sec; //-------------το timezone και οι συντεταγμένες πρέπει να οριστούν εδώ ανάλογα με την τοποθεσία εγκατάστασης----------// int timezone= 2; //Η ζώνη ώρας της Ελλάδος (ουσιαστικά δεν μας ενδιαφέρει το πρόσημο αλλά η διαφορά από το μηδέν) float latitude= 39.549159; //Γεωγραφικό Πλάτος σε μοίρες float longitude= 20.325640; //Γεωγραφικό Μήκος σε μοίρες //-------------------------------------------------------------------// //Μεταβλητές Προγράμματος int doy; //Day of year, θα υπολογίζεται απο αλγόριθμο int dow; //Day of Week, υπολογιζεται απο αλγόριθμο. int dst; //Καλοκαιρινή ώρα 1=Ναι 0=Όχι, θα υπολογίζεται απο αλγόριθμο float easn; //Elevation Angle at Solar Noon (Οι μοίρες του ύψους του ήλιου κατά το ηλιακό μεσημέρι) float elevation; //Οι τρέχουσες μοίρες ύψους του ήλιου int elevation_int; //Το elevation σε ακεραια μορφή float zenith; //η συμπληρωματική γωνία ως προς τις 90 μοίρες, η γωνία δηλαδή που πρέπει να έχουν τα φωτοβολταικά πάνελς //ως προς το έδαφος την δεδομένη στιγμή float azimuth; //οι μοίρες στις οποίες βρίσκεται ο ήλιος σε σχέση με την Ανατολή-Δύση, Νότος είναι 180 int azimuth_int; //Το azimuth σε ακέραια μορφή int motion_flag=0; //για την αναγνώριση της κίνησης 8=UP, 4=DOWN, 2=EAST, 1=WEST, 0=STOP int auto_man_flag=0; //για την ενδειξη της κατάστασης (mode) 0=Manual, 1=Auto, 2=Calibrating int elev_limits_flag=0; //για την ένδειξη των ορίων (ακραιοι δικόπτες) του elevation 2=UP, 1=DOWN, 0=NoLimit int azim_limits_flag=0; //για την ένδειξη των ορίων (ακραιοι δικόπτες) του azimuth 2=EAST, 1=WEST, 0=NoLimit int elev_pot_up_limit; //η αναλογική τιμή του ποντενσιόμετρου για το πάνω όριο του elevation int elev_pot_down_limit; //η αναλογική τιμή του ποντενσιόμετρου για το κάτω όριο του elevation int azim_pot_east_limit; //η αναλογική τιμή του ποντενσιόμετρου για το east όριο του azimuth int azim_pot_west_limit; //η αναλογική τιμή του ποντενσιόμετρου για το west όριο του azimuth int num_pot_readings=10; //αριθμός τιμών που διαβάζει (analogread) απο τα ποντενσιόμετρα για να βγάλει το μεσο όρο (smoothing) int auto_move_elev_flag;//=0;//για τον έλεγχο αν πρέπει να κινηθεί αυτόματα σε νεα θέση κάθετα (elevation) 0=πρέπει να κινηθεί, 1=οχι int auto_move_azim_flag;//=0;//για τον έλεγχο αν πρέπει να κινηθεί αυτόματα σε νεα θέση οριζόντια (azimuth) 0=πρέπει να κινηθεί, 1=οχι int auto_move_elev_deg; //μοίρες στις οποίες πρέπει να κινηθεί αυτόματα κάθετα (elevation) int auto_move_azim_deg; //μοίρες στις οποίες πρέπει να κινηθεί αυτόματα οριζόντια (azimuth) int calibration_flag; //ένδειξη για calibration mode 1=calibration, 0=no int calibration_state; //φάση στην οποία βρίσκετε το calibration 8=up calibration, 4=down calibration, 2=east calibration, 1=west calibration int mins_to_next_move_count; //αντιστροφη μέτρηση των λεπτών που απομένουν μέχρι την επόμενη κίνηση int mins_to_move_ahead=16; //μεσοδιάστημα λεπτών που θα υπολογίζονται οι συντεταγμένες και θα γίνετε η κίνηση int just_moved_flag; //ένδειξη ότι μόλις κινήθηκε 1=μόλις κινήθηκε, 0=οχι //-----------------------------------------------------------------------------------------------------------------------------------------------------// //--------------------- RTC DS1307 Routines-----------------// void sendStart(byte addr) { pinMode(_sda_pin, OUTPUT); digitalWrite(_scl_pin, HIGH); digitalWrite(_sda_pin, HIGH); digitalWrite(_sda_pin, LOW); digitalWrite(_scl_pin, LOW); shiftOut(_sda_pin, _scl_pin, MSBFIRST, addr); } //--------------------------------------------------------// void sendStop() { pinMode(_sda_pin, OUTPUT); digitalWrite(_sda_pin, LOW); digitalWrite(_scl_pin, HIGH); digitalWrite(_sda_pin, HIGH); pinMode(_sda_pin, INPUT); } //--------------------------------------------------------// void sendNack() { pinMode(_sda_pin, OUTPUT); digitalWrite(_scl_pin, LOW); digitalWrite(_sda_pin, HIGH); digitalWrite(_scl_pin, HIGH); digitalWrite(_scl_pin, LOW); pinMode(_sda_pin, INPUT); } //--------------------------------------------------------// void waitForAck() { pinMode(_sda_pin, INPUT); digitalWrite(_scl_pin, HIGH); if (digitalRead(_sda_pin)==LOW) digitalWrite(_scl_pin, LOW); } //--------------------------------------------------------// byte readByte() { pinMode(_sda_pin, INPUT); byte value = 0; byte currentBit = 0; for (int i = 0; i < 8; ++i) { digitalWrite(_scl_pin, HIGH); currentBit = digitalRead(_sda_pin); value |= (currentBit << 7-i); delayMicroseconds(1); digitalWrite(_scl_pin, LOW); } return value; } //--------------------------------------------------------// void writeByte(byte value) { pinMode(_sda_pin, OUTPUT); shiftOut(_sda_pin, _scl_pin, MSBFIRST, value); } //--------------------------------------------------------// byte readRegister(byte reg) { byte readValue=0; sendStart(DS1307_ADDR_W); waitForAck(); writeByte(reg); waitForAck(); sendStop(); sendStart(DS1307_ADDR_R); waitForAck(); readValue = readByte(); sendNack(); sendStop(); return readValue; } //--------------------------------------------------------// void writeRegister(byte reg, byte value) { sendStart(DS1307_ADDR_W); waitForAck(); writeByte(reg); waitForAck(); writeByte(value); waitForAck(); sendStop(); } //--------------------------------------------------------// byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); } //--------------------------------------------------------// void setTime(byte hour, byte min, byte sec) { if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)) && ((sec>=0) && (sec<60))) { writeRegister(REG_HOUR, decToBcd(hour)); writeRegister(REG_MIN, decToBcd(min)); writeRegister(REG_SEC, decToBcd(sec)); } } //--------------------------------------------------------// void setDate(byte date, byte mon, uint16_t year) { if (((date>0) && (date<=31)) && ((mon>0) && (mon<=12)) && ((year>=2000) && (year<3000))) { year -= 2000; writeRegister(REG_YEAR, decToBcd(year)); writeRegister(REG_MON, decToBcd(mon)); writeRegister(REG_DATE, decToBcd(date)); } } //--------------------------------------------------------// void setDOW(byte dow) { if ((dow>0) && (dow<8)) writeRegister(REG_DOW, dow); } //--------------------------------------------------------// byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); } //--------------------------------------------------------// void halt(bool enable) { byte reg = readRegister(REG_SEC); reg &= ~(1 << 7); reg |= (enable << 7); writeRegister(REG_SEC, reg); } //--------------------------------------------------------// void getRTC(){ sec=bcdToDec(readRegister(REG_SEC)&0x7f); minute=bcdToDec(readRegister(REG_MIN)); hour=bcdToDec(readRegister(REG_HOUR)&0x3f); dow=bcdToDec(readRegister(REG_DOW)); date=bcdToDec(readRegister(REG_DATE)); month=bcdToDec(readRegister(REG_MON)); year=2000+bcdToDec(readRegister(REG_YEAR)); } //---------------------------------------------------------------------------------------------------------------------------------------------------// //------------------ Motion Routines ------------------------------------------// // Elevetion UP void move_elev_UP(){ digitalWrite(elev_UP,HIGH); digitalWrite(elev_DOWN,LOW); digitalWrite(azim_EAST,LOW); digitalWrite(azim_WEST,LOW); motion_flag=8; } //--------------------------------------------------------// void automove_elev(int deg){ if (read_elev_pot()==deg) {auto_move_elev_flag=1; move_all_stop();} else if ((read_elev_pot()<deg) && (check_elev_limits()!=2)) move_elev_UP(); else if ((read_elev_pot()>deg) && (check_elev_limits()!=1)) move_elev_DOWN(); else move_all_stop(); check_elev_limits(); } //--------------------------------------------------------// //Elevation DOWN void move_elev_DOWN(){ digitalWrite(elev_UP,LOW); digitalWrite(elev_DOWN,HIGH); digitalWrite(azim_EAST,LOW); digitalWrite(azim_WEST,LOW); motion_flag=4; } //--------------------------------------------------------// //Azimuth EAST void move_azim_EAST(){ digitalWrite(elev_UP,LOW); digitalWrite(elev_DOWN,LOW); digitalWrite(azim_EAST,HIGH); digitalWrite(azim_WEST,LOW); motion_flag=2; } //--------------------------------------------------------// void automove_azim(int deg){ if (read_azim_pot()==deg) {auto_move_azim_flag=1; move_all_stop();} else if ((read_azim_pot()<deg) && (check_azim_limits()!=1)) move_azim_WEST(); else if ((read_azim_pot()>deg) && (check_azim_limits()!=2)) move_azim_EAST(); else move_all_stop(); check_azim_limits(); } //--------------------------------------------------------// //Azimuth WEST void move_azim_WEST(){ digitalWrite(elev_UP,LOW); digitalWrite(elev_DOWN,LOW); digitalWrite(azim_EAST,LOW); digitalWrite(azim_WEST,HIGH); motion_flag=1; } //--------------------------------------------------------// //BOTH motor STOP void move_all_stop(){ digitalWrite(elev_UP,LOW); digitalWrite(elev_DOWN,LOW); digitalWrite(azim_EAST,LOW); digitalWrite(azim_WEST,LOW); motion_flag=0; } //--------------------------------------------------------// //Check Elevation Limits int check_elev_limits(){ int limits_reading; limits_reading=0; limits_reading=limits_reading + digitalRead(limit_UP); //2 limit up limits_reading=limits_reading << 1; limits_reading=limits_reading + digitalRead(limit_DOWN); //1 limit down elev_limits_flag=limits_reading; return limits_reading; } //--------------------------------------------------------// //Check Azimuth Limits int check_azim_limits(){ int limits_reading; limits_reading=0; limits_reading=limits_reading + digitalRead(limit_EAST); //2 limit EAST limits_reading=limits_reading << 1; limits_reading=limits_reading + digitalRead(limit_WEST); //1 limit WEST azim_limits_flag=limits_reading; return limits_reading; } //--------------------------------------------------------// //Check Buttons int check_buttons(){ int buttons_reading; int old_button_state=0; int button_state=0; long last_debounce_time =0; long debounce_delay=20; buttons_reading=digitalRead(but_UP); //8 UP buttons_reading=buttons_reading << 1; buttons_reading=buttons_reading + digitalRead(but_DOWN); //4 DOWN buttons_reading=buttons_reading << 1; buttons_reading=buttons_reading + digitalRead(but_EAST); //2 EAST buttons_reading=buttons_reading << 1; buttons_reading=buttons_reading + digitalRead(but_WEST); //1 WEST if (buttons_reading!=old_button_state){ last_debounce_time=millis(); } if((millis()-last_debounce_time)>debounce_delay){ button_state=buttons_reading; } old_button_state=buttons_reading; return buttons_reading; } //---------------------------------------------------------------------// //Αλγόριθμος υπολογισμού του αριθμού της ημέρας του χρόνου από 1 εώς 365 ή 366 για δύσεκτο έτος void dayofyear() { int dom[11]={31,28,31,30,31,30,31,31,30,31,30}; //Πίνακας από 11 τιμές με τις μέρες των μηνών (Φεβρουάριος 28). //Δεν χρειαζόμαστε τον Δεκέμβριο. boolean leapyear; //Για τον υπολογισμό Δύσεκτου Έτους int x; doy=0; if (month>1) { for (x=1 ; x<month ; x=x+1) { doy=doy+dom[x-1]; } } doy=doy+date; if (year%400==0) leapyear=true; // else if (year%100==0) leapyear=false; //Υπολογισμός δύσεκτου έτους else if (year%4==0) leapyear=true; // else leapyear=false; // if ((leapyear) && (month>2)) doy = doy+1; } //--------------------------------------------------------// //Αλγοριθμος για τον υπολογισμό της μέρας της βδομαδας ώστε να χρησιμοποιηθεί στον υπολογισμό του DST //1=Δευτέρα, 2=Τρίτη, 3=Τετάρτη, 4=Πέμπτη, 5=Παρασκευή, 6=Σάββατο, 7=Κυριακή /*void dayofweek(){ byte d; /*int a,y,m,d; a=(14-month)/12; y=year-a; m=month+(12*a)-2; d=(date+y+y/4-y/100+y/400+(31*m)/12)%7;*/ /* d=dow-1; if (d==0) dow=7; else dow=d; }*/ //--------------------------------------------------------// //Αλγόριθμος για τον υπολογισμό Θερινής-Χειμερινής ώρας μιας ημερονηνίας, DST //Γινεται θερινή την τελευταία Κυριακή του Μαρτίου //Γίνεται χειμερινή την τελευταία Κυριακή του Οκτωβρίου void dstcalc(){ //dst=0 -->Winter //dst=1 -->Summer if (month>3 && month<10) dst=1; if (month<3 || month>10) dst=0; if ((month==3) && (date>=24)) { if ((dow==7) && (int(hour)>1)) dst=1;} //else if ((month==3) && (date<24)) dst=0; if ((month==10) && (date>=24)) { if ((dow==7) && (int(hour)>1)) dst=0;} //else if ((month==10) && (date<24)) dst=1; time_change(); } //--------------Αλλαγή της Ώρας---------------------------// void time_change(){ int dst_in_ram; dst_in_ram=readRegister(REG_DST); if ((dst==1) && (dst_in_ram==0)){//αρχιζει η καλοκαιρινή ώρα hour=hour+1.0; setTime((int)hour,(int)minute,(int)sec); writeRegister(REG_DST,dst); } if ((dst==0) && (dst_in_ram==1)){//αρχιζει η χειμερινή ώρα hour=hour-1.0; setTime((int)hour,(int)minute,(int)sec); writeRegister(REG_DST,dst); } } //--------------------------------------------------------// //Υπολογισμοί για την θέση του ήλιου void sunposition(int hour_to_calculate,int min_to_calculate){ float b; //μια μεταβλητή χρήσιμη float bradians; float eot; int lstm; float tcf; float lst; float sha; float declination; float decimaltime; //Μετατροπή της ώρας σε δεκαδική μορφή, είναι ίσο με hour+(minutes/60) int dst_in_ram; decimaltime=(float)hour_to_calculate+((float)min_to_calculate/60); //Μετατροπή της ώρας σε δεκαδική μορφή b=(360.00*(doy-81.00))/365.00; //Μεταβλητή για τον υπολογισμό άλλων παραμέτρων. bradians=b*rad; //το b σε ακτίνια //Equation of Time. //The equation of time (EoT) (σε λεπτά) είναι μια εμπειρική συνάρτηση //η οποία διορθώνει την ελλειπτική τροχιά της γής και την κλίση της γής ως προς τον άξονά της. eot=(9.87*sin(2*bradians))-(7.53*cos(bradians))-(1.5*sin(bradians)); //Local Standard Time Meridian (LSTM) //είναι ένας μεσημβρινός αναφοράς για την συγκεκριμένη ώρα ζώνης //παρόμοιος με κύριο μεσημβρινό ο οποίος χρησιμοποιείται για Greenwich Mean Time. //μας ενδιαφέρει η διαφορά της τοπικής ζωνης ώρας από το 0 και όχι το πρόσημο. //εδώ πρέπει να προστεθεί και η 1 ώρα διαφορά της καλοκαιρινής ώρας. //15=360/24; dst_in_ram=readRegister(REG_DST); lstm=15*(timezone+dst_in_ram); //Time Correction Factor (TC) //The net Time Correction Factor (in minutes) accounts for the variation //of the Local Solar Time (LST) within a given time zone due to the longitude //variations within the time zone and also incorporates the EoT above. //The factor of 4 minutes comes from the fact that the Earth rotates 1° every 4 minutes. tcf=(4.00*(longitude-float(lstm)))+eot; //Local Solar Time (LST) //The Local Solar Time (LST) can be found by using the previous two corrections //to adjust the local time (LT). lst=decimaltime+(tcf/60); //Hour Angle (HRA) //The Hour Angle converts the local solar time (LST) into the number of degrees //which the sun moves across the sky. By definition, the Hour Angle is 0° at solar noon. //Since the Earth rotates 15° per hour, each hour away from solar noon corresponds //to an angular motion of the sun in the sky of 15°. //In the morning the hour angle is negative, in the afternoon the hour angle is positive. sha=15.00*(lst-12.00); //The declination angle, //denoted by δ, varies seasonally due to the tilt of the Earth on its axis of rotation //and the rotation of the Earth around the sun. If the Earth were not tilted on its axis //of rotation, the declination would always be 0°. However, the Earth is tilted by 23.45° //and the declination angle varies plus or minus this amount. Only at the spring and fall //equinoxes is the declination angle equal to 0°.The declination of the sun is the angle //between the equator and a line drawn from the centre of the Earth to the centre of the sun. //Despite the fact that the Earth revolves around the sun, it is simpler to think of the sun //revolving around a stationary Earth. This requires a coordinate transformation. //Under this alternative coordinate system, the sun moves around the Earth. //The declination is zero at the equinoxes (March 22 and September 22), positive during //the northern hemisphere summer and negative during the northern hemisphere winter. //The declination reaches a maximum of 23.45° on June 22 (summer solstice in the northern //hemisphere) and a minimum of -23.45° on December 22 (winter solstice in the northern hemisphere). declination=23.45*sin(bradians); //elevation angle at solar noon easn=90.00-latitude+declination; //Elevation & Zenith angle //The elevation angle (used interchangeably with altitude angle) is the angular height of //the sun in the sky measured from the horizontal. Confusingly, both altitude and elevation //are also used to describe the height in meters above sea level. //The elevation is 0° at sunrise and 90° when the sun is directly overhead //(which occurs for example at the equator on the spring and fall equinoxes). //The zenith angle is similar to the elevation angle but it is measured from the vertical //rather than from the horizontal, thus making the zenith angle = 90° - elevation. float decrad, latrad, sharad, elev, azi; decrad=declination*rad; latrad=latitude*rad; sharad=sha*rad; elev=asin((sin(decrad)*sin(latrad))+(cos(decrad)*cos(latrad)*cos(sharad))); elevation=elev/rad; //zenith=90.00-elevation; //Azimuth Angle //The azimuth angle is the compass direction from which the sunlight is coming. //At solar noon, the sun is always directly south in the northern hemisphere //and directly north in the southern hemisphere. The azimuth angle varies throughout the day //as shown in the animation below. At the equinoxes, the sun rises directly east and //sets directly west regardless of the latitude, thus making the azimuth angles 90° at sunrise //and 270° at sunset. In general however, the azimuth angle varies with the latitude and time //of year and the full equations to calculate the sun's position throughout the day are //given on the following page. //The azimuth angle is like a compass direction with North = 0° ,South = 180°, West = 270° and East = 90° //The above equation only gives the correct azimuth in the solar morning so that: //Azimuth = Azi, for lst <12 or sha < 0 //Azimuth = 360° - Azi, for lst > 12 or sha >0 azi=acos(((sin(decrad)*cos(latrad))-(cos(decrad)*sin(latrad)*cos(sharad)))/cos(elev)); if (sha>0) azimuth=360.00-(azi/rad); else azimuth=azi/rad; } //------------------------------------------------------------// int read_elev_pot(){ int elev_pot_val; int elev_pot_reading; elev_pot_val=0; for(int i=0;i<num_pot_readings;i++){ if (motion_flag!=0) elev_pot_reading=(analogRead(elev_pot)/3); else elev_pot_reading=analogRead(elev_pot)/3; elev_pot_val=elev_pot_val+elev_pot_reading; } elev_pot_val=elev_pot_val/num_pot_readings; elev_pot_val=constrain(elev_pot_val,elev_pot_down_limit,elev_pot_up_limit); elev_pot_val=map(elev_pot_val,elev_pot_down_limit,elev_pot_up_limit,DOWN_LIMIT_DEG,UP_LIMIT_DEG); return elev_pot_val; } //------------------------------------// int read_azim_pot(){ int azim_pot_val; int azim_pot_reading; azim_pot_val=0; for(int i=0;i<num_pot_readings;i++){ if (motion_flag!=0) azim_pot_reading=(analogRead(azim_pot)/2); else azim_pot_reading=analogRead(azim_pot)/2; azim_pot_val=azim_pot_val+azim_pot_reading; } azim_pot_val=azim_pot_val/num_pot_readings; azim_pot_val=constrain(azim_pot_val,azim_pot_east_limit,azim_pot_west_limit); azim_pot_val=map(azim_pot_val,azim_pot_east_limit,azim_pot_west_limit,EAST_LIMIT_DEG,WEST_LIMIT_DEG); return azim_pot_val; } //-----------------------------------------// int check_auto_man(){ int auto_man_state; auto_man_state=digitalRead(auto_man); auto_man_flag=auto_man_state; return auto_man_state; } //--------------------------------------// void printdata(){ int dst_in_ram; Serial.flush(); Serial.println("ACK"); delay(10); switch(dow){ case 1: Serial.print("Mon"); break; case 2: Serial.print("Tue"); break; case 3: Serial.print("Wed"); break; case 4: Serial.print("Thu"); break; case 5: Serial.print("Fri"); break; case 6: Serial.print("Sat"); break; case 7: Serial.print("Sun"); break; } Serial.print(" "); if (date<10){ Serial.print("0"); } Serial.print(date); Serial.print("/"); if (month<10){ Serial.print("0"); } Serial.print(month); Serial.print("/"); Serial.print(year); Serial.print(" "); if (hour<10){ Serial.print("0"); } Serial.print(hour,0); Serial.print(":"); if (minute<10){ Serial.print("0"); } Serial.print(minute,0); Serial.print(":"); if (sec<10){ Serial.print("0"); } Serial.print(sec); Serial.print(" Time Zone = "); Serial.print(timezone,DEC); Serial.print(" DST = "); dst_in_ram=readRegister(REG_DST); switch(dst_in_ram){ case 1:Serial.print("Summer"); break; case 0:Serial.print("Winter"); break; } Serial.print(" Coordinates = "); Serial.print(latitude,6); Serial.print(" , "); Serial.println(longitude,6); delay(10); Serial.println(int(elevation)); delay(10); //Serial.println(zenith,0); //delay(10); Serial.println(int(azimuth)); delay(10); Serial.print(auto_move_elev_deg); Serial.print("-->"); Serial.println(read_elev_pot()); delay(10); Serial.print(auto_move_azim_deg); Serial.print("-->"); Serial.println(read_azim_pot()); delay(10); Serial.println(elev_limits_flag); delay(10); Serial.println(azim_limits_flag); delay(10); Serial.println(auto_man_flag); delay(10); Serial.println(motion_flag); delay(10); Serial.println(mins_to_next_move_count); } //-----------------------------------------------------// void current_sun_calculate(){ getRTC(); dayofyear(); //dayofweek(); dstcalc(); sunposition(hour,minute); if (just_moved_flag==1) just_moved_flag=0; else mins_to_next_move_count=mins_to_next_move_count-1; } //-----------------------------------------------------// void sun_calculate(){ int future_min; int future_hour; getRTC(); dayofyear(); //dayofweek(); dstcalc(); future_min=minute+mins_to_move_ahead/2; future_hour=hour; if (future_min>59) { future_min=future_min-60; future_hour=future_hour+1; if (future_hour>23) future_hour=future_hour-24; } sunposition(future_hour,future_min); elevation_int=int(elevation); azimuth_int=int(azimuth); //elevation_int=-1; //elevation_int=40; //azimuth_int=170; if (elevation_int<=0) {auto_move_elev_deg=UP_LIMIT_DEG;auto_move_azim_deg=SOUTH_DEG;} if (elevation_int>0) { if (elevation_int<DOWN_LIMIT_DEG) auto_move_elev_deg=DOWN_LIMIT_DEG; else auto_move_elev_deg=elevation_int; if (azimuth_int<EAST_LIMIT_DEG) auto_move_azim_deg=EAST_LIMIT_DEG; else if (azimuth_int>WEST_LIMIT_DEG) auto_move_azim_deg=WEST_LIMIT_DEG; else auto_move_azim_deg=azimuth_int; } auto_move_elev_flag=0; auto_move_azim_flag=0; if ((mins_to_next_move_count<mins_to_move_ahead) && (just_moved_flag==0) ){ mins_to_next_move_count=mins_to_move_ahead; just_moved_flag=1; } } //-----------------------------------------------------// void calibrate_pot_UP(){ int cal_elev_pot_val; int cal_elev_pot_reading; delay(2000); cal_elev_pot_val=0; for(int i=0;i<num_pot_readings;i++){ /*if (motion_flag!=0) elev_pot_reading=(analogRead(elev_pot)/2)+1; else */cal_elev_pot_reading=analogRead(elev_pot)/3; cal_elev_pot_val=cal_elev_pot_val+cal_elev_pot_reading; } cal_elev_pot_val=cal_elev_pot_val/num_pot_readings; writeRegister(ELEV_UP_POT_LIMIT,cal_elev_pot_val); delay(10); elev_pot_up_limit=readRegister(ELEV_UP_POT_LIMIT); read_elev_pot(); calibration_state=4; } //-----------------------------------------------------// void calibrate_pot_DOWN(){ int cal_elev_pot_val; int cal_elev_pot_reading; delay(2000); cal_elev_pot_val=0; for(int i=0;i<num_pot_readings;i++){ /*if (motion_flag!=0) elev_pot_reading=(analogRead(elev_pot)/2)+1; else */cal_elev_pot_reading=analogRead(elev_pot)/3; cal_elev_pot_val=cal_elev_pot_val+cal_elev_pot_reading; } cal_elev_pot_val=cal_elev_pot_val/num_pot_readings; writeRegister(ELEV_DOWN_POT_LIMIT,cal_elev_pot_val); delay(10); elev_pot_down_limit=readRegister(ELEV_DOWN_POT_LIMIT); read_elev_pot(); calibration_state=2; } //-----------------------------------------------------// void calibrate_pot_EAST(){ int cal_azim_pot_val; int cal_azim_pot_reading; delay(2000); cal_azim_pot_val=0; for(int i=0;i<num_pot_readings;i++){ /*if (motion_flag!=0) azim_pot_reading=(analogRead(azim_pot)/2)+1; else */cal_azim_pot_reading=analogRead(azim_pot)/2; cal_azim_pot_val=cal_azim_pot_val+cal_azim_pot_reading; } cal_azim_pot_val=cal_azim_pot_val/num_pot_readings; writeRegister(AZIM_EAST_POT_LIMIT,cal_azim_pot_val); delay(10); azim_pot_east_limit=readRegister(AZIM_EAST_POT_LIMIT); read_azim_pot(); calibration_state=1; } //-----------------------------------------------------// void calibrate_pot_WEST(){ int cal_azim_pot_val; int cal_azim_pot_reading; //int azim_pot_EAST; //int azim_pot_WEST; delay(2000); cal_azim_pot_val=0; for(int i=0;i<num_pot_readings;i++){ /*if (motion_flag!=0) azim_pot_reading=(analogRead(azim_pot)/2)+1; else */cal_azim_pot_reading=analogRead(azim_pot)/2; cal_azim_pot_val=cal_azim_pot_val+cal_azim_pot_reading; } cal_azim_pot_val=cal_azim_pot_val/num_pot_readings; writeRegister(AZIM_WEST_POT_LIMIT,cal_azim_pot_val); delay(10); azim_pot_west_limit=readRegister(AZIM_WEST_POT_LIMIT); read_azim_pot(); //azim_pot_EAST=readRegister(AZIM_EAST_POT_LIMIT); //azim_pot_WEST=readRegister(AZIM_WEST_POT_LIMIT); //writeRegister(AZIM_SOUTH,azim_pot_EAST+((azim_pot_WEST-azim_pot_EAST)/2)-2); calibration_state=0; } //-----------------------------------------------------// void setup() { Serial.begin(9600); Serial.flush(); // Set the clock to run-mode pinMode(_scl_pin, OUTPUT); digitalWrite(_scl_pin, LOW); pinMode(_sda_pin, OUTPUT); digitalWrite(_sda_pin, LOW); halt(false); //setTime(16,41,1); //setDate(5,10,2012); //setDOW(5); //writeRegister(REG_DST,1); dst=readRegister(REG_DST); pinMode(elev_UP, OUTPUT); pinMode(elev_DOWN, OUTPUT); pinMode(azim_EAST, OUTPUT); pinMode(azim_WEST, OUTPUT); pinMode(but_UP, INPUT); pinMode(but_DOWN, INPUT); pinMode(but_EAST, INPUT); pinMode(but_WEST, INPUT); pinMode(limit_UP, INPUT); pinMode(limit_DOWN, INPUT); pinMode(limit_EAST, INPUT); pinMode(limit_WEST, INPUT); digitalWrite(elev_UP,LOW); digitalWrite(elev_DOWN,LOW); digitalWrite(azim_EAST,LOW); digitalWrite(azim_WEST,LOW); pinMode(limits_LED,OUTPUT); pinMode(auto_man,INPUT); pinMode(elev_pot,INPUT); pinMode(azim_pot,INPUT); t.every(2000,printdata); //2 sec t.every(60000,current_sun_calculate); //1 min t.every((long)mins_to_move_ahead*60*1000,sun_calculate); // 16 min (16 * 60sec/min* 1000msec/sec)=960000 //writeRegister(ELEV_UP_POT_LIMIT,250); //writeRegister(ELEV_DOWN_POT_LIMIT,146); //writeRegister(AZIM_EAST_POT_LIMIT,2); //writeRegister(AZIM_WEST_POT_LIMIT,251); //writeRegister(AZIM_SOUTH,2+((251-2)/2)); elev_pot_up_limit=readRegister(ELEV_UP_POT_LIMIT); elev_pot_down_limit=readRegister(ELEV_DOWN_POT_LIMIT); azim_pot_east_limit=readRegister(AZIM_EAST_POT_LIMIT); azim_pot_west_limit=readRegister(AZIM_WEST_POT_LIMIT); //azim_south=readRegister(AZIM_SOUTH); mins_to_next_move_count=0; just_moved_flag=0; sun_calculate(); current_sun_calculate(); } //-----------------------------------------------------// //Κυρίως Πρόγραμμα void loop(){ if (calibration_flag==HIGH){ switch (calibration_state){ case 8:if (check_elev_limits()==2) {move_all_stop(); calibrate_pot_UP();} else {move_elev_UP(); auto_man_flag=2;auto_move_elev_flag=0;} break; case 4:if (check_elev_limits()==1) {move_all_stop(); calibrate_pot_DOWN();} else {move_elev_DOWN(); auto_man_flag=2;auto_move_elev_flag=0;} break; case 2:if (check_azim_limits()==2) {move_all_stop();calibrate_pot_EAST();} else {move_azim_EAST(); auto_man_flag=2; auto_move_azim_flag=0;} break; case 1:if (check_azim_limits()==1) {move_all_stop();calibrate_pot_WEST();} else {move_azim_WEST(); auto_man_flag=2; auto_move_azim_flag=0;} break; case 0:{move_all_stop();auto_man_flag=LOW;calibration_flag=LOW;} break; } } else { if (check_auto_man()==LOW){ switch(check_buttons()){ case 8:if (check_elev_limits()==2) move_all_stop(); else {move_elev_UP(); auto_move_elev_flag=0;} break; case 4:if (check_elev_limits()==1) move_all_stop(); else {move_elev_DOWN(); auto_move_elev_flag=0;} break; case 2:if (check_azim_limits()==2) move_all_stop(); else {move_azim_EAST(); auto_move_azim_flag=0;} break; case 1:if (check_azim_limits()==1) move_all_stop(); else {move_azim_WEST(); auto_move_azim_flag=0;} break; case 10:{calibration_flag=HIGH; calibration_state=8;} break; case 0:move_all_stop(); break; } } if (check_auto_man()==HIGH){ if (elevation_int<=0) auto_man_flag=3; if (auto_move_elev_flag==0) automove_elev(auto_move_elev_deg); else if (auto_move_azim_flag==0) automove_azim(auto_move_azim_deg); } } if ((check_elev_limits()>0) || (check_azim_limits()>0)) digitalWrite(limits_LED,HIGH); else digitalWrite(limits_LED,LOW); t.update(); }