DEV Community

Hedy
Hedy

Posted on

How to control DC motor with Arduino?

Here are two reliable ways to control a brushed DC motor with Arduino—one-direction speed control (simplest) and full direction + speed with an H-bridge.

Option A — One direction (speed only) with a logic-level N-MOSFET

Use when: you just need on/off + speed control.

Parts

Wiring

Motor +  ─────────── +VMOTOR (battery/PSU)
Motor −  ──•── D (MOSFET)
           |
          S (MOSFET) ─── GND (shared with Arduino)
          G (MOSFET) ── 100Ω ── D9 (PWM)
                     └─ 10kΩ ── GND  (pull-down)
Flyback diode: anode to MOSFET D / motor−, cathode to +VMOTOR
Arduino GND ──────────────────── common with VMOTOR GND
Enter fullscreen mode Exit fullscreen mode

Code (speed with PWM on pin 9)

const int PWM_PIN = 9;   // any PWM-capable pin (Uno: 3,5,6,9,10,11)
void setup() {
  pinMode(PWM_PIN, OUTPUT);
}
void loop() {
  // ramp up
  for (int s = 0; s <= 255; s++) { analogWrite(PWM_PIN, s); delay(10); }
  delay(1000);
  // ramp down
  for (int s = 255; s >= 0; s--) { analogWrite(PWM_PIN, s); delay(10); }
  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Notes

  • Choose a MOSFET with low Rds(on) at Vgs = 4–5 V and current rating ≥ motor stall current.
  • Keep Arduino 5 V separate from motor supply; only GND is common.
  • Put a 0.1 µF ceramic across motor terminals (and 100 µF across supply) to tame noise.

Option B — Direction + speed with a dual H-bridge (e.g., TB6612FNG or DRV8833)

Use when: you need forward/reverse, brake, and efficient drive (better than L298N).

Parts

  • Arduino
  • TB6612FNG (pins: AIN1/AIN2/PWMA/STBY + BIN1/BIN2/PWMB if using 2nd channel)
  • Motor + external supply (e.g., 6–12 V)
  • Wires; decoupling caps

Wiring (one motor on channel A)

VM  (driver) ─── +VMOTOR
GND (driver) ─── GND (shared with Arduino & motor supply)
VCC (driver) ─── 5V from Arduino
AIN1 ─────────── D7
AIN2 ─────────── D8
PWMA ─────────── D9 (PWM)
STBY ─────────── D6 (tie HIGH to enable)
Motor A+ ─────── Motor +
Motor A− ─────── Motor −
Enter fullscreen mode Exit fullscreen mode

Code (forward/reverse/brake + PWM speed)

const int AIN1 = 7, AIN2 = 8, PWMA = 9, STBY = 6;

void setup() {
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(STBY, OUTPUT);
  digitalWrite(STBY, HIGH); // exit standby
}

void drive(int speed) { // speed: -255..255 (sign = direction)
  if (speed > 0) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); }
  else if (speed < 0) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); speed = -speed; }
  else { // brake
    digitalWrite(AIN1, HIGH); digitalWrite(AIN2, HIGH);
  }
  analogWrite(PWMA, constrain(speed, 0, 255));
}

void loop() {
  drive(180); delay(2000);   // forward
  drive(0);   delay(500);    // brake
  drive(-180);delay(2000);   // reverse
  drive(0);   delay(1000);   // brake
}
Enter fullscreen mode Exit fullscreen mode

Why TB6612/DRV8833 over L298N?

Much lower losses (MOSFET vs bipolar), runs cooler, works well at 3.3–5 V logic, handles fast PWM.

Sizing & safety checklist

  • Supply: motor current at load and at stall; PSU must handle stall or use current limiting/slow-start.
  • Grounds: Arduino GND ↔ motor driver GND must be common.
  • Protection: always include a flyback path (diode or the H-bridge’s body diodes). Add a polyfuse if you expect stalls.
  • Noise/EMI: twist motor wires, add caps (0.1 µF at motor, 100 µF near driver), keep high-current loops short.
  • PWM frequency: Arduino Uno PWM is ~490 Hz (pins 3,9,10,11 ~490; 5,6 ~980 Hz). For audible whine reduction, use pins 5/6 or change timer prescalers/libraries.

Picking a driver (quick guide)

  • Small toy motors (<1 A): L9110S, DRV8833.
  • 1–2 A range: TB6612FNG, DRV8833/DRV8838.
  • >3 A or big motors: DRV8871/8876 single-channel, or a MOSFET H-bridge module; consider heat sinking.

Top comments (0)