This type of thing can be done with event discrimination.
An event discriminator accepts signals with the proper amplitude and frequency content.
To accomplish this in a simple micro-controller of moderate capability (say 16MHz or better):
Forget the A2D, and apply your piezo signal to an analog comparator. The comparator's output then connects to an input pin configured as an interrupt.
Once the 1st pulse arrives, start a timer, and continue to count input pulses. Once the desired number of pulses are detected, or the timer has run out, exit from the loop.
If you get the desired number of counts, and the timer is below some count, then the signal is too high in frequency, and can be discarded.
If the timer has expired, and the count is still too low, then the signal is too low in frequency, and can be discarded.
Else, the signal can be counted as an event.
Of course you could do all of this with your A2d data, it would just take a cpu with more horsepower.
"What are the proper settings?" Look at a ball bounce with a scope attached to the comparator's output. Determine the number of pulses that are the most common for s single pong-ball bounce, as well as the min and max time corresponding to the frequency.
Good luck!
Pseudo Code:
//******************************************************************************
//
// INTERRUPT HANDLERS
//
//******************************************************************************
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt
void Port_1(void) {
//Only defined interrupt should be (P1.0). Yes, slimy cheating here to keep things fast.
//Bit1.0 - Initial Pulse detected. Start Discrimination.
//Start Window timing, TA1R should already be set to 0 somewhere else.
TA1CTL |= TIMER_A_CONTINUOUS_MODE;
//Start Pulse counting, TA2R should already be set to 0 somewhere else.
TA2CTL |= TIMER_A_CONTINUOUS_MODE;
//Disable this pin input interrupt
P1IE = 0x0; //Hard-coded and blunt-force trauma for speed.
State = Active;
}
//Handle interrupts from Timer A1 ('Timer1_A'), section 0 ('0') which connects to CCR0
//This is the Frequency Window timer.
#pragma vector=TIMER1_A0_VECTOR
__interrupt
void TIMER1_A0_ISR(void){
//if we've made it here, then we've run out of time. Abort. Low Frequency.
//Turn off/reset Pulse counter
Timer_A_stop(TIMER_A2_BASE);
Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
//Turn off/reset this (Window) counter
Timer_A_stop(TIMER_A1_BASE);
State = LowF;
}
//Handle interrupts from Timer A2 ('Timer2_A'), section 0 ('0') which connects to CCR0
//This is the pulse counter.
#pragma vector=TIMER2_A0_VECTOR
__interrupt
void TIMER2_A0_ISR(void){
//if we've made it here, then we have enough pulses. Check for event...
//Turn off/reset the window counter
Timer_A_stop(TIMER_A1_BASE);
Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
//Turn off/reset this (Pulse) counter
Timer_A_stop(TIMER_A2_BASE);
//Verifiy timer results outside the ISR, and determine is this is really a good event
State = Verify;
}