Цепляем микрофон по кривой схеме :) источник <<<назад
Взбрела в голову идея собрать старую игрушку - управление светом с
хлопков в ладоши. Подцепил микрофон к Arduino - выяснилось что сигнал
слабоватый, и вообще-то надо ставить операционник. Под рукой никакого
операционника не нашлось - придумал идиотскую схему через RC-цепочку. С
такой схемой при тишине получаем на выходе ноль вольт, а различные
хлопки дают слабенький сигнал.
Чтобы его хоть как-то поймать, переключаем диапазон АЦП с 5 на 1.1 вольта, и уже что-то там начинает ловиться.
Для защиты от ложных срабатываний программа ловит 2 последовательных хлопка с обязательной тишиной между ними.
Микрофон
подобный обычно зовется в радиомагазине как "электретный обычный
китайский, сейчас посмотрю по бумагам... CNZ15E" :). Можно брать любой
подобный - китайцы такие куда только не суют. Чувствительность каждого
конкретного микрофона сильно зависит от значения R1. Если я ничего не
путаю, то при нормальном значении R1 нога 1 микрофона имеет потенциал
примерно половина от напряжения питания. В данном случае в .pdf'ке на
микрофон указан R1=2.2k, но при 9.1k он значительно чувствительнее.
схема.

исходник.
-------------
int MicPin = 0; //вход микрофона
int CtlPin = 13; //нога, которой управляем
int CtlVal = 0; //состояние этой ноги сразу после включения
int ClapMargin = 11; //порог хлопка (определяется экспериментально)
int SkipLen = 1500; //длительность защитной паузы
int SilenceLen = 3000; //длительность тишины после хлопка
int NextClapLen = 1000; //время, в течение которого ждем след. хлопок
void setup()
{
//настраивыем выход управления
pinMode(CtlPin, OUTPUT);
digitalWrite(CtlPin, CtlVal);
//устанавливаем предел АЦП на 1.1В (для увеличения чувствительности микрофона)
analogReference(INTERNAL);
// Serial.begin(115200);
}
int mic_prev = 0;
//ф-ия ReadNext выдает следующий байт данных. Это не просто напряжение на MicPin входе, а
//модуль разницы между текущим значением и предыдущим. Фактически - модуль производной
int ReadNext() {
int result;
int d;
d = analogRead(MicPin); //читаем
result = abs(mic_prev-d); //считаем модуль разницы
mic_prev = d; //сохраняем текущее значение
return result; //возвращаем результат
}
//ф-ия ожидает хлопка в течении WaitLen циклов. Если за это время хлопок произошел,
//возвращает 1, иначе 0. Если WaitLen == -1, то по времени ограничения нет
//Если был хлопок, то завершается сразу как только его обнаружит
int WaitForClap(int WaitLen) {
int d, i;
i = 0; //счетчик циклов
do {
d =
ReadNext();
//читаем вход
i++;
//увеличиваем счетчик
if (d > ClapMargin) { //если есть хлопок
return
1;
//возвращаем 1
}
if ( (WaitLen
!= -1) && (i >= WaitLen) ) { //если счетчик досчитал до
WaitLen и WaitLen не равен -1
return
0;
//возвращаем 0
}
} while (1);
}
//ф-ия просто ждет SkipLen циклов
void Skip(int SkipLen) {
int i;
for (i=0; i<SkipLen; i++) {
ReadNext();
}
}
void loop() {
int d1, d2;
WaitForClap(-1); //ждем хлопок
Skip(SkipLen);
//пропускаем после него защитный интервал
d1 = WaitForClap(SilenceLen); //слушаем тишину
if (d1 == 0)
{
//если была тишина
d2 = WaitForClap(NextClapLen); //ждем 2го хлопка
if (d2 == 1)
{
//если есть 2й хлопок
CtlVal = 1 -
CtlVal;
//переключаем выход управления на противоположный
digitalWrite(CtlPin, CtlVal);
}
}
Skip(SkipLen);
//пропускаем еще один защитный интервал
}