Comments (10)
Perhaps the heater power rating is too low for the quicker response you need.
If manually turning on the heater (full on), how long does it take for the temperature to reach 80C ?
Could you show the example code you're using?
What type of heater (PTC?) and SSR are you using?
from stune.
I ran a test and it took 3min 40sec to heat up to 80C full on. Even if I add another 190W heater it will still take at least a minute to heat up. I'm just trying it keep the temp around 80C during use.
Code used is below:
I have tried a few different outputSpan settings but haven’t had much luck.
Also tried setting debounce to 0
#include <max6675.h>
#include <sTune.h>
#include <QuickPID.h>
// pins
const uint8_t relayPin = 3;
const uint8_t SO = 12;
const uint8_t CS = 27;
const uint8_t sck = 26;
// user settings
uint32_t settleTimeSec = 10;
uint32_t testTimeSec = 500; // runPid interval = testTimeSec / samples
const uint16_t samples = 500;
const float inputSpan = 200;
const float outputSpan = 1000;
float outputStart = 0;
float outputStep = 50;
float tempLimit = 150;
uint8_t debounce = 1;
// variables
float Input, Output, Setpoint = 80, Kp, Ki, Kd;
MAX6675 module(sck, CS, SO); //SPI
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);
delay(3000);
Output = 0;
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 = module.readCelsius();
tuner.plotter(Input, Output, Setpoint, 0.5f, 3); // output scale 0.5, 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 * 0.1);
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 = module.readCelsius();
myPID.Compute();
tuner.plotter(Input, optimumOutput, Setpoint, 0.5f, 3);
break;
}
}
The heater is an AC cartridge heater similar to what you would find in a 3D printer, just bigger. The SSR is BRM-25DA that I got off amazon.
from stune.
Ah sorry I didn’t mean to do that
from stune.
Thank you for the details. Could you give this a try?
#include <max6675.h>
#include <sTune.h>
#include <QuickPID.h>
// pins
const uint8_t relayPin = 3;
const uint8_t SO = 12;
const uint8_t CS = 27;
const uint8_t sck = 26;
// user settings
uint32_t settleTimeSec = 10;
uint32_t testTimeSec = 700; // runPid interval = testTimeSec / samples
const uint16_t samples = 700;
const float inputSpan = 200;
const float outputSpan = 1000;
float outputStart = 0;
float outputStep = 400;
float tempLimit = 150;
uint8_t debounce = 1;
// variables
float Input, Output, Setpoint = 80, Kp, Ki, Kd;
MAX6675 module(sck, CS, SO); //SPI
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);
delay(3000);
Output = 0;
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 = module.readCelsius();
tuner.plotter(Input, Output, Setpoint, 0.5f, 3); // output scale 0.5, 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 = module.readCelsius();
myPID.Compute();
tuner.plotter(Input, optimumOutput, Setpoint, 0.5f, 3);
break;
}
}
from stune.
It was doing good at first but started to throttle around 50C, it seems to be going up but significantly slower. I'm going to keep it running to see if it's able to get up to temp.
from stune.
It might help if the proportional gain is increased by using something like this
myPID.SetTunings(Kp * 2, Ki, Kd);
Could also try increasing the outputStep to 600.
Hopefully later this year I'll get some time to do some testing with non-ptc type heaters (like yours) and do some work on updated code, examples and documentation.
from stune.
It was able to get up to temp with an output step of 600. I couldn’t see if it was holding temp because the serial monitor stopped receiving data (loose cable). Is it supposed to print out pid values when it is done?
I couldn’t get the Kp * 2 working the error was about a float* multiplying with an int. I tried a float but it didn’t work either.
from stune.
With the example above, it will keep printing every 3rd sample as long as the PID is running.
from stune.
I just did some manual tuning using the QuickPID library. It is working well with some custom PWM code. I will close this for now since it seems auto-tunning is not the best method for systems with lots of lag.
You mentioned it prints every 3ed sample, but not the tuned kp, ki, kd values, only Output, Input, and Setpoint.
from stune.
Hello, I am also having some issues getting a system with significant lag to work.
I am using a toaster oven, a K type thermocouple wired to a MAX6675, and an esp32 controlling an SSR.
In my case, the test finishes after only 45 seconds (though the testTimeSec = 500
). The calculated tunings don't work at all and result is the oven being on for less than 10% of the time (visually).
Here is the test:
sec: 9.0000 out: 500.00 pv: 0.000 settling ⤳⤳
sec: 8.0000 out: 500.00 pv: 22.000 settling ⤳⤳
sec: 7.0000 out: 500.00 pv: 21.750 settling ⤳⤳
sec: 6.0000 out: 500.00 pv: 22.000 settling ⤳⤳
sec: 5.0000 out: 500.00 pv: 21.750 settling ⤳⤳
sec: 4.0000 out: 500.00 pv: 21.500 settling ⤳⤳
sec: 3.0000 out: 500.00 pv: 21.750 settling ⤳⤳
sec: 2.0000 out: 500.00 pv: 22.250 settling ⤳⤳
sec: 1.0000 out: 500.00 pv: 21.750 settling ⤳⤳
sec: 0.0000 out: 500.00 pv: 21.750 tan: 0.000 →
sec: 1.0000 out: 750.00 pv: 21.750 tan: 0.000 →
sec: 2.0000 out: 750.00 pv: 21.750 tan: 0.000 →
sec: 3.0000 out: 750.00 pv: 21.500 tan: -0.021 ↘
sec: 4.0000 out: 750.00 pv: 21.750 tan: -0.021 →
sec: 5.0000 out: 750.00 pv: 21.750 tan: -0.021 →
sec: 6.0000 out: 750.00 pv: 21.750 tan: -0.021 →
sec: 7.0000 out: 750.00 pv: 21.750 tan: -0.021 →
sec: 8.0000 out: 750.00 pv: 21.750 tan: -0.021 →
sec: 9.0000 out: 750.00 pv: 21.750 tan: -0.021 →
sec: 10.0000 out: 750.00 pv: 22.250 tan: 0.021 ↗
sec: 11.0000 out: 750.00 pv: 21.500 tan: 0.000 ↘
sec: 12.0000 out: 750.00 pv: 22.000 tan: 0.021 ↗
sec: 13.0000 out: 750.00 pv: 22.000 tan: 0.042 ↗
sec: 14.0000 out: 750.00 pv: 21.750 tan: 0.292 ↗
sec: 15.0000 out: 750.00 pv: 21.750 tan: 0.062 ↘
sec: 16.0000 out: 750.00 pv: 21.750 tan: 0.062 →
sec: 17.0000 out: 750.00 pv: 22.000 tan: 0.083 ↗
sec: 18.0000 out: 750.00 pv: 22.000 tan: 0.104 ↗
sec: 19.0000 out: 750.00 pv: 21.500 tan: 0.083 ↘
sec: 20.0000 out: 750.00 pv: 21.750 tan: 0.083 →
sec: 21.0000 out: 750.00 pv: 22.000 tan: -0.396 ↘
sec: 22.0000 out: 750.00 pv: 22.000 tan: 0.333 ↗
sec: 23.0000 out: 750.00 pv: 22.000 tan: -0.125 ↘
sec: 24.0000 out: 750.00 pv: 21.500 tan: -0.167 ↘
sec: 25.0000 out: 750.00 pv: 22.250 tan: 0.104 ↗
sec: 26.0000 out: 750.00 pv: 21.750 tan: 0.104 →
sec: 27.0000 out: 750.00 pv: 22.000 tan: 0.125 ↗
sec: 28.0000 out: 750.00 pv: 22.000 tan: -0.104 ↘
sec: 29.0000 out: 750.00 pv: 22.250 tan: -0.083 ↗
sec: 30.0000 out: 750.00 pv: 22.250 tan: 0.437 ↗
sec: 31.0000 out: 750.00 pv: 22.250 tan: 0.250 ↘
sec: 32.0000 out: 750.00 pv: 22.250 tan: 0.042 ↘
sec: 33.0000 out: 750.00 pv: 22.250 tan: 0.062 ↗
sec: 34.0000 out: 750.00 pv: 22.750 tan: 0.125 ↗
sec: 35.0000 out: 750.00 pv: 22.750 tan: 0.687 ↗
sec: 36.0000 out: 750.00 pv: 22.750 tan: 0.042 ↘
sec: 37.0000 out: 750.00 pv: 23.000 tan: 0.604 ↗
sec: 38.0000 out: 750.00 pv: 22.750 tan: 0.437 ↘
sec: 39.0000 out: 750.00 pv: 22.750 tan: 0.500 ↗
sec: 40.0000 out: 750.00 pv: 23.000 tan: 0.333 ↘
sec: 41.0000 out: 750.00 pv: 23.250 tan: 0.417 ↗
sec: 42.0000 out: 750.00 pv: 23.500 tan: 0.521 ↗
sec: 43.0000 out: 750.00 pv: 22.750 tan: 0.562 ↗
sec: 44.0000 out: 750.00 pv: 23.000 tan: 0.625 ↗
sec: 45.0000 out: 750.00 pv: 23.500 tan: 0.229 ↘
The results:
Controller Action: directIP
Output Start: 500.00
Output Step: 750.00
Sample Sec: 1.0000
Pv Start: 21.750
Pv Max: 25.998
Pv Diff: 4.248
Process Gain: 0.049
Dead Time Sec: 32.000
Tau Sec: 35.971
Tau/Dead Time: 1.1 (easy to control)
Tau/Sample Period: 36.0 (good sample rate)
Tuning Method: NoOvershoot_PID
Kp: 13.892
Ki: 0.028 Ti: 499.703
Kd: 0.062 Td: 222.269
Ideally, the oven should have an initial phase where it is 100% on, then slowly taper off as it reaches it's temp. Instead it completes the test and immediately reverts to such a small on-time that the oven actually cools while the PID loop is trying to heat it.
I will try to tune the oven manually but i'd really like to use autotuning as the thermal mass in the oven will vary greatly, and it would be amazing to have the oven calibrate itself to the contents every run.
Here is my code:
/ user settings
uint32_t settleTimeSec = 10;
uint32_t testTimeSec = 200; // runPid interval = testTimeSec / samples
const uint16_t samples = 200;
const float inputSpan = 350;
const float outputSpan = 1000;
float outputStart = 500;
float outputStep = 750;
float tempLimit = 150;
uint8_t debounce = 1;
// variables
float Input, Output, Setpoint = 100, Kp, Ki, Kd;
MAX6675 module(sck, CS, SO); //SPI
sTune tuner = sTune(&Input, &Output, tuner.NoOvershoot_PID, tuner.directIP, tuner.printALL);
QuickPID myPID(&Input, &Output, &Setpoint);
void setup() {
pinMode(relayPin, OUTPUT);
Serial.begin(115200);
delay(3000);
Output = 0;
tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
tuner.SetEmergencyStop(tempLimit);
}
void loop() {
float optimumOutput = tuner.softPwm(relayPin, Input, Output, Setpoint, outputSpan, debounce);
//Serial.print("Temp: ");
//Serial.printf("%f", Input);
//Serial.println("deg C");
switch (tuner.Run()) {
case tuner.sample: // active once per sample during test
Input = module.readCelsius();
//tuner.plotter(Input, Output, Setpoint, 0.5f, 3); // output scale 0.5, 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 * 0.1);
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 = module.readCelsius();
Serial.printf("PV: %f deg C \r", Input);
myPID.Compute();
//tuner.plotter(Input, optimumOutput, Setpoint, 0.5f, 3);
break;
}
}
from stune.
Related Issues (20)
- How to use sTune. (Doc issue? PBCAK?) HOT 8
- PTC Heater Requires Using `direct5T` Test HOT 3
- optimumOutput from softPwm looks incorrect HOT 7
- "outputStep" is not working correct HOT 2
- Reset() doesn't properly re-initialize internal variables HOT 2
- After PID has run the heater doesn't reach it's setpoint HOT 1
- Big overshoot in tuning with NoOvershoot_PID HOT 1
- error in example HOT 1
- output always nan HOT 17
- PID does not work properly on my environment. HOT 4
- Noisy thermocouple input HOT 44
- Example sTune QuickPID Example dont work
- softPwm --> ledcWrite
- Hi,
- Use of 0-10V instead of relay
- Relay Heater sTune HOT 20
- Relay heater example HOT 7
- Can't compile Autotune_PID_v1 example. HOT 1
- On startup, Integral Term Adds to Overshoot HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stune.