Piezo Velocity

Hi all this is my first post, not sure if Im in the right section! :blush:

Basically I’m building a MIDI controller for my final project at uni. Ive got the buttons and pots working, and am getting note on and note off messages from my piezos. However I can’t get velocity to work on them, I’ve googled everything possible, and it either doesnt seem to work or it too complicated for me to understand :~

This is what I have so far from utilising the knock example:

#include <MIDI.h>

const int knockSensor = A0; // the piezo is connected to analog pin 0
const int threshold = 20; // threshold value to decide when the detected sound is a knock or not

int velocity;
int sensorReading = 0; // variable to store the value read from the sensor pin

void setup() {
MIDI.begin (1); //send MIDI on channel 1


void loop() {
// read the sensor and store it in the variable sensorReading:
sensorReading = analogRead(knockSensor);
velocity = map(sensorReading, 0, 1023, 0, 127);

if (sensorReading >= threshold) {
MIDI.sendNoteOn (50, velocity, 1); //send note on D2
delay(20); //sustain
MIDI.sendNoteOff (50, 0, 1);//send note off



Apologies if this is something really simple, but Ive tried numerous things including dividing the analogRead by 8… but all it does is change the set velocity as opposed to giving me various values. The hardware set up is just from this link http://leucos.lstilde.org/wp/2009/06/piezo-transducer-signal-conditioning/

Any help would be appreciated! XD

Welcome to the forum.

Are you using this library ?

And you want the 'velocity' parameter according to how hard you knock ?

I should work like you have in your sketch, but perhaps your sketch is too simple.
The delay of 100ms at the end of the loop() makes that you sample 10 times a second. Ten times a second might not good be enough to detect the size of the knock pulse. But I can not find a library that has solved this.

This project uses a different number when mapping the analog value. Perhaps you can try that.


Im using this library http://playground.arduino.cc/Main/MIDILibrary#.UzAgoV4SGqw

I’ve incorporated the code from the instructables page into mine and got this:

#include <MIDI.h>

int piezo = A0;
int threshold = 50;//anything over fifty means we’ve hit the piezo
int sensorReading = 0;

void setup(){


void loop(){
sensorReading = analogRead(piezo);
if (sensorReading >= threshold){
int maxPiezoVal = getMaxVal(sensorReading);
byte velocity = map(sensorReading, 0, 1023, 50, 127);//velocity between 50 and 127 based on max val from piezo
MIDI.sendNoteOn(50, velocity, 1);
MIDI.sendNoteOff(50, 0, 1);

int getMaxVal(int lastVal){
int currentVal = analogRead(piezo);
while (currentVal>lastVal){
lastVal = currentVal;
currentVal = analogRead(piezo);
return lastVal;


Hurray it reads velocity! Although its not very accurate where sometimes a harder hit is still producing a small velocity, and it seems to jump from low to high, there doesnt seem to be an increase in velocity as the hit gets gradually harder. It just jumps from one to another! Is this normal for a piezo? Or can some sort of code smooth it out? Thanks for your help!

I think that is normal. It is a combination of the piezo element, the hardware filter and the sketch.

For a better way to detect the strength of the ‘knock’, you would have to calculate the surface of the knock pulse. That requires a higher sample rate. I have been searching for code or a library for that, but I have not found it.

There are other ways that are in between the two methods. For example calculating how steep the curve is, or how fast the peak is reached after a certain threshold.
The example from instructables tries sampling until the peak is reached, and used the peak value. That is already a lot better.

However, you have mixed your code with the instructables code, and the result is not working.
You have to use the peak value “maxPiezoVal” for the map() function, and you still use the “sensorReading”, which is the value after the threshold.
Can you fix that ? It should improve the velocity a lot. Perhaps some finetuning is needed with the map() function values.

Yes that seems to have helped! And I have put the lowest new value to 0... thanks a lot! :smiley:

Now to have multiple piezos running in the same code... Oh dear! :blush: