Цифровой звуковой датчик

У меня возникла проблема с цифровым датчиком звука. Моя цель: хлопнуть 2 раза, и заиграет лид. Итак, я написал этот код. Я не знаю, правильно это или нет. Это происходит: Если я хлопаю, то из последовательного монитора я получаю не один HIGH, а несколько (пробовал менять чувствительность звукового датчика, но это не помогает), но в моем коде есть условия, при которых только Допускается одновременное использование 1 HIGH. Таким образом, я не знаю, неверен ли мой код или мой датчик работает неправильно. Ребята, вы можете мне помочь, пожалуйста? Это мой код:

int soundPin = 13;             // Цифровой звуковой контакт
int ledPin = 7;
int claps = 0;                 // Сколько раз я хлопал в ладоши
int readingState ;             // Первое чтение из soundPin
int readingState2 ;            // Второе чтение из soundPin
int soundDetectionTime ;       // Время после первого хлопка
int soundDetectionTime2 ;      // Время после второго хлопка
int timeBetweenSounds = 1000;  // Время между звуками, которое я хочу. Там
                                  is an If-statement further on. 

void setup(){
  pinMode(soundPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  readingState = digitalRead(soundPin);    // Первое чтение из
                                              soundPin (digital pin)

  Serial.println(readingState);

  if (readingState == HIGH){               // Если чтение из
                                             soundPin is HIGH, then start 
                                             timing. Also claps value 
                                             increased by 1 and the 
                                             second reading is happening. 
    soundDetectionTime = millis();
    claps++ ;
    readingState2 = digitalRead(soundPin);   

      if (readingState2 == HIGH){          // Если приведенный выше оператор
                                              true, then this if-statement 
                                              is executed. If the second 
                                              reading is HIGH, 
                                              soundDetectionTime two will 
                                              start counting
    soundDetectionTime2 = millis();    // Также количество хлопков увеличивается на 1,
                                          so now claps = 2. 
        claps++;
   }
   }

   if ((soundDetectionTime - soundDetectionTime2) > timeBetweenSounds && 
claps==2){                            // Если между
                                         two readings and if I clapped 
                                         twice, then LED is HIGH. 
    digitalWrite(ledPin, HIGH);
   }
   }

ОБНОВЛЕНИЕ: мне удалось отделить два HIGH друг от друга, и теперь светодиод горит. Таким образом, проблема, должно быть, в том, что датчик выдает мне слишком много HIGH, если я хлопаю один раз, например: 0,0,0,0,1,1,1,0,0. Что вы думаете, ребята?

, 👍1

Обсуждение

Что подключено к звуковому штырю? Можете ли вы предоставить схему? ссылка на датчик?, @esoterik

Это датчик: https://hobbyking.com/en_us/keyes-microphone-sound-detection-sensor-module-for-arduino.html?gclid=CjwKCAjwhLHaBRAGEiwAHCgG3rTULQSiOsXd9Uxke7d5vLY9ZFFI-MktrlDSSUPvsXlvcahoxTs2nBoCKK8QAvD_BwE& gclsrc=aw.ds&___store=en_us Кроме того, схема очень легкий. Я подключил GND и 5В. И цифровой вывод датчика звука к цифровому выводу на Arduino., @jan


2 ответа


0

Ваша логика ошибочна; у вас нет никакой задержки между readingState и readingState2, кроме serial.Print(), на который вы не должны полагаться для задержки.

Вам нужно отслеживать состояние в вашем цикле. Вам нужно зафиксировать время первого ввода, увидеть, как он становится низким, затем записать время второго ввода. Время между инструкциями NB ослепительно быстрое даже на «медленных» процессорах.

что-то вроде:

// edit: просто немного рефакторингую
// правка: добавлено подавление дребезга
unsigned long start, end, time;
int state = 0;
...
#define BOUNCE 10
int dbounce(unsigned long time, unsigned long start, unsigned long len)
{
    return (time - start) > len;
}
...
void loop()
{
  pin = digitalRead(soundPin);
  time = millis();
  switch(state)
  {
  case 0:
      if (pin == HIGH)
      {
        start = millis();
        state = 1;
      }
      break;
  case 1:
      if dbounce(time,start,BOUNCE) 
          break; // один из способов устранения дребезга
      if( pin == LOW)
          state = 2;
      break;
  case 2:
      if(pin == HIGH)
      {
         end = millis();
         state = 3;
      }
      break;
  case 3:
      if(dbounce(end,start,1000))
      {
         // делать что-то
      }
      state = 4;
      break;
  case 4:
      if((pin == LOW) && dbounce(time,end,BOUNCE)) //еще один способ устранения дребезга
         state = 0; // начать заново
      break;
  }
}
,

Итак, мне следует сделать это с помощью функции pulseIn? Таким образом я смогу измерить время между HIGH и LOW. Как вы рекомендуете мне это сделать? Я только неделю назад начал работать с Arduino, я не очень хорошо знаком с различными методами кодирования., @jan

@jan pulse in измеряет, как долго контакт находится на высоком уровне, вы можете использовать pulseIn(pin, HIGH); start = millis(); pulsein(pin, HIGH); end = millis(); if(end-start) ..., @esoterik

@jan мне только что пришло в голову, что time = pulseIn(pin, LOW); может делать именно то, что вам нужно., @esoterik

Но звуковой датчик все еще проблема. Потому что он дает мне много HIGH, когда я хлопаю, а не только один. Иногда он дает: 0,0,1,0,1. У меня два HIGH очень быстро с одним хлопком, @jan

@jan Я добавил в код функцию устранения дребезга и сделал его немного лучше; надеюсь, вы понимаете, как это работает., @esoterik


1

Вот «урезанная версия» эскиза, который я использовал для копирования переключателя Clap On, Clap Off, который был у нас в 1980-х годах. Он работает с модулем звукового датчика KY-038, который у вас сейчас есть. Вам нужно будет установить библиотеку VirtualDelay.

Модуль звукового датчика очень чувствителен. Четверть оборота потенциометра вокруг «точки наилучшего восприятия» имеет огромное значение. Слишком чувствителен, и цифровой выход постоянно высокий. Если он недостаточно чувствителен, то вам придется физически «нажимать» на микрофон, чтобы получить от него переход с высокого на низкий уровень.

Обратите внимание: в этом скетче используется delay(), который является «блокирующим кодом», и его использование обычно не рекомендуется.

#include "avdweb_VirtualDelay.h"
byte clapCounter = 0;
const byte soundSensorPin = 2;
const unsigned long loopDelay = 1;
const unsigned long clapCounterDelay = 400;
unsigned long clapCounterTimerDuration = 1000;
unsigned long previousMillis = 0;

void setup(){
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop(){

  // Объект таймера.
  static VirtualDelay clapCounterTimer;

  // Получить текущее время.
  unsigned long currentMillis = millis();

  // Проверьте наличие звука хлопка (1 мс подойдет). Если слишком много времени
  // здесь истекает, вы можете пропустить «начало» хлопка.
  if(myTimer1(loopDelay, currentMillis) == 1){

    // Обнаружен хлопок.
    if(digitalRead(soundSensorPin) == 1){

      clapCounter += 1;

      // При обнаружении первого хлопка запустите таймер
      // для сброса счетчика хлопков на 0 через 1 секунду.
      if(clapCounter == 1){
        clapCounterTimer.start(clapCounterTimerDuration);
      }

      // Задержка выполнения цикла. 400 мс — это хорошо.
      delay(clapCounterDelay);

      // Если обнаружен второй хлопок, переключить светодиод в положение ВКЛ/ВЫКЛ.
      if(clapCounter > 1){
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
      }

    }
  }

  // Сбросить счетчик хлопков на 0 через 1 секунду. Если
  // если ты этого не сделаешь, ты можешь похлопать один раз, подожди немного
  // минуту, затем хлопните еще раз, и светодиод изменит состояние.
  if(clapCounterTimer.elapsed()){
    clapCounter = 0;
  }

}

// Таймер цикла хлопков.
byte myTimer1(unsigned long loopDelay, unsigned long currentMillis){
  if(currentMillis - previousMillis >= loopDelay){previousMillis += loopDelay;return 1;}
  else{return 0;}
}

РЕДАКТИРОВАТЬ: Чтобы ответить на ваш вопрос относительно множественных переходов с высокого на низкий уровень на цифровом выходе модуля, вы можете использовать DSO, чтобы посмотреть на соотношение между аналоговыми и цифровыми сигналами, которые он производит.

На следующем изображении цифровой сигнал (желтая дорожка) и аналоговый сигнал (синяя дорожка) наложены друг на друга. Белая пунктирная линия (E) установлена на 2,8 В постоянного тока, что приблизительно соответствует напряжению аналогового выходного контакта с окружающим шумом помещения. Когда вы хлопаете перед микрофоном, генерируется эта форма волны.

Весь хлопок длится около 5,6 мс, и модуль дает вам 18 переходов с высокого на низкий уровень на своем цифровом выходном контакте. Когда аналоговое напряжение падает ниже определенного напряжения, цифровой выход становится высоким. Когда аналоговое напряжение поднимается выше этого напряжения, цифровой выход становится низким.

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

Вместо использования delay(), как я, вы можете увеличить «счетчик хлопков» до значения «1» при первом переходе цифрового выходного контакта с низкого на высокий. Затем запустите неблокирующий таймер millis(), который ждет, прежде чем вы снова прочитаете цифровой выходной контакт. Если цифровой выход становится высоким после 400 мс, это ваш второй хлопок, поэтому измените состояние светодиода. Второй таймер millis() может сбросить «счетчик хлопков» до 0 после 1 секунды.

,

Спасибо тебе огромное, мужик, думаю, теперь все получится. Попробую сейчас., @jan