




#include <Wire.h>
#include <Math.h>
#define RTC_ADDR 0x68

  int current_day;

  int sunrise;         // v minútach od polnoci VS
  int sunset;          // v minútach od polnoci ZS
  unsigned long motorstarttime;

  // Global Vars
  
  int OP         = 0;  // OPEN
  int CLO        = 1;  // CLOSE
  int STOP       = 2;
  int UNKNOWN    = 2;
  int DoorState  = 2;  // predpokladajte, že nie sú otvorené ani zatvorené
  
  int EnMotorPin         = 3;
  int CloseDoorPin       = 4;
  int OpenDoorPin        = 5;
  int bottomSwitchPin    = A2;
  int topSwitchPin       = A3;

  int second;
  int minutex;
  int hour;
  int dayOfWeek;
  int dayOfMonth;
  int month;
  int year;
 
void setup(){
  
  pinMode(EnMotorPin,      OUTPUT);
  pinMode(CloseDoorPin,    OUTPUT);  // motor nadol
  pinMode(OpenDoorPin,     OUTPUT);  // motor nahor
  pinMode(topSwitchPin,     INPUT);  // horný spinač
  pinMode(bottomSwitchPin,  INPUT);  // dolný spínač
  digitalWrite(EnMotorPin,    LOW);
  digitalWrite(CloseDoorPin,  LOW);  
  digitalWrite(OpenDoorPin,   LOW);  
 
  DoorState = GetDoorState();
  if (DoorState ==     UNKNOWN) 
  OpenDoor();
  
  Wire.begin();
  ReadTime();
  int current_day = dayOfMonth;
  getRiseSet();
 
  Serial.begin(9600);
  Serial.print        (" VS  : ");
  Serial.println        (sunrise);
  Serial.print        (" ZS  : ");
  Serial.println         (sunset);
  //  Serial.print(" Aktual: ");
  //  Serial.println       (year);
  //  Serial.println      (month);
  //  Serial.println (dayOfMonth);
  //  Serial.println       (hour);
  //  Serial.println    (minutex);
  Serial.print        (" Time: ");
  Serial.println ((hour*60)+minutex);
     
}

//  Prevod normálnych desatinných čísel na binárne desatinné čísla 
    byte decToBcd(byte val)
{
    return ( (val/10*16) + (val%10) );
}

//  Prevod binárnych kódovaných desatinných čísel na normálne desatinné čísla
    byte bcdToDec(byte val)
{
    return ( (val/16*10) + (val%16) );
}
 
void OpenDoor() {
  motorstarttime = millis();
  DoorState = GetDoorState();
  while (DoorState != OP) {
  MotorControl(OP);
  DoorState = GetDoorState();
  if (millis() - motorstarttime > 20000) { break; } // Po uplynutí 20 sekúnd zastavte motor
}
  delay(50);
  MotorControl(STOP);
}
 
void CloseDoor() {
  motorstarttime = millis();
  DoorState = GetDoorState();
  while (DoorState != CLO) {
  MotorControl(CLO);
  DoorState = GetDoorState();
  if (millis() - motorstarttime > 20000) { break; } // Po uplynutí 20 sekúnd zastavte motor
}
  delay(50);
  MotorControl(STOP);
}
 
void MotorControl(int Direction) {
 
  if (Direction        == OP) {
   digitalWrite(CloseDoorPin,  LOW);
   digitalWrite(OpenDoorPin,  HIGH);
   digitalWrite(EnMotorPin,   HIGH);
}  else if (Direction == CLO) {
   digitalWrite(CloseDoorPin, HIGH);
   digitalWrite(OpenDoorPin,   LOW);
   digitalWrite(EnMotorPin,   HIGH);
}  else if (Direction == STOP) {
   digitalWrite(CloseDoorPin,  LOW);
   digitalWrite(OpenDoorPin,   LOW);
   digitalWrite(EnMotorPin,    LOW);
}  
}
 
int GetDoorState() {
 
  // Read switch states
  int topSwStatus    = digitalRead   (topSwitchPin);
  int bottomSwStatus = digitalRead(bottomSwitchPin);
  int returnValue    = UNKNOWN;
 
  // skontrolujte, či sú dvere medzi stavmi
  if ((topSwStatus    == 0) and (bottomSwStatus == 0)) { returnValue = UNKNOWN; }
  // skontrolujte, či sú dvere otvorené
  if (topSwStatus    == 1) { returnValue = OP; }
  // skontrolujte, či sú dvere zatvorené
  if (bottomSwStatus == 1) { returnValue = CLO; }
  return(returnValue);
}
 
void getRiseSet()
{
   sunrise = int(291 + (90*cos(((((month-1)*30.5)+dayOfMonth)+8)/58.1)));
   sunset = int(1256 + (90*sin(((((month-1)*30.5)+dayOfMonth)-83)/58.1)));
}

void NewDay()
{
   current_day = dayOfMonth;
   getRiseSet();
   OP  = 0;
   CLO = 1;
}

void ReadTime()
{
   Wire.beginTransmission(RTC_ADDR);   // Otvorte riadok I2C v režime zápisu 
   Wire.write(0x00);                   // Nastavte ukazovateľ registra na (0x00) 
   Wire.endTransmission();             // Koniec zápisu prenosu 
   Wire.requestFrom(RTC_ADDR, 7);      // Otvorte riadok I2C v režime odosielania

   second     = bcdToDec(Wire.read() & 0x7f); //  Prečítať sedem bajtov údajov 
   minutex    = bcdToDec(Wire.read());
   hour       = bcdToDec(Wire.read() & 0x3f);  
   dayOfWeek  = bcdToDec(Wire.read());
   dayOfMonth = bcdToDec(Wire.read());
   month      = bcdToDec(Wire.read());
   year       = bcdToDec(Wire.read());
   int current_time = (hour*60)+minutex;
}

void loop() {

   delay(3000);       // 3 sek 
   ReadTime();
   if (current_day!=dayOfMonth)
{
   NewDay();
}
 
   int current_time = (hour*60)+minutex;
 
    // Zatvorte alebo otvorte dvere,skontroluje aktuálny stav dverí.
    if ((current_time > sunrise) && (current_time < sunset))
{
    OpenDoor();
}   else {
    CloseDoor();
}

}
 
 
