From Feeling to Firmware: Build Your First Haptic Feedback Device (10 Minutes)
Subtitle: Stop asking "what motor should I use." Start with "what do I want this to feel like."
The Moment Your Device Misses the Point
You built it. The sensor detects. The motor spins. The code compiles clean.
But when you hold it -- the vibration is technically there, but it's emotionally absent.
You didn't build the wrong thing. You built the right parts in the wrong order.
Most tutorials start with components. You started with components too. That's not the failure -- the failure is that you never stepped back and asked:
"Before I pick a motor, what feeling am I actually trying to create?"
The designers of the products you use every day -- your phone, your game controller, your smartwatch -- all asked that question first. That's why their devices feel intentional. Yours felt like a parts list that happened to run code.
Today we're going to do it the other way around.
Fig 1: You already know what intentional haptic feedback feels like -- the question is how to design it deliberately
What We're Building: "The Noticeable Nudge"
Not a vibration. Not an alert. Not a rumble.
A tactile acknowledgment -- the digital equivalent of a brief nod from someone who noticed you walk into the room.
This is not...
- no an alarm
- no a gaming rumble
- no a buzzy confirmation
- no a long pulse
This is...
- yes a brief tactile acknowledgment
- yes a "yes, I noticed you" in physical form
- yes a socially readable moment -- like a tap on the shoulder
You feel it in your hand, it registers immediately, and it's gone before it becomes annoying. That's our haptic target. Everything that follows -- the spec, the motor, the circuit, the code -- exists to serve this one sentence.
What you'll actually learn:
- How to define a feeling as a measurable engineering spec
- How to reverse-engineer component choices from that spec
- How to wire a driver circuit that preserves the feeling you designed
- How to write code that doesn't kill the crispness you worked so hard to create
Time: 10-15 minutes
Step 1: Define the Feeling Before You Touch Anything
Close the component catalog. Open a blank sheet of paper.
Write this sentence:
"I want someone to feel a short, warm tap. Like a finger saying 'I notice you.' Not aggressive. Not startling. A crisp, friendly nudge."
That's your haptic target. Every decision that follows is a test: does this serve that sentence, or am I drifting?
Step 2: Translate the Feeling Into Numbers
Feelings can't be selected from a menu. Specs can be selected from a menu.
Fig 2: The Feeling to Spec Translation. Each feeling word has a measurable engineering equivalent.
These numbers aren't arbitrary. They're the engineering translation of "crisp, friendly nudge."
Step 3: Reverse-Engineer the Component
Now we have a spec. Now we match the component to it.
First: Know What You're Choosing Between
Fig 3a: ERM -- Eccentric Rotating Mass. The most common vibration motor. Sealed disc, two wires. Red = positive.
The ERM is a small DC motor with an eccentric weight on the shaft. When it spins, the off-center mass creates vibration. This is what's in your phone and your game controller. It's buzzy, diffuse, and hard to control precisely. An ERM running at full speed feels like a phone ringing -- not like a deliberate tap.
Fig 3b: ERM vs LRA vs Piezo -- each motor type produces a different tactile feel. Only LRA matches our "crisp tap" spec.
| Motor Type | What It Feels Like | Matches Our Spec? |
|---|---|---|
| ERM | Diffuse rumble. Hard to control precisely. | no Too coarse |
| LRA | Clean tap, sharp pulse, precise onset | yes |
| Piezo | Micro-tap at very high frequency | no |
Our pick: 12mm LRA module. Its linear motion produces the sharp onset and clean cutoff our spec demands. An ERM can never give you that.
The Transistor You Need: Real Component
Fig 3c: PN2222 / 2N2222 -- TO-92 through-hole package. Flat face toward you, legs down: E on the left, B in the middle, C on the right.
[warning] Check your pinout. Some transistor brands have a different leg order. Always verify with your specific datasheet before wiring.
The Diode You Need: Real Component
Fig 3d: 1N4148 diode. The band on one end marks the cathode. This band must face toward +5V. Install it backwards and the diode shorts out when the motor turns off -- damaging your transistor.
The Resistor You Need: 330 Ohm
Fig 3e: 330 Ohm resistor. Color bands: Orange (3) . Orange (3) . Brown (x10) = 33 x 10 = 330 Ohm.
FAQ: "What if I want it stronger -- just use a bigger motor?"
A bigger ERM at full speed doesn't give you stronger. It gives you rougher. What you actually want is precision -- exactly the right amount of force, delivered exactly the way you designed it. That's a control problem, not a motor size problem. Which is why the spec comes first.
FAQ: "I have ERM parts lying around -- can I use them?"
Yes, but the sensation won't match your spec. ERM at full speed is buzzy. For a "friendly tap," ERM will always feel like a compromise. If your spec says "crisp tap," trust the spec and use LRA.
Step 4: The Circuit -- Why Each Component Exists
Here's the complete schematic:
Fig 4: Complete schematic -- every component exists to preserve the "crisp, friendly nudge" feeling
Pin-by-pin connection:
Arduino Pin 3 -> 330 Ohm resistor -> Transistor Base (B)
Arduino GND -> Transistor Emitter (E)
5V external -> Diode band (anode) / LRA (+)
Transistor Collector (C) -> LRA (+)
LRA (-) -> GND rail
Fig 5: Why each component exists in feeling terms.
Why This Exact Circuit -- In Feeling Terms
"Why the transistor?"
The Arduino pin can source about 40mA. The LRA needs 100-200mA. With direct wiring, the Arduino pin strangles the LRA -- you get a weak, mushy pulse. The transistor lets the Arduino control a switch, not power the motor. Result: a clean, strong tap.
"Why the flyback diode?"
When you cut power to a motor, its magnetic field collapses and sends a voltage spike back into the circuit. Without the diode, that spike degrades the transistor over time. In feeling terms: the diode keeps the tap consistent after hundreds of uses.
[warning] Diode Direction Matters: The 1N4148 diode has a stripe on one end. This is the cathode -- it MUST face toward +5V. Install it backwards and the diode shorts out when the motor turns off -- damaging your transistor.
[warning] Transistor Pinout: When the flat face is toward you with legs down: E (Emitter) on the left, B (Base) in the middle, C (Collector) on the right. Some clones have a different pin order. Always check your specific datasheet.
"Why external 5V, not the Arduino's 5V pin?"
The Arduino's onboard regulator can't supply enough stable current. With a phone charger or USB power bank on the external input, the tap stays strong and consistent -- every single time.
The Physical Wiring
Use a half-size breadboard (400 tie points). This size fits the Arduino Nano across the center channel.
Fig 5b: Half-size breadboard -- Arduino Nano sits across the center channel.
Fig 6: Complete breadboard wiring.
Common Errors -- Before They Happen
"The LRA doesn't vibrate" -- Debug in order:
- Is the transistor's emitter connected to Arduino GND? (Shared ground is required -- #1 mistake)
- Is the LRA's negative terminal on the collector side of the transistor?
- Is the external 5V supply connected and providing 1A or more?
- Is the diode's band facing toward +5V?
"The tap feels too weak" -- Try in order:
- Check your LRA voltage rating
- Increase tap duration in code from 80ms to 120ms
- Add a 10uF capacitor across the LRA terminals for sharper onset
Step 5: The Code -- Written for Feeling
const int hapticPin = 3;
void setup() {
pinMode(hapticPin, OUTPUT);
digitalWrite(hapticPin, LOW);
}
void loop() {
tap(100);
delay(600);
}
void tap(int duration) {
digitalWrite(hapticPin, HIGH);
delay(duration);
digitalWrite(hapticPin, LOW);
delay(30);
}
The 30ms delay(30) is the feeling guardian.
The LRA is a physical mass on a spring. When you cut power, the mass doesn't stop instantly -- it oscillates. That oscillation creates a second, weaker pulse that your hand feels as mushiness.
The 30ms pause gives the mass time to settle before the next signal arrives. Result: each tap is clean, distinct, and intentional.
Tuning Your Tap
| If the tap feels... | Adjust this | Direction |
|---|---|---|
| Too soft | tap(duration) |
Increase ms |
| Too strong | tap(duration) |
Decrease ms |
| Mushy / double-hit | delay(30) |
Increase to 40-50ms |
| Too short to notice | tap(duration) |
Increase to 80-100ms |
Start with tap(80) and delay(30). Adjust by 20% until it feels like "a brief nod."
Three Feeling Presets
// THREE FEELING PRESETS
// 1. friendlyNudge()
void friendlyNudge() {
digitalWrite(hapticPin, HIGH);
delay(80);
digitalWrite(hapticPin, LOW);
delay(30);
}
// 2. alertTap()
void alertTap() {
digitalWrite(hapticPin, HIGH);
delay(150);
digitalWrite(hapticPin, LOW);
delay(40);
}
// 3. softPulse()
void softPulse() {
digitalWrite(hapticPin, HIGH);
delay(50);
digitalWrite(hapticPin, LOW);
delay(60);
}
These aren't fixed settings -- they're starting points. Once you understand why the duration and delay values produce those sensations, you can tune them precisely for your specific project.
What You Actually Learned
You didn't learn how to wire an LRA motor.
You learned the reverse-engineering process:
Feeling -> Spec -> Component -> Circuit -> Code
^ |
<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<
(each step tests the feeling)
That's the skill that transfers to your next project. Not the LRA -- the thinking process.
The Question Your Next Project Will Face
You just completed "The Noticeable Nudge" -- a case where you knew the feeling you wanted, because I gave it to you.
Your next project will be harder: you'll start with a vague intention -- something like "I want it to feel responsive."
How do you turn vague intention into a precise spec?
You already know the process. Step 1 asked: "What feeling do you want?" Step 2 translated it into numbers. Step 3 found the component.
That's exactly what the Project Direction Worksheet is built to answer:
-> Get the Project Direction Worksheet ($6)
This article gave you one case. The worksheet gives you the method to define your next one.
Parts Reference
| Component | Spec to Match | Purchase Notes |
|---|---|---|
| Arduino Nano (or Uno) | Digital pin output | Pin 3 in this project |
| 12mm LRA module | 3V-5V, <=200mA | Linear motion = crisp tap |
| PN2222 / 2N2222 NPN transistor | Current gain 100+, TO-92 | Through-hole, breadboard-compatible |
| 1N4148 flyback diode | Reverse voltage 75V+ | Band (cathode) MUST face +5V |
| 330 Ohm resistor | 1/4W, through-hole | Orange-Orange-Brown color bands |
| External 5V supply | 1A or more, stable | Phone charger or USB power bank |
| Half-size breadboard | 400 tie points | Fits Arduino Nano across center |
Appendix: Connecting to a Touch Sensor
const int hapticPin = 3;
const int touchPin = 2;
void setup() {
pinMode(hapticPin, OUTPUT);
pinMode(touchPin, INPUT);
}
void loop() {
if (digitalRead(touchPin) == HIGH) {
friendlyNudge();
delay(200);
}
}
Tags: #hapticfeedback #Arduino #interactiondesign #LRA #prototype
This is the free prototype guide. The Project Direction Worksheet gives you the method to design your next one.

Top comments (0)