To drive a vibration motor with an Arduino, you must choose between an Eccentric Rotating Mass (ERM) motor for simple on/off buzzing or a Linear Resonant Actuator (LRA) for crisp, programmable haptic feedback. You cannot drive either directly from an Arduino GPIO pin. An ATmega328P GPIO maxes out at 20mA, while even small haptic motors demand 50mA to 120mA. ERMs require a logic-level MOSFET switch, while LRAs demand a dedicated haptic driver IC like the TI DRV2605L to manage AC waveform generation and auto-resonance tracking.
This guide breaks down the physics, sizing math, and exact wiring topologies for integrating haptic feedback into your embedded projects, assuming a standard 5V Arduino Uno or 3.3V ESP32 environment at 25°C ambient.
ERM vs LRA vs Piezo: Which Vibration Motor Fits Your Load?
The load profile for a vibration motor is not a traditional mechanical shaft load; it is the mass of the enclosure you are trying to accelerate. Choosing the wrong type results in a weak, muddy buzz or a high-pitched whine. Below is the definitive comparison for haptic actuation.
| Motor Type | Torque/Force Profile | Control Needs | Typical Cost (2026) | Best Use Case |
|---|---|---|---|---|
| ERM (Eccentric Rotating Mass) | Broadband, frequency-dependent. Force increases with RPM. Slow start/stop (20-50ms). | Simple DC PWM via logic-level N-channel MOSFET. | $0.80 - $2.50 | Game controllers, basic alerts, pagers, low-cost wearables. |
| LRA (Linear Resonant Actuator) | Narrowband peak at resonant frequency (usually 175Hz). Fast start/stop (<10ms). High peak G-force. | AC sine/square wave driver with auto-resonance tracking (e.g., DRV2605L). | $2.00 - $5.50 | Smartwatches, premium UI 'clicks', medical wearables, VR haptics. |
| Piezo Bender | Extremely high frequency (200Hz-300Hz+), very low displacement. Instantaneous response. | High-voltage AC driver (often requires a step-up transformer or dedicated piezo IC). | $3.00 - $8.00 | Ultra-thin devices, silent alerts, high-fidelity texture simulation. |
The Verdict: If your application only needs to notify the user that an event occurred (like a washing machine finishing a cycle), an ERM is cheaper and easier to code. If you are building a UI where the user needs to feel distinct 'clicks', 'bumps', or textures (like a smart thermostat dial), you must use an LRA.
Sizing Rule of Thumb: Matching Motor Force to Enclosure Mass
A common mistake in embedded haptics is buying a motor based solely on its physical diameter (e.g., '10mm coin motor') without calculating the required acceleration. The sizing rule of thumb relies on Newton's second law: Acceleration (G-force) = Motor Force / Mass of Object.
For a haptic 'click' to be distinctly perceptible to human skin through a plastic or aluminum enclosure, you need to generate a minimum of 1.5G to 2.0G of peak acceleration. For a rumble or ambient alert, 0.5G to 1.0G is sufficient.
Target: Crisp UI click (2.0G peak acceleration).
Mass: 100g (0.1 kg).
Required Force: F = m × a. In G-force terms, a motor rated for 2.0G at a 100g test mass will deliver exactly what you need. Looking at manufacturer spec sheets, a standard 8mm ERM (like the Vybronics 304-103) only produces about 0.8G at 100g—resulting in a weak, muddy feel. However, a 10mm LRA (like the Jinlong COPAL Z622015) produces 2.2G at a 100g test mass. Selection: The 10mm LRA is the correct choice for this load profile.
| Part Number (Example) | Type | Diameter | Rated Voltage | Resonant Freq | Peak Accel (at rated mass) |
|---|---|---|---|---|---|
| Vybronics 304-103 | ERM | 10mm | 3.0V DC | N/A (Broadband) | 0.8G @ 100g |
| Jinlong Z622015 | LRA | 10mm | 2.0V RMS | 175Hz ± 15Hz | 2.2G @ 100g |
| ADA-1895 (Adafruit) | ERM | 12mm | 5.0V DC | N/A (Broadband) | 1.2G @ 150g |
| TI Haptic Eval Kit | LRA | 20mm | 2.0V RMS | 150Hz ± 10Hz | 4.5G @ 200g |
Wiring and Terminal Identification: DRV2605L and Discrete MOSFETs
How you wire the motor depends entirely on the type you selected. Never connect a motor terminal directly to an Arduino digital pin; the inductive kickback will destroy the microcontroller's output stage.
Wiring an LRA with the TI DRV2605L
The Texas Instruments DRV2605L is the industry standard for LRA control. It handles the complex AC waveform generation and auto-resonance tracking via I2C.
- VIN / VCC: Connect to Arduino 5V (or 3.3V if using an ESP32 and a breakout with an onboard regulator).
- GND: Connect to Arduino GND.
- SCL / SDA: Connect to I2C pins (A5/A4 on Uno, GPIO 22/21 on ESP32).
- OUT+ / OUT-: Connect directly to the LRA terminals. Polarity does not matter for the motor itself, but keep the wires short to minimize parasitic inductance.
Wiring an ERM with a Discrete MOSFET
For an ERM, use a logic-level N-channel MOSFET like the IRLZ44N or a smaller 2N7000 for low-current coin motors.
- Gate: Connect to Arduino PWM pin via a 220Ω resistor. Add a 10kΩ pulldown resistor from Gate to GND to prevent the motor from spinning during Arduino boot-up.
- Drain: Connect to the negative terminal of the ERM.
- Source: Connect to GND.
- Motor Positive: Connect to your power supply (e.g., 3.3V or 5V, matching the motor's rated voltage).
- Flyback Diode: Place a 1N4148 or BAT54 Schottky diode across the motor terminals (cathode to positive, anode to negative). This clamps the inductive voltage spike when the MOSFET turns off.
Failure Signatures: Diagnosing Hum, Overheat, and Stall
Haptic motors fail in highly specific ways that tell you exactly what is wrong with your circuit or code. Here is the diagnostic matrix for the most common bench failures.
1. The 'Hum' or 'Whine' (Audible Noise, Weak Vibration)
Culprit: Driving an LRA off-resonance, or PWM frequency too low on an ERM.
The Physics: An LRA is a spring-mass system. If you drive it at 50Hz but its resonant frequency is 175Hz, the mass barely moves, and the energy is dissipated as audible coil whine. For ERMs, if your Arduino PWM frequency is below 20kHz (the default on some Uno pins is ~490Hz), you will hear the PWM switching frequency as a high-pitched whine.
The Fix: For LRAs, ensure your driver IC (like the DRV2605L) is set to 'Auto-Resonance' mode, not 'Closed-Loop' with a hardcoded frequency. For ERMs, change the Arduino PWM timer prescalers to push the frequency above 20kHz, or accept the noise if the application permits.
2. Overheat (Motor casing > 60°C, smell of melting enamel)
Culprit: Continuous 100% duty cycle without thermal management, or driving an LRA with DC voltage.
The Physics: Haptic motors are rated for intermittent duty (usually 1-2 seconds on, followed by a cooldown). Driving them continuously causes the copper windings to exceed their thermal limits. Furthermore, if you apply raw DC voltage to an LRA, the mass slams to one side of the spring and sits there, turning the coil into a pure resistive heater.
The Fix: Implement a software watchdog that limits haptic events to 2-second bursts. Never wire an LRA directly to a DC power rail; always use an AC-coupled driver.
3. Stall and Magic Smoke (MOSFET burns out, motor seizes)
Culprit: Mechanical jam on an ERM causing locked-rotor current spike.
The Physics: When an ERM stalls, back-EMF drops to zero, and the motor draws its maximum stall current (often 3x to 5x the running current). If your MOSFET or power supply cannot handle this, or if the flyback diode is missing, the inductive spike will punch through the MOSFET's drain-source junction.
The Fix: Ensure your flyback diode is correctly oriented. If the motor is in a high-impact environment where mechanical jamming is possible, add a polyfuse (PTC) in series with the motor's positive supply line to limit stall current.
When wiring the DRV2605L to an ESP32 or a bare ATmega328P chip, ensure your I2C bus has 4.7kΩ pull-up resistors on SDA and SCL to VCC. Many cheap breakout boards omit these to save $0.02 in manufacturing. Without them, the Arduino will hang on
Wire.endTransmission() or fail to initialize the haptic driver.
Implementing the DRV2605L: Copy-Paste Arduino Code
Below is a robust implementation using the Adafruit DRV2605L library. This code initializes the driver, sets it to auto-resonance mode for an LRA, and triggers a sharp 'click' waveform from the built-in ROM library.
#include <Wire.h>
#include <Adafruit_DRV2605.h>
Adafruit_DRV2605 drv;
void setup() {
Serial.begin(115200);
// Initialize I2C and check for DRV2605L at address 0x5A
Wire.begin();
if (!drv.begin()) {
Serial.println(F('Could not find DRV2605L at I2C address 0x5A. Check wiring and pull-ups.'));
while (1) { delay(10); } // Halt execution
}
Serial.println(F('DRV2605L initialized successfully.'));
// Select Library 6 (LRA waveforms, sharp clicks and transitions)
// Library 1-5 are optimized for ERM motors
drv.selectLibrary(6);
// Set I2C control mode (default)
drv.setMode(DRV2605_MODE_INTTRIG);
}
void loop() {
// Trigger a 'Sharp Click 1' (Waveform sequence 1 in Library 6)
drv.setWaveform(0, 1);
drv.setWaveform(1, 0); // End of sequence marker
drv.go(); // Fire the haptic engine
Serial.println(F('Haptic click triggered.'));
// Wait 2 seconds before next click (respecting intermittent duty cycle)
delay(2000);
}
By matching the correct motor topology to your enclosure mass and using the appropriate driver IC, you eliminate the trial-and-error phase of haptic design. Remember that the physical coupling of the motor to your enclosure—using double-sided VHB tape or a press-fit silicone gasket—will affect the perceived G-force just as much as the electrical drive signal.






