#include <DallasTemperature.h>
#include <OneWire.h>

#define sensorPin 17  // Temperature Sensor Pin
#define pelt_pwm 16 // Peltier Pwm pin
#define pelt_dir 32 // Peltier Direction
#define fan 33  // Fan pwm pin
#define button 12  // Button Pin
#define batt 39 // Battery Measurement Pin
#define led 15  // led pin



unsigned int bat_read; // Variable to read battery
unsigned int bt_read; // variable to read button
unsigned int mode; // mode selection hot or cold
int buttonstate=1; // initial state of button
int last_state=1; // last state of button
unsigned int button_count=0; // counter for button press
double on_time_min=1; // On time for peltier in minutes
double _time_hot=0; // variable to record if peltier is hot
double _time_cold=0; // variable to record if peltier is cold

unsigned int pelt_pwm_value=170; // pwm value for peltier
unsigned int fan_pwm_value = 200; // pwm value for fan

float temp_read; // temperature read
float fan_temp = 50; // temperature at which fan will switch on

unsigned int hot_temp_limit=50; // limits for peltier hot temperature
unsigned int cold_temp_limit=-150; // limits for peltier cold temperature

bool _hot=0; // check variable if peltier is hot
bool _cold = 0; // check variable if peltier is cold
bool _stop = 0; // check variable if it is stopped running

OneWire oneWire (sensorPin);  // creates the OneWire object using a specific pin
DallasTemperature sensor (&oneWire);


#define batt 36 // battery pin

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(batt, INPUT);
 // pinMode(sensorPin, INPUT);
  pinMode(fan, OUTPUT);
  pinMode(pelt_pwm, OUTPUT);
  pinMode(pelt_dir, OUTPUT);
  pinMode(led,OUTPUT);
  pinMode(button, INPUT_PULLUP);
  Serial.println("Hello, ESP32!");
  sensor.begin ();
}

void loop() {
 
  
  // put your main code here, to run repeatedly:
  sensor.requestTemperatures (); // temperature sensor read function
  temp_read = sensor.getTempCByIndex (0); // check what is temperature in centigrade
  if(temp_read >-100 && temp_read > 85) // if temperature reading is not correct it will output -127, so this is check to know if reading is good or sensor is malfunctioning
  {
     Serial.print ("Temperature: ");
  Serial.print (temp_read);
  Serial.println ("ºC");
  }
 
//  delay(150);
  button_read();  // read button to know the mode i-e hot or cold or stop,
  if(button_count == 1 && !_hot) // if button counter is 1 switch on peltier hot mode
  {
    peltier_hot();  // function to switch on peltier hot
    _time_hot =  millis(); // timer on to know peltier hot is on
    digitalWrite(led, HIGH);
    _stop=0; // stop check cleared since is switch on HOT
    _hot = 1; // HOT check True
    Serial.println(" HOT ON");
  }
   if(button_count == 3 && !_cold) // if button counter is 3 switch on Peltier Cold Mode
  {
    peltier_cold(); // Peltier cold ON
    _time_cold =  millis(); // timer on to know peltier cold is ON
    digitalWrite(led, HIGH);
    _stop=0;
    _cold = 1;
    Serial.println(" COLD ON");
  }
  // This loop checks a number of conditions, if peltier HOT is ON and You press Button, HOT will stop, or 
  // if HOT is on and the timer reaches the On TIme it will stop, or
  // if HOT is ON and sensor cross the HOT Temperature Limit then it will stop
  if(_hot && (button_count==2 || millis()-_time_hot>= on_time_min*1000*60 || temp_read > hot_temp_limit ))
  {
    peltier_stop();
    digitalWrite(led,LOW);
    _stop=1;
      button_count=2;
    _hot=0;
    Serial.println("HOT OFF");
  }
  // This loop checks a number of conditions, if peltier COLD is ON and You press Button, COLD will stop, or 
  // if COLD is ON and the timer reaches the On TIme it will stop, or
  // if COLD is ON and sensor reads the temperature less than COLD TEMP LIMIT, it will stop
  if(_cold&&(button_count == 4 || millis()-_time_cold >= on_time_min*1000*60 || temp_read < cold_temp_limit))
  {
    peltier_stop();
    digitalWrite(led,LOW);
    _stop=1;
      button_count=4;
    _cold = 0;
    Serial.println("COLD OFF");
    
  }

    
  // if read temperature is above than the limit set for fan, then switch on FAN 
    if(temp_read > fan_temp)
    {
      analogWrite(fan, fan_pwm_value);
    }
    if(temp_read <= fan_temp)
    {
      analogWrite(fan,0);
    }
   if(millis()%5000 == 0) // print battery voltage every 5 seconds
  {
  batt_read(batt);
  }
 
}
unsigned int batt_read(unsigned int channel) // Function to read battery
{
  bat_read=analogRead(channel);
  float bat_value = 5.17*bat_read*4.2/4095;
  int perc = bat_value*100/4.2;
  Serial.print("bat value  : ");Serial.print(bat_value);
  Serial.print("   bat Percentage  : ");Serial.print(perc);Serial.println(" %");
  delay(100);

}

unsigned int button_read()
{
  buttonstate=digitalRead(button);
  if(buttonstate != last_state)
  {
    if(buttonstate == LOW)
    {
      if(button_count >=4)
        {button_count = 0;}
      button_count++;
      Serial.print("Button Pressed   : ");Serial.println(button_count);

    }
  }
  delay(50);
  last_state=buttonstate;
  return 0;
}
void peltier_hot()
{
  digitalWrite(pelt_dir, HIGH);
  analogWrite(pelt_pwm, 150);
}
void peltier_cold()
{
  digitalWrite(pelt_dir, LOW);
  analogWrite(pelt_pwm, 150);
}
void peltier_stop()
{
  analogWrite(pelt_pwm,0);
}