Fork me on GitHub

Project Notes

#376 Piezo Vibration Detector and BPM Counter

Counting beats per minute with a piezo tap sensor and an Arduino/ATmega328 analog comparator.



Some time back I picked up some Piezo Transducers, and they’ve been waiting for a project to happen.

This experiement is a building block. What I’d like to be able to do is detect (count) pulses from the piezo transducer. That is, as opposed to capturing an accurate waveform from the piezo - I just want to know when a “tap” is picked up.

There are many ways to approach this, but what I’ll expore here is using the built-in analog comparator of an Arduino/ATmega328 to trigger interrupts and do some software de-bouncing/noise abatement. As a result is derives and displays a beats-per-minute (BPM) estimate.

Piezo Transducers

What happens when a piezo transducer picks up a vibration?

Here’s a scope capture of a raw signal, unfiltered, when the surface near the transducer is struck reasonably hard. The capture is DC coupled, so what this shows is a wave peaking between +1.5V to -1V, with a total duration of say 3.6ms.


In other tests, it appears I can get the piezo to peak at over 6V, as well as going significantly negative. I’m not sure if this is really required (because I suspect the power is extremely low), but I’ve added a 3.3V zener across the piezo to clamp the input.

Some specifications of the piezo transducer I’m using:

  • Model: ZX-18T9A1
  • Material: Brass + ceramic
  • Resonant frequency: 8.0 +/- 0.7kHz;
  • Resonant resistance: 350Ω (max);
  • Capacitance: 7000pF +/- 30%;
  • Input voltage: for DC 30V;
  • Operating temperature: -20~+70C;
  • Storage temperature: -30~80C;
  • Brass disc: 18mm +/- 0.1mm x 0.15mm +/- 0.05mm;
  • Ceramic disc: 14mm +/- 0.1mm x 0.34mm +/- 0.05mm;
  • Lead length: 7cm

Using the Analog Comparator

The PiezoVibrationDetector.ino sketch sets up the analog comparator to trigger an interrupt when a “beat” is detected. The code then counts and averages these beats to derive a BPM measure.

The analog comparator will use two pins:

ATmega Pin Functions Arduino Pin Usage
PD6 PCINT22/OC0A/AIN0 6 Analog Comparator Positive Input - raw piezo pulse input
PD7 PCINT23/AIN1 7 Analog Comparator Negative Input - adjustable threshold reference voltage

There are two registers of significance for setting this up:


Clearing the Analog Comparator Multiplexer Enable in ADCSRB means the comparator will use the threshold reference voltage provided on AIN1


The Analog Comparator Interrupt Flag is set to enable interrupts, and the ACIS1 and ACIS0 bits set the mode:

ACIS1 ACIS0 Interrupt Mode
0 0 Comparator Interrupt on Output Toggle
0 1 Reserved
1 0 Comparator Interrupt on Falling Output Edge
1 1 Comparator Interrupt on Rising Output Edge

The code sets a rising edge interrupt and implements the interrupt service routine to record the time between beats.

Counting Beats

We want to extract a single pulse from the noisy raw piezo input, so it needs filtering and “de-bouncing”. This could be done off-board with comparators and filters, but in this case I’m doing it within the ATmega with the following techniques:

  • the analog comparator reference threshold set with R1 prevents (ilters) weaker pulses triggering the input
  • discard pulses faster than 250 BPM/240ms - “too fast to be useful”
  • reset when pulses below 33 BPM/1800ms - “threshold of the perceptual present”

The resulting BPM measure is calculated as an exponential moving average.

At the moment, the sketch just outputs the BPM to the serial console. Here’s an example of me trying to maintain 120bpm:





I used a small piece of protoboard to anchor the connections and mount the threshold pot and zener diode:


Finished “tap pad”:


Credits and References

About LEAP#376 ArduinoPiezo
Project Source on GitHub Return to the LEAP Catalog

This page is a web-friendly rendering of my project notes shared in the LEAP GitHub repository.

LEAP is my personal collection of electronics projects, usually involving an Arduino or other microprocessor in one way or another. Some are full-blown projects, while many are trivial breadboard experiments, intended to learn and explore something interesting (IMHO!).

The projects are usually inspired by things found wild on the net, or ideas from the sources such as:

Feel free to borrow liberally, and if you spot any issues do let me know. See the individual projects for credits where due. There are even now a few projects contributed by others - send your own over in a pull request if you would also like to add to this collection.