Built-in project · Arduino Uno R3

Motor on a transistor, on an Arduino Uno

A DC motor driven from pin 9 through a 2N2222, with a flyback diode across it. The PWM ramps up and down and the shaft follows. The whole build, an Arduino Uno and 4 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 20 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $33. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Switching a motor with a transistor
  • PWM speed control
  • A flyback diode protecting the transistor
  • Ramping a value up and down
  • Why a pin cannot drive a motor directly
  • Difficulty: Intermediate
  • Time: About 20 minutes
  • Board: Arduino Uno R3
  • Parts: 6

How it works

A pin can only give about 20 mA, far too little for a motor. So pin 9 feeds a transistor base through a 1k resistor, and the transistor switches the motor's much larger current to ground. The motor's other side is on 5V.

PWM on pin 9 switches the motor on and off quickly, and the motor averages it into a speed. The duty rises from 0 to 255 and back in steps of 5 every 40 ms, about four seconds per cycle. A diode across the motor catches the voltage spike when the current stops.

Parts list

6 parts, plus the jumper wires. They retail for about $33; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Resistor, 1k Ω pin 1Arduino Uno R3 pin 9
Diode pin CArduino Uno R3 pin 5V
DC motor pin 1Arduino Uno R3 pin 5V
Transistor (NPN or PNP) pin EArduino Uno R3 pin GND
Resistor, 1k Ω pin 2Transistor (NPN or PNP) pin B
Diode pin ATransistor (NPN or PNP) pin C
DC motor pin 2Transistor (NPN or PNP) pin C

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Motor ramp: a motor through a transistor, sped up and slowed down.
//
//   pin 9  through 1 k into the transistor's base
//   the transistor's emitter to GND, its collector to one motor terminal
//   the other motor terminal to 5 V, and a diode across the motor with its
//   band (cathode) on the 5 V side
//
// A board pin can give about 20 mA. A small motor wants ten times that
// standing still, so the pin drives a transistor and the transistor drives the
// motor: a little base current through the 1 k lets a much larger one through
// from collector to emitter. The PWM on pin 9 switches that current on and
// off 490 times a second, and the motor's own inertia averages it into a
// speed.
//
// # The diode
//
// A motor is a coil. The instant its current is cut, the coil tries to keep it
// flowing and the voltage on the collector flies up until something gives,
// which is usually the transistor. The diode across the motor gives the
// current a way round instead: it is reverse biased while the motor runs and
// only conducts on that kick. Leave it out on the bench and the transistor
// lasts an afternoon.
//
// The duty walks from 0 to 255 and back, five counts every 40 ms, so a whole
// cycle takes about four seconds.

const int DRIVE = 9;
const int STEP = 5;
const int STEP_MS = 40;

int duty = 0;
int direction = STEP;

void setup() {
  pinMode(DRIVE, OUTPUT);
  analogWrite(DRIVE, 0);
  Serial.begin(115200);
  Serial.println("Mokxi Uno: motor on a transistor, pin 9 PWM");
}

void loop() {
  analogWrite(DRIVE, duty);
  if (duty % 50 == 0) {
    Serial.print("duty ");
    Serial.print(duty);
    Serial.println(" / 255");
  }
  duty += direction;
  if (duty >= 255) {
    duty = 255;
    direction = -STEP;
  } else if (duty <= 0) {
    duty = 0;
    direction = STEP;
  }
  delay(STEP_MS);
}

Code walkthrough

The key functions of the sketch, and what each one does.

setup sketch.ino

Makes DRIVE an output and starts it at 0 so the motor is off. It then opens the serial port at 115200 and prints a hello line.

void setup() {
  pinMode(DRIVE, OUTPUT);
  analogWrite(DRIVE, 0);
  Serial.begin(115200);
  Serial.println("Mokxi Uno: motor on a transistor, pin 9 PWM");
}

loop sketch.ino

Writes duty to pin 9, prints it every 50 counts, then adds direction. When the duty reaches 255 it turns around and counts down. At 0 it counts up again. Each pass waits STEP_MS, 40 ms.

void loop() {
  analogWrite(DRIVE, duty);
  if (duty % 50 == 0) {
    Serial.print("duty ");
    Serial.print(duty);
    Serial.println(" / 255");
  }
  duty += direction;
  if (duty >= 255) {
    duty = 255;
    direction = -STEP;
  } else if (duty <= 0) {
    duty = 0;
    direction = STEP;
  }
  delay(STEP_MS);
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The motor does not spin This project
    Check the transistor pins: emitter to ground, collector to the motor, base through the 1k to pin 9.
  • The transistor gets hot or fails This project
    Put the diode across the motor with its band (cathode) on the 5V side.
  • The load never turns on, or is always on, because the legs are in the wrong order. Transistor (NPN or PNP)
    Check the pinout in the datasheet for your part. A 2N2222 or BC547 can have emitter, base, collector in a different order. Flat side orientation is easy to get wrong.
  • The base is wired straight to the pin with no resistor, or the motor has no flyback diode. Transistor (NPN or PNP)
    Put about 1k between the pin and the base. For motors and relays, add a diode across the coil with the stripe toward the positive side.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • The diode is in backwards, so nothing flows, or a flyback diode conducts all the time. Current flows from the anode to the cathode, the end with the stripe. Diode
    Put the striped end toward the more positive side for a series diode. For flyback across a coil, the stripe goes to the positive supply side of the coil.
  • A diode in series drops about 0.7 V (silicon) and 0.3 V (Schottky), so the output is lower than expected. A 1N4148 is also too small for big currents. Diode
    Count the drop in your voltage budget. Use a 1N4007 or similar for amps, and a Schottky when you need a small drop.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.