Open Wurstnase opened 8 years ago
Looks good! And the plan about ideal for making this a button-click later.
Right. Just using this two values in configtool.
I'll split out PID-values for each heater without EEPROM (from PID autotune). https://github.com/Traumflug/Teacup_Firmware/commit/74afc4d57a1e
Next step is the implementation in config-tool. After that i will continue the autotune, because this is more or less a step before.
One question to it. Is it a printer or a board-property?
So far, heaters and sensors are considered to be a board property. Putting PID to printer configuration while keeping sensors and heaters on the board page is probably confusing.
Yes, I thought the same. Where should I move then bang bang and pid controller and later the pid autotune?!?
A good place for PID parameters appears to be the temp sensor page. On this page is already some knowledge on which heaters have a temp sensor and which not. Temp sensors without heater are possible, too.
For the autotune checkbox it looks like a good idea to make this the first item on a new page "Calibration" next to "Board" and "Printer".
There is quite some prior art in one of the older branches. There are three branches starting with issue74..., all of which provide some work in the PID area; including a commit adding P, I and D as part of the heater definition. Another branch on the topic is ProportionalBandPID If you could look into this stuff, sort it, pick the useful parts and drop the others it'd be awesome. Such topic branches only make sense if they eventually lead to new code.
This autotuning procedure could be used to generate data to find parameters for a FOPDT (First-Order Plus Deadtime) model. I think that would provide the transfer function that was mentioned in #188. You'd need to run autotuning and report time, heater output setting and the temperature. FOPDT parameter search, however, is too hard to run it on the MCU. You'd need to to it on a PC. That would be semi-auto-tuning :)
@Wurstnase, does this autotune code allow to do a repeatible measurement of how well temperature regulation works? I mean, we have a number of patches now which mean to improve regulation, so I'd like to measure the quality of each of them. Not trivial, because we all have different hardware, so one strategy might work better here while another might work better there. Having an objective measurement procedure would be great.
This code is somehow called Ziegler-Nichols 'classic' method. Currently my testmachine is a hotend on my ground without cooling. So testing up to 80° is the limit. But this algorithm for autotune is nothing new. Marlin implement this first and the results for PID are very repeatable and the controller is really stable. This mechanism just loop X times through a given temperature. So heating up to 200° at given P and heat 3s longer. Cool down to 200° and cool 3s (I need to look how long exactly) longer. Do this twice and reduce or higher P to have a stable control. After some loop we have the timings of the curve, min/max.
I take this means a "no, doesn't allow repeatible measurements".
Yes, and I guess that there is no real method.
Thanks for your work on the autotuning feature.
Is this branch working for you in this state or are there some missing commits?
I had to apply the attached diff [1] in order to compile.
But then at the end of the procedure, I receive something like:
Ku: 0 Tu: 5199
Ku: 0 Tu: 4265
Ku: 0 Tu: 4712
Thus, Ku is always null. I'm not able to spot a problem in the code at first glance. Is it something missing in the branch or more likely an error on my side?
[1] compile_fix.txt
Hi @asnt thanks for testing. Currently the pid-autotune is not finished. The only way, that Ku becomes zero is, when heater_runtime[h].d becomes zero. This should not happen.
Can you please enable debug? You need to add a new DEBUG in debug.h
#ifdef DEBUG
#define DEBUG_ECHO 1
#define DEBUG_INFO 2
#define DEBUG_ERRORS 4
#define DEBUG_DRYRUN 8
#define DEBUG_PID 16
#define DEBUG_DDA 32
#define DEBUG_POSITION 64
#define DEBUG_AUTOTUNE 128
#else
// by setting these to zero, the compiler should optimise the relevant code out
#define DEBUG_PID 0
#define DEBUG_DDA 0
#define DEBUG_POSITION 0
#define DEBUG_ECHO 0
#define DEBUG_INFO 0
#define DEBUG_DRYRUN 0
#define DEBUG_AUTOTUNE 0
#endif
The debug itself should be already in the heater.c -> https://github.com/Traumflug/Teacup_Firmware/commit/fcec05777b3595dd2094656115c8defafcacf5a9#diff-f3f72c353ecceeca9075f2012e2e8d3dR417
One idea. I test this code on a 32bit-board. So maybe this line in heater.c needs a change:
uint16_t Ku = (heaters_runtime[h].d << 17) / (201 * ((heaters_runtime[h].max_temp - heaters_runtime[h].min_temp)));
to
uint16_t Ku = (uint16_t)(((uint32_t)heaters_runtime[h].d << 17) / (201 * ((heaters_runtime[h].max_temp - heaters_runtime[h].min_temp))));
Just a guess.
Having a 32-bit CPU doesn't guarantee that all math is done in 32 bits anyways, so yes, good idea.
@Traumflug I will make a patch.
To get the PID-values you need one extra value. The tick-time of your heater. On the current master it is 10ms. We are working on a tick of 250ms.
For a slight overswing:
heater-tick = 0.01s = 10ms
Ku_f = Ku / 128
Tu_f = Tu / 128
P = 0.6 * Ku_f
I = 2 * P / Tu_f * 0.01
D = P * Tu_f / 8 / 0.01
DEFAULT_P = P * 1024 * 4
DEFAULT_I = I * 1024 * 16
DEFAULT_D = D * 1024 * 8
Not 100% sure if this is correct, but this is how I would make a first test.
Edit: I must again think about it.
Maybe I'm again wrong with the units. I need to sleep now and will verify my formulas later.
Edit: Don't try unit conversion after 11pm, tired and with dimmed light.
for 250ms-heater-tick:
P = DEFAULT_P = 0.6 * Ku * PID_SCALE / 128 I = DEFAULT_I = 64 * P / Tu
for D I have a mental block with TH_COUNTS... gone
D = DEFAULT_D = TH_COUNTS * P * Tu / 128 * 4
TH_COUNTS could be implemented directly in the PID-algorithm.
Thanks @Wurstnase .
I tried the last commits with the 32bit cast. It seems the tuning procedure loops indefinitely. I will investigate further over the weekend.
Did you set PID_MAX to 255? Else it could be not reach the target temperature. This is a feature I want to add later for high power hotends (using 12V heater with 24V).
It all works fine now.
The 32bit cast does the trick.
The infinite loop was because of PID_AUTOTUNE not enabled in the printer config. Sorry for the noise.
Now, I can compute the Kp and Ki. Not sure about Kd: what is the TH_COUNTS?
But on the current master and experimental, the heater tick is 10ms. So the calculations above don't count. You could also try the latests commits in heaters_intervals.
what is the TH_COUNTS?
TH_COUNTS simply stretches time. Instead of current and last temperature, current and temperature 8 readings back are compared. I think this can go away unless code runs into accuracy issue, then (difference between the last two readings being to small for a meaningful calculation).
I think this can go away
Yes, when we take the new 250ms-interval-code.
I found some time to test this code.
Issues currently, the temperature values are too rough. For Ku we calculate the temperature difference of min and max. This value could be ~1°. In my tests Ku varied by factor 2, because with rounding and some scalings this can be 1° or 0,5°.
So especially for the pid-autotune it could be recommended to oversample and expand the temperature at least to 12.4 fixpoint.
@Wurstnase In Marlin,
Ku = (4 * d) / (pi * (temp_max - temp_min) / 2)
In the current Teacup implementation,
Ku = (4 * d) / (pi * (temp_max - temp_min))
Is this not the factor two you are describing?
I tested this code against the heaters_interval branch and the autotuning seems fine.
With some minor adaptations for the 250ms ticks and with
Ku = (d << 16) / (201 * (temp_max - temp_min))
Tu = (t_low + t_high) << 5
Yes, it's wrong for 9.7 fixpoint. But correct is:
Ku = (d << 18) / (201 * (temp_max - temp_min))
It's 1/(1/2)!
https://github.com/Traumflug/Teacup_Firmware/commit/fcec05777
First commit is done.
This is currently not that simple as it will be in near future.
Go into your printer.x.h and enable PID_AUTOTUNE. In the same moment you deactivate any normal control of your heaters. Upload the firmware and connect your host.
With M104 Sxxx you start the autotune, where xxx is the temperature you want to control. Now you just need to wait about 5 to 10 minutes.
In the end you get some numbers. Like:
Ku: 1625, Tu: 3904
This is Ku and Tu in 9.7 fixpoint notation.With Ziegler-Nichols you can now calculate your PID-values. The standard is pretty good so we use in this example: Kp = 0.6_Ku Ki = 2_Kp/Tu Kd = Kp*Tu/8
PID-values are .10 fixpoint. So with
Ku: 1625, Tu: 3904
Kp = 0.6 * Ku * 8 = 7800 Ki = 2 * Kp * (2^7) / Tu = 511 Kd = Kp * Tu / 8 / (2^7) = 47580