Hi guys,
I am very new to programming and arduino. I am using an Arduino Mega2560. I got the task to optimize a programm for a heater. I managed to find the right values for the PID parameters after a lot of struggle. But still I have some problems with the programm. Depending on the setpoint and the start temperatur I always have to adjust the Kp, Ki, Kd parameters. There is a big difference if I want to increase the temperature from 50-80C°,150-180C° or from 30-200C°.
So my question is: Is it normal, that I always have to adjust the parameters, or is there a solution, that I can use always the same parameters no matter what my heating rate is.
I would be really greatfull if you could help me to solve my problem.
By the way, this is my code:
#include <PID_v1.h>
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <Adafruit_ADS1015.h>
#include <math.h>
Adafruit_MCP4725 DAC_strom;
Adafruit_MCP4725 DAC_spannung;
Adafruit_ADS1115 ADC_PT100(0x48);
double Setpoint = 0, Input, Output, Current;
double Kp = 5;
double Ki = 0.008;
double Kd = 15;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, P_ON_E, DIRECT); //PID Objekt erzeugen, direct mode, proportional on error
double temp = 0;
long messzeit = 100300000;
void setup() {
Serial.begin(9600);
Serial.println("ClearRange,A,1,D,50000");
Serial.println("LABEL,Zeit,Ist_Temperatur,Soll_Temperatur,Kp,Ki,Kd");
Serial.println("CELL,GET,FROMSHEET,Simple Data,G,5"); Setpoint = Serial.readStringUntil(10).toFloat();
Serial.println("CELL,GET,FROMSHEET,Simple Data,G,6"); Kp = Serial.readStringUntil(10).toFloat();
Serial.println("CELL,GET,FROMSHEET,Simple Data,G,7"); Ki = Serial.readStringUntil(10).toFloat();
Serial.println("CELL,GET,FROMSHEET,Simple Data,G,8"); Kd = Serial.readStringUntil(10).toFloat();
ADC_PT100.begin();
DAC_strom.begin(0x60); //0x60 bei Adr auf GND
DAC_spannung.begin(0x61); //0x61 bei Adr auf Vdd
DAC_spannung.setVoltage(2730,false); //Setzen der Spannung des Netzteils auf 24V (äquivalent 2730Bit / 3.333V)
DAC_strom.setVoltage(0,false);
//PID setzen
Input = Temp_auslesen();
myPID.SetOutputLimits(0, 500); //PID Limits setzen, SetOutputLimits(min,max)
//PID SetTunings(Kp, Ki, Kd, POn), wenn die tuning paramter sich verändern.. evtl für verschiedene Temperturbereiche, schnellere Anfahrtszeiten
//PID SetSampleTime(int>0 in ms), wie oft der alkorithmus ausgeführt wird. Default ist 200ms.
//PID SetCOntrollerDirection(Direction:Direct/Reverse), DIRECT ist default
myPID.SetMode(AUTOMATIC); //PID SetMode(): AUTOMATIC - PID ein, MANUAL - PID aus
delay(1000);
}
void loop() {
if (millis() <= messzeit+1)
{
Input = Temp_auslesen();
myPID.Compute();
// if (Output <= 0)
// {
// Output = 0;
// }
// if (Output >= 3250)
// { //evtl möglich wegzulassen, redundant
// Output = 3250;
// }
Current=sqrt(1.3414*Output); // 1.3414 Berechneter Strom aus Leistung durch Kalibrationsfunktion 0.7455x^2=P
DAC_strom.setVoltage((115.22*Current+100), false); //Ausgabewert nach folgender Formel berechnet: y=115.22x+100
Temp_ausgabe(Temp_auslesen(), 1000); //Temperaturausgabe über Funktion Temp_ausgabe mit float von Temp_auslesen alle 500ms
// Pause 100 bis 1000 ms
}
else{
DAC_strom.setVoltage(0,false);
}
}
//----------------------Unterfunktionen-------------------------------
double Temp_auslesen() { //Tempbereich 0-250°C
int16_t Messwandler_spg_bit = 0;
double Temperatur = 0 ;
Messwandler_spg_bit = ADC_PT100.readADC_SingleEnded(1);
Temperatur = Messwandler_spg_bit * (0.000187 * 50); //0.187mV: bit->0-5V, 50: 0-5V->0-250°C
return Temperatur;
}
void Temp_ausgabe(double temperatur, int Ausgabeintervall) {
static long letzteAusgabe;
if (millis() - letzteAusgabe >= Ausgabeintervall) {
Serial.print("DATA,"); Serial.print((millis() / 1000)-2); Serial.print(","); Serial.print(temperatur); Serial.print(","); Serial.println(Setpoint);
letzteAusgabe = millis();
//Setpoint=Setpoint+1;
}
}