#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include "GyverPID.h"

#define DHTPIN 5
#define RELAYPIN A2
#define FANPIN A3
#define SERVOPIN A1
#define ANGLE 90

float temperature = 38.7;
float humidity = 51.5;

bool workMode = 0;
DHT dht(DHTPIN, DHT22);
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo sr;

float kp = 5;
float ki = 0.3;
float kd = 2;
float dt = 100;
GyverPID pidTemp(kp, ki, kd, dt);
GyverPID pidHum(kp, ki, kd, dt);

void check_temp(float temp)
{
  static uint32_t tmr = 0;
  if(millis() - tmr > dt)
  {
   tmr = millis();
   pidTemp.input = temp;
   pidTemp.getResult();
   analogWrite(RELAYPIN, pidTemp.output);
  }
}
void check_hum(float hum)
{
  static uint32_t tmr = 0;
  if(millis() - tmr > dt)
  {
   tmr = millis();
   pidHum.input = hum;
   pidHum.getResult();
   analogWrite(FANPIN, pidHum.output);
  }
}
void setMode()
{
  workMode = !workMode;
  if(workMode==0)
  {
    temperature = 38.7;
    humidity = 51.5;
  }
  else 
  {
    temperature = 37.5;
    humidity = 67;
  }
  pidTemp.setpoint = temperature;
  pidHum.setpoint = humidity;
}
void setup() {
  Serial.begin(9600);
  dht.begin();
  sr.attach(SERVOPIN);
  lcd.begin(16,2);
  lcd.init();
  lcd.backlight();
  lcd.noCursor();

  pidTemp.setpoint = temperature;
  pidHum.setpoint = humidity;

  pinMode(RELAYPIN, OUTPUT);
  pinMode(FANPIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2), setMode, LOW);
   sr.write(0);
}

void loop() {
float h, t;
static uint64_t tmrServo;
static bool direction = true;
if(millis() - tmrServo > 1000*5 )
{
  tmrServo = millis();
  if(direction)
  {
   sr.write(90);
   delay(50);
  }
  else 
  {
  sr.write(0);
  delay(50);
  }
  direction = !direction;
  delay(10);
}


static uint64_t ta;
if(millis() - ta > 100 )
{ ta = millis();
   h = dht.readHumidity();
   t = dht.readTemperature();
  
  if(isnan(t)||isnan(h))
  {
    lcd.print("ERROR");
  } 
  else
  {
    lcd.setCursor(0,0);
    lcd.print("Temp ");
    lcd.setCursor(5,0);
    lcd.print(t);
    lcd.setCursor(11,0);
    lcd.print("Mod");
    lcd.setCursor(15,0);
    lcd.print(workMode);
    lcd.setCursor(0,1);
    lcd.print("Hum ");
    lcd.setCursor(4,1);
    lcd.print(h);
  }
}
  
 check_temp(t);
 check_hum(h);
 Serial.print(pidTemp.input);Serial.print('\t');
 Serial.print(pidTemp.output);Serial.print('\t');
 Serial.print(pidTemp.integral);Serial.print('\t');
 Serial.println(pidTemp.setpoint);

}