//Υπολογισμός θέσης του ήλιου
//Δίνει την θέση του ήλιου στον ουρανό σε μοίρες όσο αφορά το ύψος και την ανατολή-δύση
#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();
}
//Δίνει την θέση του ήλιου στον ουρανό σε μοίρες όσο αφορά το ύψος και την ανατολή-δύση
#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();
}
No comments:
Post a Comment