Detection of a vibration peak

Hi everyone,
I have been developing using arduino for about a year now, in several different niches.
I am having a real hard time on trying to detect a duble tap on a surface.
The system made of: arduino uno, mems piezoelectric horizontal beam, parller with 1 mgh rsistor conected to the anlog read pin a0.

Can someone please offer me a good algorithm ti isolte the knock?
The main problem is that the first knock leavs noise for about 10ms during the time i need to measure the second tap..
Hance i cant really isolate the first and second tap.

I would be very grateful for any enlightenment in knocking/ tapping detection algorithm.
Thank u very much for any comment and good luck all!

It sounds as if your transducer it not suitable for the job.

But..., could you post an oscilloscope picture of the signal you see?

regards

Allan

Hi thank you very much for replying.
The piezo beam I am using is - https://www.sparkfun.com/datasheets/Sensors/Flex/MiniSense_100.pdf

I have add 2 scope pic of the signal peak hope u can see it.
And after countless attempts now I got to this code:

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

}

void loop() {
vibe = analogRead(knockSensor);

if (vibe > 12 && vibe < 30) {
xEvg();
getData();

for (int k = 7, zeroSum = 0 ; k < 13; k++) {
zeroSum += amp[k];
}
if (zeroSum <= 2)
zeroCheck = 1;
else
zeroCheck = 0;

if (((evgAmp[1] - evgAmp[2]) > 10) && (amp[6] == 0 && amp[7] == 0) && (evgAmp[0] < 22) && (zeroCheck == 1)) { // checking trash hold conditions
zeroCheck = 0;
knock = 1;
}

else
knock = 0;

if (knock == 0) {
for (int k = 0 ; k < 8; k++)
evgAmp[k] = 0;

for (int k = 0 ; k < 16; k++)
amp[k] = 0;

}

if (knock == 1) {
Serial.print("detection: ");
Serial.println(knock , DEC);
Serial.println("the knock Data: 8bit ,16 bit ");
for (int k = 0 ; k < 8; k++) {
Serial.print(evgAmp[k], DEC);
Serial.print(", ");
}
Serial.print("\n");
for (int k = 0 ; k < 16; k++) {
Serial.print(amp[k], DEC);
Serial.print(", ");
}
Serial.print("\n\n");
delay(70);
Amplitude = (xEvg1 + xEvg2) / 2 - (xEvg3 + xEvg4) / 2;
knock = 0;
for (int k = 0 ; k < 8; k++)
evgAmp[k] = 0;
for (int k = 0 ; k < 16; k++)
amp[k] = 0;

signalMax = 0;
signalMin = 254;
ampCount = 0;
}

delay(1);
}

}

void xEvg() {

for (int k = 0 ; k < 4; k++)
xEvg1 += amp[k];

xEvg1 /= 4 ;

for (int k = 4 ; k < 8; k++)
xEvg2 += amp[k];

xEvg2 /= 4;

for (int k = 8 ; k < 12; k++)
xEvg3 += amp[k];

xEvg3 /= 4;

for (int k = 12 ; k < 16; k++)
xEvg4 += amp[k];

xEvg4 /= 4;

Evg[0] = xEvg1;
Evg[1] = xEvg2;
Evg[2] = xEvg3;
Evg[3] = xEvg4;
return;
}

void getData() {
for (int k = 0, ampCount = 0 ; k < 16; k++) { //measure the max and min signal in one knocking time

for (int i = millis(), j = millis() ; i < (j + tapTime); i = millis()) { //measure the max and min signal in one knocking time
vibe = analogRead(knockSensor);
if (vibe > signalMax) {
signalMax = vibe;
}
else if (vibe < signalMin) {
signalMin = vibe;
}
}
amp[ampCount] = signalMax;
signalMax = 0;
signalMin = 254;
ampCount++;
}

for (int k = 0, i = 0 ; k < 8; k++, i += 2) {

evgAmp[k] = (amp + amp[i + 1]) / 2;

Why reinvent the wheel? This is a very common problem that has been solved many times.

Google "peak detection algorithms" for general approaches.

Please use code tags when posting.

Hi jremington,
I have tried to look up for peak detection algorithm most of the results were just pseudo code or code in languages I am not familier with.( not C);
It would be great if you could send me a link or an example for a good peak detection you may know.
thanks,
Berry

What is wrong with pseudo code? It is easy to write C based on it (much easier than spending a year flailing around by yourself).

Try the smoothed z-score algorithm or one of the simpler algorithms in that thread, and let us know how you get on.

The sensor (with weight) seems to be made for low frequencies (<75Hz).

Is this for human knocking.
A common bare 1" piezo disc works fine for that.
Leo..

Jremington I did see it before but Ill give it a try now you advice on that thanks .
Will update soon.

wawa - thanks but the standard piezoelectric buzzr is not sensitive enough to detect light tapping on s big table.
Which is what I am trying to achieve. I am using now a piezo horizante beam which is a bit better I guss because its more sensitive to vibration.
What do you think about using a mic with gain ?
thanks for replaying all

berlad180:
wawa - thanks but the standard piezoelectric buzzr is not sensitive enough to detect light tapping on s big table. Which is what I am trying to achieve.

Not true.
This sketch can detect a pin dropping on my desk.
That is, if the piezo is attached/glued/weighed down properly. Experimenting required.
Leo..

// knock sensor/alarm
// Piezo, with 1Megohm load resistor across, connected to A0 and ground
// optional 5volt buzzer on pin 13

int threshold = 100; // alarm threshold from 1 (very sensitive) to 1022 <<<<<<<<
int alarmDuration = 100; // alarm duration in milliseconds <<<<<<<<

const byte piezoPin = A0;
int rawValue; // raw A/D readings
int piezoValue; // peak value
const byte onboardLED = 13; // onboard LED and/or buzzer

void setup() {
  analogReference(INTERNAL); // remove this line if too sensitive
  Serial.begin(115200); // serial monitor for raw piezo output
  pinMode (onboardLED, OUTPUT);
}

void loop() {
  // reset
  piezoValue = 0;
  // read
  for (int x = 0; x < 250; x++) { // multiple A/D readings
    rawValue = analogRead(piezoPin);
    if (rawValue > piezoValue) {
      piezoValue = rawValue; // store peaks
    }
  }
  // print
  if (piezoValue > 0) {
    Serial.print(F("Piezo value is "));
    Serial.println(piezoValue);
  }
  // action
  if (piezoValue > threshold) {
    Serial.print(F("Knock was over the threshold of "));
    Serial.println(threshold);
    digitalWrite (onboardLED, HIGH);
    delay(alarmDuration);
    digitalWrite (onboardLED, LOW);
  }
}

I would love to see the schematics, you didn't use any amplifier ?
You actually got a read above 100 from a piezo buzzer from s light tap on the table ?

No preamp. Just the 1" piezo connected to A0 and ground, with a 1Megohm resistor across.
The code uses 1.1volt Aref, to make it 5x more sensitive.
And samples at least 3/4 of a "tap wave", to make sure a positive peak is found even if the fist one is negative going.
With the piezo flat on the desk, and a pen on top to keep it there, you can just detect footsteps in the room.
Leo..

Oh great thanks! I actually didnt know that u can change the voltage Ref'.
how do you exactly change the ref?
You just connect a voltage divider with the 5V ?
Thanks for helping

Code from post#8.
The first line in void setup() calls 1.1volt Aref.

analogReference(INTERNAL); // remove this line if too sensitive

Leo..

WAWA thank u so much trying this configuration this weekend will update!

Sounds like the perfect application for a correlation detector - determine the waveform of the normal
tap and correlate the signal against this, it should reject most of the noise and make secondary
taps stand out clearly.

Of course correlation is compute-intensive and may require a DSP level of performance rather than
an 8-bit MCU level of performance... Reducing the sample rate to the minimum needed will help
reduce the work required, using hardware LPF.