/* Start of program:
The surface or sky temperature using the IR MLX90614 sensor (I2C).
The thermistor for air temperature measurement (analog).
The BME280 sensor will be used for pressure, temperature, and relative humidity. I2C. (NEEDS TO BE ADDED)
The AHT20 temperature and humidity sensor will be used. I2C. (NEEDS TO BE ADDED)
The VEML7700 for solar radiation.  I2C.  (NEEDS TO BE ADDED)
INSTALL THE ADAFRUIT LIBRARIES FOR THE I2C sensors using the library manager under Sketch.

The chronodot is used for time and date.  Time has to be set, and check the batteries to see if they are good for backup. I2C.
The microSD card for saving data. SPI interface.
 */

#include <Wire.h> // For the Chronodot and IR sensor.
#include <Adafruit_MLX90614.h> // for the IR sensor. 
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
#include <SPI.h>  // For the microSD.
#include <SD.h>   // For the microSD.
#include "Adafruit_VEML7700.h"

Adafruit_VEML7700 veml = Adafruit_VEML7700();

File mySensorData           ;  // Filename for the microSD writing of data.
// char fheader[]= "header.csv"; //write the header to SD card
// char fsensor[]="sensor.csv" ;  //write the sensor data  to SD card
// String topOfFile;
 
// Global variable definitions. 
// Thermistor temperature sensor set up variables.
int sensorPin = A0;    // Analog input pin for the thermistor voltage.
float sensorValue = 0.0;   // Variable to store the measurement from the sensor.
int i ;  // variable in for loop.
float TC; // Calculated temperature value in Celcius.
int delTime = 0  ; // Delay time in milliseconds between measurements, may adjust to optimize data.
int iMeas = 3000  ; // Number of measurements to do for the Thermistor measurement.
float xMeas = (float)iMeas ; // Number of measurements as a floating value for doing the average.
float Rfixed=10.0 ; // Resistance in kOhms of the fixed resistor used in the voltage divider.

// Chronodot variables for keeping time.
int seconds; //00-59;
int minutes; //00-59;
int hours;//1-12 - 00-23;
int days;     //  1-7 assuming Sunday is day 1.
int date;//01-31
int months;//01-12
int years;//0-99;

// We put out setup code here, to run only once at the start:
void setup() {
/***************** Write header for the top of the file and the serial port ********/        ;
// topOfFile="Date,Time,IRGnd_C,Therm_C,IR_C"         ;
// topOfFile.concat("Pressure_mb,BoardTemp_C")                                              ;
Serial.begin(9600) ;  // Sets the serial port to 9600 bits per second transfer.
Serial.println(F("Date,Time,IRGnd_C,Therm_C,IR_C,S_W/m2"));
        
Wire.begin();         // For the chronodot.
mlx.begin();          // IR sensor set up.



// CS pin used for the microSD card.
pinMode(10, OUTPUT) ;
// Check the microSD card.
SD.begin(10) ; // Initialize
if (!SD.begin(10)) {
}
// Write the variable information to the top of the file.
mySensorData = SD.open("header.csv", FILE_WRITE);//Open SD File, Append if the file is already exist
mySensorData.println("Date,Time,IRGnd_C,Therm_C,IR_C,S_W/m2"); //the file header
mySensorData.close(); 

// VEML Set up. 
  if (!veml.begin()) {
    Serial.println("VEML Sensor not found");
    while (1);
  }
  Serial.println("VEML Sensor found");



}  // End the set up loop here.


// We put our main code here, to run repeatedly:
void loop() {
  // to read lux using automatic method, specify VEML_LUX_AUTO
  float lux = veml.readLux(VEML_LUX_AUTO)*0.0079; // Watts/m2


// First the thermistor temperature sensor measurement.
// *************************************************** // 
TC = 0.0 ; // Initialize the temperature measurement for doing an average measurement.
for (i=0 ; i < iMeas; i++) {
    sensorValue = analogRead(sensorPin)*0.00488759; // Converts to voltage.
    TC += get_T_From_V() ;  // Converts voltage to temperature.
    delay(delTime) ; 
} // loop over i, the thermistor temperature sensor measurements.
TC = TC / xMeas ;
// *************************************************** // 

// Next get the IR sensor data.
float IRbodyTemp   = mlx.readAmbientTempC()  ;
float IRtargetTemp = mlx.readObjectTempC()   ;

// Get time and date from the Chronodot.
get_date();  // 
get_time();  // 

/************ Write the data to the serial port to look at it. *****************/
digitalClockDisplay()          ; /* Writes the time and date from the RTC to the Serial port */
Serial.print(IRtargetTemp,3)   ; Serial.print(F(",")) ;
Serial.print(TC,3)             ; Serial.print(F(",")) ;
Serial.print(IRbodyTemp,3)     ; Serial.print(F(",")) ;
Serial.println(lux,3)          ;

/************************* WRITE DATA TO THE SD CARD NOW **********************************/
mySensorData = SD.open("sensor.csv", FILE_WRITE); /* Open SD File, Append if the file is already exist. */
digitalClockDisplaySD()     ; /* Writes the time and date from the RTC */
mySensorData.print(IRtargetTemp,3)   ; mySensorData.print(",") ;
mySensorData.print(TC,3)             ; mySensorData.print(",") ;
mySensorData.print(IRbodyTemp,3)     ; mySensorData.print(",") ;
mySensorData.println(lux,3)          ;
mySensorData.close(); 

}  // Main loop repeats here.




/* Function to calculate the thermistor temperature from the voltage divider
   measurement of thermistor resistance.
   RT is the thermistor resistance calculated from the voltage divider.
   Rfixed is the fixed value of resistance. 
   5.0 is the voltage of the Arduino power supply.
   Thermistor model: Gikfun 100K ohm NTC B4267 ATC Semitic 104GT-2 Thermistor for 3D Printer Reprap EK9018.
*/
    float get_T_From_V() {  // Calculate thermistor temperature from voltage.
    float Ttherm ;  // Thermistor temperature calculated here.
    float RT  ;  // Resistance of the thermistor.
    float logRT ; // Natural log of RT, used in temperature calculation.
    float aa=7.58546e-4   ; // thermistor calculation constant a from table.
    float bb=2.18117e-4   ; // thermistor calculation constant b from table.
    float dd=5.53062e-8  ; // thermistor calculation constant  d from table.

      RT = Rfixed * sensorValue / (5.0-sensorValue) ; // Thermistor resistance in kOhms.     
      logRT = log(RT) + 6.907755279 ; // The second term comes from conversion to Ohms
      Ttherm = aa + bb*logRT + dd*logRT*logRT*logRT ;
      Ttherm = 1.0/Ttherm - 273.15  ; // Thermistor temperature in Celcius.
    return Ttherm ; 
  }



 //  FUNCTIONS NEEDED FOR THE CHRONODOT TIME MEASUREMENT  //
 /*  SD card printing of actual time and date.
*   Write the digital clock output to the SD card writer. */
void digitalClockDisplaySD(){
  SDPrintDigits(months)      ;
  mySensorData.print("/")    ;
  SDPrintDigits(date)        ; 
  mySensorData.print("/")  ;
  SDPrintDigits(years)       ;
  mySensorData.print(",")    ;
  SDPrintDigits(hours)       ;
  mySensorData.print(":")    ;
  SDPrintDigits(minutes)     ;
  mySensorData.print(":")    ;
  SDPrintDigits(seconds)     ;
  mySensorData.print(",")    ;
}
void SDPrintDigits(int digits){
  if(digits < 10) mySensorData.print("0") ; 
  mySensorData.print(digits) ;
}

 void digitalClockDisplay()
{
  SerialPrintDigits(months)  ;
  Serial.print("/")          ;
  SerialPrintDigits(date)    ; 
  Serial.print("/")          ;
  SerialPrintDigits(years)   ;
  Serial.print(",")          ;
  SerialPrintDigits(hours)   ;
  Serial.print(":")          ;
  SerialPrintDigits(minutes) ;
  Serial.print(":")          ;
  SerialPrintDigits(seconds) ;
  Serial.print(",")          ;
} 
void SerialPrintDigits(int digits){
  if(digits < 10)
    Serial.print('0') ; 
  Serial.print(digits) ;
}


/* Procedure to get date from the Chronodot RTC */
void get_date()
{
  Wire.beginTransmission(104); 
  Wire.write(3);//set register to 3 (day)
  Wire.endTransmission();
  Wire.requestFrom(104, 4); //get 5 bytes(day,date,month,year,control);
  days   = bcdToDec(Wire.read()); 
  date  =  bcdToDec(Wire.read());   
  months = bcdToDec(Wire.read()); 
  years  = bcdToDec(Wire.read());  
}

void get_time()
{
  Wire.beginTransmission(104); 
  Wire.write(0);//set register to 0
  Wire.endTransmission();
  Wire.requestFrom(104, 3);//get 3 bytes (seconds,minutes,hours);
  seconds = bcdToDec(Wire.read() & 0x7f);
  minutes = bcdToDec(Wire.read());
  hours   = bcdToDec(Wire.read() & 0x3f);
}
   
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}



      