reading piezo sensor


I have a Piezo sensor attached - it is outputing the following

ÿ DEC : 255 HEX: FF OCT: 377 BIN:11111111 ù DEC : 249 HEX: F9 OCT: 371 BIN:11111001 à DEC : 224 HEX: E0 OCT: 340 BIN:11100000 ? DEC : 136 HEX: 88 OCT: 210 BIN:10001000 » DEC : 187 HEX: BB OCT: 273 BIN:10111011 ÿ DEC : 255 HEX: FF OCT: 377 BIN:11111111 ? DEC : 253 HEX: FD OCT: 375 BIN:11111101 ? DEC : 240 HEX: F0 OCT: 360 BIN:11110000 È DEC : 200 HEX: C8 OCT: 310 BIN:11001000 ? DEC : 132 HEX: 84 OCT: 204 BIN:10000100 ? DEC : 130 HEX: 82 OCT: 202 BIN:10000010 ÿ DEC : 255 HEX: FF OCT: 377 BIN:11111111

I am running the following code

int ledPin = 13; // led connected to control pin 13 byte analogValue = 0; byte oldAnalogValue = 1; // variable to store the value read from the sensor pin

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

void loop() { analogValue = analogRead(0); // read the sensor and store it in the variable "val" //Serial.println(analogValue, 0); if (analogValue != oldAnalogValue){ oldAnalogValue = analogValue; // print it out in many formats: Serial.print(analogValue); // print as an ASCII-encoded decimal Serial.print("\t DEC : "); // print a tab character Serial.print(analogValue, DEC); // print as an ASCII-encoded decimal Serial.print("\t HEX: "); // print a tab character Serial.print(analogValue, HEX); // print as an ASCII-encoded hexadecimal Serial.print("\t OCT: "); // print a tab character Serial.print(analogValue, OCT); // print as an ASCII-encoded octal Serial.print("\t BIN:"); // print a tab character Serial.print(analogValue, BIN); // print as an ASCII-encoded binary Serial.println(); } delay(100); // we have to make a delay to avoid overloading the serial port }

I do not understand why this is not outputting a better range of integers. I have a 1M resister and a 5.1V Zener Diod in parallel with the Piezo.



That one is hard to answer, since the rise and decay of the signal from the piezo is goign to be very fast. The Arduino sampling rate, especially with the serial commands and the 100ms delay, is a lot slower in comparison.

Do you have an oscilloscope? That would be the quickest way to see what the piezo is actualy putting out.

The zener diode may be also influencing things. It's a good idea for protection, although I never use them and haven't had a problem... I just connect the piezo across an analog input and ground, with a 100K resistor in parallel. The resistor might be your problem-- the 1M resistor might not be small enough to allow the piezo's potential to drain quickly enough.

OK I have guessed at everything possible here, hope this helps! :)


Just adding to daniel's excellent response.

All those print statements use a looooot of time... remove all that HEX, BIn etc... print only one value and up the serial speed at 115200

also you might want to print data only if it goes above a certain value...

all that printing is makin you miss all the good values :)


Brilliant thanks so much for your advice - I'll trim the resistor to 100K and remove all the prints - which were there to see what was happening - I alsdo realised I instantiated the 'analogValue' variable as a BYTE hence not getting the nive INT's I was expecting



Just wanted to add my thanks as well for Daniel’s advice, I’m about to start a project based on the “spookyarduino” MIDI drum kit ( which uses a 1M resistor and zener diode in parallel with the piezo. Garth, would I correct in assuming you’re working on something similar? In any case, good luck :slight_smile:


i was using a one-ince diameter piezo… or 2.67cm or something like that!

If you have a giant piezo that could well damage the Atmega inputs.
Now that I htink of it, the diode should be OK, it’s probably the resistor… any luck yet?


Thanks Daniel

Yes I am just using the smaller Piezo as well - I changed the resistor and took the Zener out - the responce is much better but still not all that great - I not the highest output is around 800, and it does not seem to output very consistent figures - multiple taps of similar strength output quite different responces, so perhaps it is still not seeing the envelop of the sensor properly?

I am interested in using several to form a trigger matrix for samples with some velocity sensativity that I will smooth in Max/MSP as there seems to be no way of smoothing in Arduino?

I'll look at it a bit more tonigh and get back to you - the main problem is consistency of responce - perhaps I need better quality Piezos? Any suggestions on that front?



what value resistor did you try? Try putting a 100K pot across the piezo terminals, and turning it to a smaller and smaller resistance while monitoring the values...

yes thats a good idea - I have just such a pot with connector pins soldered on for the Arduino. I have a 100K resistor in there at the moment. I just got 10 smaller Piezos off eBay which actually seem to respond better than the larger one I have. The larger one is about 28mm across, the smaller one is about 22mm.

I'll try the pot idea tomorrow.

Thanks again.

PS. I got the Arduino2Max running today - SWEET :-)



The charge generated by the piezo when it is whacked is very tiny. You'll likely find that adding a resistor smaller than 1M will result in lower values read from analogRead(). This is because the smaller the resistor is, the faster the piezo's charge will be dissipated. Trying to accurately capture the tiny voltage peak generated by the piezo is tough. Ideally I think you'd have no resistor at all and then use Arduino itself to discharge the built-up charge once it has been read. Something like this might work (note, not tested at all): pinMode(piezoPin,INPUT); val = analogRead(piezoPin); // read piezo pinMode(piezoPin,OUPUT); digitalWrite(piezoPin,LOW); // discharge piezo

This assumes the input resistance of the Arduino is very high, >10M at least. I think this is the case, but I've not checked. And it runs the risk that you'll miss the whack on the piezo when you're spending time draining the charge. This is the reason for the 1M resistor in the original circuit: it acts as a constant charge drain so you don't need to worry about doing it yourself, at the expense of accuracy because you're never sure of getting an accurate reading.

I solved this quite accurately before by sticking an op-amp configured as a comparator between the piezo and microcontroller. The op-amp amplified the signal and turned it into a digital value where the HIGH time measured the intensity of the hit on the piezo.

And you'll still probably want the zener though. Piezos can generate kilovolts, more than enough to fry the input pins of your Arduino.

thanks tobot

thats very helpfull - I was also thinking of running serval resistors to different pins a comparing the outputs. I teach Electronic Arts and Electronic Music at the University of Western Sydney, and we have been doing quite a bot of stuff with sensors - I am new to Arduino, and was inspired by your Drum Kit project to check out the accuracy and responce for some drum students who would enjoy adding sampled sounds this way. Arduino is cheap enough to be in their price range, and Piezos are of course much cheaper than FSR's or other options.

What OpAmp did you use and how did you configure it?

Thanks in advance