Emile666 / stc1000_stm8

STC1000p for the STM8 microcontroller (HW version WR-032)
GNU General Public License v3.0
45 stars 10 forks source link

PID Tuning peltier #18

Open JasperBFH opened 8 months ago

JasperBFH commented 8 months ago

Good afternoon,

I came across your github and I see that you are very experienced in realizing PID controllers. I am working on creating a PID controller for controlling the water temperature using a peltier, H-bridge and PID. The PID for heating has been tuned using your document PID_Controller_Calculus. I have also tried this with cooling, but this does not work at all. Can you help me to tune the PID for cooling.

Emile666 commented 7 months ago

You closed this, so you probably figured it out already. A normal STC1000 works as a thermostat, meaning that heating (and cooling) is switched off if the temperature is reached. I added a PID controller for heating to this, since a heating element is typically controlled by a SSR, which is controlled by a PWM signal. Which is a perfect for a PID controller.

Cooling (compressor in a fridge) on the other hand cannot be controlled by a PID controller. So there you have the standard thermostat algorithm.

Hope this helps understanding the function of the PID controller I implemented.

lalo-uy commented 7 months ago

For the cooling side, if you use chiller an recirculating pump or electro valves, you ca use a very slow pwm, 1 minute period or even more.

El El lun, 20 nov. 2023 a la(s) 13:11, Emile @.***> escribió:

You closed this, so you probably figured it out already. A normal STC1000 works as a thermostat, meaning that heating (and cooling) is switched off if the temperature is reached. I added a PID controller for heating to this, since a heating element is typically controlled by a SSR, which is controlled by a PWM signal. Which is a perfect for a PID controller.

Cooling (compressor in a fridge) on the other hand cannot be controlled by a PID controller. So there you have the standard thermostat algorithm.

Hope this helps understanding the function of the PID controller I implemented.

— Reply to this email directly, view it on GitHub https://github.com/Emile666/stc1000_stm8/issues/18#issuecomment-1819362372, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACXBW4P54MMUNB3FUFV6K4TYFN6JNAVCNFSM6AAAAAA7OEH3YOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMJZGM3DEMZXGI . You are receiving this because you are subscribed to this thread.Message ID: @.***>

JasperBFH commented 7 months ago

I have 2 sides. On one side a water pump with fan. And on the other side a water pump with a container of water where the temperature must be regulated (cooling and heating). I control the H-bridge (Heating & cooling) with a PWM of 20KHz. The sample time for the PID algorithm is 3 seconds. With the help of Ziegler Nichlos and pidtuner.com i determined my parameters for heating & cooling.

Cooling Kp= 175, Ki = 1.45, Kd = 0, Heating Kp = 20, Ki = 0.0889, Kd = 0,

I tried your type C Takashi PID controller. Unfortunately I'm getting crazy results with your code. I used a different PID code and it does produce the desired results.

PIDCoolingTest

What am I doing wrong? Surely a better PID controller (Type C Takashi) should work and not change the parameters?

float PID_Update (PIDController *PID, float setpoint, float measurement
{
// Calculate Error
float error = setpoint - measurement;

//Calculate the integral error
pid->integrator = pid->integrator + pid->Ki  * error;

//calculate the measurement derivative
float dpv = (measurement - pid->prevMeasurement);

//calculate the PID output
pid->P  = pid->Kp * error;
pid->I  = pid->integrator;
pid->D  = -pid->Kd * dpv;
pid->out = pid->P + pid->I + pid->D;

// implement anti-reset windup
if (pid->out > pid->limMax)
{
    pid->I =  pid->I - pid->Ki  * error;
    pid->integrator = pid->I;
    pid->out = pid->limMax;
}
else if (pid->out < pid->limMin)
{
    pid->I =  pid->I - pid->Ki  * error;
    pid->integrator = pid->I;
    pid->out = pid->limMin;
}

pid->prevMeasurement = measurement;
return pid->out;}
JasperBFH commented 7 months ago

I guess the problem is in the PID algorithm. I will solve this myself to realize it for heating and cooling.

I do have one more question. If I start heating with the PID for heating, do I have to use the PID for cooling to make the calculations for cooling in the background so that the integrator adjusts when the temperature rises again

Emile666 commented 7 months ago

There's a define GMA_LLIM that is currently set to 0, but if you set this to -1000, it will do cooling as well. You only have to add some code that a negative output is sent to the Peltier element (as a positive percentage), and that a positive output is sent to the heating element as usual. In this way you can do a step-response as described in the document.

JasperBFH commented 7 months ago

Okay, that's clear. The problem I am experiencing is that the P value is negative and therefore the system/PID controller does nothing when heating with the formula pid->P = pid->Kp * (pid->xk_1 - xk) I get negative numbers.

If xk_1 is 25 degrees and xk = 26 degrees then you get a value of 20 * (25 - 26) = -20

This is strange if the set point is 30 degrees and the system needs to heat up. Then it seems to me that the P value must be positive?

Emile666 commented 7 months ago

My PID function is a type C velocity algorithm, it calculates a delta, so it is perfectly normal to get negative numbers, meaning that the PID-output should be decreased. The PID-output can still be positive, but it is getting a lower value. And since the setpoint is removed from the P and D action, it is less obvious to see. If xk_1 - xk < 0 in your case, then xk_1 < xk, meaning that ek < ek_1, which indicates that the error-value is decreasing. And therefore it is logical that the PID delta is less than 0, so that the PID output will be decreased as well.

JasperBFH commented 7 months ago

Okay. Hmm okay, that's clear. But the problem remains that the output with PID never starts up. Like your example in the brewing process where the output goes to 100% when starting.

My tuned/calculated parameters (with the other PID algorithm) Kp, Ti, Td, Ts values ​​are 20, 239, 0, 3.

If I run the PID algorithm for the first time with room temperature then it is Kp = 20 * (0-22.09) Kp = -441.875

Ki = 0.25 * (30 - 22.09) Ki = 1.98

Kd = 0

Out += P + I + D Out = 0

the PID returns 0 and the water will never heat. What am I doing wrong?

Emile666 commented 7 months ago

So you run only 1 iteration of the PID-controller and based on that you conclude that the 'water will never heat'? That's what I call premature. If xk and xk_1 was properly initialized to the environmental temperature prior to starting the controller, you wouldn't have the large negative transient (that is called ' bumpless transfer'). If you run the PID-controller for at-least 6 seconds prior to enabling it, the controller starts without negative transients. That's why I always use an enable signal for the controller. It always runs every Ts seconds, but only starts calculating an output when the controller is enabled.

I am not going to give a lecture on digital control systems here, but hopefully you can convince yourself by running multiple iterations (every 3 seconds in your case) and see what it does. Because the I-action keeps on integrating, while the P-action becomes less negative (because xk_1 is approximately equal to xk), so you have a controller that starts in a nice and relaxed way. If your Ki is 1.98, then after 10 * 3 seconds, you already have something like 40 % total output. But if you only look at the very first iteration, then you are not getting the picture. Again, you have to understand what exactly a velocity type algorithm is (controller calculates a delta and you should add that to the cumulative output) and what a type-C controller does.