DEV Community

張旭豐
張旭豐

Posted on

When You Squeeze, It Vibrates — How to Build a Haptic Feedback Device with Arduino

When You Squeeze, It Vibrates — How to Build a Haptic Feedback Device with Arduino


Feel the feedback. Then build it yourself.


The Moment Your Controller Hits Back

You're mid-match. You squeeze the trigger a little harder — and thump — the controller pushes back into your palm.

That vibration isn't random. It's engineered: a tiny motor inside the grip, spinning at exactly the right speed, for exactly the right duration, to make you feel the impact.

But here's the thing most people never think about: that feedback was a design decision. Someone chose to put a motor there. Someone calibrated the vibration strength. Someone wrote the code that decided when and how hard the haptic pulse should fire.

And here's the part that actually matters:

You can build that yourself.

Not in a lab. Not with expensive equipment. With an Arduino, a force sensor, and a vibration motor — you can design and build your own haptic feedback system, from scratch, in an afternoon.

This article walks you through exactly how to do that.


When Would You Actually Want Haptic Feedback?

Before we touch a single wire, let's ask the real question:

What would you use haptic feedback for?

Here are some scenarios where force-sensitive vibration feedback makes all the difference:

  • Fitness training — Your grip strengthener vibrates harder the tighter you squeeze. Each rep gets instant, physical confirmation that you're hitting your target. No guessing whether you actually engaged the muscle.

  • VR interaction — Squeeze a virtual object and feel actual resistance. Let go, and the vibration stops. Your hands start to believe in things that aren't there.

  • Musical expression — Play a pressure-sensitive surface and trigger different vibration rhythms depending on how hard you strike. The instrument plays with you, not just for you.

  • Game controller modding — Upgrade a standard controller so every punch in a fighting game has real weight behind it. The difference between playing a game and feeling it.

  • Art installations — Build a piece where the viewer's force directly translates into vibration. The harder they push, the more the work responds. The piece feels them pushing back.

What connects all of these? They're all built on the same translation: force becomes feeling.

And that's exactly what an FSR + Arduino can do.


The Core: How an FSR Reads Your Force

At the heart of this system is a component called an FSR — Force Sensing Resistor.

The name says it all: a resistor that changes its value based on force.

Here's how it works:

When you press on an FSR, its electrical resistance decreases — proportionally to how hard you press.

Light touch = high resistance. Hard press = low resistance.

This change in resistance creates a change in voltage across the circuit. And that voltage change is exactly what Arduino's analog input pins can read.

The full signal chain looks like this:

  1. Sense — FSR detects your press and changes its resistance
  2. Read — Arduino measures the voltage, converts it to a number (0–1023)
  3. Respond — Arduino maps that number to a vibration motor's speed, and drives it

Once you understand this loop, you've understood the entire system. Everything else is just wiring and code.


What You'll Need

Here's the complete parts list:

Component Recommended Spec Purpose
FSR Force Sensor Interlink 402 or 406 series, 5–10mm sensing area Detects your press, converts it to resistance change
Arduino Nano ATmega328P, with USB cable The brain — reads the signal, drives the output
LRA Vibration Motor 3V or 5V, flat/coin style (6mm or 10mm) Linear resonant actuator — fast response, precise control
OR ERM Vibration Motor 3V–5V, cylindrical Classic eccentric rotating mass — stronger vibration, slightly slower
NPN Transistor 2N2222 or S8050 Acts as a switch to control motor current from Arduino
Diode 1N4001 or 1N4148 Flyback protection — prevents motor's reverse voltage from killing your transistor
10kΩ Resistor 1/4W Forms a voltage divider with the FSR
1kΩ Resistor 1/4W Base resistor — protects Arduino's output pin
Breadboard + Wires Various sizes Quick prototyping

⚠️ Power safety: A vibration motor can draw significant current. Do not power a motor directly from Arduino's 5V pin. Use an external power supply for the motor if it exceeds 200mA, and always share ground between Arduino and motor power.


Wiring: Step by Step

Let's build this in five steps, from sensor to motor.

Step 1 — The FSR Voltage Divider

  1. Connect one leg of the 10kΩ resistor to Arduino's 5V pin.
  2. Connect the other leg of the resistor to Arduino's A0 analog input pin.
  3. Connect one leg of the FSR to Arduino's A0 pin — the same point as the resistor.
  4. Connect the other leg of the FSR to GND.

This creates a voltage divider: when you press the FSR, its resistance drops, and the voltage at A0 rises proportionally.

Step 2 — The Transistor Switch

  1. Connect the transistor's base (B) through the 1kΩ resistor to Arduino's Pin 9 (PWM output).
  2. Connect the transistor's collector (C) to the motor's positive lead.
  3. Connect the transistor's emitter (E) to GND.

This arrangement lets Arduino's small signal at Pin 9 control a much larger current flowing through the motor.

Step 3 — Motor Flyback Protection

  1. Connect the 1N4001 diode in parallel with the motor terminals — positive (marked end) to motor positive, negative to ground.

This is essential. When a motor stops spinning, it generates a reverse voltage spike that can destroy your transistor. The diode shorts that spike to ground before it reaches anything fragile.

Step 4 — Connect the Motor

  1. Connect the motor's positive lead to an external 5V power source (or Arduino's 5V pin for small motors only).
  2. Connect the motor's negative lead to the transistor's collector (C).

Step 5 — Verify Before Powering

  • Double-check all grounds are connected together.
  • Make sure the diode is oriented correctly (band toward positive).
  • Use a multimeter to check for shorts before turning on power.

The Code

Here's the complete Arduino sketch. Copy and paste it directly into your IDE and upload:

// FSR + Arduino Haptic Feedback System
// Reads force, maps it to vibration motor intensity

const int fsrPin = A0;    // FSR connected to analog pin 0
const int motorPin = 9;    // Motor driver transistor on PWM pin 9

void setup() {
  Serial.begin(9600);
  pinMode(motorPin, OUTPUT);
}

void loop() {
  int fsrValue = analogRead(fsrPin);  // Read FSR value (0–1023)

  int vibration = 0;

  if (fsrValue > 50) {
    // Map force to motor speed (30–255 to account for LRA minimum threshold)
    vibration = map(fsrValue, 50, 1023, 30, 255);
    vibration = constrain(vibration, 0, 255);
  }

  analogWrite(motorPin, vibration);  // Drive motor

  // Optional: monitor values in Serial Monitor at 9600 baud
  Serial.print("FSR: ");
  Serial.print(fsrValue);
  Serial.print(" -> Motor: ");
  Serial.println(vibration);

  delay(50);
}
Enter fullscreen mode Exit fullscreen mode

How the code works:

  • analogRead(fsrPin) samples the voltage at A0, returning a value from 0 (no press) to 1023 (full scale).
  • The if (fsrValue > 50) threshold filters out noise when the FSR is idle — without this, the motor would jitter constantly.
  • map(fsrValue, 50, 1023, 30, 255) scales your press to the motor's usable range. Starting at 30 (not 0) because most LRAs need a minimum voltage before they actually spin.
  • analogWrite(motorPin, vibration) sends a PWM signal to the transistor base, controlling how fast the motor spins.

Testing:

  1. Upload the sketch and open the Serial Monitor at 9600 baud.
  2. Lightly touch the FSR — you should see values in the 200–400 range.
  3. Press hard — values should approach 1023.
  4. Watch the motor: light touch = gentle buzz, hard press = strong vibration.

If the motor doesn't respond, double-check the transistor's pin orientation (B/C/E) and the diode's polarity.


What You Just Built

You now have a complete closed-loop haptic feedback system:

  • A force sensor translates physical pressure into an electrical signal
  • An Arduino reads that signal, interprets your intent
  • A vibration motor translates the Arduino's decision back into physical feedback

The whole thing fits on a breadboard. The finished device can be miniaturized into a palm-sized enclosure with a 3D-printed case and a small battery.


That Hit Was Yours

Here's what actually happened today:

You built something that felt you.

The moment you pressed down and the motor hummed in response — that wasn't magic. That was a system you designed, wire by wire, line by line. You translated your force into electricity, your pressure into code, and your code into motion.

The vibration you felt was your own work, reflected back at you.

That's the part that never gets old.


If you built this — or if you have questions about extending it — drop a comment below. I'd love to see what you made.

Part 2 is coming: we're adding Bluetooth so you can control the vibration intensity from your phone. Same principle, wireless.


📎 Friends Link

Follow my latest interactive system builds and breakdowns:

👉 https://medium.com/@phd.hfchang/919940182a24


If you found this useful, feel free to share it with someone who's into Arduino, haptics, or building things that actually feel good to use.

Top comments (0)