Датчик для обнаружения удара мяча

Я хочу обнаружить удар мяча о ракетку для настольного тенниса.

В настоящее время я использую пьезо-диски, плотно закрепленные в деревянном корпусе ракетки.

Однако помимо правильного определения удара датчик также обнаруживает внезапные ускорения ракетки. Например, очень часто делают быстрое движение назад непосредственно перед ударом по мячу.

Мой подход очень наивен: я считываю АЦП как можно быстрее, и если среднее значение последних 10 измерений достигает порогового значения, я считаю влияние обнаруженным. (Я пробовал другие числа, кроме 10.)

Вопросы:

  • Есть ли лучший датчик для этой цели?
  • Если нет, то как я могу отличить (или отфильтровать) внезапные движения от ударов мяча.
Я бы рекомендовал использовать акселерометр.
простой микрофон может работать.
@Trevor Мне нравится твоя идея, но может быть сложно отфильтровать удары противников или если мяч просто отскочит от пола. Сочетание микрофона и акселерометра гарантирует, что удар произошел и ваша ракетка закачалась. Или микрофон + пьезодиски.
Выгрузите несколько примеров воздействия в Excel и разработайте алгоритм обработки в Excel. Протестируйте алгоритм на предмет ложных срабатываний.
Я думаю, что использование пьезодатчика — хорошая идея (дешевое и очень простое преобразование сигнала). Я ожидаю, что сигнал при ударе мяча будет намного сильнее (более высокое напряжение) и короче (FWHM <0,1 с), чем любое ускорение, вызванное перемещением ракетки вручную. Должно быть легко различать оба сигнала.
Вы можете комбинировать данные с пьезоэлемента и микрофона для получения более точных результатов. Вам не нужно полагаться только на один датчик.

Ответы (2)

Я думаю, вам нужно подключить датчик к осциллографу и сравнить сигнал напряжения во время движений руки и во время удара мяча или сбросить данные АЦП и построить их (как упоминал @Harry Svensson). Если у вас нет хороших данных, то вы просто угадываете правильный алгоритм.

Я думаю, что удар по мячу будет иметь очень быстрое время нарастания напряжения, тогда как движения рук будут медленными. Если данные подтверждают это, вы можете поставить операционный усилитель, сконфигурированный как дифференциатор, перед АЦП. Его выход будет зависеть от скорости изменения пьезосигнала, а не от фактического уровня.

введите описание изображения здесь

Диаграмма выше взята из хорошего учебника по схеме дифференциатора на http://www.electronics-tutorials.ws/opamp/opamp_7.html .

По сути, чем быстрее нарастает (или падает) сигнал пьезоэлектрического напряжения, тем больше будет отклонение Vout. Затем ваш код просто ищет превышение порога, такого как ваш нынешний алгоритм.

Имейте в виду, что максимальное отклонение напряжения может быть положительным или отрицательным во время удара мяча в зависимости от того, как вы сориентировали свой пьезоэлемент. Ваш анализ необработанных данных датчика покажет это.

Если ваш MCU достаточно быстр, вы можете делать это даже в цифровом виде в режиме реального времени. По сути, вам просто нужно посмотреть разницу между сэмплами и триггером, когда вы увидите большую разницу.

Такого рода вещи могут быть сделаны с дискриминацией событий .

Дискриминатор событий принимает сигналы с надлежащей амплитудой и частотным составом.

Чтобы выполнить это в простом микроконтроллере со средними возможностями (скажем, 16 МГц или лучше):

Забудьте об A2D и подайте свой пьезосигнал на аналоговый компаратор. Затем выход компаратора подключается к входному контакту, сконфигурированному как прерывание.

После поступления 1-го импульса запустите таймер и продолжайте считать входные импульсы. Как только будет обнаружено желаемое количество импульсов или истечет время таймера, выйдите из цикла.

Если вы получаете желаемое количество отсчетов, а таймер находится ниже некоторого отсчета, то сигнал имеет слишком высокую частоту и может быть отброшен.

Если время таймера истекло, а счетчик все еще слишком мал, значит, сигнал имеет слишком низкую частоту и может быть отброшен.

В противном случае сигнал можно считать событием .

Конечно, вы можете сделать все это с вашими данными A2d, просто потребуется процессор с большей мощностью.

« Каковы правильные настройки? » Посмотрите на отскок мяча с помощью прицела, подключенного к выходу компаратора. Определите количество импульсов, наиболее характерных для одного отскока мячика для пинг-понга, а также минимальное и максимальное время, соответствующее частоте.

Удачи!

Псевдокод:

//******************************************************************************
    //
    // 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; 
    }
Для «псевдокода» наверняка есть много специфичных для устройства, синтаксически правильных исходных кодов C...
@Cuadue ya, используя этот термин, чтобы снять с себя любую ответственность за (неправильное) использование.