Skip to content

Arduino - DC Motor

A DC motor (Direct Current motor) is the most common type of motor, used in everything from toys to fans to robot wheels. This tutorial will guide you through controlling a DC motor’s on/off state, speed, and direction using modern components and best practices.

Critical Safety Warning: Never connect a motor directly to an Arduino’s digital pins. Motors are inductive loads that can draw far more current than a pin can supply, and they generate voltage spikes when turned off. Doing so will permanently damage your Arduino. Always use a dedicated motor driver circuit.

Part 1: Simple On/Off Control with a MOSFET

Section titled “Part 1: Simple On/Off Control with a MOSFET”

To safely switch a motor on and off, we will use a MOSFET, which acts as a robust, electronically controlled switch.

  • 1 × Arduino UNO
  • 1 × Small DC Motor (e.g., 5V-9V)
  • 1 × Logic-Level N-Channel MOSFET (e.g., TIP120, IRLZ44N). A TIP120 is a Darlington Transistor but works similarly here.
  • 1 × 1N4001 Diode (or similar). This is the crucial flyback diode.
  • 1 × Separate Power Supply for the Motor (e.g., a 9V battery or a 4xAA battery pack). This is highly recommended.
  • Jumper Wires and a Breadboard

The MOSFET has three pins: Gate, Drain, and Source. The Arduino sends a signal to the Gate to control the flow of current from the Drain to the Source.

  1. Connect the MOSFET Source to the Ground rail of your breadboard.
  2. Connect the Arduino’s GND pin to the same Ground rail.
  3. Connect the Ground of your motor’s power supply to the same Ground rail. All grounds must be connected.
  4. Connect Arduino Pin 9 to the MOSFET Gate.
  5. Connect one motor terminal to the MOSFET Drain.
  6. Connect the other motor terminal to the Positive terminal of your motor’s power supply.
  7. Crucially, connect the 1N4001 diode in parallel with the motor. The diode’s stripe (cathode) must connect to the positive side, and the non-striped side (anode) to the negative (MOSFET Drain) side. This protects your circuit from voltage spikes.
const int motorPin = 9; // Use a PWM pin
void setup() {
// Set the motor control pin as an output
pinMode(motorPin, OUTPUT);
}
void loop() {
// Turn the motor on to full speed
digitalWrite(motorPin, HIGH);
delay(2000); // Run for 2 seconds
// Turn the motor off
digitalWrite(motorPin, LOW);
delay(2000); // Wait for 2 seconds
}

We can easily extend the previous circuit to control speed. By using Pulse-Width Modulation (PWM) with analogWrite(), we can vary the average voltage supplied to the motor, thus controlling its speed.

This code will make the motor ramp up to full speed and then ramp down.

const int motorPin = 9; // Must be a PWM pin (marked with ~ on Uno)
void setup() {
pinMode(motorPin, OUTPUT);
}
void loop() {
// Ramp up speed
for (int speed = 0; speed <= 255; speed++) {
analogWrite(motorPin, speed);
delay(10);
}
// Ramp down speed
for (int speed = 255; speed >= 0; speed--) {
analogWrite(motorPin, speed);
delay(10);
}
}

Part 3: Controlling Direction with an H-Bridge

Section titled “Part 3: Controlling Direction with an H-Bridge”

To make a motor spin in both directions, we need an H-Bridge. This circuit can reverse the polarity of the voltage applied to the motor. The L298N module is a common, though inefficient, H-bridge driver perfect for beginners.

While we will use the L298N, for your future projects, consider a more modern driver like the TB6612FNG. It is much more efficient (less power wasted as heat), smaller, and requires less current to operate, making it a superior choice.

The L298N module controls two motors. We will use ‘Motor A’.

  1. Connect your motor to the OUT1 and OUT2 screw terminals.
  2. Connect your motor’s external power supply to the VMS (or 12V) and GND screw terminals.
  3. Remove the 5V enable jumper if one is present.
  4. Connect the L298N GND to the Arduino GND.
  5. Connect L298N IN1 to Arduino Pin 8.
  6. Connect L298N IN2 to Arduino Pin 7.
  7. Connect L298N ENA (Enable A) to Arduino PWM Pin 9.

This code uses helper functions for clean, readable control.

// L298N H-Bridge Pin Definitions
const int motorEnablePin = 9; // ENA - Must be PWM
const int motorIn1Pin = 8; // IN1
const int motorIn2Pin = 7; // IN2
void setup() {
// Set all control pins to outputs
pinMode(motorEnablePin, OUTPUT);
pinMode(motorIn1Pin, OUTPUT);
pinMode(motorIn2Pin, OUTPUT);
}
void loop() {
// Move forward at full speed for 2 seconds
moveMotor(255, true);
delay(2000);
// Stop for 1 second
stopMotor();
delay(1000);
// Move backward at half speed for 2 seconds
moveMotor(128, false);
delay(2000);
// Brake for 1 second
brakeMotor();
delay(1000);
}
/**
* @brief Controls the motor's speed and direction.
* @param speed The speed from 0 (off) to 255 (full).
* @param forward True for forward, false for backward.
*/
void moveMotor(int speed, bool forward) {
if (forward) {
digitalWrite(motorIn1Pin, HIGH);
digitalWrite(motorIn2Pin, LOW);
} else {
digitalWrite(motorIn1Pin, LOW);
digitalWrite(motorIn2Pin, HIGH);
}
analogWrite(motorEnablePin, speed);
}
/**
* @brief Stops the motor by letting it coast freely.
*/
void stopMotor() {
// Disables the motor driver
analogWrite(motorEnablePin, 0);
}
/**
* @brief Actively brakes the motor by shorting its terminals.
*/
void brakeMotor() {
digitalWrite(motorIn1Pin, HIGH);
digitalWrite(motorIn2Pin, HIGH);
analogWrite(motorEnablePin, 255); // Brake needs to be enabled
}