#include <science.h>
Temperature t( PIN2 );
Stats stats;
enum
{
SAMPLE_TIME_IN_MS = 300,
MILLISECONDS_PER_SECOND = 1000,
OUTMIN = 0,
OUTMAX = 255
};
class PID
{
double kp; // Proportional coefficient
double ki; // Integral coefficient
double kd; // Derivative coefficient
double previous_input;
unsigned long lastTime;
int output;
public:
double Integral;
double Target;
PID( double Kp, double Ki, double Kd, double target )
{
Integral = 0;
previous_input = target;
output = 0;
Target = target;
double seconds_per_sample = double( SAMPLE_TIME_IN_MS )
/ MILLISECONDS_PER_SECOND;
kp = Kp;
ki = Ki * seconds_per_sample;
kd = Kd / seconds_per_sample;
lastTime = millis() - SAMPLE_TIME_IN_MS;
}
int
out( double input )
{
unsigned long now = millis();
unsigned long timeChange = now - lastTime;
if( timeChange >= SAMPLE_TIME_IN_MS )
{
double error = Target - input;
Integral += ki * error;
double Proportional = kp * error;
double Derivative = kd * (previous_input - input);
previous_input = input;
if( Integral > OUTMAX )
Integral = OUTMAX;
else if( Integral < OUTMIN )
Integral = OUTMIN;
output = int( Proportional + Integral + Derivative );
if( output > OUTMAX )
output = OUTMAX;
else if( output < OUTMIN )
output = OUTMIN;
lastTime = now;
}
return output;
}
};
//
// Oscillation period is 12.67 minutes
//
// PID pid( 100, 1, 35, 98.6 );
// PID pid( 100, 1, 35, 96.8 );
// PID pid( 300, 1, 10, 98.6 ); // 160 minutes to settle
// PID pid( 400, 1, 20, 98.6 ); // 135 minutes to settle
// PID pid( 500, .5, 30, 98.6 ); // Oscillates after settling in 70 minutes
// PID pid( 350, .8, 20, 98.6 ); // Oscillates
PID pid( 340, .6, 20, 98.6 );
void
setup()
{
Serial.begin( 115200 );
pinMode( PIN3, OUTPUT );
digitalWrite( PIN3, HIGH );
}
void
loop()
{
int num = t.how_many_sensors();
if( num <= 0 )
{
Serial.println( "No sensors" );
delay( 2000 );
return;
}
t.read( 0 );
double f = t.fahrenheit( 0 );
stats.sample( f );
Serial.print( f, 4 );
Serial.print( ", " );
Serial.print( stats.get_mean(), 6 );
Serial.print( ", " );
Serial.print( stats.get_sd(), 6 );
int out = pid.out( f );
analogWrite( PIN3, out );
Serial.print( ", " );
Serial.print( out );
Serial.print( ", " );
Serial.print( pid.Integral );
Serial.print( ", " );
Serial.print( pid.Target );
Serial.println();
delay( 300 );
}