In the picture above, from left to right: The L298N motor driver, the TIP122 Darlington transistor, and the DRV8871 motor driver.
Any DC motor can be driven with PWM signals. Whether it is a miniature 3V motor for toys, or a large 12V or 24V motor for your lawn mower, the principle of operation is the same.
The larger the motor is, the more current it will require, and this is the key to controlling it efficiently and safely from your Arduino.
A motor draws the most current when it starts. A 3V DC motor with a 15Ohm total resistance in its coil will draw 0.2A. This is within the Arduino’s I/O pin current limit, but if your motor’s resistance is a bit smaller, the current can easily become more than the 0.4A limit. That’s why we use a motor shield or some other way to power the motor.
Things get worse for large motors. A 12V DC motor with nominal resistance in its coil of 15Ohm will draw around 0.8A of current when it’s starting its rotation. That’s way too much and it can destroy your Arduino.
The L298N motor driver is easy to use and cheap, but it’s peak current capability is 3A. If you want to drive a motor for a ceiling fan, this will not work.
Another motor driver is the DRV8871 which allows you to control a single DC motor. Like the L298N, you can apply PWM to control the speed of the motor. Like the L298N, you can also drive other loads using PWM, like 12V LED strips, as long as they stay within its operating parameters: 6.5V to 45V, and 3.6A peak current. What I really like about the DRV8871 is its small size, and its safety features, like over-current protection and thermal shutdown.
An easy way to control large DC motors is to use a transistor that can provide the required amount of current in its collector.
The Darlington TIP122 can provide 8A of continuous current in its collector and 15A of peak current, great for when a large motor starts. You can easily drive it with the Arduino since it only needs 2.5V in its base in order to switch it on. Add a resistor (~1KOhm) to protect the Arduino across the base of the transistor, and a diode (like the 1N4004) to deal with back-currents from the motor, and you have your own motor driver, capable of regulating the motor speed using PWM. If your motor is brushed, also add a small capacitor (~1uF) across the terminals of the motor.
With a bit of logic in your sketch and two TIP102 in your circuit, you can also reverse the motor.
You can find lectures on how to use these DC motor drivers in our courses. In lectures 900b and 900cof Arduino Step by Step Getting Serious you can learn about the L298N. You can see a sample sketch on the course repository.
You can learn how to use the DRV8871 in lecture 0903a, and find an example sketch on the course repository.
You can learn how to use the TIP122 with a 12V LED strip in the 10 lectures of section 14, starting with lectures 810a. While controlling LEDs and DC motors is not the same, these lectures will teach you how to use the TIP122. Example code is in the course code repository.