5
\$\begingroup\$

I want to detect the impact of a ball against a table tennis racket.

I'm currently using Piezo discs tightly fixed in the racket wood.

However, in addition to correctly detect impact, the sensor also detects sudden accelerations in the racket. As an example, it is very common to make a fast movement backwards just before hitting the ball.

My approach is very naive: I'm reading the ADC as fast as possible and if the average of the last 10 measures reaches a threshold, I consider the impact detected. (I tried other numbers besides 10.)

Questions:

  • Is there a better sensor for this purpose?
  • If not, how can I differentiate (or filter out) sudden movements from ball impacts.
\$\endgroup\$
6
  • \$\begingroup\$ I would recommend using an accelerometer. \$\endgroup\$
    – Daniel
    Aug 9, 2017 at 19:33
  • 4
    \$\begingroup\$ a simple microphone might work. \$\endgroup\$
    – Trevor_G
    Aug 9, 2017 at 19:35
  • 1
    \$\begingroup\$ @Trevor I like your idea, but it might be difficult to filter out the opponents hit, or if the ball just bounce on the floor. A mix of a microphone and an accelerometer would make sure a hit happened and that your racket was swung. Or microphone + piezo discs. \$\endgroup\$ Aug 9, 2017 at 19:58
  • 1
    \$\begingroup\$ Dump several example impacts into excel and design a processing algorithm in excel. Test the algorithm against false impacts. \$\endgroup\$
    – Andy aka
    Aug 9, 2017 at 20:15
  • \$\begingroup\$ I think using a piezo sensor is a good idea (cheap and very simple signal conditioning). I'd expect the signal at ball impact to be much stronger (higher voltage) and shorter (FWHM < 0.1s) than any acceleration caused by manually moving the racket. It should be easy to discriminate both signals. \$\endgroup\$
    – Curd
    Aug 9, 2017 at 23:04

2 Answers 2

3
\$\begingroup\$

I think you need to connect the sensor to an oscilloscope and compare the voltage signal during hand movements and during ball impact, or dump your ADC data and plot it (as @Harry Svensson mentioned). If you don't have good data, then you're just guessing at the correct algorithm.

I think the ball hit will have a very fast voltage rise time whereas hand movements will be slow risetime. If data confirms this then you might put an opamp configured as a differentiator before the ADC. It's output will vary based on how fast the piezo signal is changing, instead of being based on the actual level .

enter image description here

The diagram above is from a good tutorial on the differentiator circuit at http://www.electronics-tutorials.ws/opamp/opamp_7.html

Basically, the faster the piezo voltage signal rises (or falls) the greater Vout excursion will be. Your code than then just look for exceeding a threshold like your present algorithm.

Keep in mind the highest voltage excursion can be positive or negative during the ball hit depending on which way you've oriented your piezo. Your analysis of your raw sensor data will reveal this.

If your MCU is fast enough, you could even do this digitally in real time. Basically you just need to look the difference between samples and trigger when you see a large difference.

\$\endgroup\$
4
\$\begingroup\$

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; 
    }
\$\endgroup\$
2
  • \$\begingroup\$ For "pseudocode" there sure is a lot of device-specific, syntactically correct C source... \$\endgroup\$
    – Cuadue
    Aug 11, 2017 at 17:35
  • \$\begingroup\$ @Cuadue ya, using the term to remove any responsibility for (mis)use. \$\endgroup\$ Aug 11, 2017 at 21:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.