Advises on programming/tuning a PID for Peltier element  - Page 1
Forum section: electronics / beginners

author: arronar
author_rank: Contributor
timestamp: November 19, 2018, 10:41:01 pm
content: Hi again.In another thread I described that I'm driving a Peltier element using the Syren 10A driver with a raspberry pi zero. According todriver's manual, I'm using it with the R/C mode where on page 11 says the following:QuoteSo now I'm trying to program a PID controller to make Peltier element keep a stable temperature. I'm writing it in python language and here is the code so far:Code:from time import sleepfrom w1thermsensor import W1ThermSensorimport pigpiopi = pigpio.pi()def GET_TEMP():sensor = W1ThermSensor()temp = sensor.get_temperature()return tempdef PLTR_CTRL( PWM_VALUE ):pi.set_servo_pulsewidth( PLTR_PIN, PWM_VALUE )def FAN_CTRL( FAN_VALUE ):pi.write( FAN_PIN, FAN_VALUE )# PIN CONFIGURATIONPLTR_PIN = 18FAN_PIN = 5# PARAMETERS CONFIGURATIONSAMPLE_TIME = 1PWM_ON = 2000PWM_OFF = 1500PWM_REVERSE = 1000TARGET_TEMP = 40KP = 0.55KD = 0.72output = 1OldMin = 0OldMax = 1NewMax = 2000NewMin = 1500prevError = 0 # Previous error# MAIN PROGRAM STARTS HERE# INITIALLY OPEN THE FANFAN_CTRL(1)# AND THE PELTIERPLTR_CTRL( PWM_ON )# OPEN FILEf = open("temp_data.txt", "w+")try:while True:error = TARGET_TEMP - GET_TEMP()output += (error * KP) + (prevError * KD)# Turn it in a value between 0 an 1output = max(min(1, output),0)# Rescale the output into 1500 - 2000 rangenewPulse = ((( output - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin# Apply the new pulsePLTR_CTRL( int(newPulse) )print("Temperature: ", GET_TEMP(), "\tError: ", error, "\t\tOutput: ", int(newPulse) )f.write( "%f\n" % GET_TEMP() )sleep(SAMPLE_TIME)prevError = errorexcept KeyboardInterrupt:PLTR_CTRL( PWM_OFF )FAN_CTRL(0)f.close()pi.stop()So far I have implemented only the proportional and the derivative parts. As you can see I'm calculating the output variable based on the KP, KD and the error. Then I transform this output variable into a meaningful for the driver range of values by scaling it up between 1500 and 2000 usec pulses. I didn't include pulses smaller than 1000 usec because then the polarity get inverted and the Peltier element cools instead of heat.So now I'm actually trying to tune the whole idea and because its the first time that I'm doing something like that I would be interested to read your opinions and advises on the way that I'm approaching it and of course if you have any hint or pipeline that will help me achieve a good enough tuning.

author: rstofer
author_rank: Super Contributor
timestamp: November 20, 2018, 12:05:27 am
content: Derivative is usually omitted and integral is usually included. However, 'wind-up' of integral error needs to be handled otherwise it can become the dominant term.First things first, get proportional working. Get the timing and factor squared away for proportional before even considering integral or derivative.When you have the gain right for proportional, there will probably be some overshoot and settling within a very few oscillations. But the actual output will have some steady state error and that is removed by integrating the error until it becomes large enough to be a factor.Here is a pretty good article about PID but Google is FULL of similar documents. I like this one because I have Matlab and as soon as I get it printed, I'm going to play with it.

author: langwadt
author_rank: Super Contributor
timestamp: November 20, 2018, 12:30:44 am
content: Quote from: arronar on November 19, 2018, 10:41:01 pmit'd think it should be, output += (error * KP) + ((prevError-error) * KD)

author: rstofer
author_rank: Super Contributor
timestamp: November 20, 2018, 02:43:11 am
content: EEVacademy video:

author: arronar
author_rank: Contributor
timestamp: November 20, 2018, 04:17:15 pm
content: QuoteExcuse me but I don't understand what you are saying here. What's the timing? You mean to change the sampling period?Quoteyou probably forgot the link.QuoteYou probably are right. I'll double check it.

author: kosine
author_rank: Regular Contributor
timestamp: November 20, 2018, 05:21:33 pm
content: I had to read that twice myself! "Squared away" just means "sorted out", nothing to do with the mathematics of PID.Timing is how quickly you adjust the PWM output. Trying to make the system respond too quickly can cause it to oscillate rather than settle down at the set-point. The power of the heater and the location of the temperature sensor will affect the response time, so you'll need to play with the sampling frequency and KP factor to find values that give a reasonable result.As mentioned above, the derivative term can usually be omitted. In theory it's purpose is to compensate for any sudden changes, but in practice there often aren't any to worry about. (A large thermal mass won't suddenly change it's temperature just because someone opens a nearby window. It would probably only be needed if you're expecting sudden changes to occur.)The integral term adjusts for heat loss from the system by providing an additional bias power. Under ideal conditions the proportional term will tend to zero, so you're just left with the integral term which compensates for natural cooling.For a simple system the proportional term is often enough by itself. Focus on getting that as good as you can with minimal oscillation. If it's not stable enough for your needs then try adding the integral term or try moving the temperature sensor to a different location if possible. (I've had industrial PID systems oscillate wildly due to bad sensor locations and no choice of PID settings would lead to stable operation. So sensor location can sometimes be more important than the code.)

author: rstofer
author_rank: Super Contributor
timestamp: November 20, 2018, 07:04:58 pm
content: Here is a terrific series of videos (7 in all) that really gets into PID control and mostly defers the s-domain stuff until later videos. If Laplace isn't one of your best friends, don't worry!Video 7 gets into the discussion of continuous versus discrete PID control and discusses the importance of sample rate. Not surprisingly, many of the examples are augmented with MATLAB demonstrations but lacking MATLAB isn't really an issue.There is a lot of add-on material in the links with each video.The author has his own channel as well but I haven't watched the videos:https://www.youtube.com/channel/UCq0imsn84ShAe9PBOFnoIrgYou can also Google for 'ziegler nichols' . Basically, you disable integral and derivative functions and crank up proportional gain until the system oscillates but the output doesn't grow without bound. You measure the period of the oscillation and then there is a little pencil whipping to convert the proportional gain you already found plus the period to get all 3 coefficients. A handy guide is shown in one of the videos above.You can't always use Ziegler-Nichols because it isn't always a good idea to get a mechanical system into oscillation but it should work fine for heating. Think of flaps on an airplane, definitely not ideal for them to oscillate in flight just to tune the controller!

author: Vtile
author_rank: Super Contributor
timestamp: November 20, 2018, 07:16:45 pm
content: I think I do not have much to add rstofer's information.I just want to point out that Ziegler-Nichols oscillation (or limit frequency response) method is dangerous in many systems and ie. in industry it is mostly loathed. In other hand Ziegler-Nichols step response method (and all the variations of it) are much more generally safe to use as it doesn't drive the system to unstable state as easily and it is easier for the instrumentation and other field devises.Traditional Ziegler-Nichols coefficients (formulas) do give high(ish) overshoot, with settling oscillation. Derivatives (of Ziegler-Nichols method) are optimized many times a bit differently.

author: arronar
author_rank: Contributor
timestamp: November 20, 2018, 08:01:03 pm
content: Ok let me explain what I've done so far. From the script, I posted as you can see I generate a text file that keeps logs of the temperature for each cycle (1sec). In order to decide which proportional weight is the best to use, I generated such files for different KPs. Then I took those files and I used R-language to calculate the mean error from the set point (I really don't know if this was right enough).Here is the R code btw:Code:for( pfile in prop_files){path <- paste0("propotional/",pfile)p <- read.table(file = path)error <- mean(abs(p$V1 - 40))print(paste("Error:", error, "weight:", path))}and here are the results :Code: "Error: 3.79919230769231 weight: 0.15 "Error: 3.35218181818182 weight: 0.18 "Error: 3.3664054054054 weight: 0.2 "Error: 3.40386021505376 weight: 0.25 "Error: 3.26013605442177 weight: 0.27 "Error: 3.55074418604651 weight: 0.29 "Error: 3.25048623853211 weight: 0.35 "Error: 3.3104923857868 weight: 0.38 "Error: 3.19131531531531 weight: 0.4 "Error: 2.92779381443299 weight: 0.45 "Error: 3.12755421686747 weight: 0.48 "Error: 2.79556603773585 weight: 0.5 "Error: 2.5856357615894 weight: 0.55 "Error: 2.6910162601626 weight: 0.58And that's why I used the 0.55 as KP.Here is also a plot of the values (set point 40)So by keeping 0.55 as KP then I added a value 0.007 for KI and I realized that the results got worse. Intuitively I decided to decrease the KP more and let the KI constant (0.007). The results then got better with 0.2 value for KP but still with big enough overshoots (+/-4/5Cdeg). But this means that I didn't calculate correctly initially the proper value of KD. Should I try more values than the ones I tried for KP? It seems to need really brute force methods.

author: Vtile
author_rank: Super Contributor
timestamp: November 20, 2018, 09:00:00 pm
content: Kp 0.1 and Ki 0.03, just lottery before going to sleep.

author: Kleinstein
author_rank: Super Contributor
timestamp: November 20, 2018, 09:39:48 pm
content: The driver shown is made to work with a motor and does output just a relatively slow PWM. This is not really good for driving a Pletier element.It gets especially bad if the peak current is more than about half the nominal current. At high currents and low frequency PWM drive also reduces the life of the Peltier element due to thermal stress.For a relatively slow control one can get away without the derivative term. If it has to be relatively fast (compared to the system) one does need the derivative term. However this requires a reasonably good set of parameters. With just 2 parameter in the PI regulator one might still find a good solution by try and error. It's much more difficult in the PID case.A Peltier element is a nonlinear control element. One one gets closer to the maximum current it gets quite nonlinear.For fast and accurate regulation over a larger range, it might be worth to include this nonlinear (but know relatively simple formula) relationship. So the PID would calculate the required power and a second step would be to calculate the required current from the desired power.Ideally one would also include the other side temperature as a kind of feed forward or a little simpler (because no extra parameters needed) as a part of the formula to calculate the required current.

author: Momchilo
author_rank: Regular Contributor
timestamp: November 21, 2018, 03:58:25 am
content: I never tried to control the temperature of a Peltier element. But I think it's necessary to have two PI-controllers in a cascade. The D-part isn't important.One controller (inner loop) for the current and the outer controller for the temperature. The output of the outer controller is the setpoint of the current controller. The current controller should be much faster than the temperature controller, because you can change the current immediately, but the temp only very slowly.It's very similar to a speed control of a dc motor.But I don't know, if that's the best way.

author: Kleinstein
author_rank: Super Contributor
timestamp: November 21, 2018, 07:01:46 am
content: There is usually no need for an extra digital cascade control. The output stages are usually reasonably well behaved, so that one can pretty much predict the current from the set value. If at all this could be done linear, as a kind of current controlling amplifier.

author: arronar
author_rank: Contributor
timestamp: November 22, 2018, 07:18:22 am
content: QuoteSo, then which is a good driver/way to drive a Peltier?

author: chemelec
author_rank: Contributor
timestamp: November 22, 2018, 05:44:59 pm
content: I use Mosfets to turn them on and Off.

author: perieanuo
author_rank: Frequent Contributor
timestamp: November 23, 2018, 07:17:09 am
content: I had in a company I worked a module for a peltier that did reverse temperature control (heating or cooling), the output stage was triacs with moc's (and a second variant with mosfets, that one was Ok too) the micro msp 432 something, an lcd and some switches attached and as sensor we had analog parametrable input (lm72 if I remember correctly).The limitation was the sensor to 115 deg C but as sensor was parametrable it was adaptable(the project focused on 37 deg C as middle temp).Beside the power heating/cooling comming from peltier type solution, the idea is not bad.The PID was configurable via PC app to adapt to different heat capacity and peltier modules.Me, I was using it to preheat pcb-s combined with hotair soldering or for big radiators (later I replaced with an arduino with thermocouple amplifier for raising the temp ).I don't have the code for the pid...but it was stable with the Derivative part too (I usually tune mostly the P and I part).I love triac style cause of EEM stuff but for hobby cost decides.Regards,PierreEnvoyé de mon iPad en utilisant Tapatalk

author: arronar
author_rank: Contributor
timestamp: November 23, 2018, 10:39:01 am
content: Quote from: chemelec on November 22, 2018, 05:44:59 pmI thought that too but I wasn't sure that there are MOSFETs that can afford the currents and voltages that a Peltier consumes. Can you describe the way you follow to choose a proper MOSFET to use?

author: rstofer
author_rank: Super Contributor
timestamp: November 24, 2018, 10:41:03 pm
content: Quote from: arronar on November 23, 2018, 10:39:01 amPerhaps a link to the actual Peltier? If there is some kind of commercial controller, perhaps a link to that? Since there are MOSFETs working up to hundreds of amps and quite high voltage, I suspect they will work quite well. The fact that this setup requires a servo type pulse is puzzling (to me).I got rather too interested in this project, more specifically, control systems in general. In watching the Brian Douglas videos, he plays around with heating and PID. He uses this gadget for the demo board and links it to MATLAB but it also has Python code. Lots of Python code...http://apmonitor.com/pdc/index.php/Main/ArduinoTemperatureControlFor $35 out of Amazon, it is quite useful. Among other things there is a PID control loop written in Python and the results of set point and temperature are displayed on a nice chart along with captured data in a file.You really can't get very far with control constants without knowing step response of the system. You already have a start on that with your data file.A simplified approach that doesn't include Derivative, similar in concept to Ziegler-Nichols but here the presenter gets time constants from the step response curve.

author: Vtile
author_rank: Super Contributor
timestamp: November 24, 2018, 10:55:51 pm
content: Quote from: rstofer on November 24, 2018, 10:41:03 pmYes. That is coined also as Ziegler-Nichols, but step response (or closed loop) method I were referring earlier. Much better in general than the Ziegler-Nichols open loop / oscillation method. There is lots of variations (the coefficient multipliers) for this closed loop response method. Also many PID autotuning methods are rather simple algorithms and use open loop tuning, might be interesting to take a peek...

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2018, 04:44:14 am
content: Attached is the graphical output of the Python PID controller test program for that TemperatureLab gadget I talked about in Reply #17. I have left the coefficients as given.