PID Temperature Controller


Introduction: PID Temperature Controller

My friend is building a plastic extruder for plastic recycling ( He needs to control the extrusion temperature. For that purpose he is using a nozzle heater band. In this nozzle, there is a thermocouple and a heating unit which allow us to measure the temperature and finally reach the desired temperature (make a retroaction loop).

When I heard that he needed to by several PID controllers to control all these nozzle heater bands, it immediately gave me the desire to try to make our own.

Step 1: Tools and Material


  • soldering iron, solder wire and flux
  • tweezer
  • milling machine (chemical etching is also possible for PCB prototyping) (you can also order the PCB with my eagle file)
  • thermometer (for calibration)
  • arduino (any type) or an AVR programmer
  • FTDI serial TTL-232 USB cable
  • laser cutter (optional)
  • multimeter (ohmmeter and voltmeter)


  • Bakelite single side copper plate (60*35 mm minimum) (I ruined my saw buying the fiberglass one so be careful: Bakelite)
  • Attiny45 microcontroller
  • LM2940IMP-5 voltage regulator
  • AD8605 operational amplifier
  • NDS356AP transistor
  • a bunch of resistors and capacitors (I have the SMT 0603 adafruit book)
  • 230V-9V ac-dc transformer
  • 1N4004 diodes
  • solid state relay
  • nail polish (optional)

Step 2: Etch the PCB

I used my Proxxon MF70 CNC transformed and a conical end bit to mill the PCB. I think that any engraving end bit would work. The Gcode file was directly generated by eagle and the pcb-gcode plugin. Only three passes where done to ensure a good route separation but without spending hours milling all the copper. When the PCB went out of the CNC machine, I cleaned the routes with a cutter and tested them with a multimeter.

Parameters: feed rate 150mm/min, depth 0.2mm, rotation speed 20'000 t/min

Step 3: Solder the Components

With the tweezer and the soldering iron, place the components at the right places and solder it using flux (it helps) and beginning with the smallest components. Again, check with a multimeter that you don't have any short circuits or unconnected elements.

You can choose the amplifier gain by choosing the resistor you want (gain=(R3+R4)/R4). I took 1M and 2.7k so in my case the gain equal approximately 371. I can't know the exact value because I am using 5% tolerance resistor.

My thermocouple is a J type. It means that it gives 0.05mV for each degree. With the gain of 371, I obtain 18.5mV per degree from the amplifier output (0.05*371). I want to measure around 200°C so the amplifier output should be around 3.7V (0.0185*200). The result should not exceed 5V because I use the 5V reference voltage (external).

The image correspond to the first (not working) version I made but the principle is the same. In this first version, I used a relay and put it right in the middle of the board. As soon as I was switching with high voltage, I had spikes who made the controller reboot.

Step 4: Program the Microcontroller

Using an arduino like in this instructables: you can load the code.

I used a pro trinket with a FTDI-USB cable to program the Attiny 45 but this method is equivalent. I then plugged the pin PB1 and GDN directly into the RX and GND of the FTDI-USB cable to receive the serial data and be able to debug.

You should put all the parameters to zero (P=0, I=0, D=0, K=0) in the arduino sketch. They will be set during the tuning step.

If you don't see smoke or smell burnt, you can jump to the next step!

Step 5: Assembling and Calibrating

Caution: Never plug the power supply and the 5V from the programmer at the same time! Otherwise you will see the smoke I was taking about in the previous step. If you are not sure to be able to respect that, you can simply remove the 5v pin for the programmer. I let it because it was more convenient for me to program the controller without power supply and to test the controller without having the heater heating like crazy in front of my face.

Now you can branch the thermocouple on the amplifier and see if you are measuring something (respect the polarity). If your heating system is at the room temperature, you should measure zero. Heating it with hand should already lead to some small values.

How to read these values? Simply plug the pins PB1 and GDN directly into the RX and GND of the FTDI-USB cable and open the arduino serial monitor.

When the controller starts, it sends the value red by the internal thermometer of the chip. This is how I compensate temperature (without using a dedicated chip). It means that if the temperature changes during the operation, it will not be taken in account. This value is very different from one chip to another so it has to be entered manually in the REFTEMPERATURE definition at the beginning of the sketch.

Before connecting the solid state relay, verify that the voltage output is in the range supported by your relay (3V to 25V in my case, the circuit generates around 11V). (respect the polarity)

These values are not temperatures in degree or Fahrenheit but the result of the analog to digital conversion so they vary between 0 and 1024. I use the 5V reference voltage thus when the amplifier output is near 5V, the conversion result is near 1024.

Step 6: PID Tuning

I need to mention that I am not a control expert, so I found some parameters that work for me but I do not guarantee that it is working for everyone.

First of all, I have to explain what the program does. I implemented a sort of software PWM: a counter is incremented at each iteration until it reaches 20'000 (in which case is reset to 0). A delay slows the loop down to a millisecond. The most discerning of us will notice that the control period is around 20 second. Each loop begin with a comparison between the counter and a threshold. If the counter is lower than the threshold, then I turn the relay off. If it is bigger, I turn it on. So I regulate the power by setting the threshold. The threshold calculation happens every second.

What is a PID controller?

When you want to control a process, you have the value you measure (analogData), the value you want to reach (tempCommand) and a way to modify the state of that process (seuil). In my case it is done with the threshold ("seuil" in french but much easier to write and pronounce (pronounce "sey")) which determine how long the switch will be on and off (the duty cycle) thus the amount of energy put in the system.

Everyone agrees that if you are far from the point you want to reach, you can make a big correction and if you are close, a small correction is needed. It means that the correction is a function of the error (error=analogData-tempComand). Yes but how much? Let's say that we multiply the error by a factor (P). This is a Proportional controller. Mechanically a spring makes a proportional correction because the spring force is proportional to the spring compression.

You probably know that your car suspensions consist of a spring and a damper (shock absorber). The role of this damper is to avoid your car rebounding like a trampoline. This is precisely what the derivative term does. As the damper, it generate a reaction which is proportional to the error variation. If the error is changing quickly, the correction is lowered. It reduces oscillations and overshoots.

The integrator term is here to avoid permanent error (it integrates the error). Concretely, it is a counter that is incremented or decremented if the error is positive or negative. Then the correction is increased or lowered according to this counter. It has no mechanical equivalency (or you have an idea?). Maybe there is a similar effect when you bring your car to the service and the mechanic notice that the shocks are systematically too low and decide to add some more preload.

All of this is summarized in the formula: correction=P*e(t)+I*(de(t)/dt)+D*integral(e(t)dt), P,I and D being three parameters that have to be tuned.

In my version I added a fourth term which is the "a priori" (feed forward) command needed to maintain a certain temperature. I chose a proportional command to the temperature (it is a good approximation of the heating losses. It is true if we neglect the radiation losses (T^4)). With this term, the integrator is lighten.

How to find these parameters?

I tried a conventional method that you can find by googling "pid tuning temperature controller" but I found it difficult to apply and ended up with my own method.

My method

First put P,I,D to zero and put "K" and "tempCommand" to small values (for example K=1 and tempCommand=100). Turn the system on and wait, wait, wait... until the temperature has stabilized. At this point you know that with a "seuil" of 1*100=100, the temperature tends to X. So you know that with a command of 100/20000=5% you can reach X. But the goal is to reach 100 because it is "tempCommand". Using a proportion you can calculate K in order to reach 100 (tempCommand). By precaution I used a smaller value than the calculated one. Indeed it is easier to heat more than cool down. So finally


Now when you start the controller, it should naturally tends to the temperature you want but it is a really slow process because you only compensate the heating losses. If you want to go from one temperature to another, a quantity of thermal energy has to be added in the system. P determines at which rate you put the energy into the system. Set P to a small value (for exemple P=10). Try a (almost) cold start. If you don't have a big overshoot, try with the double (P=20) if now you have one try something in between. If you have 5% overshoot, it is good.

Now increase D until you have no overshoot. (always trials, I know this is not science) (I took D=100)

Then add I=P^2/(4*D) (It is based on the Ziegler-Nicholts method, it should guarantee stability)(for me I=1)

Why all these trials, why not science?

I know... I know! There is a huge theory and you can calculate the transfer function and the Z transform and blablabla. I wanted to generate a unitary jump and then record for 10 minutes the reaction and write the transfer function and then what? I don't want to make arithmetic with 200 terms. So if anyone has an idea, I would be happy to learn how to do that properly.

I also thought to my best friends Ziegler and Nichols. They told me to find a P that generate oscillations and then apply their method. I never found these oscillations. The only thing I found was an oooooooovershoot to the sky.

And how to model the fact that heating is not the same process as cooling?

I will continue my research but now let's package your controller if you are happy with the performance you obtain.

Step 7: Pack It

I had access to the Moscow fablab ( and their laser cutter and I am grateful. This opportunity allowed me to make a nice package generated in one click by a plugin who makes boxes of the wanted dimensions (h=69 l=66 d=42 mm). There are two holes (diam=5mm) on the top for the led and the switch and one slit on the side for the programming pins. I secured the transformer with two pieces of wood and the PCB with two screws. I soldered the terminal block to wires and to the PCB, added the switch between the transformer and the PCB power input, connected the led to PBO with a resistor (300 Ohms) in series. I also used nail polish for electrical insulation. After the last test, I glued the box. That's it.

Microcontroller Contest

This is an entry in the
Microcontroller Contest



    • Woodworking Contest

      Woodworking Contest
    • Make it Move Contest

      Make it Move Contest
    • Casting Contest

      Casting Contest

    We have a be nice policy.
    Please be positive and constructive.