-
Notifications
You must be signed in to change notification settings - Fork 25
Trying to figure out tuning values for PolyFormer #17
Firstly, thank you for an amazing library, and continuing to improve the PID_V1 library.
I'm hoping to use this library to control a hot-end in a PullStruder called the PolyFormer.
To get the temperature in Celsius from from thermistor I'm using the NTC_Thermistor library and passing the reading to the "Input" variable in the TCLab_Thermal_PWM/sTune_QuickPID example.
However I cannot seem to get the example to set the output to full power, or avoid a large overshoot. I know its a PBCAK, but not sure how to configure this.
The simplified schematic for the control circuit is here. The thermistor being used is a 3950
image
The desired setpoint is 220C using a FQP30N06L or AO3400 MOSFET
The test code I'm trying to use is the following
sTune QuickPID Example
This sketch does on-the-fly tunning and PID Digital Output control
of a thermal heater (TIP31C). Tunning parameters are quickly
determined and applied during the temperature ramp-up to setpoint.
Open the serial plotter to view the graphical results.
*****************************************************************/
#include <sTune.h>
#include <QuickPID.h>
#include <Thermistor.h>
#include <NTC_Thermistor.h>
#define SENSOR1_PIN PA2
#define REFERENCE_RESISTANCE 4700
#define NOMINAL_RESISTANCE 100000
#define NOMINAL_TEMPERATURE 25
#define B_VALUE 3950
#define STM32_ANALOG_RESOLUTION 65535 //16 Bit resolution
Thermistor* thermistor1;
// pins
//const uint8_t inputPin = 0;
const uint8_t relayPin = PA7;
// user settings
uint32_t settleTimeSec = 10;
uint32_t testTimeSec = 500;
const uint16_t samples = 500;
const float inputSpan = 50;
const float outputSpan = 1000;
float outputStart = 0;
float outputStep = 300;
float tempLimit = 280;
// variables
float Input, Output, Setpoint = 220, Kp, Ki, Kd;
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printOFF);
QuickPID myPID(&Input, &Output, &Setpoint);
void setup() {
pinMode(relayPin, OUTPUT);
Serial.begin(9600);
analogReadResolution(16); //Set Resolution of ADC to 16 bit, this will pad any lower resolution values, giving us future flexability
thermistor1 = new NTC_Thermistor(
SENSOR1_PIN,
REFERENCE_RESISTANCE,
NOMINAL_RESISTANCE,
NOMINAL_TEMPERATURE,
B_VALUE,
STM32_ANALOG_RESOLUTION // <- for a thermistor calibration
);
while (!Serial) delay(10);
delay(3000);
tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
tuner.SetEmergencyStop(tempLimit);
}
void loop() {
tuner.softPwm(relayPin, Input, Output, 0, outputSpan, 1);
switch (tuner.Run()) {
case tuner.sample: // active once per sample during test
Input = thermistor1->readCelsius();
tuner.plotter(Input, Output * 0.1, Setpoint, 1, 3);
break;
case tuner.tunings: // active just once when sTune is done
tuner.GetAutoTunings(&Kp, &Ki, &Kd); // sketch variables updated by sTune
myPID.SetOutputLimits(0, outputSpan);
myPID.SetSampleTimeUs(outputSpan * 1000 - 1);
myPID.SetMode(myPID.Control::automatic); // the PID is turned on
myPID.SetProportionalMode(myPID.pMode::pOnMeas);
myPID.SetAntiWindupMode(myPID.iAwMode::iAwClamp);
myPID.SetTunings(Kp, Ki, Kd); // update PID with the new tunings
break;
case tuner.runPid: // active once per sample after tunings
Input = thermistor1->readCelsius();
myPID.Compute();
tuner.plotter(Input, Output, Setpoint, 0.1f, 3);
break;
}
}
Any advice is greatly appreciated
All reactions
Thanks for the test results.
Yes, sTune will complete its test early (at the inflection point if set to tuner.directIP.
sTune doesn't try to reach any setpoint ... it just determines how a system responds to a step change in power. There's no PID control while using sTune.
Note that the outputStep was set to 50. Since the outputSpan is 1000, this is only 5% power and the temp only increased about 4C during the test. I suggest trying outputStep of 500 (50% power). The temp doesn't need to reach 90C, but if the sTune test could bring it up to at least 50C, then the results would be much better.
You could also try using tuner.direct5T which is much slower, but might give better results:
sTun...
Replies: 6 comments 4 replies
Thanks for the detailed information. In your example, the plotter was scaled to 0.1, but this doesn't affect the actual output which would go to 1000 max.
In the following updated example, I've changed the input span to 280 as this was set too low.
The output scale is now 0.2 so it will show 1/5th of the true output. The output at 1000 max will show 200, but it won't re-scale the overall plot and make the Input graph smaller.
Also, since the desired setpoint is quite high, I've changed the outputStep to 500.
/****************************************************************** sTune QuickPID Example This sketch does on-the-fly tunning and PID Digital Output control of a thermal heater (TIP31C). Tunning parameters are quickly determined and applied during the temperature ramp-up to setpoint. Open the serial plotter to view the graphical results. *****************************************************************/ #include <sTune.h> #include <QuickPID.h> #include <Thermistor.h> #include <NTC_Thermistor.h> #define SENSOR1_PIN PA2 #define REFERENCE_RESISTANCE 4700 #define NOMINAL_RESISTANCE 100000 #define NOMINAL_TEMPERATURE 25 #define B_VALUE 3950 #define STM32_ANALOG_RESOLUTION 65535 //16 Bit resolution Thermistor* thermistor1; // pins //const uint8_t inputPin = 0; const uint8_t relayPin = PA7; // user settings uint32_t settleTimeSec = 10; uint32_t testTimeSec = 500; const uint16_t samples = 500; const float inputSpan = 280; const float outputSpan = 1000; float outputStart = 0; float outputStep = 500; float tempLimit = 280; uint8_t debounce = 1; // variables float Input, Output, Setpoint = 220, Kp, Ki, Kd; sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printOFF); QuickPID myPID(&Input, &Output, &Setpoint); void setup() { pinMode(relayPin, OUTPUT); Serial.begin(115200); analogReadResolution(16); //Set Resolution of ADC to 16 bit, this will pad any lower resolution values, giving us future flexability ------------------------------------------------- thermistor1 = new NTC_Thermistor( SENSOR1_PIN, REFERENCE_RESISTANCE, NOMINAL_RESISTANCE, NOMINAL_TEMPERATURE, B_VALUE, STM32_ANALOG_RESOLUTION // <- for a thermistor calibration ); while (!Serial) delay(10); delay(3000); tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples); tuner.SetEmergencyStop(tempLimit); } void loop() { float optimumOutput = tuner.softPwm(relayPin, Input, Output, Setpoint, outputSpan, debounce); switch (tuner.Run()) { case tuner.sample: // active once per sample during test Input = thermistor1->readCelsius(); tuner.plotter(Input, Output, Setpoint, 0.2f, 3); // output scale 0.2, plot every 3rd sample break; case tuner.tunings: // active just once when sTune is done tuner.GetAutoTunings(&Kp, &Ki, &Kd); // sketch variables updated by sTune myPID.SetOutputLimits(0, outputSpan); myPID.SetSampleTimeUs((outputSpan - 1) * 1000); //debounce = 0; // ssr mode Output = outputStep; myPID.SetMode(myPID.Control::automatic); // the PID is turned on myPID.SetProportionalMode(myPID.pMode::pOnMeas); myPID.SetAntiWindupMode(myPID.iAwMode::iAwClamp); myPID.SetTunings(Kp, Ki, Kd); // update PID with the new tunings break; case tuner.runPid: // active once per sample after tunings Input = thermistor1->readCelsius(); myPID.Compute(); tuner.plotter(Input, optimumOutput, Setpoint, 0.2f, 3); // output scale 0.2, plot every 3rd sample break; } }
All reactions
Thank you so much for getting back to me so quickly, I have tried the modified code that you sent, but still seem to be having issues with throttling the power to the heater before it reaches the setpoint. Do you know what I may be doing wrong?
image
All reactions
Looking at the red input, the graph begins with the input temperature still cooling from a previous test. You'll need to make sure the input temperature has settled (stable) prior to starting a new test. (you may need to wait up to 15 minutes between tests).
Also, try increasing outputSpan to 2000 (2 seconds) and testTimeSec to 750.
All reactions
the changes you mentioned resulted in the following output, after making sure the input temperature was stable by not using it for a few hours.
Is there a way to make it reach the setpoint faster my forcing the output to a higher output percentage until its closer to the setpoint?
image
I'm going to see if using Analogue write makes any difference to the output, but it looks like the output starts at the "outputStep" value, and slowly moves from there. Is that the expected outcome?
All reactions
Yes, after sTune completes, the PID output starts at the outputStep value to allow "on-the-fly tuning.
I suppose you could speed things up by boosting the proportional gain by using something like this
myPID.SetTunings(Kp * 2, Ki, Kd);
It might be helpful to see the serial print of the Get_All_Tunings example that uses your settings.
All reactions
I ran the following code
/****************************************************************************
sTune Get All Tunings Example (TCLab - Thermal Heater using digital output)
****************************************************************************/
#include <sTune.h>
#include <Thermistor.h>
#include <NTC_Thermistor.h>
#define SENSOR1_PIN PA2
#define REFERENCE_RESISTANCE 4700
#define NOMINAL_RESISTANCE 100000
#define NOMINAL_TEMPERATURE 25
#define B_VALUE 3950
#define STM32_ANALOG_RESOLUTION 65535 //16 Bit resolution
Thermistor* thermistor1;
// pins
//const uint8_t inputPin = 0;
const uint8_t relayPin = PA7;
// user settings
uint32_t settleTimeSec = 10;
uint32_t testTimeSec = 500;
const uint16_t samples = 500;
const float inputSpan = 150;
const float outputSpan = 1000;
float outputStart = 0;
float outputStep = 50;
float tempLimit = 90;
// variables
float Input, Output;
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printALL);
void setup() {
// analogReference(EXTERNAL); // 3.3V
pinMode(relayPin, OUTPUT);
Serial.begin(9600);
analogReadResolution(16); //Set Resolution of ADC to 16 bit, this will pad any lower resolution values, giving us future flexability
thermistor1 = new NTC_Thermistor(
SENSOR1_PIN,
REFERENCE_RESISTANCE,
NOMINAL_RESISTANCE,
NOMINAL_TEMPERATURE,
B_VALUE,
STM32_ANALOG_RESOLUTION // <- for a thermistor calibration
);
while (!Serial) delay(10);
delay(3000);
Output = 0;
tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
tuner.SetEmergencyStop(tempLimit);
}
void loop() {
tuner.softPwm(relayPin, Input, Output, 0, outputSpan, 1);
switch (tuner.Run()) {
case tuner.sample: // active once per sample during test
Input = thermistor1->readCelsius(); // get degC
break;
case tuner.tunings: // active just once when sTune is done
Output = 0;
tuner.SetTuningMethod(tuner.TuningMethod::DampedOsc_PID);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::NoOvershoot_PID);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::CohenCoon_PID);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::Mixed_PID);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::ZN_PI);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::DampedOsc_PI);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::NoOvershoot_PI);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::CohenCoon_PI);
tuner.printTunings();
tuner.SetTuningMethod(tuner.TuningMethod::Mixed_PI);
tuner.printTunings();
break;
}
}
It resulted in the serial output attached
SerialOutput1.txt
It looks like its maxing out at 1 step of power, and timing out before it reaches the intended setpoint of 90C.
The output is a 40W heater attached to a 3d printer hot end if that's of any help to track down the issue
Thank you for all of your help
All reactions
Thanks for the test results.
Yes, sTune will complete its test early (at the inflection point if set to tuner.directIP.
sTune doesn't try to reach any setpoint ... it just determines how a system responds to a step change in power. There's no PID control while using sTune.
Note that the outputStep was set to 50. Since the outputSpan is 1000, this is only 5% power and the temp only increased about 4C during the test. I suggest trying outputStep of 500 (50% power). The temp doesn't need to reach 90C, but if the sTune test could bring it up to at least 50C, then the results would be much better.
You could also try using tuner.direct5T which is much slower, but might give better results:
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.direct5T, tuner.printALL);
All reactions
Ah, ok, so it just runs at 5% power for the full test. It feels odd that it isn't seeing any oscillation to work out the PID tuning, but some amazing maths must be going on in the background ^_^
I'm going to test the 50% power output now
All reactions
I tried 100% power, and got the following serial output. I think this is for a range of 109C
SerialOutput2.txt
I will try the "tuner.direct5T" setting once the system cools back down for a stable temperature.