/* 0- General */

int decimalPrecision = 4;

/* Mereni spotreby tarify */
#define pintarif A5
float spotrebaNT = 0;
float spotrebaVT = 0;

/* 1- Mereni frekvence */

unsigned long startMicros;
unsigned long currentMicros; 
int expectedFrequency = 50;
int napetiPin = A2;
float frequencySampleCount = 0; 
float frequency = 0 ;
float a;
float switch01 = 0;
float vAnalogRead = 0; 

/* 2- Mereni napeti */

float voltageSampleRead  = 0;
float voltageLastSample  = 0; 
float voltageSampleSum   = 0;   
float voltageSampleCount = 0;   
float voltageMean ;                      
float RMSVoltageMean ;   
float FinalRMSVoltage;        

/* 3. Mereni proudu */
int merenaHodnota = 0;
int maximum = 0;
unsigned long proudCasovac = millis();

#define pinSenzor A0

float odpor = 988.0;
float napetiSpickove;
float proudSpickovyPresRezistor;
float proudRMSPresRezistor;
float proudRMSmereny;
float odberWatt;

/* Print promenne */
unsigned long printCasovac = millis();

void setup()
{

  /* 0- General */

  Serial.begin(9600);            
  
  /* 1- setup frekvence */

  startMicros = micros();                  

  pinMode(pinSenzor, INPUT);
  pinMode(pintarif, INPUT);
}

void loop()
{
  /* 1- Mereni napeti */
  if (micros() >= voltageLastSample + 1000 )                                                             
  {
    voltageSampleRead = (analogRead(napetiPin) - 512);                                                      
    voltageSampleSum = voltageSampleSum + sq(voltageSampleRead) ;                                     
    voltageSampleCount = voltageSampleCount + 1;                                 
    voltageLastSample = micros() ;                                               
  }

  /* 1- mereni frekvence */
  currentMicros = micros();                  
  vAnalogRead = analogRead(napetiPin) - 512;  

  if (vAnalogRead >= 0 && switch01 == 0)            
  {
    frequencySampleCount = frequencySampleCount + 1 ;      
    switch01 = 1;                                      
  }

  if (vAnalogRead < 0 && switch01 == 1)                   
  {
    switch01 = 0;                                             
    /* this purpose is to make sure whole wave form is complete and counting quantity of sample with no mistake */
  }

  if (frequencySampleCount == 50)                   
  {
    a = currentMicros - startMicros ;                            
    frequency = 1 / ((a / 1000000) / frequencySampleCount);      
    voltageMean = voltageSampleSum / voltageSampleCount;                                                   
    RMSVoltageMean = (sqrt(voltageMean)) * 1.5;                                                                                                                                                                        
    FinalRMSVoltage = RMSVoltageMean;                                                  
    if (FinalRMSVoltage <= 5)                                                                     
    {
      FinalRMSVoltage = 0;
      frequency = 0;
    }
    voltageSampleSum = 0;                                                                            
    voltageSampleCount = 0;                                                                            
    startMicros = currentMicros;                           
    frequencySampleCount = 0;                                  
  }

  /* 3. Mereni proudu */
  merenaHodnota = analogRead(pinSenzor);
  if (merenaHodnota > maximum) {
    maximum = merenaHodnota;
  }

  if (millis() >= proudCasovac + 1000 )
  {
    napetiSpickove = (maximum * 5.0) / 1024.0; 
    proudCasovac = millis();
    maximum = 0;
  }

  proudSpickovyPresRezistor = (napetiSpickove / odpor) * 1000.0;
  proudRMSPresRezistor = proudSpickovyPresRezistor * 0.707;
  proudRMSmereny = proudRMSPresRezistor * 2000;
  odberWatt = FinalRMSVoltage * (proudRMSmereny / 1000.0);
  /* Odeslani vysledku */
  if (millis() >= printCasovac + 1000 )
  {
    Serial.print(frequency, 0);
    Serial.print(":");
    Serial.print(FinalRMSVoltage, decimalPrecision);
    Serial.print(":");
    Serial.print(proudRMSmereny, decimalPrecision);
    Serial.print(":");
    Serial.print(odberWatt, decimalPrecision);
    Serial.print(":");
    if(((analogRead(pintarif)* 5.0) / 1024.0)>4)
    {
      Serial.print("0");
    }
    else
    {
      Serial.print("1");
    }
    Serial.print(":");
    Serial.println(millis()-printCasovac);
    
    printCasovac = millis();
  }
}
