Reading analog input from piezo

I'm trying to make a very simple knock sensor out of a piezo and it just wont give me anything. I'm following tutorial and code found at arduino [dot] cc/en/Tutorial/Knock which is also included with the arduino software. Alternate wiring diagrams for breadboard and info here: fritzing [dot] org/projects/knock/. (had to break up the urls because it wouldn't let me post them on my first post)

I'm fairly new to arduino, but I feel like this should not be an issue whatsoever. Anyway, I'm using the code provided and I've added the line: Serial.println(analogRead(knockSensor)); which should print out the sensor value regardless of whether or not it's hit the threshold. However, it always reads "0" despite any amount of knocking I do. Only when I disconnect the wire to Analog 0 do I begin to get random values in the Serial.

a few notes: Yes, I do have the piezo element oriented correctly in terms of +/- (it works fine in playing simple tunes for other sketches). And I am using the recommended 1 mega ohm resistor in parallel with the ground.

And that's about it. Seems idiot proof. Guess not.

Any idea what could be wrong and/or how to fix it?

Thank you !!

I'll place the code below for reference:

/* Knock Sensor
   This sketch reads a piezo element to detect a knocking sound. 
   It reads an analog pin and compares the result to a set threshold. 
   If the result is greater than the threshold, it writes
   "knock" to the serial port, and toggles the LED on pin 13.
   The circuit:
      * + connection of the piezo attached to analog in 0
      * - connection of the piezo attached to ground
      * 1-megohm resistor attached from analog in 0 to ground

   created 25 Mar 2007
   by David Cuartielles 
   modified 30 Jun 2009
   by Tom Igoe


// these constants won't change:
const int ledPin = 13;      // led connected to digital pin 13
const int knockSensor = 5;  // the piezo is connected to analog pin 0
const int threshold = 100;  // threshold value to decide when the detected sound is a knock or not

// these variables will change:
int sensorReading = 0;      // variable to store the value read from the sensor pin
int ledState = LOW;         // variable used to store the last LED status, to toggle the light

void setup() {
 pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
 Serial.begin(9600);       // use the serial port

void loop() {
  // read the sensor and store it in the variable sensorReading:
  sensorReading = analogRead(knockSensor);    
  // if the sensor reading is greater than the threshold:
  if (sensorReading >= threshold) {
    // toggle the status of the ledPin:
    ledState = !ledState;   
    // update the LED pin itself:        
    digitalWrite(ledPin, ledState);
    // send the string "Knock!" back to the computer, followed by newline

  delay(100);  // delay to avoid overloading the serial port buffer

What piezo element are you using? Do you have a reference for it?

Only when I disconnect the wire to Analog 0 do I begin to get random values in the Serial

Do you disconnect both the piezo element and the resistor?

I don't have data sheets for the piezos that I have. One came with an assortment of sensors and stuff that came with arduino from makershed, and the other is a small salvaged speaker from an old digital camera. The piezo from the kit is clearly labeled with a "+" on one side along with a long leg. The speaker had a red and black wire coming out of it which I've verified as standard +- .

When I disconnect the piezo, I'm only pulling out the jumper that goes from + on the piezo to analog input 0. I've got my current setup on a breadboard, so the resistor stays in place but shouldn't be doing anything because it completes no circuit(?). I've tried several different resistors and still nothing. I've also tried all possible setups too(there aren't that many) and tried different analog inputs also. I even tried with no resistor and was extra careful not to overload the input. Still nada.

I can get my force sensor to work fine. I can even get 16 force sensors to work fine through my Analog multiplexer. I just can't crack this one somehow.

Does this help any? Thanks for the help!

so the resistor stays in place but shouldn’t be doing anything because it completes no circuit(?)

The resistor should connect the analog input to ground which I believe does complete a circuit. The net effect should be a reading of zero.

How certain are you that the two piezos really are piezos? I ask because there are “magnetic buzzers” that act like piezo-electric buzzers when making sound but I don’t think they work the other way; as knock sensors.

As you get random values when you open circuit the analogue input means that your software is working correctly. A 1M pull down with nothing else attached will reduce these random values.

Can you post a picture of the sensor you have. Get a Flicker account, up load your picture to that and post the URL between the brackets of the icon third from the left.

I’m attaching a (somewhat blurry) photo of my piezos. The small black one has a “+” on one side, and “HXD®” on the other which I’m assuming is a brand name. I’d be surprised if it wasn’t a piezo, as the kit it came with allegedly came with a piezo and it’s the only thing that fits the description. The other is just a tiny speaker that I pulled from an old digital camera.

My understanding is that whether a piezo or speaker, it would give me some sort of voltage as feedback as the piezo element or speaker was deformed by sound, knocking, etc… This is why one can use headphones as a microphone in a pinch.

The resistor should connect the analog input to ground which I believe does complete a circuit. The net effect should be a reading of zero.

when placed on the breadboard as I have it now (, and I disconnect the + from analog 0, there should be no circuit which is why I’m getting random values. My understanding when it is hooked up that the resistor essentially drains some of the voltage from the piezo back to ground to prevent damage to the analog input.

again, thank you for your time and input.

Can't really help with the piezo other than confirming that the black object plugged into the breadboad is a fairly standard piezo speaker, but wiring an LED like that with a Duemilanove is a good way of destroying the Arduino output and/or the LED. I know theres a tutorial floating about wired like that but its with a much older type Arduino that has a resistor built in to pin 13. The Duemilanove has no such resistor inline with the pin and there is nothing to limit the current. It has a built in LED on pin 13 which has a resistor also built in (for the builtin LED but not to the pin) thus making the external LED redundant.

wiring an LED like that with a Duemilanove is a good way of destroying the Arduino output and/or the LED.

good to know! I did "know" this at some point, but I guess I forgot.


I've used a piezo for outputting sounds, but not as an input device. don't they momentarily produce high AC voltages using them in 'reverse' ?

Yes that's not the sort of sensor used in the knock project. Those are more like flat brass circles. What you have is a piezo speaker and while it will work as a microphone you need an amplifier to make the output big enough to measure directly with the ardunio. You also need a series diode and resistor to ground to make sure you don't get any negative voltage in the arduino.

thanks! I'll look into amplification then.

I'll look into amplification then

Much better off if you look into the right sort of transducer.

Is the wire really connected to pin0? Looks like pin5 to me!

Maybe there is different pin layouts, but my pin0 is not where you have connected the wire.

Is the wire really connected to pin0? Looks like pin5 to me!

in the photo it is. I was switching pins in both the code and on the arduino just to make sure the pin wasn’t dead or malfunctioning.

Hey, any luck with this? I'm having the exact same problem using the Fritzing circuit ( I'm using a proper piezo vibration sensor too.

Shouldn't that +5v go somewhere? Do I really need to amplify?

The knock.pde code was giving me absolutely nothing, so I pared down the code to this:

int sensorPin = 0; int sensorValue = 0;

void setup() { Serial.begin(9600); }

void loop() { sensorValue = analogRead(sensorPin); Serial.println(sensorValue); delay(500); }

Which returns 0.


Ah! Not sure why, but it works with this wiring: and the pared down code. Ockham ftw.

Eep, third (and last) post, but this piezo speaker-as-sensor circuit just came in the Jameco newsletter. Might be useful: