

/* DAC je pripojen na pin 11 a 13. CS je na pin 10.

   PAC 1934 Microchip
   snimani napeti a proudu na CH1 a CH2
   ve smycce loop je napsan vzorec pro vypocet jednotlivych hodnot
       pro CHANNEL 1 je snimani sekundaru, kde je R=0,05 ohm, a FSC= 2
       pro CHANNEL 2 je snimani primaru, kde je R=0,02 ohm, FSC =5
   - (float)VBUS2 je pro pretypovani hodnot. Kdyby se tak neudelalo, tak by vysledne hodnoty byly jenom integer
   - registr pro snimani napeti byl zvolen registr AVARANGE
   - na zacatku LOOP je refresh command pro reafresh merenych hodnot

*/


//import knihovny pro komunikaci I2C
#include <Wire.h>
#include <LiquidCrystal.h>


#define PAC1934_ADDRESS 0x10                //adresa zařízení zjisteni z datasheetu a nebo pomoci programu "zjisteni I2C"
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);        // zadefinovane piny

//*******************************************

// PROMENNE ****************************  neznamenkovy 16-bit integer; zadefinovani promennych
uint16_t VSENSE1;                           //proud na sekundarni strane [0,05 ohm]
uint16_t VBUS1;                             //napeti na sekundarni strane
uint16_t VBUS2;                             //napeti na primarni strane
uint16_t VSENSE2;                           //proud na sekundarni strane [0,02 ohm]

//PRIMAR
float V_prim;
float I_prim;

//SEKUNDAR
float V_sek;
float I_sek;


// pouzite knihovny pro DAC
#include <SPI.h>
#include <MCP48x2.h>

#define MAX_VALUE 255                               // MCP4802 je 8-bit prevodnik, => 255

#define CSPIN 10                                    // datasheet

byte channelA = CHANNEL_A | GAIN_1 | MODE_ACTIVE;   // definovani pro kanal A;  gain_1 = 2,07V a gain_2= 4V

float i = 0 ;
float outputValue = i;                              // hodnota výstupu

int casovani = 5000;                                //nastaveni casu mezi hodnotama
uint32_t t_nakonci;
bool k = 0;                                         // jen pro prvni loop aby nemeril až po 5 sekundách


MCP48x2 dac(MCP4802, CSPIN);

//2. cast ***********************************************************************************************************************************************************

void setup() {
  //Inicializace knihovny
  //Pokud se zada s parametrem, je zarizeni pridelena adresa
  Wire.begin();
  SPI.begin();
  // zahajeni a zapis na adresu 01H
  Wire.beginTransmission(PAC1934_ADDRESS);          //zahajeni komunikace s PAC na pozadovane adrese
  Wire.write(0x01);                                 //(Register ADDRESS 01H) (otevru registr)
  Wire.write(0xC0);                                 //zapis do registru      (zapsani hodnoty- nastaveni registru)
  Wire.endTransmission();                           //ukonceni komunikace

  // Zahajeni zapis na adresu 1C (chanell-dis, SMBUS)   - nastaveni kanalu, on/off
  Wire.beginTransmission(PAC1934_ADDRESS);          //zahájeni komunikace s PAC na pozadovane adrese
  Wire.write(0x1C);                                 //(Register ADDRESS 1CH) (otevru registr)
  Wire.write(0x32);                                 //zapis do registru      (zapsani hodnoty- nastaveni registru)
  Wire.endTransmission();                           //ukonceni komunikace

  // Zahajeni zapis na adresu 1D (NEG_PWR)  - nastaveni rozsahu pro mereni
  Wire.beginTransmission(PAC1934_ADDRESS);          //zahajeni komunikace s PAC na pozadovane adrese
  Wire.write(0x1D);                                 //(Register ADDRESS 1DH) (otevru registr)
  Wire.write(0x00);                                 //zapis do registru      (zapsani hodnoty- nastaveni registru)
  Wire.endTransmission();                           //ukonceni komunikace

 
  // nastaveni displeje
  lcd.begin(16, 2);

  t_nakonci = millis();                             // mereni casu
}
//3. cast****************************************************************************************************************************************************

void loop() {

  //*****************************************************snimani hodnot**************************************************************************
  // REFRESH_V- hodnot
  Wire.beginTransmission(PAC1934_ADDRESS);
  Wire.write(0x1F);
  Wire.endTransmission();

  // REFRESH_V- hodnot
  Wire.beginTransmission(PAC1934_ADDRESS);
  Wire.write(0x1E);
  Wire.endTransmission();

  // nacteni hodnot z PACU
  VBUS1 = getVBUS1();                                 //nacteni napeti z kanalu CH1 pro VBUS1
  VSENSE1 = getVSENSE1();                             // nacteni proudu z kanalu CH1 pro VSENSE1
  VBUS2 = getVBUS2();                                 //nacteni napeti z kanalu CH2 pro VBUS2
  VSENSE2 = getVSENSE2();                             // nacteni proudu z kanalu CH2 pro VSENSE2

  // vypocet hodnot pro primarni stranu
  V_prim = 0.00048828125 * (float)VBUS2;              // vypocet podle vzorcu v datasheetu
  I_prim = 0.0000762939453125 * (float)VSENSE2;

  //vypocet hodnot pro sekundarni stranu
  V_sek = 0.00048828125 * (float)VBUS1;
  I_sek = 0.000030517578125 * (float)VSENSE1;        


  //********************************************vypsani hodnot na displej******************************************************************

  lcd.setCursor(0, 0);                                // nastaveni kurzoru
  lcd.print(V_prim);                                  // vypsana hodnota
  lcd.print("V");                                       //jednotky

  lcd.setCursor(5, 0);
  lcd.print(I_prim);
  lcd.print("A");

  lcd.setCursor(0, 1);
  lcd.print(V_sek);
  lcd.print("V");

  lcd.setCursor(5, 1);
  lcd.print(I_sek);
  lcd.print("A");

  // prikon
  float P_prim;
  P_prim = V_prim * I_prim;

  // vykon
  float P_sek;
  P_sek = V_sek * I_sek;

  lcd.setCursor(11, 0);   
  lcd.print(P_sek);
  lcd.print("W");

  //Ucinnost
  float ucin;
  ucin = (P_sek / P_prim) * 100;

  lcd.setCursor(11, 1);   
  lcd.print(ucin);
  lcd.print("%");

  //********************************************************nastaveni hodnot po 5-ti sekundach***************************************
  if (millis() >= t_nakonci + casovani || k == 0) {
    k = 1;

    if (i > MAX_VALUE) {                    // od 0 do maximalni hodnoty
      i = 0;
    }

    if (i < 0) i = 0;
    dac.send(channelA, i);                  // vystup DA prevodniku (A)


    if (i > MAX_VALUE) i = MAX_VALUE;
    dac.send(channelA, i);                  


    
    i = i + 25.5;
    t_nakonci = millis();
  }
}

//4. cast**************************************************************************************************************************************************************************

//-----------------------------------------------FUNKCE1 pro vypis napeti na CH1------------------------------------------------------------

uint16_t getVBUS1() {                       // nacteni hodnoty pomoci knihovny Wire.h

  uint16_t vbus1;                           //interni proměnná pro měření 16bit promenna
  Wire.beginTransmission(PAC1934_ADDRESS);  //zahajeni komunikace s PAC na pozadované adrese
  Wire.write(0x0F);                         // adresa pro napeti na CH1 (Vbus1_AVG)
  Wire.endTransmission();                   //ukoncení komunikace - automaticky posle read bit
  Wire.requestFrom(PAC1934_ADDRESS, 2);     //pozadavek na dva bajty od zarizeni s adresou PAC1934_ADDRESS 0x07


  vbus1 = Wire.read();                      //pricteni dat (horní bajt)
  vbus1 <<= 8;                              //bitovy posun o 8 bitu vlevo- potreba pro 16-bit
  vbus1 += Wire.read();                     //pricteni dat (dolni bajt)


  return vbus1;                             //navráceni výsledku
}


//-------------------------------------------FUNKCE2 pro vypis produ na CH1------------------------------------------------------------

uint16_t getVSENSE1() {                       // nacteni hodnoty pomoci knihovny Wire.h

  uint16_t vsense1;                           //interni proměnná pro měření 16bit promenna
  Wire.beginTransmission(PAC1934_ADDRESS);    //zahajeni komunikace s PAC na pozadované adrese
  Wire.write(0x13);                           // adresa pro vypis proudu z CH1 (Vsense1_AVG)    
  Wire.endTransmission();                     //ukonceni komunikace - automaticky posle read bit
  Wire.requestFrom(PAC1934_ADDRESS, 2);       //pozadavek na dva bajty od zarizeni s adresou PAC1934_ADDRESS 0x0B


  vsense1 = Wire.read();                      //precteni dat (horni bajt)
  vsense1 <<= 8;                              //bitovy posun o 8 bitů vlevo- potreba pro 16-bit
  vsense1 += Wire.read();                     //pricteni dat (dolni bajt)


  return vsense1;                             //navraceni vysledku
}



//-------------------------------------------FUNKCE3 pro výpis napeti na CH2------------------------------------------------------------

uint16_t getVBUS2() {                       // nacteni hodnoty pomoci knihovny Wire.h

  uint16_t vbus2;                           //interni promenna pro merení 16bit promenna
  Wire.beginTransmission(PAC1934_ADDRESS);  //zahajeni komunikace s PAC na pozadované adrese
  Wire.write(0x10);                         // adresa pro napeti na CH1 (Vbus1_AVG)
  Wire.endTransmission();                   //ukoncení komunikace - automaticky posle read bit
  Wire.requestFrom(PAC1934_ADDRESS, 2);     //pozadavek na dva bajty od zarizeni s adresou PAC1934_ADDRESS 0x08


  vbus2 = Wire.read();                      //precteni dat (horni bajt)
  vbus2 <<= 8;                              //bitovy posun o 8 bitu vlevo- potreba pro 16-bit
  vbus2 += Wire.read();                     //pricteni dat (dolni bajt)


  return vbus2;                             //navraceni vysledku
}


//-------------------------------------------FUNKCE4 pro vypis produ na CH2------------------------------------------------------------

uint16_t getVSENSE2() {                       // nacteni hodnoty pomoci knihovny Wire.h

  uint16_t vsense2;                           //interní promenna pro mereni 16bit promenna
  Wire.beginTransmission(PAC1934_ADDRESS);    //zahájeni komunikace s PAC na pozadované adrese
  Wire.write(0x14);                           // adresa pro vypis proudu z CH1 (Vsense1_AVG)
  Wire.endTransmission();                     //ukonceni komunikace - automaticky posle read bit
  Wire.requestFrom(PAC1934_ADDRESS, 2);       //pozadavek na dva bajty od zarizeni s adresou PAC1934_ADDRESS 0x0C


  vsense2 = Wire.read();                      //precteni dat (horni bajt)
  vsense2 <<= 8;                              //bitovy posun o 8 bitu vlevo- potreba pro 16-bit
  vsense2 += Wire.read();                     //přičtení dat (dolni bajt)


  return vsense2;                             //navraceni vysledku
}
