Home > Projects > PIC PID Micro-Controller

PIC PID Micro-Controller

March 14th, 2005 Leave a comment Go to comments

PID ThumbDoing this project really turned me on to systems and controls theory. A friend and I implemented a fully functioning PID motor speed and positioning controller onto a PIC MCU. This is a pretty thorough guide to building this very hand robotics peripheral.


As part of the IEEE hardware team I’ve done a lot of projects, but I’m proudest of this one. This was a PIC based system that implemented a closed-loop PID controller for position and speed control of two DC motors. In addition, the control loop could be adjusted to induce arcs.

The system was designed as a peripheral for another processor so it also had an SPI command interface that allowed it to be communicated with on a high level while it controlled the motors on a low level. The peripheral had a serial console that allowed you to tune, test, and drive the robot.

The Board

Shout outs go to Dr. John Peatman and my esteemed partner in this endeavor Jacques Fortier.


In order to complete its task, the robot needed to have precise control of its speed and position. Because much of the way finding of this robot was accomplished through dead reckoning, it was also especially important to maintain accurate information regarding the distance traveled by the robot.

In order to give the robot all of these features, we designed a special sub-processor that was devoted to the low-level control of the two primary motors. We implemented this system on a Microchip PIC18F252. This processor was housed on the same board as the motor driver which took control signals from this controller and used them to actually drive the motors.

Our sub-processor monitored the motors, and applied an appropriate pulse width modulated (PWM) signals to allow them to reach their goal. This controller also had the ability to communicate with the primary controller to receive speed and distance commands as well as report accomplished speed and distance traveled back to the commanding processor.


In order to get speed and distance information from the motors, we purchased motors with built in encoders that output a quatrature encoder interface (QEI) signal. This signal is comprised of two pulse trains that tell when the wheel travels a part of a rotation, and the direction of motion. When channel A makes a low to high transition, the value of channel B is checked to determine the direction. A sample QEI output can be seen below.

Quatrature Encoder Interface (QEI)

The motion controller was able to interrupt on low to high transitions from the QEI on channel A and create an estimate of instantaneous speed and direction by monitoring the number of counts obtained during a specified time interval. We used this information as inputs to the control loop that determines and compensates for errors in speed or distance.

The Control Loop

We implemented a PID (Proportional, Integral, and Differential) control loop to control the speed of the motors. The speed of the motors is manipulated by altering the duty cycle of a PWM signal generated by the processor. The duty cycle of this signal is known as the control value. below is a functional diagram of the control loop.

PID Flow Chart

This algorithm first determines the difference between the commanded speed and the actual speed. This value is known as error. The integral error is determined by adding the error to an accumulator, and the derivative error is calculated by subtracting the error from the previous error.

Every time the control loop executes, each of these errors are multiplied by a gain constant that has been tuned to optimize response time and accuracy. These errors, multiplied by their gain constants are then be added to the control value to compute the new control value.

In this way, the control value is continuously updated based on the response of the motors. This ensured that the motors are moving at the desired speed despite drag, obstacles, or other unexpected track conditions.

A final compensation factor is summed along with the P, I, and D errors. This is an error generated by inconsistencies in the two wheels. This helps to ensure that the robot goes straight by compensating for factors that slow one wheel but not the other.

Position Control

This was accomplished by controlling the speed based on the robot’s proximity to the desired position. The motor controller could take commands from the main processor that told it how many ‘ticks’ to travel. This value corresponded exactly to the number of QEI pulses that the robot should move.

The exact distance represented by each tick was determined by the resolution of the encoders and the diameter of the wheel. Our control system was capable of responding to 2944 ticks per revolution. With wheels that were 2.2 inches in diameter, the total distance per tick was 2.346×10-3 inches. Thus, very detailed motor control was possible.

The position control algorithm allowed the robot to approach its target distance at any speed. Then, as the target approached, it would slow its speed so that it could stop accurately when desired. This was achieved with a simple algorithm diagramed below.

Position Control Flow Chart

The motors position was monitored and continuously updated in local variables. Once the motors reached a distance a certain threshold before the desired position, the position control section of the algorithm would command the motors to stop. This would ensure that as the motors slowed down and achieved a speed of zero the robot would be at the desired position. These two systems were independent for the left and right wheel so that they could be commanded to go different distances for turning purposes.


These abilities provided the robot with the tools needed to control the speed and distance of travel. However, in order to be truly useful, this sub processor needed to be able to receive commands from the master processor, and provide information regarding the motor status back.

We accomplished this by using an SPI (Serial Peripheral Interface) communication protocol. The communication was message-based. The main processor could send eight-byte messages to the PID controller. These messages began with a one byte op-code telling the sub processor what type of command the message contained. The next seven bytes held data such as the desired speed, or the desired distance to be traveled.

The sub processor could simultaneously send back eight bytes that held instantaneous speed, and total distance traveled information. With the ability to control speed, position, and communicate with the main processor completed, the motion control system was almost done.

Tuning the Control

The final step was to tune the PID control algorithm. This is accomplished by adjusting the gain constants by which each error is multiplied by before summing it with the previous control effort. This is a complicated process that is mostly achieved through trial and error.

Another tool that helped was using GNUplot to make graphs of debug data output by the PID controller. This allowed us to see the interaction of different errors. This interaction can be seen below.

Plots used to Tune Controller

The work of tuning the processor was simplified by developing a user interface on the PID controller that was separate from the main processor. This allowed the control system to be tuned over serial by adjusting gain constants stored in EEPROM.

With the motor controller fully tuned, it performed very well and provided excellent speed and position control for the robot without bothering the main processor with this low level task. Full code for this motion controller is below.

The Motor Driver

All of this fluffy code stuff is great, but you always need some good ol’ power electronics too. The motor driver was required to step up logic level PWM signals to 9.7V motor driving PWM at up to 3A. In order to accomplish this, we used an L298 H-bridge chip and some glue logic. In addition, it was a nice place to house the PIC chip that implemented the PID controller. We added some handy plugs for programming, connecting to other processors, and attaching motors and power. Just because I’m a nice guy, I’ve included a schematic and layout for the board as well as the code below.


PID C Code (8kb)
Motorboard Schematic (184kb)
Motorboard Layout (54kb)

Final Thoughts

I was really happy with this project. Below you can see me and Jacques giving our ‘gang sign.’ In case you can’t read it that says “PIC” … as in the PIC chip we wrote the PID controller on.

But more seriously, there were some valuable lessons learned. I really got the hang of SPI. It may have been better to use I2C for this, but I’ll have to save that for next time. I also got really turned on to systems and controls. The idea of a closed loop control system that uses its error to correct itself is very clever and elegant. I strongly recommend taking a class on systems and controls if you haven’t yet.

Another thing I’d like to share is *ALWAYS* program in C. Assembly is sooo much more annoying. We started the project in assembly and quickly realized that things were getting out of hand so we switched to C (God’s own language) and everything started going very smoothly.

If I had it to do over again, I might also make the position control better. As it was, you really needed to tweak constants every time you changed the default speed of the system. It was highly accurate, but it would be a little more robust if I had implemented a PID position control algorithm in addition to the PID speed control algorithm.

  1. Ahmad
    May 30th, 2008 at 09:03 | #1

    Nice to read your article, its very impressive, i want to simulate transf
    er function of the dc-motor in matlab. so could you please share the transfer function of your motor and its parameters. i would be obliged.


  2. May 30th, 2008 at 15:48 | #2

    Ahmad, For this project we used real-life motors and never needed to identify the transfer function. PID controllers are so versatile that they can be tuned rather quickly to work with a motor even if the transfer function is unknown.

  3. Truong Trong Hieu
    July 19th, 2008 at 13:57 | #3

    I’m trying to put PID into MCU and fortunately found your works. That’s all what I want. I’m tranfering the code to my AVR and my PCB. Thank you

  4. July 26th, 2008 at 12:16 | #4


  5. Stephen D. Barnes
    January 18th, 2009 at 22:07 | #5

    If you are willing, could you publish more information concerning your build environment(MPLAB, gnu, etc.)? I also noticed that there are two files(main.c and serial.c) but no reference to each other in the code (or did I just miss calls?). Nice work. Do you mind if I attempt to use this in a strictly home hobby project?

  6. Tony
    January 25th, 2009 at 04:02 | #6

    Hi Shawn,
    Your project is very interesting to me but some part I don’t understand. Could you please explain to me. The part that look like flat ribbon cable, where is this cable connected to, and what is the purpose?
    The SV2, SV6, SV7, SV8 what are these used for? I see these ports left open.
    What motor did you use ? could you please show me how to connect the motor to the schematic?
    Thanks for your help.

  7. January 26th, 2009 at 16:54 | #7

    Hi Tony. The ribbon cable is a Serial cable used to communicate between the PC and the controller (over the open SV pins). This allowed nice tests while we were getting it working. Another cable connected the controller to the robot.

    I forget the motor, but this project will work with most DC motors that can be driven with PWM voltage. The controller needs to be tuned for every motor as described in the post.

    Hope that helps.

  8. james
    January 28th, 2009 at 08:59 | #8

    hi shawn,

    thanks alot for your project its really helpful would you please tell me what enviroment did you use to build this this project?

  9. hizman
    April 5th, 2009 at 08:00 | #9

    Your project is very interesting to me but some part I don’t understand. Could you please explain to me. The part that look like flat ribbon cable, where is this cable connected to, and what is the purpose?
    What motor did you use ? could you please show me how to connect the motor to the schematic? and can you show me the circuit….
    Thanks for your help.

  10. April 29th, 2009 at 10:04 | #10

    There were several cables:
    (1) connected the board to the computer for debugging
    (2) connected to the left motor
    (3) connected to the right motor
    (4) connected to the main controller to receive commands and transmit status updates.

    I’m not sure of the motor, but this should work for any DC motor with a quadrature encoder. You’ll have to tune the weights on the PID controller, of course.

    The schematic is linked above. The motors connect to MA1,2 and MB1,2.

  11. April 29th, 2009 at 10:10 | #11

    I used MPLAB with the HI-TECH C compiler.

  12. ümit
    May 17th, 2009 at 13:07 | #12

    ? have a project about light sensitivity control with digital pid.Can someonehelp me .What can i do?

  13. Mark P
    June 6th, 2009 at 10:27 | #13

    Hi i want to ask a question(dumb), is it possible that the code of yours will work if I use it on a pic16f877a?

    Your answer is really much appreciated. Thanks

  14. Azam
    October 20th, 2009 at 11:14 | #14

    I am doing a project on Closed loop speed control of a DC motor.

    I need some guide line on this PLEASE….

    I dont know which micro controller to use on that and the diver circuit.

    Kindly Help me with this…

  15. October 21st, 2009 at 12:28 | #15

    This post talks about using a PIC18F252 to implement a closed-loop PID controller of a DC motor based on QEI motor feedback. You can use the L298 chip to step up the voltage/current to drive the motors as stated in the post.

  16. Jame
    March 14th, 2010 at 06:53 | #16

    Thnk you every much…

  17. Baris
    April 22nd, 2010 at 15:07 | #17

    that is a masterpiece! you mentioned that u would do a better position control on this project, what is wrong with this one, i could not understand the position control part? i am working on a project so similar to this one, a generator excited by a speed and position controlled dc motor, do you think this project can be adopted to the one i am working on?

    your answers and advices are really appreciated

  18. April 22nd, 2010 at 19:13 | #18

    The position control here is more like an AC or a cruise control than a legit PID control system. This means that it worked but it wasn’t as exact as I wanted.

    In terms of hooking this system up to your project, I don’t see why it wouldn’t work. The challenge will be in conditioning the inputs to the algorithm so they match approximately.

    If you finish your project and write it up online, send me a link and I’ll send some traffic your way.

  19. baris
    May 1st, 2010 at 16:41 | #19

    as a star i am trying to control the speed and the position of 2 dc motors with a pid bas pic microcontroller but i do not need it to communicate with the pc so, which parts should i ignore in source code and in the shmatic in order to do this?

  20. baris
    May 1st, 2010 at 16:47 | #20

    and i don’t understand the schematics where do you get the feedback from, i don’t see any connection between the pic and the driver and encoder, what are the sv1,sv2,sv3… connections under the pic and the unused logic?

  21. Jeff
    May 7th, 2010 at 00:03 | #21

    @Shawn Lankton

    In what way is this not a “legit PID control system”? Do you have ideas on how to avoid changing the tuning for each change in speed?


  22. September 9th, 2010 at 20:14 | #22

    I am new to control systems and am experimenting with some of the basic theory that it encapsulates. I am about to embark on a project to control a DIY Servo (Brushless DC Motor/Optical Encoder/Hall Effect Sensor) through packets sent over P2P ZigBee Network (the commands initially read by a PIC Controller through via RS232 at one end and ultimately conveyed to the motor through a PWM output at the other end . Would I be correct in my assumption that the Integral part of the PID closed loop is missing in your example? Do you not need to monitor the torque using either back EMF or Hall Sensor Voltage?

  23. September 9th, 2010 at 20:30 | #23

    Sorry I meant the Differential Part of the PID

  24. nonamly
    May 18th, 2011 at 11:32 | #24

    I am currently designing a motor control system for a small robot,I also plan to use a pic18 microcontroller for PID control.
    I’m pretty sure that I am on the right track, however I don’t fully understand how a PID is used to do this.
    If your document can help me to do that please send it to me
    thanks so much!!!

  25. Hans
    July 18th, 2011 at 07:33 | #25

    Hi Shawn,

    How difficult would it be to let the chip accept direction and step signals ?
    (instead of spi signals)
    I would like to use these pid controllers for a cnc system…

  26. Hans
    July 18th, 2011 at 07:35 | #26

    (now entered the correct email address :-)

  27. August 29th, 2011 at 20:00 | #27

    http://www.shawnlankton.com/2005/03/pic-pid-controller/” Hi I am wanting to know if I may use this post on one of my blogs if I link back to you? Thanks

  28. Ahmed Mohsen
    September 28th, 2011 at 18:04 | #28

    Hi, this is a master piece of work. I am working on a personal home research project. I am using multiple MCUs to separate concerns and have a better control of time based tasks. So I can easily introduce a separate MCU for PID using PIC which I am already familiar with. My question is how to modify the code to control Hitec servos instead of DC motors; I am using standard continuous rotation servos and Nubotics quadrature encoders. Thanks

  29. TJ Sarmiento
    October 6th, 2011 at 04:35 | #29

    Mr. Shawn,

    Good afternoon!
    This is TJ Sarmiento, a Mechanical Engineering student from Manila, Philippines. I have a project wherein I need to control the speed of a small windmill/wind turbine in relation to changing wind speeds. My control system should involve PID control. I plan to make an air duct with controllable guide vanes inside, controlled by some servo motor. To maintain constant exit air speed from the air duct, the guides vanes should be controlled so that my windmill outside will rotate at constant speed.

    Sir, I’m starting from scratch, and I’m considering the use of PIC16F877A. Also, I still don’t have idea on the programming aspect. My proposed setup is shown on my attached PDF file (pls see attached file). Sir, please advise on what materials, components and accessories I should use.

    Looking forward to your favorable response. Thank you.


  30. mohamed yacout
    October 22nd, 2011 at 09:09 | #30

    I am interested
    IN “Micro PROCESSOR Based PID controller COMPLET WITH A/M Transfer station one Element System configuration Via Integral
    P:S 220 volt , 50HZ
    I/p Signal 4-20mA from pressure
    O/P signal: 4-20mA
    Alarm Contact
    24 VDC power supply for pressure Transmitter
    Dim: 96×96 or 172,×44
    With display for PV,S.P.,O/P.



  31. Kas
    December 10th, 2011 at 22:12 | #31

    Hi Shawn,

    This is a great write. Down to the point.

    How did you manage to handle angles and arcs with this code ? This is one of the problems im facing and I have no idea how to handle it in a microcontroller with all the trignometry

  32. December 12th, 2011 at 08:54 | #32

    We just used a simple lookup-table for sin and cos. We just typed that thing into a big, ugly block of if-then statements. Worked great!

  33. Frank Senftle
    February 8th, 2012 at 12:40 | #33

    Shawn, just getting into a temperature controlled device using a PID controller.
    I was thinking of using a Microchip PIC (PIC16F1823) since I needed alot of I/O
    and not needing a SPI/I2C since I’m having the LED display on the same PCB.
    Parallel data sent (not 3 lines for SPI or 2 for I2C)…just keeping it simple for
    the display.
    The PIC16F1823 has a full H-bridge and wondered if this was the best choice since I wanted a PID controller interface. Your advice is greatly respected and appreciated.

  34. Frank
    February 8th, 2012 at 12:40 | #34

    Shawn, just getting into a temperature controlled device using a PID controller.
    I was thinking of using a Microchip PIC (PIC16F1823) since I needed alot of I/O
    and not needing a SPI/I2C since I’m having the LED display on the same PCB.
    Parallel data sent (not 3 lines for SPI or 2 for I2C)…just keeping it simple for
    the display.
    The PIC16F1823 has a full H-bridge and wondered if this was the best choice since I wanted a PID controller interface. Your advice is greatly respected and appreciated.

  35. August 19th, 2013 at 15:54 | #35

    Definitely consider that which you said. Your favorite justification seemed to be at
    the web the easiest factor to take into account of.
    I say to you, I definitely get irked at the same time as other people consider worries that they just don’t recognise about. You controlled to hit the nail upon the highest as smartly as outlined out the whole thing without having side-effects , other folks could take a signal. Will likely be back to get more. Thank you

  36. October 22nd, 2013 at 02:19 | #36

    “PIC PID Micro-Controller | Shawn Lankton Online” was indeed a quite nice article, .
    Keep posting and I’ll try to keep on reading through! Thank you -Dora

  37. July 24th, 2014 at 10:32 | #37

    Finding the right house for your family means finding the best nest will help
    you to take care of your kids better. You are the only one will be hurt
    by this, so there is no reason not to be honest. If you are not in the
    mood of spending much on moving, the moving service
    provides the facility of a trailer.

  38. Ricardo
    April 8th, 2016 at 20:05 | #38

    Hi sir! Do u have this project working on Isis Proteus?

  1. July 21st, 2009 at 09:53 | #1
  2. February 5th, 2010 at 13:42 | #2
  3. February 28th, 2010 at 00:00 | #3
  4. October 28th, 2010 at 03:04 | #4
  5. March 4th, 2011 at 16:01 | #5
  6. January 23rd, 2014 at 10:35 | #6
  7. July 14th, 2014 at 15:59 | #7