/*

*/

#define thermistorPin 4
#define pCONTROLE 5

const int    SAMPLE_NUMBER      = 10;
const double BALANCE_RESISTOR   = 9880.0;
const double MAX_ADC            = 4095.0;
const double BETA               = 3974.0;
const double ROOM_TEMP          = 298.15;
const double RESISTOR_ROOM_TEMP = 10000.0;
double       currentTemperature = 0;

double setP = 1.0, setI = 0.0, setD = 0.0;
int controlePWM = 50;

class PID{
public:

	double error;       double sample;    double lastSample;
	double kP, kI, kD;  double P, I, D;   double pid;

	double setPoint;    long lastProcess;

	PID(double _kP, double _kI, double _kD){kP = _kP; kI = _kI; kD = _kD;}
	void addNewSample(double _sample){sample = _sample;}
	void setSetPoint(double _setPoint){setPoint = _setPoint;}

	double process(){
		// Implementação P ID
		error = setPoint - sample;
		float deltaTime = (millis() - lastProcess) / 1000.0;
		lastProcess = millis();
		P = error * kP; //Controle P
		I = I + (error * kI) * deltaTime; //Controle I
		D = (lastSample - sample) * kD / deltaTime; //Controle D
		lastSample = sample;
		pid = P + I + D; //Soma dos controles P, I e D
		return pid;
	}
};

PID PIDcontrol(setP, setI, setD);

void setup() 
{
 Serial.begin(9600);
 Serial.println("Start!");
 pinMode(2, OUTPUT);
 pinMode(pCONTROLE, OUTPUT);
 pinMode(thermistorPin, INPUT);

 PIDcontrol.setSetPoint(30);
 
}

void loop() 
{
  digitalWrite(2, ( millis() % 500) < 50 );

  if ( ( millis() % 500 ) <= 1 ) {
    currentTemperature = pSENSOR();
    Serial.print(currentTemperature); Serial.print(" °C ");
    Serial.print(controlePWM); Serial.println(" PWM");
  }

	PIDcontrol.addNewSample(currentTemperature);
	controlePWM = (PIDcontrol.process() + 50);
	analogWrite(pCONTROLE, controlePWM); 
}

double pSENSOR() 
{

  double rThermistor = 0;            // Holds thermistor resistance value
  double tKelvin     = 0;            // Holds calculated temperature
  double tCelsius    = 0;            // Hold temperature in celsius
  double adcAverage  = 0;            // Holds the average voltage measurement
  int    adcSamples[SAMPLE_NUMBER];  // Array to hold each voltage measurement
  
  for (int i = 0; i < SAMPLE_NUMBER; i++  ) { adcSamples[i] = analogRead(thermistorPin); delay(10); }
  for (int i = 0; i < SAMPLE_NUMBER; i++  ) { adcAverage  = adcSamples[i]; }

  adcAverage /= SAMPLE_NUMBER;
  rThermistor = BALANCE_RESISTOR * ( (MAX_ADC / adcAverage) - 1);
  tKelvin = (BETA * ROOM_TEMP) / (BETA + (ROOM_TEMP * log(rThermistor / RESISTOR_ROOM_TEMP)));
  tCelsius = tKelvin - 273.15;  // convert kelvin to celsius
  tCelsius = tCelsius * (-1);   //Por algum motivo desconhecido é necessário tornar a temp positiva

  return tCelsius;    // Return the temperature in Celsius
}