#include <Wire.h>
#include <DS3231.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <SD.h>
#include <Adafruit_INA219.h>

Adafruit_INA219 ina219;


DS3231 rtc_modul;
LiquidCrystal_I2C lcd(0x3F, 20, 4);

bool moje_PM = 1, moje_h12 = 1, moje_Century = 0, on_state ;
int x=0, i, rpm_val, count_while=0, rpm_max=0;
int value_V, value_A,hall_count;
float voltage_while, amper_while, voltage_avg, amper_avg, power_while, power_avg, voltage_max, amper_max, power_max;
unsigned long  rpm_avg, start, end_time, time_passed;


#define hall_pin 2        // vstup pro mereni otacek
#define hall_thresh 2     // pocet impulsu na jedno mereni
#define interval 2000     //pocet ms na jeden cyklus meření RPM




File myFile;

void setup()  {
  Serial.begin(9600);
  Wire.begin();

 rtc_modul.enableOscillator(1,1,3);
 rtc_modul.setA2Time(1,20,21,0b1110000, false, false, false); 
 rtc_modul.turnOnAlarm(2);

 lcd.init();
 lcd.backlight();

 if(!SD.begin(10)){
  Serial.println("FAIL!");
  lcd.setCursor(12,0);
  lcd.print("SD_FAIL");
 }
 else {Serial.println("DONE!");
  lcd.setCursor(12,0);
  lcd.print("SD_DONE");
 }

 pinMode(hall_pin, INPUT);
 uint32_t currentFrequency;
 ina219.begin();

   /* rtc_modul.setYear(21);
    rtc_modul.setMonth(4);
    rtc_modul.setDate(18);
    rtc_modul.setDoW(7);
    rtc_modul.setHour(11);
    rtc_modul.setMinute(39);
    rtc_modul.setSecond(0);*/
                }
 
void loop() {
  
   lcdWriteHour(14,2); // funkce zobrazujici cas na LCD
   lcdWriteDate(12,3); // zobrazeni date na LCD
   lcdWriteMeasure();  // zobrazeni merenych velicin
  
    if(rtc_modul.checkIfAlarm(2)){                    //kdyz uplyne 1 min
   
         SD.begin(10);
         myFile=SD.open("test.txt", FILE_WRITE);
         
        if(myFile){                                     //funkce pro ukladani hodnot na sd kartu
          SDWriteDate();                                //zobrazeni na novem radku
          myFile.print (voltage_avg / x);
          myFile.print(" ");
          myFile.print (amper_avg / x);
          myFile.print(" ");
          myFile.print(power_avg / x);
          myFile.print(" ");
          myFile.print(rpm_avg / x);
          myFile.print(" ");
          myFile.print(voltage_max);
          myFile.print(" ");
          myFile.print(amper_max);
          myFile.print(" ");
          myFile.print(power_max);
          myFile.print(" ");
          myFile.println(rpm_max);
          myFile.close();
      
          x = 0;
          voltage_avg = 0;
          amper_avg = 0;
          power_avg = 0;
          rpm_avg = 0;

          voltage_max = 0;
          amper_max = 0;
          power_max = 0;
          rpm_max = 0;
          
        }
        else{
        if(!SD.begin(10)){
           lcd.setCursor(12,0);
           lcd.print("SD_FAIL");
             }
        else {Serial.println("DONE!");
              lcd.setCursor(12,0);
              lcd.print("SD_DONE");
              }
        
        
        }
        }
         lcd.noBacklight();    
        ///............mereni...........///

  hall_count = 0;
  start = millis();
  on_state = false;
  rpm_val = 0;
  count_while=0;
  
  while(true){
    if (digitalRead(hall_pin)==0){
      if (on_state==false){
        on_state = true;
        hall_count+=1;
      }
                                 }
       else{
          on_state = false;
           }
    
    end_time = millis();
    if((end_time-start)>interval){
      time_passed = ((end_time-start)/1000.0);
      rpm_val = (int)((hall_count/time_passed)*60);
      break;
    }
    }
    
        x++;
        voltage_while = ina219.getBusVoltage_V();
        amper_while = ina219.getCurrent_mA();
        power_while = ina219.getPower_mW();
        
        voltage_avg += voltage_while;
        amper_avg += amper_while;
        power_avg += power_while;
        rpm_avg += rpm_val;

        if(voltage_max<voltage_while){
          voltage_max = voltage_while;
          }
        if(amper_max<amper_while){
          amper_max = amper_while;
          }
        if(power_max<power_while){
          power_max = power_while;
          }
        
        if(rpm_max<rpm_val){
          rpm_max = rpm_val;
          }
 
}


void lcdWriteHour(int post, int slp) //int sloupec, radek
{
  
  lcd.setCursor(post,slp);
  if((rtc_modul.getHour(moje_h12,moje_PM))<10){
    lcd.print("0");
    lcd.print(rtc_modul.getHour(moje_h12,moje_PM));
    }
  else{
    lcd.print(rtc_modul.getHour(moje_h12,moje_PM));
    }
   lcd.print(":");
            //Zobrazeni minut//
  if((rtc_modul.getMinute())<10){
    lcd.print("0");
    lcd.print(rtc_modul.getMinute());
    }
  else{
    lcd.print(rtc_modul.getMinute());
    }
  }

  void lcdWriteDate(int post, int slp) //int sloupec, radek
{
          //zobrazeni date
  lcd.setCursor(post,slp);
  if((rtc_modul.getDate())<10){
    lcd.print("0");
    lcd.print(rtc_modul.getDate());
    }
  else{
    lcd.print(rtc_modul.getDate());
    }
   lcd.print(".");
            //Zobrazeni mesic//
  if((rtc_modul.getMonth(moje_Century))<10){
    lcd.print("0");
    lcd.print(rtc_modul.getMonth(moje_Century));
    }
  else{
    lcd.print(rtc_modul.getMonth(moje_Century));
    }
   lcd.print(".");
   
           //Zobrazeni year//
   lcd.print(rtc_modul.getYear());
    
  
  
  }

   void SDWriteDate() // funkce pro zapsani datumu na sd kartu
{
    myFile.print(rtc_modul.getDate());
    myFile.print(".");
    myFile.print(rtc_modul.getMonth(moje_Century));
    myFile.print(".");
    myFile.print(rtc_modul.getYear());
    myFile.print(" ");
    myFile.print(rtc_modul.getHour(moje_h12,moje_PM));
    myFile.print(":");
    myFile.print(rtc_modul.getMinute());
    myFile.print(" ");
  }


  void lcdWriteMeasure()
  {
   lcd.setCursor(0,0);
   lcd.print("U=");  
   lcd.print(voltage_while);   
   lcd.print(" V ");
   lcd.setCursor(0,1);
   lcd.print("I=");
   lcd.print(amper_while); 
   lcd.print(" mA ");
   lcd.setCursor(0,2);
   lcd.print("P=");
   lcd.print(power_while); 
   lcd.print(" mW ");
   lcd.setCursor(0,3);
   lcd.print("N=");
   lcd.print("0000");
   if(rpm_val>1000)
   {
    lcd.print(rpm_val);
    }
   if(rpm_val<1000 & rpm_val>99){
    lcd.setCursor(3,3);
    lcd.print(rpm_val);
   }
   else if(rpm_val<100 & rpm_val>9){
    lcd.setCursor(4,3);
    lcd.print(rpm_val);
   } 
    else if(rpm_val<10){
    lcd.setCursor(5,3);
    lcd.print(rpm_val);
   } 
    
    
    }
