НЕСТАНДАРТНЫЙ Детектор хлопков (только хлопков)
- Войдите на сайт для отправки комментариев
Занялся такой проблемой: создание детектора хлопков, чтобы исключить реагирование на другие звуки.
Пытался построить устройство на основе програмного фильтра, по следующему алгоритму : при срабатывании детектора, ардуино записывает в массив состоящий из 500 ячеек каждый такт. Таким образом записал 100 хлопков. Получилась очень грязная картина синусоиды. С Очень расплывчатыми периодами подъема и спада синусоиды.
На других форумах мне посоветовали сделать аппаратный фильтр звука вместе с программным. Но представления о том как это сделать равны 1- 2 %
На других форумах дали несколько вариантов как решить эту проблема, ниже приведу парочку из них:
"Анализатор спектра на ардуино))), ну даже быстрое преобразование фурье для 8 битного контроллера задача не простая.
Можно попробовать реализовать корреляцию сигналов, но это нужно сделать таблицу, в которую ещё нужно заполнить, далее нужно измерять уровень при помощи АЦП и считать, и организовать смещение массива, вобщем-то тоже нужно постараться.
А если взять компаратор, выставить порог срабатывания при котором он будет переключаться, выход компаратора, повесить на счетчик, скажем того же ардуино, но счетчик будет тактироваться внешним сигналом компаратора, задача просто скажем каждые 50мс смотреть чего там насчитал таймер, если настроить так чтобы за 1 хлопок регистрировал от 3 до 7 переключений, и соответственно если это так, регистрировать хлопок.
PS: сам я это не проверял, это просто идея)))"
Вот второй совет: en555 lm358 что то на них похожее если хлопок то сначала его обработает en555 задаст частоту после два операционника они эту частоту фильтруют по продолжительности импульса после когда импульс сформированный кидаем его на лапку контролера и программно описываем задержку после чего опршиваем лапку и смотрим что там происходит если импульс длица значит разговор если нет значит хлопок ну перд микрофоном я бы еще простой частотный фильтр бы применил
Как видите, в этих советах нет четких последовательностей.
Буду очень признателен если вы поможите:
1) Понять каким образом можно создать аппаратный фильтр (желательно на пальцах) Если не трудно с пояснением принципа работы каждого из элементов.
2) Сформировать последовательный список задачь , который поможет решить эту проблему.
P.S. Я ЗАИНТЕРЕСОВАН В СОТРУДНИЧЕСТВЕ С ЛЮДЬМИ БОЛЕЕ ЗНАЮЩИМИ ЧЕМ Я( В ЭЛЕКТРОНИКЕ).ГОТОВ ОТБЛАГОДАРИТЬ ДЕНЕЖНО. ТЕХ КТО БУДЕТ СОПРОВОЖДАТЬ МЕНЯ В ЭТОМ ПРОЕКТЕ.
Попробуйте всё-таки сначала программно, не заморачиваясь с фильтрами
вот раз: clap_detector.ino
/* Clapper project Author: Manoj Kunthu Update: 2/2/13 */ /*----------------------------- Method Prototypes -----------------------------*/ void initialize(); void runDetector(); boolean clapDetected(); int detectClaps(int numClaps); void indicateClaps(); void readMic(); void printStats(); /*----------------------------- Variable Declarations -----------------------------*/ int TOTAL_CLAPS_TO_DETECT = 2; // The number of claps detected before output is toggled int offset = 80; // The point above average that the clap is detected int CLAP_TIME = 4000; // The time allowed between each clap int sensorValue = 0; //the value read through mic int toggleOutput = -1; int SIZE = 3; int buffer[3]; int loopIteration = 0; int average = 0; int total = 0; //BOARD INPUT MIC const int inPin0 = A0; //BOARD OUTPUT SIGNALS const int clapLed1 = 12, clapLed2 = 11, out = 10, readyPin = 13; //CLAP STATE CONSTANTS const int FINAL_DETECTED = 0, LOST_CONTINUITY = 1, CLAP_NOT_DETECTED = 2; void setup() { Serial.begin(9600); //direct representation of the light bulb that toggles on/off pinMode(out, OUTPUT); //once initialize() runs the ready pin turns on pinMode(readyPin, OUTPUT); //respective clap LEDs, more can be added pinMode(clapLed1, OUTPUT); pinMode(clapLed2, OUTPUT); } void loop() { initialize(); runDetector(); } /** Purpose: Prepares the buffer to recognize ambient noise levels in room. */ void initialize() { loopIteration = 0; total = 0; average = 0; digitalWrite(clapLed1, LOW); digitalWrite(clapLed2, LOW); digitalWrite(out, LOW); for (int i = 0; i < SIZE; i++) { readMic(); buffer[i] = sensorValue; total = total + sensorValue; average = (total / (i + 1)); Serial.print("INIT - AVE: "); Serial.print(average); Serial.print(" Total: "); Serial.print(total); Serial.print(" Sensor: "); Serial.print(sensorValue); Serial.print(" Change: "); Serial.println(sensorValue - average); delay(50); } digitalWrite(readyPin, HIGH); } /** Purpose: Runs the detector algorithm. Developers can change the number of claps by adjusting TOTAL_CLAPS_TO_DETECT variable up at the top. */ void runDetector() { while (true) { int clapState = detectClaps(TOTAL_CLAPS_TO_DETECT); if (clapState == FINAL_DETECTED || clapState == LOST_CONTINUITY) { Serial.println("--done--"); indicateClap(0);//turn off any clap indicating lights } } } /** Purpose: Detects the number of claps specified. This method is recursive */ int detectClaps(int numClaps) { int clapNum = numClaps; //Base Case - if clapNum is 0, then all claps have been accounted. if (clapNum == 0) { //the output can now be toggled. toggleOutput *= -1; indicateClap(clapNum); Serial.println("----- Clap Limit Reached - Output Toggled -----"); return FINAL_DETECTED; } //Read from mic and update ambient noise levels. readMic(); total = (total - buffer[loopIteration]) + sensorValue; average = (total / SIZE); buffer[loopIteration] = sensorValue; loopIteration = (loopIteration + 1) % SIZE; if (clapDetected()) { Serial.print("detectClaps - Claps:"); Serial.println(TOTAL_CLAPS_TO_DETECT + 1 - numClaps); printStats(); indicateClap(clapNum); delay(100); for (int i = 0; i < CLAP_TIME; i++) { int clapState = detectClaps(clapNum - 1); if (clapState == FINAL_DETECTED || clapState == LOST_CONTINUITY) { return clapState; } } return LOST_CONTINUITY; } return CLAP_NOT_DETECTED; } /** Purpose: Turns the LED on appropriately to signal a clap detection. */ void indicateClap(int clapNum) { if (clapNum == 0) { if (toggleOutput == 1) { digitalWrite(out, HIGH); } else { digitalWrite(out, LOW); } digitalWrite(clapLed1, LOW); digitalWrite(clapLed2, LOW); } else if (clapNum == 1) { digitalWrite(clapLed1, HIGH); } else if (clapNum == 2) { digitalWrite(clapLed2, HIGH); } delay(110); } /** Purpose: Prints basic statistics data for more info with sensor readouts and data points. */ void printStats() { Serial.print("--- AVE: "); Serial.print(average); Serial.print(" Total: "); Serial.print(total); //Serial.print(" iterNum: "); //Serial.print(loopIteration); Serial.print(" Sensor: "); Serial.print(sensorValue); Serial.print(" Change: "); Serial.println(sensorValue - average); //This is what I used to determine the 'offset' value } /** Purpose: A clap is detected when the sensor value is greater than the average plus an offset. The offset might need to be fine tuned for different sound sensors. */ boolean clapDetected() { return sensorValue > average + offset; } /** Purpose: Reads mic input and stores it in a global variable. */ void readMic() { sensorValue = analogRead(inPin0); }вот два: библиотеки с fft и fht, после которых брать бин частоты клэпа
http://wiki.openmusiclabs.com/wiki/ArduinoFHT
вот три: пример low-pass программного фильтра, можно, разумеется, сделать и high pass и band pass на частоту хлопка
https://bochovj.wordpress.com/2013/07/07/bass-detection-with-arduino/
Спасибо, вы считаете, что програмный фильтр может все-таки работать? (на стандартном ардуиновском микрофоне)
Если под стандартным вы имеете в виду KY-038 с алиэкспресса ( https://tkkrlab.nl/wiki/Arduino_KY-038_Microphone_sound_sensor_module ), то смело выкидывайте его в ведро, он очень дубовый. Но и с ним сработает, только хлопать надо не далее, чем в 5 см от микрофона.
Микрофон с EBAY. Но тоже китайский.
http://www.ebay.co.uk/itm/1pc-Analog-Sound-Sensor-Board-Microphone-MIC-Controller-For-Arduino-Pop/162351879439?_trksid=p2045573.c100507.m3226&_trkparms=aid%3D555017%26algo%3DPL.CASSINI%26ao%3D1%26asc%3D38661%26meid%3Dac6cfc7e8fb84c979371c352796cd904%26pid%3D100507%26rk%3D1%26rkt%3D1%26
Какой бы вы посоветовали?
Не знаю :), я не звукач; а fft для avr мучил, пробуя вылепить из ардуины vlf sdr, модуль микрофона же подключал для проверки кода.
Kollname, то, о чем Вы пишете, по большому счету является задачей распознавания, которую современная наука разрешить не в состоянии. Поэтому ни о каких четких алгоритмах здесь не может быть и речи.
Можно попытаться нащупать какой-нибудь эмпирический алгоритм, обладающий приемлемым количеством ошибок срабатывания, но для этого нужны некоторые познания: в первую очередь в акустике, ну и как необходимое (нр не достаточное) условие - в радиоэлектронике и программировании.
Суды по Вашим вопросам, ни первым, ни вторым, ни третьим Вы не обладаете. Тогда чего Вы хотите? Если невозможного - сразу бросьте эту затею. Если чему-то научиться, начните с учебника по акустике. Если чтобы за Вас что-то сделали - это в раздел "Ищу исполнителя". Только, боюсь, в последнем варианте никто за такую задачу не возмется. А если и возмется, вряд ли сделает.
У меня конкретная цель - я её упомянул выше. Согласен, что знаний у меня более чем недостоточно. Но это не мешает мне их накопить (хотя это может занять очень много времени). Мне всего-лишь нужно знать куда копать.
P.S. Кто знает сколько мс длится хлопок?
P.S. Кто знает сколько мс длится хлопок?
твой хлопок длится ровно один мой чих.
четыре эха от моего чиха заменяют один мой хлопок.
не хлопай - у меня насморк.
Спасибо, очень полезно!
Боги электроники Помогите!
Как програмно можно создать алгоритм на основе этих частот??
вторая картинка это обычный шум
первая это хлопок
1) сколько по времени длится хлопок?
2) Как (с помощью чего) можно разложить хлопок по частотам?
1. запиши свой хлопок и посмотри в аудиоредакторе длину
2. с помощью того же аудиоредактора.
Я думаю Ваша задача очень абстрактна. Вы попробуйте хотя бы что то написать, глядишь заработает. Со стандартным микрофоном или с каким то еще попробуйте. А когда устаните хлопать выложите сей скетч сюда, может мы тоже его зальем и похлопаем. Если на Вашем скрине с ютуба по горизонтали миллисекунды то хлопок длится 4 мс.
Я бы написал по такому алгаритму. Слушаем эфир, принимаем значение за фон и фильтруем его. Если идет увеличение смотрим на сколько больше фона, если не значительно (параметр значительности регулируем допустим с подстройки для удобства) то перезаписываем уровень громкости фона и слушаем дальше. Если значительный то засекаем сколько он длится. Если больше чем наш хлопок то значит это не хлопок и слушаем дальше. Если хлопок по времени говорим что хлопок. Но это например может быть и стук и резкий чих уважаемого Клапауция...
ну, шо за бред?
кто-то вообще пробовал хлопать в своём жилом помещении чаще, чем два раза в сутки?
ваша собака, жена, тёща, соседка вас на*уй после этого не послали?
вы, сцуко, в замках живёте, где каждый занимает по 300 квадратов студии и эхо от хлопков можно отличить от чиха вашей собаки?
Спасибо, очень полезно!
Боги электроники Помогите!
Хера взываеш среди ночи? Спят усе.
Твоя задача - амплитудная детекция и селекция по длительности. Хлопок по громкости выше чем шум и длится мало. Пиши код и не возропщи нах...
Я так полагаю код который мне скинули работает по тому же принципу. Плохо понимаемый!
void initialize(); 012 void runDetector(); 013 boolean clapDetected(); 014 015 int detectClaps(int numClaps); 016 void indicateClaps(); 017 void readMic(); 018 019 void printStats(); 020 021 /*----------------------------- 022 Variable Declarations 023 -----------------------------*/ 024 025 int TOTAL_CLAPS_TO_DETECT = 2; // The number of claps detected before output is toggled 026 int offset = 80; // The point above average that the clap is detected 027 int CLAP_TIME = 4000; // The time allowed between each clap 028 029 030 int sensorValue = 0; //the value read through mic 031 032 int toggleOutput = -1; 033 034 int SIZE = 3; 035 int buffer[3]; 036 int loopIteration = 0; 037 int average = 0; 038 int total = 0; 039 040 041 042 //BOARD INPUT MIC 043 const int inPin0 = A0; 044 045 //BOARD OUTPUT SIGNALS 046 const int clapLed1 = 12, clapLed2 = 11, out = 10, readyPin = 13; 047 048 //CLAP STATE CONSTANTS 049 const int FINAL_DETECTED = 0, LOST_CONTINUITY = 1, CLAP_NOT_DETECTED = 2; 050 051 void setup() { 052 Serial.begin(9600); 053 054 //direct representation of the light bulb that toggles on/off 055 pinMode(out, OUTPUT); 056 057 //once initialize() runs the ready pin turns on 058 pinMode(readyPin, OUTPUT); 059 060 //respective clap LEDs, more can be added 061 pinMode(clapLed1, OUTPUT); 062 pinMode(clapLed2, OUTPUT); 063 } 064 065 066 void loop() { 067 initialize(); 068 runDetector(); 069 } 070 071 /** 072 Purpose: Prepares the buffer to recognize ambient noise levels in room. 073 */ 074 void initialize() 075 { 076 loopIteration = 0; 077 total = 0; 078 average = 0; 079 080 digitalWrite(clapLed1, LOW); 081 digitalWrite(clapLed2, LOW); 082 digitalWrite(out, LOW); 083 084 for (int i = 0; i < SIZE; i++) 085 { 086 readMic(); 087 088 buffer[i] = sensorValue; 089 total = total + sensorValue; 090 average = (total / (i + 1)); 091 092 Serial.print("INIT - AVE: "); 093 Serial.print(average); 094 Serial.print(" Total: "); 095 Serial.print(total); 096 Serial.print(" Sensor: "); 097 Serial.print(sensorValue); 098 Serial.print(" Change: "); 099 Serial.println(sensorValue - average); 100 101 delay(50); 102 } 103 digitalWrite(readyPin, HIGH); 104 } 105 106 /** 107 Purpose: Runs the detector algorithm. Developers can change the number of claps by adjusting TOTAL_CLAPS_TO_DETECT variable up at the top. 108 */ 109 void runDetector() 110 { 111 while (true) 112 { 113 int clapState = detectClaps(TOTAL_CLAPS_TO_DETECT); 114 115 if (clapState == FINAL_DETECTED || clapState == LOST_CONTINUITY) 116 { 117 Serial.println("--done--"); 118 indicateClap(0);//turn off any clap indicating lights 119 } 120 } 121 } 122 123 /** 124 Purpose: Detects the number of claps specified. This method is recursive 125 */ 126 int detectClaps(int numClaps) 127 { 128 int clapNum = numClaps; 129 130 //Base Case - if clapNum is 0, then all claps have been accounted. 131 if (clapNum == 0) 132 { 133 //the output can now be toggled. 134 toggleOutput *= -1; 135 indicateClap(clapNum); 136 137 Serial.println("----- Clap Limit Reached - Output Toggled -----"); 138 139 return FINAL_DETECTED; 140 } 141 142 //Read from mic and update ambient noise levels. 143 readMic(); 144 145 total = (total - buffer[loopIteration]) + sensorValue; 146 average = (total / SIZE); 147 buffer[loopIteration] = sensorValue; 148 149 loopIteration = (loopIteration + 1) % SIZE; 150 151 if (clapDetected()) 152 { 153 Serial.print("detectClaps - Claps:"); 154 Serial.println(TOTAL_CLAPS_TO_DETECT + 1 - numClaps); 155 156 printStats(); 157 indicateClap(clapNum); 158 159 delay(100); 160 for (int i = 0; i < CLAP_TIME; i++) 161 { 162 int clapState = detectClaps(clapNum - 1); 163 164 if (clapState == FINAL_DETECTED || clapState == LOST_CONTINUITY) 165 { 166 return clapState; 167 } 168 } 169 return LOST_CONTINUITY; 170 } 171 return CLAP_NOT_DETECTED; 172 } 173 174 /** 175 Purpose: Turns the LED on appropriately to signal a clap detection. 176 */ 177 void indicateClap(int clapNum) 178 { 179 if (clapNum == 0) 180 { 181 if (toggleOutput == 1) 182 { 183 digitalWrite(out, HIGH); 184 } 185 else 186 { 187 digitalWrite(out, LOW); 188 } 189 digitalWrite(clapLed1, LOW); 190 digitalWrite(clapLed2, LOW); 191 } 192 else if (clapNum == 1) 193 { 194 digitalWrite(clapLed1, HIGH); 195 } 196 else if (clapNum == 2) 197 { 198 digitalWrite(clapLed2, HIGH); 199 } 200 delay(110); 201 } 202 203 /** 204 Purpose: Prints basic statistics data for more info with sensor readouts and data points. 205 */ 206 void printStats() 207 { 208 Serial.print("--- AVE: "); 209 Serial.print(average); 210 Serial.print(" Total: "); 211 Serial.print(total); 212 //Serial.print(" iterNum: "); 213 //Serial.print(loopIteration); 214 Serial.print(" Sensor: "); 215 Serial.print(sensorValue); 216 Serial.print(" Change: "); 217 Serial.println(sensorValue - average); //This is what I used to determine the 'offset' value 218 } 219 220 /** 221 Purpose: A clap is detected when the sensor value is greater than the average plus 222 an offset. The offset might need to be fine tuned for different sound sensors. 223 */ 224 boolean clapDetected() 225 { 226 return sensorValue > average + offset; 227 } 228 229 /** 230 Purpose: Reads mic input and stores it in a global variable. 231 */ 232 void readMic() 233 { 234 sensorValue = analogRead(inPin0); 235 }Волнует такая проблема. Написал скетч реагирующий на хлопок, но микрофон, который я использую - гавнецо. Исправно работает на расстоянии 50 см. Подскажите пожайлуста, схему усилителя с микрофоном, чтобы можно было расширить возможности детектора до 4-5 метров
Спасибо, что скинул столько полезной информации. Все зашло кроме последнего скетча. Там просит LowPassFilter.c Весь инет прорыл не нашел такой библиотеки
Просто надо быть чуть внимательнее :) http://t-filter.engineerjs.com/
Ох Спасибо, с английским не очень... Я знаю много от вас прошу и уже задолбал Вас. Но в моем конкретном случае, исходя из спектра хлопка какие параметры фильтра выставить лучше?
Обещаю это последняя просьба =)))
то, что там наверху, на картинках - это не спектр хлопка ) ну, допустим, попробуйте, реагировать на частоту где-то около 4-5 кГц
Ок спасибо =)