Noisy thermocouple input #14
Replies: 46 comments
-
Oh, I'm always interested in test results, the log files are very helpful. I see the resolution is ±0.25 and as I scroll down through the settling mode data, it jumps by 2 resolution-steps max, but follows a very gradual warming trend. Yes, this test algorithm is quite tolerant to noise ... on the TCLab I was able to get results with a step change of 1, but had the board in a covered case so any moving air wouldn't cause a disturbance. In the next release, It shouldn't be a problem to add a reset function, option to print instantaneous values and a looser tolerance for settling so the next step test can begin sooner. |
Beta Was this translation helpful? Give feedback.
-
I'm afraid that the auto-tuned parameters did not work at all. I think it might be a scaling problem. Let's say I use the values from the pid4.log file, Kp 0.0230 K 0.0013 Kd 0.0145 The output went from 100 to 400 (out of a possible 2000). But when I use those values in my program, the PWM out value is around 3 (out of 2000) even if the temperature is 30C away from the goal and dropping. after 100 seconds, PWM out is 5, and the temperature keeps dropping fast (it requires at least 300 to keep an higher than room temperature stable) What am I doing wrong? Is there a scaling parameter I'm missing? |
Beta Was this translation helpful? Give feedback.
-
Not sure what board you're using ... is it 8-bit PWM? Seems that the process gain is too low .. might need to scale the output range and/or min and max output limits. This is sTune's internal calculation for process gain: // calculate the process gain
_Ku = abs((pvMax - pvStart) / (_outputStep - _outputStart)); Also might need to use Arduino's I'll have a new revision ready shortly that addresses the issues (tested on my TCLab setup) ...
|
Beta Was this translation helpful? Give feedback.
-
I've pushed an update to the repository. |
Beta Was this translation helpful? Give feedback.
-
Sorry, I mentioned it elsewhere. My system is made of a 300w heating plate controlled by an SSR. Since you can't really PWM an SSR, I used what most people do: I selected a 2000msec window, and the PWM range is 0 to 2000. When the output is, say, 1000, the SSR is on for 1 second, off for one. With 1500, on for 1.5 seconds, off for 0.5 seconds. I read the temperature every second. It's a very slow system. If the temperature is dropping, say from 100C and I apply 100% power, the temperature keeps dropping another 5-10 seconds (2-3C drop) before it starts stabilizing, and it takes at least another 5-6 seconds to cross 100C again So I need to understand what range your code uses (i.e. what is 0% and 100%), and map it to my values. That is for both the range and the pvStart/pvStop values. And also select the right values for pvStart and pvEnd It would be very easy for users if your code always assumed, say, 0 to 100 range, so that I could map 0 to 0 and 100 to 2000. And, once the parameters are calculated, then I could use the same scaling in the code (basically, in my case, multiply everything by 20). It might be already the case, btw, I'm just a bit lost at this point, I'm afraid |
Beta Was this translation helpful? Give feedback.
-
Ah, sorry ... I was mistakenly thinking of hardware PWM and PID output range and limits. sTune only directly sets an output value as entered. In this case, its just a slowly timed output with an on time of 0-2000ms. sTune works with seconds for time units, so this might explain the low tuning values. After manually recalculating results from pid4.log, I get: Output Control Range is 0.000 to 2.000 seconds
Output Start: 0.10
Output Step: 0.40
Process Gain: 38.33
Kp: 23.0
Ki: 1.3
Kd: 14.5 No mapping required as the process gain is just ... |
Beta Was this translation helpful? Give feedback.
-
The part I'm still not sure about, is if the above are values are out by a factor of 60. The tuning rule constants (I'm quite sure) are based on minutes. In sTune.cpp lines 193-194, I've already divided by 60 to convert to seconds which works well with true PWM based control. However, controlling a digital output based on time might require a different conversion ... I'll need to do some research on this as I'm not a PID guru. |
Beta Was this translation helpful? Give feedback.
-
One thing I'm noticing, using Kp 23, Ki 1.3, and Kd 14.5 is that the system overshoots (expected), then slowly turns the output lower until 0% output. Let's say my set temperature is 100C. The PID algorithm starts from output 20%, say, al the way to 100%. at around 90C, the output starts dropping, but not fast enough, and it overshoots by 15-20C. Then the output goes to 0 and the temperature drops. I would expect that around 105C or so the PID output started rising, to slow the undershoot. But it stays at 0 until the measure temperature drops below 100C, and only at that point it slowly starts raising the output, and it undershoots by at least 10C. My system is such that to maintain a 100C temperature, it needs a constant 20-25% output. So now it starts again to increase the output until it overshoots to, say 110C. But from this point on it never converges, as it always waits for the temperature to drop below 100C to start heating again I have an espresso coffee machine with a PID, which in many ways it's similar to my plate heater: very slow to heat, and requires constant output to maintain the temperature once reached. That PID was auto tuned, and it works exceptionally well. IT overshoots target by a bit on the first rise, starts slowing down the drop before the setpoint, undershoots and overshoots once more by 2-3C, then it's rock solid. The key is that I can see its starting to increase the output while the temperature drops, well before it drops under the setpoint. That is a commercial PID, and it uses an SSR as well I have an encyclopedic ignorance when it comes to PIDs (i.e. what I don't know can fill a volume :), so I have no idea what changes I should make to help "brake" the descent below the setpoint. |
Beta Was this translation helpful? Give feedback.
-
To add: the PID for the espresso machine is a Fuji PXR3 (https://americas.fujielectric.com/files/prod_selector_v/Micro%20Controller%20X%20Operation%20Manual%20Model%20PXR3%20(ECNO%20409d).pdf?r=false) and according to the manual the ranges for P, I and D are P 0.0 to 999.9% and my autotuned values for that are P=4.3, I=95 and D=18.3 But P doesn't seem to be the same as in your library, since the manual says "When is too small, control will be unstable, and when is too large, the response will be delayed.", and from what I can see this behaves differently in my code |
Beta Was this translation helpful? Give feedback.
-
This sounds good. Should expect up to 25% overshoot using |
Beta Was this translation helpful? Give feedback.
-
The overshoot is not the problem, sorry if I was not clear. That will get smaller over time, if the undershoot also improves. The current problem is that it always undershoots by 10C, no matter what the starting point is. Since it always undershoots the same amount, it never converges. And the problem is that the output doesn't start increasing until after the input temperature goes below the setpoint. To avoid undershoot, the system should start increasing the output once the temperature is dropping and it's 2-3C above setpoint. Instead it only starts after the drop. And the system inertia means that it wll always undershoot the same amount unless the PID output starts increasing sooner |
Beta Was this translation helpful? Give feedback.
-
In this case, P = 4.3 x 100 = 430% |
Beta Was this translation helpful? Give feedback.
-
I'll take a closer look at the code when I get a chance later ... perhaps the output temporarily reverts to outputStart value in between step tests or from step test completion to initializing and starting the PID. Or perhaps the PID needs to start with the outputStep value so it doesn't try to climb from 0 output. |
Beta Was this translation helpful? Give feedback.
-
I ran a few tests using the old Autotune library https://github.com/br3ttb/Arduino-PID-AutoTune-Library. The average of a few runs (even when using wildly different tuning ranges) was Kp=33, Ki=0.17 and Kd=0. Using those parameters, I get really good performance: minimal overshot, stabilizes without oscillations (even if the output stays at 0 when dropping). I'm enclosing the data from my program (not the autotune) I first set a holding temperature of 100C from room temperature. Once it stabilizes at 100C, I drop the setpoint to 70C and wait for stable output again. Considering how slow my system is to cool (and can heat much faster than cooling), a great performance. Not sure why the original algorithm found much better values. Happy to run any test for you if you like |
Beta Was this translation helpful? Give feedback.
-
Interesting. I haven't used the PID-AutoTune-Library before but I have seen it. Do you have an example of how you're using it in code? Also curious how long the AutoTune test run takes. If you're using QuickPID, note that it defaults to a more advanced anti-windup mode that reduces overshoot, so this could partially be the cause of the minimal overshoot and no oscillations.
Thanks ... I still need to catch up a bit with more testing with my setup. Ive just finished comparing several settle time values here. It looks looks like you have the PID-AutoTune-Library controller mode set to PI, which uses different constants than PID mode. I think its using Ziegler Nichols rules for a relay step test ... I'll look more closely later and compare with the reaction curve method and constants that sTune uses. So far, sTune seems to be working great with others and on my setup with PWM control, but has some issue with the constants when using "bang-bang" output control for a relay. |
Beta Was this translation helpful? Give feedback.
-
"It works using logic by offsetting outputCorr by -9 while the error is positive and +9 while the error is negative and using offset of 0 when there is no error." - really interesting approach. How did you found offset value "9"? Aproximate output difference between points 1 and 2? |
Beta Was this translation helpful? Give feedback.
-
Yes, but not measured, just the next integer higher than ±8.33ms which is the timing for ½ cycle @ 60Hz AC. For 50Hz AC, ½ cycle is 10ms, so I'll try a value of 12 which should work with SSRs connected to 50Hz or 60Hz AC plus an extra ±1ms for software timing variances. The idea is to force ±½ cycle power control while operating within the dead-band area between each AC ½ cycle. Basically it's to enhance power control resolution. For the next test, I'll post a plot with setpoint at only 50°C using a 10x shorter window size (500ms) and using ±12 offset. Edit: The best improvement was to use an offset just lower than the ½ cycle timing so here's the plot using ZN_PID, setpoint = 50°C, window size 500ms and ±8 offset: The software PWM function for SSR relay control: void softPwm() {
if (Input > Setpoint) outputCorr = Output - 8;
else if (Input < Setpoint) outputCorr = Output + 8;
else outputCorr = Output;
if (outputCorr < 0) outputCorr = 0;
if (!relayStatus && outputCorr > (msNow - windowStartTime)) {
if (msNow > nextSwitchTime) {
nextSwitchTime = msNow + debounce;
relayStatus = true;
digitalWrite(relayPin, HIGH);
}
} else if (relayStatus && outputCorr < (msNow - windowStartTime)) {
if (msNow > nextSwitchTime) {
nextSwitchTime = msNow + debounce;
relayStatus = false;
digitalWrite(relayPin, LOW);
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Ive updated sTune and examples. The Just today I've received a MAX6675 module, so I'll be able to eventually create examples and wiki page for this (time permitting). |
Beta Was this translation helpful? Give feedback.
-
sTune 2.3.1New examples and reference is ready for the MAX6675 hardware setup. |
Beta Was this translation helpful? Give feedback.
-
I've updated your previous example in case you're interested in giving it a run with the latest revision of sTune (2.3.2). It would be interesting to see the plot results. /********************************************************************************
sTune QuickPID Adaptive Control Example (robcazzaro)
This sketch does on-the-fly tunning and PID SSR control of a PTC heater
using the ZN_PID tuning method. When sTune completes, we need the input
to approach setpoint for the first time. As the input gets closer, the gains
(tunings) are gradually applied. This helps keep the integral term to a
minimum to help reduce initial overshoot. Final overshoot correction is made
at the first crossover from setpoint. Here, a full AC cyle is dropped from
the output and 100% PID control resumes with ½ AC cycle optimized SSR control.
Open the serial plotter to view the graphical results.
Reference: https://github.com/Dlloydev/sTune/wiki/Examples_MAX6675_PTC_SSR
*******************************************************************************/
#include <Arduino.h>
#include <sTune.h>
#include <QuickPID.h>
#include "Wire.h"
#include <LiquidCrystal.h>
#include <max6675.h>
// ***** PIN ASSIGNMENT *****
int ssrPin = 11;
int thermocoupleSOPin = A3;
int thermocoupleCSPin = A4;
int thermocoupleCLKPin = A5;
int lcdRsPin = 8;
int lcdEPin = 9;
int lcdD4Pin = 4;
int lcdD5Pin = 5;
int lcdD6Pin = 6;
int lcdD7Pin = 7;
// pins
const uint8_t inputPin = 0;
const uint8_t outputPin = ssrPin;
const uint8_t ledPin = LED_BUILTIN;
// user settings
uint32_t settleTimeSec = 15;
uint32_t testTimeSec = 1000;
const uint16_t samples = 500;
const float inputSpan = 240;
const float outputSpan = 2000;
float outputStart = 0;
float outputStep = 400;
float tempLimit = 150;
uint8_t debounce = 1;
uint8_t startup = 0;
// variables
float Input, Output, Setpoint = 100, Kp, Ki, Kd;
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.direct5T, tuner.printALL);
QuickPID myPID(&Input, &Output, &Setpoint);
LiquidCrystal lcd(lcdRsPin, lcdEPin, lcdD4Pin, lcdD5Pin, lcdD6Pin, lcdD7Pin);
MAX6675 thermocouple(thermocoupleCLKPin, thermocoupleCSPin, thermocoupleSOPin);
void setup()
{
pinMode(outputPin, OUTPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(outputPin, LOW);
Serial.begin(57600);
tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
tuner.SetEmergencyStop(tempLimit);
// Start-up splash
lcd.begin(16, 2);
lcd.clear();
}
void loop()
{
float optimumOutput = tuner.softPwm(outputPin, Input, Output, Setpoint, outputSpan, debounce);
switch (tuner.Run())
{
case tuner.sample: // active once per sample during test
Input = thermocouple.readCelsius();
lcd.setCursor(0, 1);
lcd.print(Input);
lcd.print("C pwm=");
lcd.print((int)Output);
lcd.print(" ");
//Serial.println(Input);
tuner.plotter(Input, Output * 0.5, 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 * 0.5);
myPID.SetSampleTimeUs(outputSpan * 1000 * 0.2);
debounce = 0; // switch to SSR optimum cycle mode
myPID.SetMode(myPID.Control::automatic); // the PID is turned on
myPID.SetProportionalMode(myPID.pMode::pOnMeas);
myPID.SetAntiWindupMode(myPID.iAwMode::iAwClamp);
myPID.SetTunings(Kp, 0, 0); // update PID with the new Kp (P-controller)
break;
case tuner.runPid: // active once per sample after case "tunings"
Input = thermocouple.readCelsius();
lcd.setCursor(0, 1);
lcd.print(Input);
lcd.print("C pwm=");
lcd.print((int)Output);
lcd.print(" ");
//Serial.println(Input);
if (Input > Setpoint && startup == 6) {
Output -= 9; // drop half AC cycle
myPID.SetMode(myPID.Control::manual); // toggle PID control mode
myPID.SetMode(myPID.Control::automatic); // now PID uses the new output value
startup++;
} else if (Input > Setpoint - 3 && startup == 5) {
myPID.SetTunings(Kp, Ki, Kd); // 100% of gains
startup++;
} else if (Input > Setpoint - 6 && startup == 4) {
myPID.SetTunings(Kp, Ki * 0.8, Kd * 0.8); // 80% of gains
startup++;
} else if (Input > Setpoint - 9 && startup == 3) {
myPID.SetTunings(Kp, Ki * 0.6, Kd * 0.6); // 60% of gains
startup++;
} else if (Input > Setpoint - 12 && startup == 2) {
myPID.SetTunings(Kp, Ki * 0.4, Kd * 0.4); // 40% of gains
startup++;
} else if (Input > Setpoint - 15 && startup == 1) {
myPID.SetTunings(Kp, Ki * 0.2, Kd * 0.2); // 20% of gains
startup++;
} else if (Input > Setpoint - 18 && startup == 0) {
myPID.SetTunings(Kp, Ki * 0.1, Kd * 0.1); // 10% of gains
startup++;
}
myPID.Compute();
tuner.plotter(Input, optimumOutput * 0.5, Setpoint, 1, 3);
break;
}
} |
Beta Was this translation helpful? Give feedback.
-
I am trying to use sTune in my setup which is a Keurig coffee heating tank
with original thermistor and an SSR. The tank heats up very quickly (< 15
seconds to 100*º*C) but is very slow to cool. With an experimental setpoint
at 70 or 80 I get big overshoot with any setting (well, any I come up with)
and very long times to settle. I am even trying bringing it close to
temperature via other methods then invoking your code. I will gladly keep
playing and testing and get you any data that can be helpful to you (to
help others and me!), but can you guess at some good starting parameters
and settings for me to try?
Thanks for any suggestions.
-Craig
…On Sat, Feb 5, 2022 at 1:02 AM Dlloydev ***@***.***> wrote:
@robcazzaro <https://github.com/robcazzaro>
I've updated your previous example in case you're interested in giving it
a run with the latest revision of sTune (2.3.2). It would be interesting to
see the plot results.
/********************************************************************************
sTune QuickPID Adaptive Control Example (robcazzaro)
This sketch does on-the-fly tunning and PID SSR control of a PTC heater
using the ZN_PID tuning method. When sTune completes, we need the input
to approach setpoint for the first time. As the input gets closer, the gains
(tunings) are gradually applied. This helps keep the integral term to a
minimum to help reduce initial overshoot. Final overshoot correction is made
at the first crossover from setpoint. Here, a full AC cyle is dropped from
the output and 100% PID control resumes with ½ AC cycle optimized SSR control.
Open the serial plotter to view the graphical results.
Reference: https://github.com/Dlloydev/sTune/wiki/Examples_MAX6675_PTC_SSR
*******************************************************************************/
#include <Arduino.h>
#include <sTune.h>
#include <QuickPID.h>
#include "Wire.h"
#include <LiquidCrystal.h>
#include <max6675.h>
// ***** PIN ASSIGNMENT *****
int ssrPin = 11;
int thermocoupleSOPin = A3;
int thermocoupleCSPin = A4;
int thermocoupleCLKPin = A5;
int lcdRsPin = 8;
int lcdEPin = 9;
int lcdD4Pin = 4;
int lcdD5Pin = 5;
int lcdD6Pin = 6;
int lcdD7Pin = 7;
// pins
const uint8_t inputPin = 0;
const uint8_t outputPin = ssrPin;
const uint8_t ledPin = LED_BUILTIN;
// user settings
uint32_t settleTimeSec = 15;
uint32_t testTimeSec = 1000;
const uint16_t samples = 500;
const float inputSpan = 240;
const float outputSpan = 2000;
float outputStart = 0;
float outputStep = 400;
float tempLimit = 150;
uint8_t debounce = 1;
uint8_t startup = 0;
// variables
float Input, Output, Setpoint = 100, Kp, Ki, Kd;
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printALL);
QuickPID myPID(&Input, &Output, &Setpoint);
LiquidCrystal lcd(lcdRsPin, lcdEPin, lcdD4Pin, lcdD5Pin, lcdD6Pin, lcdD7Pin);
MAX6675 thermocouple(thermocoupleCLKPin, thermocoupleCSPin, thermocoupleSOPin);
void setup()
{
pinMode(outputPin, OUTPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(outputPin, LOW);
Serial.begin(57600);
tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
tuner.SetEmergencyStop(tempLimit);
// Start-up splash
lcd.begin(16, 2);
lcd.clear();
}
void loop()
{
float optimumOutput = tuner.softPwm(outputPin, Input, Output, Setpoint, outputSpan, debounce);
switch (tuner.Run())
{
case tuner.sample: // active once per sample during test
Input = thermocouple.readCelsius();
lcd.setCursor(0, 1);
lcd.print(Input);
lcd.print("C pwm=");
lcd.print((int)Output);
lcd.print(" ");
//Serial.println(Input);
tuner.plotter(Input, Output * 0.5, 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 * 0.5);
myPID.SetSampleTimeUs(outputSpan * 1000 * 0.2);
debounce = 0; // switch to SSR optimum cycle mode
myPID.SetMode(myPID.Control::automatic); // the PID is turned on
myPID.SetProportionalMode(myPID.pMode::pOnMeas);
myPID.SetAntiWindupMode(myPID.iAwMode::iAwClamp);
myPID.SetTunings(Kp, 0, 0); // update PID with the new Kp (P-controller)
break;
case tuner.runPid: // active once per sample after case "tunings"
Input = thermocouple.readCelsius();
lcd.setCursor(0, 1);
lcd.print(Input);
lcd.print("C pwm=");
lcd.print((int)Output);
lcd.print(" ");
//Serial.println(Input);
if (Input > Setpoint && startup == 6) {
Output -= 9; // drop half AC cycle
myPID.SetMode(myPID.Control::manual); // toggle PID control mode
myPID.SetMode(myPID.Control::automatic); // now PID uses the new output value
startup++;
} else if (Input > Setpoint - 3 && startup == 5) {
myPID.SetTunings(Kp, Ki, Kd); // 100% of gains
startup++;
} else if (Input > Setpoint - 6 && startup == 4) {
myPID.SetTunings(Kp, Ki * 0.8, Kd * 0.8); // 80% of gains
startup++;
} else if (Input > Setpoint - 9 && startup == 3) {
myPID.SetTunings(Kp, Ki * 0.6, Kd * 0.6); // 60% of gains
startup++;
} else if (Input > Setpoint - 12 && startup == 2) {
myPID.SetTunings(Kp, Ki * 0.4, Kd * 0.4); // 40% of gains
startup++;
} else if (Input > Setpoint - 15 && startup == 1) {
myPID.SetTunings(Kp, Ki * 0.2, Kd * 0.2); // 20% of gains
startup++;
} else if (Input > Setpoint - 18 && startup == 0) {
myPID.SetTunings(Kp, Ki * 0.1, Kd * 0.1); // 10% of gains
startup++;
}
myPID.Compute();
tuner.plotter(Input, optimumOutput * 0.5, Setpoint, 1, 3);
break;
}
}
—
Reply to this email directly, view it on GitHub
<#3 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHKHBZDSPG3RZGFVT575GF3UZS4O5ANCNFSM5LNU3TWA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
--
Craig Haller, Special Education Advocate
Haller Advocacy
617.435.1759
Fax: 617.738.8197
SPEDadvocate.com <http://spedadvocate.com/>
|
Beta Was this translation helpful? Give feedback.
-
@craig02445 |
Beta Was this translation helpful? Give feedback.
-
Apologies for the delay in replying, @Dlloydev , but I was working on another project and didn't have access to the hardware. I cut&pasted your modified code and run it as is. The results are really puzzling, not just for how slow the auto tuning was (35 minutes!), but also when switching to normal mode, the output was never above 200 (out of 2000), so the temperature stays around 80C, never reaching the 100C set temperature. I'm including the whole log as a txt file (given how long it is) The calculated parameters (Kp: 6.75, Ki: 0.08, Kd: 0.32) are roughly one order of magnitude too small. It looks as if there's a missing 0 somewhere in the example parameters (it's very slow to increase temperature, and still overshoots to above 130C) |
Beta Was this translation helpful? Give feedback.
-
Thanks, The modified code did a direct5T test, so this actually completes in 3-4 time constants, so that's 3-4 x 9.4 minutes on your system. I had the test run with a lower step value so that it would do a complete tuning test below setpoint, then gradually apply the new PID gains, but yes, the gains did come out too small. I've still got some work to do with the software and lot's of testing. I've reformatted your latest test results and pasted / saved it here in the online PID Tuner which is a great tool. Here, you can view the plot, view or change / re-scale its identified gains and more. It identified the time constant tau to be 848.6 sec (14 min). Using the "scale gains" slider, the overshoot would disappear with Kp = 25, Ki = 0.03, Kd = 0. If I manually entered the gains from sTune, the plot would reveal the oscillations. Click the "back" button 3 times to see the data table and the plot in more detail. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the additional info. I tried using Kp=25, Ki=0.03 and Kd=0, but the system is super slow to reach the 100C set temperature. It reaches 90C after roughly 180 seconds, but reaches 100C only after 1300 seconds (more than 20 minutes), which is way too long. No overshot, clearly :) I got these values from running Brett's autotune, Kp=28, Ki=0.17 and Kd=15, and with those I get a 10C overshot after roughly 120 seconds, then it stabilizes at 100C after 500 seconds. My ideal tuning would be for a system that reaches 100C in under 240 seconds, with no more than 5C overshot. |
Beta Was this translation helpful? Give feedback.
-
Oh, that was just playing with the settings to dial out the overshoot.
This specification helps ... here's some gains I've tried with each example getting more aggressive. Note the plot's time scale is zoomed in to max to reveal the response in just the first 342 seconds. Kp = 50, Ki = 0.0625, Kd = 0 Kp = 100, Ki = 0.125, Kd = 0 Kp = 150, Ki = 0.1875, Kd = 0
I've made some fixes to sTune and will push an update after I get a chance to do more testing. My goal is to have sTune determine gains that are a closer match to the gains determined by the online PID Tuner. |
Beta Was this translation helpful? Give feedback.
-
pidtuner really helpfull, but please pay attention to bottom graph also. Sometimes to achieve faster response pidtuner offers both positive and negative CV, but for heaters it's impossible =( and there is no way in pidtuner to consider any constrains (if you have any). Which may drammaticaly cause on results while using gains provided to pidtuner. If robcazzaro have transition from room ambient ~25C degree to 100C we will get 75 degree transition.
looks like with provided gains CV will be limited and results may be confusing. |
Beta Was this translation helpful? Give feedback.
-
sTune 2.4.0 is published. Includes various fixes, updated and new examples and documentation. |
Beta Was this translation helpful? Give feedback.
-
@robcazzaro @Dlloydev I am very much interested in controlling these slow systems most of us DIYers use (repurposed irons @robcazzaro , cheap Aliexpress components etc). For my quick test setup I am using cup heater + MAX6675 + SSR |
Beta Was this translation helpful? Give feedback.
-
Hello, |
Beta Was this translation helpful? Give feedback.
-
Not sure if this is a real issue, but I thought that in any case you would be interested in more data.
I'm building a hot plate for SMD soldering with a k-type thermocouple connected to a MAX6675 and a plate heater controlled by a SSR. I use a relay-like control for the SSR, with 2 sec window and the SSR on for a fraction of that time. I built an Arduino program to auto tune my physical setup.
Unfortunately the MAX6675 output is very noisy, due to the thermocouple limitations. The output can easily change by a degree centigrade just due to noise. When looking at Brett's old autoune library, there was a specific note about noise http://brettbeauregard.com/blog/2012/01/arduino-pid-autotune-library/. The library had a setting for dealing with noise SetNoiseBand()
You are clearly using a different algorithm, and I'm not sure how impacted it is by noise. I also mentioned in another issue that it's very hard for a setup like mine to reach steady state. So even if I'm trying to use always the same conditions (5% output stepping up to 20%, but since I use a 2000 msec PWM window, the values you will see are 100 and 400), the actual values change quite a lot.
I modified your library to also print the thermocouple input value, not just the average, so you can see how noisy the system is. I'm attaching 4 different runs with identical settings but different starting conditions. The suggested K values are actually very consistent, considering the noise and starting conditions
//user settings
const uint32_t testTimeSec = 600;
float outputStart = 100; // 5% start
float outputStep = 400; // 20% step
const uint16_t samples = 600;
const uint32_t settleTimeSec = 300; //5 minutes to settle
pid2.log
pid3.log
pid4.log
pid5.log
Beta Was this translation helpful? Give feedback.
All reactions