Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Arduino & Microcontrollers

Arduino PID Controller: Precise Motor and Temperature Control

Arduino PID Controller: Precise Motor and Temperature Control

March 11, 2026 /Posted byJayesh Jain / 0

An Arduino PID controller is one of the most powerful techniques you can add to your embedded projects. Whether you need rock-solid motor speed regulation or precise temperature control, a properly tuned PID loop eliminates the hunting and overshoot that simple on/off or proportional-only control inevitably produces. In this comprehensive tutorial, we break down the PID algorithm from first principles, show you exactly how to implement it on Arduino hardware, and walk through two complete real-world examples — DC motor speed control and a temperature regulation system.

Table of Contents

  • What Is a PID Controller?
  • The PID Equation Explained
  • Using the Arduino PID Library
  • Project 1 – DC Motor Speed Control
  • Project 2 – Temperature PID Control
  • PID Tuning: Ziegler–Nichols and Manual Methods
  • Advanced Tips: Anti-Windup, Derivative Filter
  • Frequently Asked Questions

What Is a PID Controller?

PID stands for Proportional, Integral, Derivative. It is a closed-loop feedback control algorithm that continuously calculates an error value — the difference between a desired setpoint (SP) and a measured process variable (PV) — and applies a correction based on three terms:

  • P (Proportional): Responds to the current error. Larger error → larger correction.
  • I (Integral): Responds to accumulated past error. Eliminates steady-state offset that pure P-control leaves behind.
  • D (Derivative): Responds to the rate of change of error. Acts as a damper, preventing overshoot.

PID controllers are everywhere in the real world: industrial furnaces, automotive cruise control, quadcopter flight stabilisation, CNC machine axes, and home thermostats. On Arduino, you can implement a surprisingly capable PID loop using even the basic Uno or Nano.

Recommended: Arduino Uno R3 Beginners Kit — Ideal starting board for PID experiments; 5V logic, PWM-capable pins, and abundant community support.

The PID Equation Explained

The continuous-time PID equation is:

u(t) = Kp·e(t) + Ki·∫e(t)dt + Kd·(de/dt)

Where:

  • u(t) — controller output (e.g., PWM duty cycle 0–255)
  • e(t) — error = setpoint − measured value
  • Kp, Ki, Kd — tuning gains

For Arduino (discrete time with sample interval dt), the equation becomes:

error      = setpoint - input;
integral  += error * dt;
derivative = (error - prevError) / dt;
output     = Kp*error + Ki*integral + Kd*derivative;
prevError  = error;

The sample interval dt must be consistent. Using millis() to track time and only running the PID calculation every fixed interval (e.g., 10 ms) is the correct approach — never poll inside a delay().

Using the Arduino PID Library

Brett Beauregard’s open-source PID_v1 library is the standard choice for Arduino PID projects. Install it via the Arduino IDE Library Manager (search “PID by Brett Beauregard”).

Basic setup:

#include <PID_v1.h>

double Setpoint, Input, Output;
double Kp = 2.0, Ki = 5.0, Kd = 1.0;

PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

void setup() {
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0, 255);  // for PWM
  myPID.SetSampleTime(10);        // ms
}

void loop() {
  Input = readSensor();           // your sensor read
  myPID.Compute();                // run PID
  analogWrite(PWM_PIN, Output);  // apply output
}

The library handles sample timing internally — it will only recompute when the sample time has elapsed, so you can safely call Compute() every loop iteration.

Recommended: Arduino Mega 2560 R3 Board — Extra PWM pins and memory make it perfect for multi-axis PID systems like CNC or 3D printer control.

Project 1 – DC Motor Speed Control

In this project we use an encoder-equipped DC motor, an L298N or L293D motor driver, and a rotary encoder to close the speed loop.

Hardware Required

  • Arduino Uno or Mega
  • DC gear motor with hall-effect encoder (or optical encoder disc)
  • L298N motor driver module
  • 12 V power supply
  • Jumper wires and breadboard

Wiring Overview

  • Encoder channel A → Arduino interrupt pin 2
  • Encoder channel B → Arduino pin 3
  • L298N IN1/IN2 → Arduino digital pins 7, 8
  • L298N ENA → Arduino PWM pin 9

Complete Sketch

#include <PID_v1.h>

const int ENC_A = 2;
const int ENC_B = 3;
const int PWM_PIN = 9;
const int IN1 = 7, IN2 = 8;

volatile long encoderCount = 0;
unsigned long lastTime = 0;
long lastCount = 0;

double Setpoint = 200.0;  // target RPM
double Input, Output;
double Kp = 1.2, Ki = 0.8, Kd = 0.05;
PID motorPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

void encoderISR() {
  if (digitalRead(ENC_B)) encoderCount++;
  else encoderCount--;
}

void setup() {
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(PWM_PIN, OUTPUT);
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);  // forward
  attachInterrupt(digitalPinToInterrupt(ENC_A), encoderISR, RISING);
  motorPID.SetMode(AUTOMATIC);
  motorPID.SetOutputLimits(0, 255);
  motorPID.SetSampleTime(50);
  Serial.begin(115200);
}

void loop() {
  unsigned long now = millis();
  if (now - lastTime >= 50) {
    long count = encoderCount;
    long delta = count - lastCount;
    // Assuming 20 pulses per revolution
    Input = (delta / 20.0) * (1000.0 / 50.0) * 60.0;  // RPM
    lastCount = count;
    lastTime = now;
  }
  motorPID.Compute();
  analogWrite(PWM_PIN, (int)Output);
  Serial.print("SP:"); Serial.print(Setpoint);
  Serial.print(" RPM:"); Serial.println(Input);
}

Start with low Kp (0.5–1.5) and zero Ki, Kd. Once the motor roughly tracks the setpoint, increase Ki to eliminate steady-state error. Add a small Kd only if you see oscillation.

Project 2 – Temperature PID Control

A temperature controller is perhaps the most common PID application for makers — used in reflow ovens, sous-vide cookers, reptile enclosures, and fermentation chambers.

Hardware Required

  • Arduino Uno
  • DS18B20 or LM35 temperature sensor
  • Solid-state relay (SSR) or MOSFET module (for heater switching)
  • Resistive heating element (nichrome wire, ceramic heater, etc.)
  • 5 V power supply for Arduino
Recommended: DS18B20 Temperature Sensor Module — 1-Wire digital sensor with ±0.5°C accuracy and 12-bit resolution, ideal for PID temperature loops.
Recommended: LM35 Temperature Sensor — Analog output (10 mV/°C), no library needed, works directly with Arduino analogRead() for simple temperature PID setups.

Complete Temperature PID Sketch

#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 4
#define SSR_PIN 9
#define WINDOW_MS 5000UL  // time-proportioning window

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

double Setpoint = 60.0;  // °C target
double Input, Output;
double Kp = 5.0, Ki = 0.1, Kd = 1.0;
PID tempPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

unsigned long windowStart;

void setup() {
  sensors.begin();
  pinMode(SSR_PIN, OUTPUT);
  tempPID.SetMode(AUTOMATIC);
  tempPID.SetOutputLimits(0, WINDOW_MS);
  tempPID.SetSampleTime(1000);
  windowStart = millis();
  Serial.begin(115200);
}

void loop() {
  sensors.requestTemperatures();
  Input = sensors.getTempCByIndex(0);
  tempPID.Compute();

  // Time-proportioning output
  if (millis() - windowStart > WINDOW_MS) windowStart += WINDOW_MS;
  digitalWrite(SSR_PIN, (millis() - windowStart < Output) ? HIGH : LOW);

  Serial.print("Temp:"); Serial.print(Input);
  Serial.print(" Output:"); Serial.println(Output);
}

Time-proportioning (instead of simple PWM) is used for heaters because SSRs and heating elements respond slowly — the PID output becomes the ON-time within a 5-second window.

PID Tuning: Ziegler–Nichols and Manual Methods

Getting gains right is 80% of successful PID implementation. Two popular approaches:

Manual Tuning (Recommended for Beginners)

  1. Set Ki = 0, Kd = 0. Increase Kp until the output oscillates steadily around the setpoint.
  2. Note the oscillation period Tu. Halve Kp (this is the ultimate gain divided by 2).
  3. Set Ki = Kp / Tu. The system should now reach setpoint without steady-state error.
  4. Add Kd = Kp * Tu / 8 only if there is overshoot.

Ziegler–Nichols Closed-Loop Method

  1. Find ultimate gain Ku (value of Kp at which sustained oscillations appear).
  2. Measure oscillation period Tu.
  3. Apply: Kp = 0.6·Ku, Ki = 1.2·Ku/Tu, Kd = 0.075·Ku·Tu.

For temperature systems, start with Kp 2–10, Ki 0.05–0.5, Kd 0.5–5. For motor speed, faster dynamics demand higher Ki and lower Kd.

Advanced Tips: Anti-Windup, Derivative Filter

Integral Windup

If the output saturates (motor at full speed but can’t reach setpoint), the integral term keeps accumulating — when the system finally responds, it massively overshoots. Prevention strategies:

  • Output clamping: The PID library’s SetOutputLimits() automatically clamps the integral when output saturates.
  • Conditional integration: Only integrate when output is within limits.
  • Back-calculation: Subtract the saturation excess from the integral each cycle.

Derivative Kick

A sudden setpoint change causes a derivative spike (“D kick”). Fix: differentiate the measurement, not the error — PID_v1 does this by default when you use DIRECT mode without setpoint changes.

Derivative Filter

Noisy sensors make the D term amplify noise into wild output swings. Add a low-pass filter:

float alpha = 0.1;  // 0–1, smaller = smoother
dFiltered = alpha * (error - prevError) / dt + (1 - alpha) * dFiltered;

Sample Rate Selection

Rule of thumb: sample at 10–20× the system’s natural frequency. Slow thermal systems → 500 ms to 2 s. Fast motor loops → 5–20 ms. The Arduino Uno’s ADC conversion takes ~100 µs by default (see our fast analog read tutorial for 10× speedup).

Frequently Asked Questions

What is the best Arduino board for PID motor control?

The Arduino Uno R3 is sufficient for single-motor PID loops. For multi-axis control (e.g., CNC, 3D printer, robot arm), use the Arduino Mega 2560 which provides 15 PWM pins, more timers, and 8 KB SRAM to handle multiple concurrent PID instances without running out of memory.

How do I know if my PID is oscillating due to Kp or Kd?

If the system oscillates at a frequency close to your sample rate, it is likely derivative gain (Kd) amplifying noise — reduce Kd or add a derivative filter. If oscillations are slow and large, it is usually Kp too high — reduce it by 20–30% steps until oscillation stops.

Can I use PID without an encoder (open-loop)?

No — PID is inherently a closed-loop algorithm requiring feedback. Without measurement of the actual output (encoder counts, temperature reading, pressure sensor), there is no error to compute and the I and D terms become meaningless. The minimum viable setup is your actuator (motor/heater) plus one sensor feeding back the actual state.

Why does my temperature overshoot badly even with small Kp?

Thermal systems have significant lag — the heater puts energy in, but the sensor only sees the effect seconds later. During this lag time the integrator accumulates a large value. Reduce Ki significantly (start at 0.01–0.05), increase the time-proportioning window, and ensure your sensor is physically close to the heated element.

Does the Arduino PID library work on ESP32 and STM32?

Yes. PID_v1 uses standard C++ with no AVR-specific dependencies. It compiles cleanly on ESP32, ESP8266, STM32 (via STM32duino), and Raspberry Pi Pico (Arduino core). You may want to increase sample rates on 32-bit boards since they have faster ADCs and more SRAM.

Understanding and implementing an Arduino PID controller opens the door to genuinely precise and professional-grade projects. Start with the temperature controller — it is forgiving of slow tuning — then move to motor control once you are comfortable reading the response curves. With the right gains and good sensor placement, your system will hit its setpoint smoothly and hold it rock-steady.

Ready to build your PID project? Browse our full range of Arduino boards and modules at Zbotic — all shipped fast across India with GST invoice.

Tags: Arduino, arduino tutorial, control systems, motor control, pid controller, temperature control
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Best Arduino Clone Boards: CH3...
blog best arduino clone boards ch340 vs ftdi and what to buy 594698
blog arduino uart vs spi vs i2c choosing the right protocol 594700
Arduino UART vs SPI vs I2C: Ch...

Related posts

Svg%3E
Read more

Arduino Batch Programming: Flash Multiple Boards Quickly

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Based Radar System with Ultrasonic Sensor

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Automatic Plant Monitor: Sunlight, Moisture, Temperature

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Lie Detector: GSR Sensor Polygraph Project

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Metal Detector: Build a Treasure Finder

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now