Skip to main content

How to make a vibration sensor with Piezo Transducer

What is the piezo transducer?

A piezoelectric transducer (or piezo transducer) is a device that uses the piezoelectric effect to convert physical phenomena—such as pressure, acceleration, strain, or force—into electrical signals, or conversely, to convert electrical energy into mechanical motion or sound.

How It Works

Piezo transducers rely on special materials (typically piezoelectric ceramics like lead zirconate titanate [PZT], quartz, or certain polymers) that exhibit two primary properties:

Direct Effect (Sensors): When the material is mechanically stressed, deformed, or compressed, it generates an electrical charge across its surfaces. This makes them ideal for measuring rapid changes in pressure or vibration.

Inverse Effect (Actuators/Sound Emitters): When an electrical voltage is applied across the material, it rapidly expands or contracts, creating physical motion or sound waves (commonly used in buzzers, speakers, and ultrasound equipment).

Wiring

Wiring up buttons and switches is simple:

  1. Piezo + and Piezo - connected with 1M ohm resistor
  2. Piezo + to LM386 pin3 (IN+)
  3. Piezo + to GND
  4. Piezo - to LM386 pin2 (IN-)
  5. LM386 pin4 to GND
  6. LM386 pin5 (Vout) via 10uF capacitor to A0
  7. LM386 pin6 (Vs) to 5V

piexoTransducerVibrationSensor.png

Arduino Code

This example sends the vibration value measured from Arduino to Processing via the serial port, you can read the data from the serial monitor.

const int piezoPin = A0;

const int samples = 100;
const int noiseThreshold = 5;  // Adjust after observing readings

int restingValue;

void setup() {
Serial.begin(115200);
delay(1000);

// Measure the resting voltage while the sensor is still
long total = 0;

for (int i = 0; i < 500; i++) {
total += analogRead(piezoPin);
delay(2);
}

restingValue = total / 500;

Serial.print("Resting value: ");
Serial.println(restingValue);
}

void loop() {
long totalDeviation = 0;

for (int i = 0; i < samples; i++) {
int reading = analogRead(piezoPin);
totalDeviation += abs(reading - restingValue);
delayMicroseconds(500);
}

int vibration = totalDeviation / samples;

// Ignore small fluctuations
if (vibration < noiseThreshold) {
vibration = 0;
}

Serial.println(vibration);
delay(10);
}

Processing Code

This example used the data received from Arduino to control the sin wave in Processing. You may need to fine tune the lowest and highest values.

import processing.serial.*;
import processing.sound.*;

Serial myPort;
String val;

int datanum = 0; //number of data receiving from Arduino
int value1; 

SinOsc[] sineWaves; 
int lowest = 30;
int highest = 100;

// The number of oscillators
int numSines = 5; 

// A float for calculating the amplitudes
float[] sineVolume;

void setup() {
  size(800, 800);
  
  printArray(Serial.list()); //show all ports
  String portName = Serial.list()[3];//choose the correct port
  myPort = new Serial(this, portName, 115200);
  myPort.bufferUntil('\n'); 
  
  sineWaves = new SinOsc[numSines];
  sineVolume = new float[numSines]; 
  
    for (int i = 0; i < numSines; i++) {

    // The overall amplitude shouldn't exceed 1.0 which is prevented by 1.0/numSines.
    // The ascending waves will get lower in volume the higher the frequency.
    sineVolume[i] = (1.0 / numSines) / (i + 1);

    // Create the Sine Oscillators and start them
    sineWaves[i] = new SinOsc(this);
    sineWaves[i].play();
  }
}

void draw() {

    // Convert vibration strength to sound frequency
    float frequency = map(value1, lowest, highest, 100, 1000);
    frequency = constrain(frequency, 100, 1000);
    
    // Convert vibration strength to sound volume
    float volume = map(value1, lowest, highest, 0, 0.5);
    volume = constrain(volume, 0, 0.5);
    
    for (int i = 0; i < numSines; i++) {
    sineWaves[i].freq(frequency * (i + 1));
    sineWaves[i].amp(volume * sineVolume[i]);
    }
}


void serialEvent( Serial myPort){
  val = myPort.readStringUntil('\n');
  if (val != null)
  {
    val = trim(val);
    int[] vals = int(splitTokens(val, ","));
    
    if(vals.length >= datanum){
       value1 = vals[0];
    
      //multiple data from arduino if needed
      //value2 = vals[1] ;
    
      println(value1);
    }
  }
}