← Back to store

DC Motor Controller

FirmwareArduino

PID-controlled DC motor driver with encoder feedback. Speed control, direction, and smooth acceleration.

Features

Wiring (Arduino Uno + L298N)

D9ENA (PWM speed control) D8IN1 (direction A) D7IN2 (direction B) D2Encoder A (interrupt) D3Encoder B (interrupt) GNDCommon ground

Code

// DC Motor PID Controller — FreeRobotStore
// MIT License | freerobotstore.online/robots/motor-controller

const int ENA = 9;
const int IN1 = 8;
const int IN2 = 7;
const int ENCA = 2;
const int ENCB = 3;

// PID gains — tune for your motor
float Kp = 2.0, Ki = 0.5, Kd = 0.1;
float targetRPM = 120.0;

volatile long encoderCount = 0;
float integral = 0, prevError = 0;
unsigned long lastTime = 0;
long lastCount = 0;

void setup() {
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENCA, INPUT_PULLUP);
  pinMode(ENCB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCA), readEncoder, RISING);
  Serial.begin(115200);
  setDirection(1); // forward
}

void loop() {
  unsigned long now = millis();
  if (now - lastTime < 50) return; // 20Hz control loop

  float dt = (now - lastTime) / 1000.0;
  long count = encoderCount;
  float rpm = ((count - lastCount) / 600.0) * (60.0 / dt);

  // PID
  float error = targetRPM - rpm;
  integral += error * dt;
  integral = constrain(integral, -100, 100);
  float derivative = (error - prevError) / dt;
  float output = Kp * error + Ki * integral + Kd * derivative;
  prevError = error;

  int pwm = constrain((int)output, 0, 255);
  analogWrite(ENA, pwm);

  Serial.print("RPM: "); Serial.print(rpm, 1);
  Serial.print(" | PWM: "); Serial.print(pwm);
  Serial.print(" | Err: "); Serial.println(error, 2);

  lastTime = now;
  lastCount = count;
}

void readEncoder() {
  int b = digitalRead(ENCB);
  encoderCount += (b > 0) ? 1 : -1;
}

void setDirection(int dir) {
  digitalWrite(IN1, dir > 0 ? HIGH : LOW);
  digitalWrite(IN2, dir > 0 ? LOW : HIGH);
}

Usage

1. Copy the code into Arduino IDE. 2. Adjust Kp, Ki, Kd for your motor. 3. Set targetRPM. 4. Open Serial Monitor at 115200 baud to see RPM, PWM output, and error.

Tuning Tips

MIT License | FreeRobotStore