- #1
troubled_grad
- 1
- 1
Hello,
I have an arduino code for driving a peltier pile to a given set point (TEMP_SP). I am trying to input the set temperature from Matlab GUI (with different protocols, user will enter n temperatures and the time intervals, arduino will implement the PID controller and output the temperature to MATLAB every 1 seconds via serial communication.
I have a serious problem and I would appreciate any help.
My PID is working with arduino, I can send and receive data to/from matlab/arduino. I am using SerialEvent() to read the messages from MATLAB and print the responses accordingly.
The problem is that, (maybe because there is a huge delay between MATLAB and arduino), when I set a temperature from matlab, my peltier temperature jumps up and down crazily. E.g. I set 20 degrees celcius, my peltier jumps up to 35-40 degrees, then toggles around lower temperatures that are not super related to my set temperature. This does not happen when I run the PID on arduino and set the temperature directly from there.
PS: I am reading the temperature using a thermistor. I am changing the voltage using an external DAC and a shifter circuit because I need to both heat up and cool down ( the peltier terminals should change signs)
Algorithm:
-Set temperature (TEMP_SP)
-Read thermistor voltage-->convert to resistance-->convert to temperature (this is current state, T_C_CS)
-Find DAC output from PID
-SerialEvent() runs after every loop() to check if there's message coming from MATLAB and sets its flag accordingly.
-In each loop, check stringComplete flag and change the set temperature or print the current temperature.
This is my Arduino code:
Here is my MATLAB code:
I have an arduino code for driving a peltier pile to a given set point (TEMP_SP). I am trying to input the set temperature from Matlab GUI (with different protocols, user will enter n temperatures and the time intervals, arduino will implement the PID controller and output the temperature to MATLAB every 1 seconds via serial communication.
I have a serious problem and I would appreciate any help.
My PID is working with arduino, I can send and receive data to/from matlab/arduino. I am using SerialEvent() to read the messages from MATLAB and print the responses accordingly.
The problem is that, (maybe because there is a huge delay between MATLAB and arduino), when I set a temperature from matlab, my peltier temperature jumps up and down crazily. E.g. I set 20 degrees celcius, my peltier jumps up to 35-40 degrees, then toggles around lower temperatures that are not super related to my set temperature. This does not happen when I run the PID on arduino and set the temperature directly from there.
PS: I am reading the temperature using a thermistor. I am changing the voltage using an external DAC and a shifter circuit because I need to both heat up and cool down ( the peltier terminals should change signs)
Algorithm:
-Set temperature (TEMP_SP)
-Read thermistor voltage-->convert to resistance-->convert to temperature (this is current state, T_C_CS)
-Find DAC output from PID
-SerialEvent() runs after every loop() to check if there's message coming from MATLAB and sets its flag accordingly.
-In each loop, check stringComplete flag and change the set temperature or print the current temperature.
This is my Arduino code:
C:
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <PID_v1.h>
Adafruit_MCP4725 dac; // constructoruint32_t dac_value;// Thermistor variables
float Rref=10000; //ohms, resistance of thermistor at 25C
float B25=3977;
float TOLB=0.75;
float A=-14.6337;
float B=4791.842;
float C=-115334;
float D=-3.730535E+06;
float A1t=3.354016E-03;
float B1t=2.569850E-04;
float C1t=2.620131E-06;
float D1t=6.383091E-08;
float Vdd=5; //volts
float R_divider=10000;//ohms
//CURRENT STATE
float Vt_CS_val; //current thermistor voltage value
float Vt_CS; //current thermistor voltage
float Rt_CS;//current thermistor resistance
float T_K_CS; //current temperature in K
float T_C_CS; //current temperature in C
float input_CS_val;// current input from the DAC
float input_CS;// current input from the DAC
//SET POINT
float TEMP_SP=20; //desired temperature (celcius)
float TEMP_SP_K; //desired temperature (Kelvin)
float R_SP; //desired resistance for the TEMP_SP_K
float Vt_SP; //desired thermistor voltage//DAC output
float DAC_val;
float DAC_OUT;//DAC output voltage
//double PID_OUT;//Custom PID
float der = 0;
float err;
float err_p;
float integral;
//PID set
float Kp=1.0, Ki=0.003, Kd=10.0;
float output;
int state=1;
float read_voltage;
float temp_rec;
float temp_new=20;String inputString = ""; // a string to hold incoming data
String READ = "R";
boolean stringComplete = false; // whether the string is completevoid setup() {
Serial.begin(9600);
dac.begin(0x62); // The I2C Address: Run the I2C Scanner if you're not sure
DAC_val=2080;//2.54V
dac.setVoltage(DAC_val, false); //819:1V, 3276:4V
// reserve 200 bytes for the inputString:
inputString.reserve(200);
Serial.println('a');
char a = 'b';
while(a != 'a')
{
a = Serial.read();
}
}
void loop() {
Vt_CS_val = analogRead(A1);
Vt_CS=5.0*Vt_CS_val/1024.0; //current voltage on thermistor, current temp
Rt_CS=R_divider*Vt_CS/(Vdd-Vt_CS);
//Given R, find T
T_K_CS=pow((A1t+B1t*log(Rt_CS/Rref)+C1t*pow((log(Rt_CS/Rref)),2)+D1t*pow((log(Rt_CS/Rref)),3)),-1); //KELVIN
T_C_CS=T_K_CS-273.15; //current Celcius
///////PROCESS SET POINT
TEMP_SP_K=TEMP_SP+273.15; //Celcius to K
//Given T_SP, find R_SP
R_SP=Rref*exp(A+B/TEMP_SP_K+C/pow(TEMP_SP_K,2)+D/pow(TEMP_SP_K,3)); // R_SP
// find Vt_SP
Vt_SP=R_SP*Vdd/(R_SP+R_divider); //Set voltage for thermistor divider. Aim: Vt_SP=Vt_CS
err = Vt_SP - Vt_CS;
integral = integral + err;
output = Kp * err + (Ki * integral) + (Kd * der );
err_p = err;
DAC_OUT = -output + 2.5;
if (DAC_OUT< 1)
DAC_OUT = 1;
if (DAC_OUT > 4)
DAC_OUT = 4;
DAC_val=4096*DAC_OUT/5;
dac.setVoltage((int)DAC_val, false);
// print the answer when message arrives:
if (stringComplete) {
inputString.trim(); //remove newline characters or blanks
if( inputString==READ){
Serial.println(T_C_CS); //print the current temp
}
else //number came, take as temperature
{
temp_new=inputString.toFloat(); //set new temperature
TEMP_SP=temp_new;
Serial.println(TEMP_SP); //send the set temp back
}
inputString = "";
stringComplete = false;
}
}void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
Matlab:
%open serial object (working)
delete(instrfind({'Port'},{'COM11'}));%clear the port
%global ard;
if(~exist('serialFlag','var'))
[ard,serialFlag] = setupSerial('COM11');
end
disp('Connection successful');
isvalid=isvalid(ard);
%send set temperature (I am getting 28.00 back as TEMP_SP, so working)
x=28;
fprintf(ard,num2str(x));
msg=fscanf(ard);
disp(msg);
%read the temperature back every 3 seconds
while(1)
fprintf(ard,'R');
msg=fscanf(ard);
disp(msg);
pause(3);
end
Last edited by a moderator: