//#include <Servo.h>



//Zapojeni
//Sledování slunce:
//-RC6 - PD1
//-RC7 - PD0

//Měření energie
//-RC6 - PD3
//-RC7 - PD7

//Meteorologická část
//-RC6 - PB1
//-RC7 - PB0

//Zbyle propojeni
//definici zapadleho slunce pro blok mereni energie
//PC1 (A1) -RB1 (log.1 noc)

//pin pro odpojeni SD karty
//PC0 (A0) - GND(mereni) - VCC (mozno odpojit)

//GPS modul
//RXD - 


signed int AZIMUT, azimutOD=0; //promena pro hodnotu azimutu Slunce
int ELEVACE, elevaceOD=0; //promena pro hodnotu elevace Slunce

#include <TinyGPS.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include  <math.h>
#include  <stdlib.h>
TinyGPS gps;


SoftwareSerial ss(5, 6); //pro pripojeni modulu GPS (PD5 PD6)
char filename[10]; //pro ulozeni naszvu souboru

char dataGPS[130];
char dataUvodni[60];
char dataNATACENI[10];
float flat, flon; //zemepisna sirka, delka
unsigned long age;
int year;
byte month, day, hour, minute, second, hundredths;
byte day2=0;
unsigned long fix_age;
int c=0;
SoftwareSerial so1Serial(7, 3);
SoftwareSerial so2Serial(8, 9);
File myFile;

int odchylka=5; //definuje po jakém kroku se má sledovat slunce

void setup()
  {
  int count=0;
  Serial.begin(9600);
  ss.begin(9600);
  pinMode(10, OUTPUT); //sd karta
  so1Serial.begin(9600);
  so2Serial.begin(9600);
  if (!SD.begin(4)) {    //inicializace SD karty
    //Serial.println("inicializace se nepovedla");
    return;
    
  //nastaveni preruseni na pinu PD2
  //pro detekci vysouvani karty  
  attachInterrupt(0, off, HIGH);
  interrupts();
  
  }
  //Serial.println("inicializace provedena"); 
}

//uzavre zapis na SD karte
//pro opetovne zapnuti je potreba resetovat 
//mikropocitac
void off (void)
{
while(true)
  {
    myFile.close();
    while(true);
  }
} 

int stupne (float rad) //prevod rad na stupne
  {
  int a =(int) ((rad/3.14)*180);
  return a;
  }



float rad (float stup) //prevod stupne na rad
  {
  float a = ((stup/180)*3.14);
  return a;
  }



//provede vypocet dnu od zacatku roku

int den (int m, int d) //vstupem je mesic a den
  {
  switch (m) {
    case 1: d=d;
    break;

    case 2: d=31+d;
    break;
    
    case 3: d=58+d;
    break;
 
    case 4: d=89+d;
    break;

    case 5: d=119+d;
    break;

    case 6: d=150+d;
    break;

    case 7: d=180+d;
    break;

    case 8: d=211+d;
    break;

    case 9: d=242+d;
    break;

    case 10: d=262+d;
    break;

    case 11: d=303+d;
    break;

    case 12: d=333+d;
    break;

    default:printf("chyba");
    break; 
  }
 //Serial.println("Den: ");          
 //Serial.println(d);          
return d;
}

float deklinace (float d) //vstupem je den v roce
  {
  float b = 0.98630137;
  d=((rad(23.45))*sin(rad(b*(d-81))));
  //Serial.println("Deklinace");   
  //Serial.println(d,4);
  return d;
  }

float lstm (int gmt) //vstupem je GMT dane lokality
  {
  float a;
  a=((rad(15))*gmt);
  //Serial.println("lstm");   
  //Serial.println(a,10);
  return a;
  }

float eot (float d) //vstupem je den v roce
  {
  float a;
  a=rad(0.98630137*(d-81));
  a=9.87*sin(2*a)-7.53*cos(a)-1.5*sin(a);
  //Serial.println("eot");   
  // Serial.println(a,10);
  return a;
  }

float tc (int delka, float lstm, float eot) //vstupem je zemepisná delka, LSTM, EoT
  {
  float a;
  a=4*(float)(delka-lstm)+eot;
  //Serial.println("tc");   
  //Serial.println(a);
  return a;
  }

float lst (float lt, float tc) //vstupem je den GMT dane lokality
  {
  float a;
  a=lt+(tc/60);
  return a;
  //Serial.println("lst");   
  // Serial.println(a);
  }

float hra (float lst) //vstupem je den v roce
  {
  lst=(rad(15))*(lst-12);
  //Serial.println("hra");   
  //Serial.println(lst,4);
  return lst;
  }

//vstupem je mesic, den, hodina, minuty, GMT, zemepisna sirka ve stupnich
void poziceSL(int m, int d, int h, int minu, int gmt, float sirka, float delka) 
  {
  float den1;
  float ele,azi,deklin, lstm1, eot1, tc1, lst1, hra1;
  float lt = h+((float)minu/60);
  //Serial.println("lt");
  //Serial.println(lt);
  den1=(float) den(m,d);
  deklin=deklinace(den1);
  lstm1=lstm(gmt);
  eot1=eot(den1);
  tc1=tc(delka, lstm1, eot1);
  lst1=lst(lt,tc1); 
  hra1=hra(lst1);
  sirka=rad(sirka);
  ele=asin((sin(deklin)*sin(sirka))+(cos(deklin)*cos(sirka)*cos(hra1)));
  azi = acos(((sin(deklin)*cos(sirka))-(cos(deklin)*sin(sirka)*cos(hra1)))/(cos(ele)));
  //printf("Azimut: %6.3f\r\n", azi);
  //printf("Elevce: %6.3f\r\n", ele);
  ELEVACE=stupne(ele);
  AZIMUT= stupne(azi);
    if(hra1>0)
    {
     AZIMUT= 360-AZIMUT;
    }

  }

void datagps() //vycet tat z GPS modulu
  {
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  for (unsigned long start = millis(); millis() - start < 1000;)
    {
     while (ss.available())
      {
      char c = ss.read();
      if (gps.encode(c)) 
      newData = true;
      }
    }

  if (newData)
    {
    gps.f_get_position(&flat, &flon, &fix_age);
    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &fix_age);
    }
  }

void loop () //nekonecna smycka
  {
  int az, ele;
  byte zk;
  ss.listen();
  datagps();
  
  //int mesic, den, hodina, minuta, odchylka èasu od GMT, sirka, delka
  poziceSL(month, day, hour, minute, 0, flat, flon);

  //vytvori nazev souboru
  sprintf(filename, "MET%d%d.txt", month, day);
  //Serial.print(filename);

//pro kazdy den se vytvori novy soubor
//slouzi pro generovani uvodniho nadpisu v souboru
  if(!day2==day)
  {
    c=0;
    day2=day;
  } 

  if(ELEVACE<0)
  {
    analogWrite(A1,255);
  }  
  
//Serial.print("Azimut");  
//Serial.println(AZIMUT);

//Serial.print("ELevace");  
//Serial.println(ELEVACE);
//Priprava dat pro zapis na SD kartu
  sprintf(dataGPS,"\r\n %4.0d %2.0d %2.0d %2.0d %2.0d %3.0d %3.0d %3.0d %3.0d", year, month, day, hour, minute, (int)flon, (int) flat, (int)AZIMUT,(int) ELEVACE);
// Serial.println(dataGPS);

//zamezi nataceni solarniho panelu v noc
//prez den provede nove nastaveni solaru vzdy
//po prekroceni odchylky od slunce o uhel
//zadaný v promenné odchylka
if(ELEVACE<0)
  {
    //Serial.print("noc"); 
  } 
else  
  {
  //Serial.print("den porovnani"); 
    az=AZIMUT-azimutOD;
    az=abs(az);
    ele=ELEVACE-elevaceOD;
    ele=abs(ele);

    if((ele>odchylka)||(az>odchylka))
      {
      //Serial.print("odchylka nove nastaveni"); 
      azimutOD=AZIMUT;
      elevaceOD=ELEVACE;
      sprintf(dataNATACENI,"%d ", ELEVACE);
      Serial.print(dataNATACENI);
      delay (100);
      sprintf(dataNATACENI,"%d ", AZIMUT);
      Serial.print(dataNATACENI);
      } 
  }   

//otevre, nebo vytvory soubor
//s nazvem v promenné filename
File myFile = SD.open(filename, FILE_WRITE);

//pri privedeni napeti VDD na pin PC0 procesoru,
//dojde k uzavreni soubor a dokud nebude
//na tento pin privede GND program bude pozastaven
//Pro bezpecne odpojeni SD karty
//while(!analogRead(A0)==0)
//  {
 //   myFile.close();
 //   while(true);
  //} 

if (myFile) 
  {
    if(c==0) //obsahuje hlavicku souboru
      {
      myFile.print("Meteorologicka stanice Jan Chroust 2013 \n");
      sprintf(dataUvodni,"Mereni ze den %2.0d.%2.0d.%4.0d \n", day, month, year);
      myFile.print(dataUvodni);
      delay(10);
      myFile.print(" \n");
     // Serial.print(dataUvodni);
      c=1;
      }
    else
      {
      } 
   
    myFile.print(dataGPS); //ulozi data na SD kartu
    //Serial.print(dataGPS);
   
    so1Serial.listen();
    
    //cekani na data ze seriove linky
    while(so1Serial.available()==0)
      {
      }
    delay(1000); 

    //vycet dat ze seriove linky
    //data z blku mereni energie
    while (so1Serial.available())
      {
      char baterie = so1Serial.read();
      myFile.print(baterie);
      //Serial.print(baterie);
      }
     
    so2Serial.listen();
    
    while(so2Serial.available()==0)
      {
     }
    delay(1000); 
   //nacteni dat ze seiové linky
   //data z meteorologického bloku
    while (so2Serial.available())
      {
      char baterie = so2Serial.read();
      myFile.print(baterie);
     // Serial.print(baterie);
      }
 
    // uzavreni souboru
    myFile.close();
  }
else
  {
  //pri neotevreni souboru
  //Serial.println("Nepodarilo se otevrit soubor");
  }

delay(200); //frekvence zapisu na SD
}