In my recent project, I'm working with Peltier module. And I tried out to adjust manually to set the value of Kp, Ki, and Kd. But it not so convenient to control the desired temperature. So for the solution of this, I found one Arduino library named Arduino-PID-AutoTune. And after using this library I got my desired output but there is one problem occurred. My output Peltier module not driven. I'm using DC Motor driver to drive Peltier module.
Autotune Library:
My code is below:
#include <PID_v1.h>
#include "Adafruit_MAX31855.h"
#include <PID_AutoTune_v0.h>
int thermoDO = 3;
int thermoCS = 4;
int thermoCLK = 5;
Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);
#define PIN_OUTPUT 6
//Define Variables we'll be connecting to
//double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
//double kp = 180, ki = 30, kd =1;
byte ATuneModeRemember=2;
double input, output, setpoint = 10;
double kp = 2,ki = 0.5,kd = 2;
double kpmodel = 1.5, taup = 100, theta[50];
double outputStart = 5;
double aTuneStep = 50, aTuneNoise = 1, aTuneStartValue = 100;
unsigned int aTuneLookBack = 20;
boolean tuning = false;
unsigned long modelTime, serialTime;
PID myPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
PID_ATune aTune(&input, &output);
int IN1 = 8;
int IN2 = 9;
boolean useSimulation = true;
void setup()
{
//initialize the variables we're linked to
input = thermocouple.readCelsius();
if(useSimulation)
{
for(byte i = 0; i < 50; i++)
{
theta[i] = outputStart;
}
modelTime = 0;
}
//turn the PID on
myPID.SetMode(AUTOMATIC);
if(tuning)
{
tuning = false;
changeAutoTune();
tuning = true;
}
serialTime = 0;
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
}
void loop()
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
unsigned long now = millis();
if(!useSimulation)
{ //pull the input in from the real world
input = thermocouple.readCelsius();
}
if(tuning)
{
byte val = (aTune.Runtime());
if (val!=0)
{
tuning = false;
}
if(!tuning)
{ //we're done, set the tuning parameters
kp = aTune.GetKp();
ki = aTune.GetKi();
kd = aTune.GetKd();
myPID.SetTunings(kp,ki,kd);
AutoTuneHelper(false);
}
}
else myPID.Compute();
if(useSimulation)
{
theta[30] = output;
if(now >= modelTime)
{
modelTime += 100;
DoModel();
}
}
else
{
analogWrite(PIN_OUTPUT, output);
}
//send-receive with processing if it's time
if(millis() > serialTime)
{
SerialReceive();
SerialSend();
serialTime += 500;
}
}
void changeAutoTune()
{
if(!tuning)
{
//Set the output to the desired starting frequency.
output = aTuneStartValue;
aTune.SetNoiseBand(aTuneNoise);
aTune.SetOutputStep(aTuneStep);
aTune.SetLookbackSec((int)aTuneLookBack);
AutoTuneHelper(true);
tuning = true;
}
else
{ //cancel autotune
aTune.Cancel();
tuning = false;
AutoTuneHelper(false);
}
}
void AutoTuneHelper(boolean start)
{
if(start)
ATuneModeRemember = myPID.GetMode();
else
myPID.SetMode(ATuneModeRemember);
}
void SerialSend()
{
Serial.print("setpoint: ");Serial.print(setpoint); Serial.print(" ");
Serial.print("input: ");Serial.print(input); Serial.print(" ");
Serial.print("output: ");Serial.print(output); Serial.print(" ");
if(tuning){
Serial.println("tuning mode");
} else {
Serial.print("kp: ");Serial.print(myPID.GetKp());Serial.print(" ");
Serial.print("ki: ");Serial.print(myPID.GetKi());Serial.print(" ");
Serial.print("kd: ");Serial.print(myPID.GetKd());Serial.println();
}
}
void SerialReceive()
{
if(Serial.available())
{
char b = Serial.read();
Serial.flush();
if((b=='1' && !tuning) || (b!='1' && tuning))changeAutoTune();
}
}
void DoModel()
{
//cycle the dead time
for(byte i=0;i<49;i++)
{
theta[i] = theta[i+1];
}
//compute the input
input = (kpmodel / taup) *(theta[0]-outputStart) + input*(1-1/taup) + ((float)random(-10,10))/100;
}
My output is below:
setpoint: 10.00 input: 10.04 output: 12.20 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.13 output: 14.76 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.09 output: 14.70 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.30 output: 13.52 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.41 output: 12.30 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.23 output: 13.99 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.22 output: 11.64 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.31 output: 11.60 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.37 output: 11.70 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.10 output: 13.24 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.02 output: 13.97 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.05 output: 10.68 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.90 output: 13.46 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.79 output: 13.84 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.82 output: 11.34 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.75 output: 12.23 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.02 output: 10.23 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.07 output: 13.03 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.20 output: 11.90 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.14 output: 10.50 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.17 output: 12.47 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.37 output: 10.33 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.41 output: 10.85 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.53 output: 8.74 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.59 output: 10.84 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.62 output: 11.36 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.59 output: 10.42 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.62 output: 9.18 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.57 output: 11.08 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.64 output: 9.92 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.40 output: 9.69 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.35 output: 8.91 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.31 output: 12.12 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.32 output: 12.44 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.03 output: 11.91 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.72 output: 11.55 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.75 output: 11.12 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.54 output: 13.52 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.59 output: 10.28 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.40 output: 12.16 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.29 output: 13.12 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.58 output: 12.31 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.55 output: 11.78 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.69 output: 10.03 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.83 output: 10.69 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.87 output: 13.55 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.03 output: 11.28 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.81 output: 13.29 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.07 output: 9.85 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.30 output: 11.59 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.29 output: 11.26 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.38 output: 9.52 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.16 output: 11.14 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.06 output: 10.09 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 10.06 output: 10.43 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.68 output: 13.66 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.84 output: 12.71 kp: 2.00 ki: 0.50 kd: 2.00
setpoint: 10.00 input: 9.84 output: 12.61 kp: 2.00 ki: 0.50 kd: 2.00
I don't understand why my Peltier not driven even if all things seem right. Suggest me.
EDIT:1
One thing I noticed during testing that when I put the manual value of PID parameters then the temperature(means Input) will set according to Setpoint when I start my power supply. But when I use PID AutoTune library then temperature(means Input) set according to Setpoint even if there is no power supply there. I don't understand without power supply how can it possible to set the temperature(means Input) according to Setpoint?