The code is four lines and works first time. The wiring is where this circuit goes wrong, and it goes wrong in a way that looks like a software bug.
The mistake everyone makes first
// This does not work.
pinMode(9, OUTPUT);
analogWrite(9, 200); // motor connected straight to pin 9
An ATmega pin supplies about 20 mA comfortably. A small DC motor draws well over a hundred milliamps turning freely and close to an amp when stalled. The pin cannot deliver that. The motor sits still, the code looks correct, and the datasheet limit that was quietly exceeded is not visible anywhere in your sketch.
This is also why every simulator that lets a motor spin straight off a pin is teaching you something that will not survive contact with hardware.
The circuit that does work
One transistor, used as a switch below the motor:
| part | where it goes | why |
|---|---|---|
| Motor + | to the positive supply | current comes from the supply, not the pin |
| Motor − | to the transistor's collector | the transistor completes the circuit |
| NPN (2N2222) emitter | to ground | shared with the Arduino's GND |
| Base resistor, 1 kΩ | from a PWM pin to the base | limits base current |
| Flyback diode (1N4007) | across the motor, cathode to + | absorbs the inductive kick |
The pin now switches a few milliamps into the base; the motor's current flows through the transistor from the supply. The microcontroller controls, it does not carry.
The flyback diode is not optional. A motor is an inductor. When the transistor turns off, the collapsing magnetic field drives the collector voltage well above the supply, and without a path for that current the transistor eventually dies — usually after working perfectly for a while first, which makes it hard to diagnose.
Speed from duty cycle
const int MOTOR_PIN = 9;
const int POT_PIN = A0;
void setup() {
pinMode(MOTOR_PIN, OUTPUT);
}
void loop() {
int raw = analogRead(POT_PIN); // 0..1023
int speed = map(raw, 0, 1023, 0, 255); // 0..255
analogWrite(MOTOR_PIN, speed);
delay(20);
}
analogWrite is not analogue. It switches the pin on and off about 500 times a second, and the value from 0 to 255 sets the fraction of each cycle it spends high. What reaches the motor is the average of that switching.
Running exactly this sketch on a simulated Nano with the transistor circuit above:
| pot voltage | duty cycle | motor sees | speed |
|---|---|---|---|
| 0.00 V | 0.0% | 0.00 V | stopped |
| 1.25 V | 24.7% | 1.19 V | 915 rpm |
| 2.50 V | 49.8% | 2.39 V | 2521 rpm |
| 3.75 V | 74.9% | 3.60 V | 4127 rpm |
| 5.00 V | 100.0% | 4.80 V | 5733 rpm |
The motor voltage never quite reaches 5 V because the transistor drops a couple of tenths across itself when saturated. That is real and it is why the last row is 4.80 V rather than 5.00 V.
Average, not RMS
Here is the part that trips up people who already know some electronics. Motor speed follows the average of the PWM waveform, not its RMS value.
At 50% duty on a 5 V supply:
- average = 2.5 V → the motor runs at about half speed
- RMS = 3.54 V → would predict about 71%
Torque is proportional to current, current is proportional to applied voltage, and the rotor's inertia integrates the result — so the arithmetic that matters is the mean. RMS is the correct quantity when you are heating something, a resistor or a lamp filament, where power goes as the square of voltage. Using it for a motor overestimates speed by about 41% at half duty, which is exactly the setting a speed-control demo is most likely to use.
That inertia also explains why 500 Hz PWM does not make the motor stutter. The mechanical time constant is tens of milliseconds and the switching period is two — the rotor is a low-pass filter and it smooths the pulses on its own.
Why you do not need a driver IC for this
An L293D or L298N gives you two things: more current than a single transistor, and direction control through an H-bridge. If you only want speed in one direction, one transistor and one diode do the job, and understanding those two parts is worth more than wiring a module whose internals stay opaque.
You need the driver when you want the motor to reverse, or when the current is beyond what a small transistor handles.
Try it
CircuPilot simulates this end to end: the compiled sketch runs on a cycle-accurate AVR emulator, the PWM duty cycle is measured off the pin itself, and the motor on the canvas turns at the speed the duty cycle implies — with the rotor spinning up and slowing down rather than snapping between values.
Both kinds of PWM work. analogWrite works, and so does a loop that toggles the pin with delayMicroseconds — which is worth trying once, because it makes it obvious that PWM is nothing more than switching fast and counting the time.
Related
- Generating PWM without a microcontroller: 555 timer astable calculator and simulator
- Reading the potentiometer that sets the speed: simulate analogRead with a potentiometer
- Getting an Arduino circuit running in the browser: how to simulate an Arduino circuit online
Frequently asked questions
Can an Arduino pin drive a DC motor directly?
No. An ATmega pin supplies about 20 mA comfortably and 40 mA absolutely, while even a small toy motor draws well over a hundred milliamps running and close to an amp stalled. The pin will not deliver it, and trying usually damages the chip. Use a transistor, a MOSFET or a driver IC as a switch, with the motor's current coming from the supply rather than through the microcontroller.
Why does my motor not turn even though the code is right?
Almost always because the motor is wired straight to the pin. The pin goes high, the motor loads it down, and nothing turns. The second most common cause is a missing ground connection between the motor's supply and the Arduino — the transistor's emitter and the Arduino's GND must be the same node.
Does motor speed follow the RMS or the average of a PWM signal?
The average. Torque is proportional to current, current is proportional to the applied voltage, and the rotor's inertia integrates it — so a 50% duty cycle on a 5 V supply behaves like 2.5 V. RMS would give 3.54 V, which is about 41% too high. RMS is the right quantity for heating a resistor or a lamp filament, not for a DC motor's speed.
What does the flyback diode do?
A motor is an inductor, and when the transistor switches off, the collapsing field drives the collector voltage far above the supply. The diode, connected across the motor with its cathode to the positive rail, gives that current somewhere to go. Without it the transistor eventually fails, often after working fine for a while.
Which Arduino pins can do PWM?
On an Uno or Nano: D3, D5, D6, D9, D10 and D11. analogWrite on any other pin behaves like digitalWrite — anything above 127 goes high, anything below goes low — which looks like a motor that only runs at full speed or not at all.