I have a box of water, which temperature I have to regulate to a ramping setpoint which could go both below and above the ambient temperature. So I have decided to use a Peltier for both cooling and heating. The Peltier is driven by a regulated current source (DC-DC buck convertor), but there is a catch - it cannot go under 0.5A. Reversing of polarity is done by relay. The convertor can be switched on/off by an enable pin.

I have decided to try to use PID to control it and more specifically the PID_V2 library for arduino by Brett Beauregard.

I did an open loop manual step test in cooling direction in order to have general idea of the system and I got this: enter image description here

The step in the beginning is done by increasing the current from 1.284A to 2.258A. The temperature drops from 21.13 to 15.4 degrees, but since the outside temp has dropped by a half a degree, we can say that the drop is about 5C degrees. So dI/dT = 0.974/5 = 0.195 A/degree. Time constant seems to me like around 135 minutes. I haven't done step test with heating, because I don't want to go to high temperatures.

I know, that Peltier direction should not be reversed when there is already temperature gradient over it, so first thing that I want to make sure is that reversing polarity happens only when the Peltier is passing through zero and this is happening slow enough. So: 1 - how can I incorporate this condition in the PID control?

2 - the gap below 0.5A. Since I cannot control the current there, there are two or three possible solutions, but I don't know which will be better. First one is to just push the minimum current in the direction that I want to go. Second one is to switch to ON/OFF cycle, which at low current won't be a problem and third one - to vary the fan speed of the peltier coolers, which will affect their cold side/hot side temperature difference. I don't know how to incorporate those without confusing the PID.

3 probably biggest problem is reversing the Peltier. The transferred heat from the cold side to the hot side is more or less proportional to the current, but in the opossite direction we have to add to this the Jaul heat which is proportional to the square of the current. I assume for this I will need to switch PID coefficients and probably do some kind of calculation of the actual command to the DC-DC in order to get linear current change to a linear change of PID output. Any ideas on this one?

4 I found that Brett Beauregard PID library has a functionality that he calls "Proportional on measurement", which according to his blog article prevents overshoots on setpoint step, which I will do all the time. I want to try it, but I don't know how to calculate Kp for my system.

5 Will the direction switching confuse the PID (probably the integral part) somehow? With what Ki and Kd should I start?

For now, these are the questions that are bothering me.

  • \$\begingroup\$ Just noting: your question is very similar-looking to this other question of yours. Others may need to refer to it, if nothing else. \$\endgroup\$ Jul 28, 2023 at 13:10
  • \$\begingroup\$ @periblepsis - the other one is much broader and concerns mostly the appropriate algorithm. Here I have much more specific questions about specific algorithm and problems. \$\endgroup\$
    – irilinir
    Jul 28, 2023 at 13:20
  • \$\begingroup\$ I Know is late for answer or comment something about , but at end what happen? \$\endgroup\$ Mar 14 at 20:31

2 Answers 2


I have done a few of these PID's in commercial products.

I know, that Peltier direction should not be reversed when there is already temperature gradient over it

The best way I've found is to use a normal PID with a slew rate limiter and set the PID to be very slow. I've used PWM and not strictly ON/OFF, so the power was controlled with a hardware timer on a 5-10Hz update cycle. So if you had a 100msec window you would vary the duty cycle of the window with the hardware timer. If 1% power was needed then you would turn on for 1msec, if 50% then you'd have 50msecs and 100% would be on for 100msecs.

The hard thing is the crossover because you don't want to go from fully off to fully on ever. It's ok to slowly go against the direction of the thermal gradient, you'll burn out the peltier if you go from say 50% heating to 50% cooling. So how do you avoid that? Slew rate limiter... you calculate the velocity (previous mesurement - current mesurment = velocity) and then have an if-then statement to block it from going above a certain value, say 10%, if it's above that value, then you set it to the value. You may also need to stop the PID from winding up during this time. After it get's below the velocity you can resume normal operation.

You should hand tune the PID. You will need it to go really slow since the control energy that you have for the peltier is going to be much less to move the temperature of the whole tank, you will only be able to change the temperature around the peltier locally. It would be better to have a pump to pump water to the peltier unit and put a thermometer in the water stream than to put the peltier in the tank, because you can control a small amount of water in the stream.

You also need to place the thermal measurment at the appropriate place in the stream of water, the distance of the thermal measurment from the peltier will affect the delay. The delay will affect the PID. You want a large enough delay so the PID is not noisy, but short enough so the control loop can respond, if the delay is too long PID's dont work very well.

  • \$\begingroup\$ The tank is already built. Water is circulated by 2 pumps through 2 heatsinks on the cold sides on the 2 Peltiers. Hot sides are cooled by big high-end CPU coolers (6 heatpipes, 12cm fan at 1800 rpm, at least 150W TDP). Temperature sensor is very near the water outlets (about 15cm from the Peltiers. On the chart you can see what temperatures I'm getting at 2.25A. The Peltiers are 12710, so there is plenty of power in reserve. Isn't 5-10Hz PWM too stressful for the Peltier? I could go with currenc control untill I hit 0.5A, and below that switch to PWM. The heat at this current is not so much. \$\endgroup\$
    – irilinir
    Jul 28, 2023 at 19:13
  • \$\begingroup\$ -why the slew rate limiter has to limit the input (the measurement). Isn't better to limit the output (the control value)? The input varies very slowly, so there is no chance to have very big speed of change. In contrary, the output probably could change much faster and in oposite directions if there are overshoots. \$\endgroup\$
    – irilinir
    Jul 28, 2023 at 19:32
  • \$\begingroup\$ @irilinir, Measurement->PID->Slew Rate limiter->PWM/Duty Cycle->H-bridge , the slew rate limiter does not go on the output of the measurement, it's to limit the PID. \$\endgroup\$
    – Voltage Spike
    Jul 28, 2023 at 21:18
  • \$\begingroup\$ >The Peltiers are 12710, so there is plenty of power in reserve. Isn't 5-10Hz PWM too stressful for the Peltier? No I never had a problem with using an update cycle of 5Hz-10Hz, but that is only on the control cycle, the peltier sees pulses with the timer. The PWM does not run at 5Hz, only the update cycle, You are then using a duty cycle to control the amount of power \$\endgroup\$
    – Voltage Spike
    Jul 28, 2023 at 21:22
  • \$\begingroup\$ ok, clear. I missunderstood "previous mesurement - current mesurment". About the PWM - unfortunatelly since I allready control the current by regulator, probably I cannot do any fast PWM by switching on/off its enable pin. I have to experiment how fast it will allow me to do this, but I doubt that I can go much higher than 10 Herz with variable duty cycle. \$\endgroup\$
    – irilinir
    Jul 28, 2023 at 22:42

Ok, so my system is ready for experiments. Please, can someone suggest starting PID values?

In the first post I posted a step response. This is done by changing current from 1.284A to 2.258A. The output value range will be from -267 to 267 (- for warming, + for cooling, switching direction by relay at 0). I presume that there will be vast difference in both directions, so probably in the beginning I could start with cooling direction only.

0 output represents 0A 267 output represents 3.52A enter image description here

1.284 = output 62 2.258A = output 135

Input (PV) comes as a floating point variable in the range let say 12 - 27 degrees. Setpoint will flow gradually between 14 and 25 degrees. I'm using Brett Beauregard PID library, which is ideal model (Kp, Ki, Kd).

Update: Tested cooling side only. Kp = 10, Ki = 0.01, Kd = 0, 1 second update time enter image description here It works better than I expected for a first try, but I suppose it could be better. I suppose I have to rise one of the two parameter, but I don't know which


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.