Skip to content

Latest commit

 

History

History

PiezoVibrationDetector

#376 Piezo Vibration Detector and BPM Counter

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

Build

Notes

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.

scope_raw_input

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 PinFunctionsArduino PinUsage
PD6PCINT22/OC0A/AIN06Analog Comparator Positive Input - raw piezo pulse input
PD7PCINT23/AIN17Analog Comparator Negative Input - adjustable threshold reference voltage

There are two registers of significance for setting this up:

ADCSRB_register

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

ACSR_register

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

ACIS1ACIS0Interrupt Mode
00Comparator Interrupt on Output Toggle
01Reserved
10Comparator Interrupt on Falling Output Edge
11Comparator 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:

console_120bpm

Construction

Breadboard

Schematic

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

tap_pad_wip

Finished "tap pad":

tap_pad

Credits and References

close