How to Wire a Piezo as an Impact Sensor

Definitely. But that's what I have from adapting the Arduino Knock program.

Why does it happen every 120ms? There's a 100ms delay at the end. Could I remove that?

Your code seems to differ primarily in the samples it's taking. As I read this part

it looks like it's testing 250 times for the range of piezo values. Then the next section checks if there's a leap of more than the threshold. Is that right? And shouldn't maxValue be set initially at 0, since rawValue will never exceed 1023?

If the advantage of that code is the steady sampling of the piezo, will that still apply when I'm telling the buzzer to sound? If not, I'll need to find another solution.

void loop()
{
if (sensorReading < threshold && sensorReading > threshold2)
{
Buzzer();
Buzzer();

lcd.clear();
lcd.print("Alarm ON");
lcd.setCursor(0,1);
lcd.print("Alarming");
Buzzer();
Buzzer();
} 
} 

void Buzzer()
{
digitalWrite(buz,HIGH);
delay(10);
digitalWrite(buz, LOW);
delay(100);
}

So you still don't get it.
Max pin voltage according to the datasheet is ±0.3volt (when the Arduino is off).
and won't be able to get above 0.7volt, because of the pin's internal clamping diodes.
If you put a normal diode and a zener diode in parallel, which one do you think will conduct.
Leo..

It is. All values are set to 0 on startup, unless you add your own value to it.
Sorry, 100ms.
Delays only fire after an event, so not a worry.
My code automagically adjusts it's bias (rest) point (which is about 512),
and subtracts trigger values, so you only have one threshold.
No idea what's inside buzzer(). Is it written non-blocking.
Leo..

Thanks. I'll fix my code accordingly.

It just sounds a piezo buzzer during the alarm time; that causes some vibration picked up by the sensor, but not too much to throw off the target sensor if I set a good threshold. I'm happy to post the whole code if that isn't too much of a detour.

Ah, good to know. But here what I was asking about was if you set MaxValue to 1023, will rawValue ever exceed it?

I wondered if initially setting (or leaving) maxValue at 0 will let it rise with rawValue, while initially setting maxValue to 1023 means it stays there.

So with zener, when the power is off, on A0 will be more than 5V ?

First of all, why does the word of "5V" come up when the uC power is off?
The withstand voltage of the pin is VCC±0.5
When the power is off, It's VCC=0V

The voltage of "5V" has nothing to mean at a power-off uC, right?

1 Like

So with circuit post #41 on P0 you have max voltage 5V when power is on and ±0.5V when power is off = uC is protected or not ?

Protected with Zener.

Not protected with Zener.


When the power is off, protection is provided only by clamping with an internal protection diode.
That is, the "Zener diode" doesn't provide protection when the power is off, It's do nothing.

The question is: circuit from post #41 is safe or not. Who and when is doing the job is not important.

Is limiting input voltage to 5V on R2 and this 5V is limited to ±0.5V by internal protection diode.

I don't actively rely on the internal protection diode, so I decide that "unprotected".
Not safe.

So the producers did a bad design.

1 Like

The first reading of the A/D is about 512 (half of VCC on both piezo sides).
So maxValue (which was too low, 0) will be pulled up to 512.
minValue (which was too high, 1023) will be pulled down to 512).
Result of the subtraction will be zero.
An impact on the sensor will result in min and max being pulled apart further.
Leo..

1 Like

Where are the instructions about the wire colours?

That's a neat bit of coding to adjust to a range of values. But don't the initial lines set maxValue to 1023?

I was wondering if maxValue should start at 0.

The piezo sensor is more finicky than I'd like, meaning that there isn't as much difference as I'd hoped between readings of 'no impact' and 'impact.' Without a hit, I get readings from 470 to 560, and with a hit, from 390 to 640, so the difference between a hit and a 'normal' reading is smaller than the range of normal readings. I wonder if the piezo can be made more or less sensitive with a different arrangement or set of sensors?

Still, it does work, and I will mark Leo's post #22 as a Solution, unless something else makes more sense.

Yes, as already explained. rawValue and maxValue start at 0.

That's not right. Should be close to zero.
Is that with the breadboard setup?
Leo..

Edit:
Just tested it with my code and a breadboard setup. Piezo flat on a tabletop.
Could lower threshold to 5 (very sensitive) before noise pickup of the wires became a problem.

Except that you set maxValue to 1023. So I'm asking if it would be better to leave it at '0.' If you start with this

int rawValue, maxValue, minValue = 1023;

maxValue is now 1023, yes? So then here, can it ever exceed rawValue, if 1023 is the highest possible reading?

    rawValue = analogRead(piezoPin);
    if (rawValue > maxValue) maxValue = rawValue;

In any case, back to the wiring:

The 'noise' - the range of readings when not hitting the target - isn't steady enough to use a threshold that small. That range is greater than the relatively small leap (or drop) in voltage from an impact, so any 'hit' that's less than ideal won't register.

That makes me wonder if there's a way to reduce the noise. Does your setup give baseline readings close to zero?

Yes, just as shown (with the brass and ceramic sides now correctly wired.) Uh oh. I didn't expect to read that it should be close to zero, since mine are never under 400. Where should I look to troubleshoot?

No, that line can be written as

int rawValue = 0;
int maxValue = 0;
int minValue = 1023;

Did you try my code on it's own, before adding other things?
Is your wiring short. A high impedance piezo setup doesn't like long wiring.
Leo..

2 Likes

Ah, that's a good explanation, thanks.

I'm running the code on its own (with one added line to send the rawValue to the serial monitor), but my wires are fairly long. I'll try it with shorter wiring.

That does seem to make a difference, and I've marked Post #22 as the solution. Thanks to all who reached out to help here.

For any other newcomers who stumble across this thread , here are my takeaways on using a piezo as an impact sensor:

  • It's not a beginner project.
    That doesn't mean you can't do it, but settling on wiring for the sensor took longer than all the other steps combined. I used a motion-sensor as a temporary stand-in and got that running in minutes, compared to the long process here.

    Protecting against frying your Arduino is fundamentally different from many other goals in that you may not want to arrive at a solution by experimenting. Knowing you have it right requires understanding not just the electrical principles, but also the relevant aspects of a piezo buzzer, of multiple kinds of diodes, and of the Arduino board itself.

  • There isn't a consensus on how to approach this.

    As John noted in Post 10, there are many ways to solve a problem, but here, most of the schematics offered were judged 'wrong.' Not just different or inefficient, but plain 'wrong,' if the goal is to read the sensor while limiting current to the Arduino.

    The design of Post #22 is the only one to receive no objections, so I went with that, but that's not the same as it receiving endorsement. Were the other contributors to the thread convinced of its efficacy, or did they just not want to drag on an argument? Who knows? A beginner lacks the experience to weigh competing views.

  • The internet is full of questionable Arduino information, but on this topic more than most.
    Maybe it's because of the first point: because it's hard to tell from observation if your design is a good one, many bad ones persist. So if there's a good model project out there using a piezo buzzer as a vibration sensor, please do link it.

If you do take this on, fellow newcomer, then I hope you're especially interested in learning about more advanced elements of a circuit, or that your process goes more smoothly than mine, or both. An Arduino is a tremendous tool, and there's a lot of good projects to suit any interests at a given stage.

2 Likes

Thank you, @holdred, for your consistently humble and clarifying questions on this. 3 months later I'm benefiting greatly from this thread.

I'm an Arduino noob and nominally hold a degree in electrical engineering, but I too had the initial reaction of "Is that right? Is that OK?" to connecting 5V "straight" to ground. It becomes clear that the answer is "yes" and "yes" when I look further at it.

Why is it right? By connecting two resistors of equal resistance in series, the voltage drops halfway in the middle. This is how Wawa/Leo is achieving the 2.5V offset (which seems great to me, for not losing valuable signal information).

Why is it OK? Because the resistors are 100kΩ each. Given the equation I = V/R — current equals voltage divided by the resistance — the result is 25 µA (micro-amps, not milliamps) flowing through that path. It is the tiniest trickle of power.

Thank you, @Wawa for your consistent input on this thread. I learned a lot from you.

FWIW, I spent a few days with the diagram from jremington seen in #4 (except that I sometimes used 2MΩ for R1 in order to increase the sensitivity), with this piezo vibration sensor mounted about 1cm below the surface of a drum skin. Reading the ADC pin once every loop() callback invoked around 100Hz and hitting the drum with my hand produced the results seen below.

The yellow regions very roughly indicate when I was hitting…but of course the piezo wasn't starting to vibrate before I hit, so it's really the start of variations indicating the hit. Some problems I ran into with this, and why I'm going to try switching to the accepted solution on this page and some of the sampling code:

  1. The nice big obvious spikes happen (very roughly) 30-50ms after the sensor starts giving values. For accurate timing (lights from drumming, not nerf dart turning off alarm) this is a noticeable lag.
  2. Further evidence preventing me from just looking at the "big spikes" is that double-taps with my hand (there are four after 21,000ms in the image) sometimes peaked at only 50 (~0.25V).
  3. However, just using a small threshold value to detect a hit would result in many detections occurring for a single real hit; as seen in the image the piezo would generate values for 200ms or more, with some secondary spikes reading over 100 (~0.5V).

I solved this using the non-biased circuit and my once-per-loop() reading by "debouncing" the signal, not accepting any more hits for a short period of time after I detected one. Not perfect, but easy to implement.

Anyhow, I'm not trying to hijack this thread, and have no questions requiring a response. Just wanted to share my thanks and bit of experience here.

1 Like