Impact detector - How to count number of hits?

Hi everybody

Idea I am trying to build a device which counts the number of impacts on a surface. (e.g. three balls are thrown onto the surface --> counter shows 3). The analog signal is coming from a piezo-electric microphone which is attached to the surface. My idea was to do a numeric derivation (1st and 2nd) of the last three data points in order to detect the high peaks.

Problem The problem is that throwing the ball onto the surface causes an echo in the signal due to vibrations below the surface. The counter will be wrong if the peaks from the echo are also counted. My first intention was to set a threshold higher than the vibrations peaks. This does not work due to the fact that the peak of a "soft" hit can be lower than the echo of a "hard" hit.

Question - Is there an easier method how to calculate the peaks instead of using a numeric derivation? - Do you have any idea how to prevent that the echo is being counted as hits?

Thanks in advance for your help, Ecount

Just inhibit detection for a short delay after the impact so the echo dies away?

Good idea, thanks, but I'm not sure if this will work for my project. The intention is to count the impact of a series of particles (the ball example was just for simplification). Inhibiting the detection for a short time could result in a too low count. Counting the echo in a too high one. Let's see which one results in a lower error.

What does a graph of your Piezo data look like?

Can you identify strikes that are going to produce a big enough echo to cause an erroneous count and ignore it?

Rather than ignoring the echos, you could instead, ignore the LOUD primaries. Anything above a certain threashold will produce a detectable echo. Therefore you can ignore the primary if it's large enough to produce a discernable echo. It's echo will then be counted.

wildbill:
What does a graph of your Piezo data look like?

I don’t have a sample of the final data yet, but this one looks similar to what I expect (see attachments). The sensor was connected to a surface while I tapped on the surface with my fingers.

  • The excel plot shows the plain signal coming from the sensor. There are seven impacts. The amplitude is very low in this example compared to the maximum possible range. Have to adjust it later.
  • The other two attachments are showing a (different from the excel) audio recording of a double tap. The sensor was connected to my PC’s microphone input.

wildbill:
Can you identify strikes that are going to produce a big enough echo to cause an erroneous count and ignore it?

Will try to do this as soon as I have any real sensor data.

Thank you for all the good ideas. I hope that I can provide some real data within a week and show you the results of my first attempts filtering out the echoes.

Did some playing around with this … created some impact data, then rectified / smoothed / compared to get seven pulses.

Modify as you wish (zip file has spreadsheet).

impact.ino (2.57 KB)

Impact Detecton.zip (16.1 KB)

… a better approach …

Determine spread of the signal over a “sliding” group of 5 samples, then amplify x4, then compare with hysteresis.

Waveforms shown are Input signal, Spread x4, and Output:

impact2.ino (2.89 KB)

Impact Detecton2.zip (11 KB)

Ecount: Hi everybody

Idea I am trying to build a device which counts the number of impacts on a surface. (e.g. three balls are thrown onto the surface --> counter shows 3). The analog signal is coming from a piezo-electric microphone which is attached to the surface. My idea was to do a numeric derivation (1st and 2nd) of the last three data points in order to detect the high peaks.

Problem The problem is that throwing the ball onto the surface causes an echo in the signal due to vibrations below the surface. The counter will be wrong if the peaks from the echo are also counted. My first intention was to set a threshold higher than the vibrations peaks. This does not work due to the fact that the peak of a "soft" hit can be lower than the echo of a "hard" hit.

Question - Is there an easier method how to calculate the peaks instead of using a numeric derivation? - Do you have any idea how to prevent that the echo is being counted as hits?

Thanks in advance for your help, Ecount

Sounds like a job for an accelerometer. You using a piezo basically as a microphone I think will give you all kinds of grief (as I can see in your data... ringing... echos... amplitude uncertainty.

When an object hits your target, it's going to transfer momentum and the ratio of the masses between impactor and target will allow you to predict what signal you expect to see.

Of course, you will even be able to determine impact velocity based on the acceleration and knowing the mass of the impactor.

A 3 axis accelerometer can probably give you 3D information as to not only how hard the impactor hit the target, but also the DIRECTION it came in with.

Sounds like a fun project.....

I have been building drip impact detectors for my wife’s research (she’s a hydrogeologist) using the tap detection feature of the ADXL345 accelerometers:

http://edwardmallon.wordpress.com/category/developing-a-drip-sensor/

These accelerometers can be configured to send an interrupt alarm from a single “tap” event. So INT1 from the accelerometer is connected to pin 3 on the Arduino, and the ISR attached to that pin wakes the sleeping logger from sleep and updates a simple counter variable. The logger then “waits” for long enough for the vibrations to die down (somewhere between 15-45 ms in my case) then the logger goes back to sleep waiting for the next drip “impact”. The RTC can also wake up the logger from time to time so there are two interrupts in the sleep routine. The LowPower.powerDown functions are from Rocket Screams sleep library.

Complete logger code, with the drip counter is at: http://github.com/EKMallon/The_Cave_Pearl_Project_CODEbuilds/blob/master/_20141002_DripSensors_WithPowerControl/_20141002_DripSensors_WithPowerControl.ino

There are allot of register settings to take care of to set up tap sensing, which you can find in the
void initADXL345(); function

Most of which I figured out by following the beautifully commented code over at
http://code.google.com/p/adxl345driver/source/browse/trunk/ADXL345.cpp?r=11

The essential functions that handle the impact counting are:

while(clockInterrupt == false){   //break out of this loop if the RTC interrupt happens

      // a tap just occurred clear so need to read&clear the registers to turn off the interrupt signal
      intSource=i2c_readRegByte(ADXL345_ADDRESS,0x30); //read the ADXL345_INT_SOURCE interrupt register to clear it
      bytebuffer1=i2c_readRegByte(ADXL345_ADDRESS,0x2b); //read the ADXL345_ACT_TAP_STAT register to clear it
      
      // Now we add a delay to the response to let system stop vibrating.
      digitalWrite(READSENSOR_PIN, HIGH);      
      LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_OFF);
      digitalWrite(READSENSOR_PIN, LOW); //pip to show that a tap occurred
      
      intSource = 0;      
      intSource=i2c_readRegByte(ADXL345_ADDRESS,0x30); //read the ADXL345_INT_SOURCE interrupt register to clear it in case an int was generated during the delay
      bytebuffer1=i2c_readRegByte(ADXL345_ADDRESS,0x2b); //read the ADXL345_ACT_TAP_STAT register to clear it
      digitalWrite(adxl345intPin, HIGH);//now that the acc interrupt is gone, set internal pull up back the ADXL interrupt pin
     
      sleepNwait4AccInterrupt();
    }  //WHILE LOOP TERMINATOR for drip counter! 

// ==========later in the code ============  
 
void sleepNwait4AccInterrupt()   //this version uses the rocket scream libraries - which lets me shut off the BOD fuse
{
  noInterrupts ();          // make sure we don't get interrupted before we sleep
  attachInterrupt(0,clockTrigger, LOW);  //this is the main RTC interrupt - It breaks you out of the tap counter while loop
  attachInterrupt(1,accTrigger, LOW);
  interrupts ();           // interrupts allowed now, next instruction WILL be executed
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  //HERE AFTER WAKING UP
  detachInterrupt(1);
  detachInterrupt(0); //if you broke out of the while loop, then your RTC interrupt fired.
// here is where the drip counter gets updated
  if (accInterrupt && tapcount<429496729) {  
    tapcount=tapcount+1; 
    accInterrupt=false;
  } 
}

//==========
// ACC Tap TRIGGER FLAG
void accTrigger() {//this flag gets reset to false when the "tapcount" is updated
  accInterrupt = true; 
}

//==========
// CLOCK TRIGGER FLAG
void clockTrigger() {
  clockInterrupt = true; 
//this flag gets reset in the main program loop after you break out of the while loop
}

There is another drip counter out there called the Driptych Stalagmate. [http://www.driptych.com/] I think the Driptych uses a piezo sensor to detect the impact of the drips. My guess is that they have figured out how to get the piezo voltage spike to trigger the interrupt line, which probably uses alot less power than keeping an accelerometer running all the time. It’s probably more durable, as I have seen a fair share of sensor failures. If you are actually detecting something with as much energy as a ball you would not want to operate the ADXL it at the high sensitivity settings I have been using.