Как считать показания датчика звука и включить датчик с датчиком воды, если показания выше порогового значения и при обнаружении воды в течение 2 минут?

Я студент, новичок в Arduino и работаю над проектом, который будет вызывать оповещение, если обнаруженный уровень звука превышает пороговое значение в течение 2 минут. Но я застрял, хотел бы проверить, как написать код для аналогового считывания входа датчика звука и включения датчика, если показания превышают норму в течение 2 минут? У меня был простой код, но он сразу же загорался. :/

Я объединил код, и вот новый код, который работал с полученной помощью:

    #define led 4 // привел к D4
const int soundsensor= A0; //датчик звука на A0
const int threshold= 100; // для установки порогового значения для датчика звука
int ssanalogread; //имя считываемого аналога звукового датчика
bool wasOver;//добавляем в глобальные переменные
unsigned long firstDetect;


void setup() {
  Serial.begin(9600);
  pinMode(led,OUTPUT);
  pinMode(soundsensor,INPUT);// чтобы получить входной сигнал от датчика звука

} // завершаем установку void


void loop() {

     sound1();

} // закрываем цикл void


void sound1() {

  ssanalogread=analogRead(soundsensor); // считывает аналоговые данные с датчика звука
  Serial.println(ssanalogread);

   if ((ssanalogread > threshold)){ //заменяем if else
      if(!wasOver){
       firstDetect = millis();
   }
   if(millis() - firstDetect > 1*10*1000){
      digitalWrite(led,HIGH); //светодиод загорается, если датчик считывает больше порога
   } //конец, если
      wasOver = true;
   } // заканчиваем первым, если
  else {
     wasOver = false;
     digitalWrite(led,LOW); 
  } // конец еще

} //завершаем цикл


//этот код работает и его можно запускать. можно настроить время

, 👍0

Обсуждение

Какой «датчик звука» вы используете?, @Majenko

Привет, я использую датчик звука Grove: http://wiki.seeedstudio.com/Grove-Sound_Sensor/ и датчик воды в роще: http://wiki.seeedstudio.com/Grove-Water_Sensor/, @hmppp


2 ответа


Лучший ответ:

1

Вы устанавливаете временную метку, когда звук впервые превышает пороговое значение, и устанавливаете высокий выходной сигнал только тогда, когда millis() - firstDetect > 2*60*1000

//добавляем в глобальные переменные
bool wasOver;
unsigned long firstDetect;

//заменяем, если еще
if ((ssanalogread > threshold)){
   if(!wasOver){
       firstDetect = millis();
   }
   if(millis() - firstDetect > 2*60*1000){
      digitalWrite(led,HIGH); //светодиод загорается, если датчик считывает больше порога
   } //конец, если
   wasOver = true;
} else {
   wasOver = false;
   digitalWrite(led,LOW); 
} 
,

Привет, Рэтчет! Большое спасибо за просвещение! Я объединил ваш код со своим (отредактированным в исходном сообщении), однако появилось сообщение об ошибке: «Состояние выхода 1. Ошибка компиляции для платы Arduino/Genuino Uno». :/ Не уверен, правильно ли я определил now()..., @hmppp

@rachetfreak путает now() и millis()., @Majenko

@hmppp извини, я действительно перепутал now() и millis(). Теперь это исправлено в ответе., @ratchet freak

@rachetfreak и Маженко благодарим обоих за оперативную помощь! мне не удалось зажечь светодиод этого кода через 2 минуты. На последовательном мониторе было замечено, что данные были около 270++. установил порог на 200, однако датчик освещенности все еще не мог загореться. Для этого я использую базовый щит Grove., @hmppp

@rachetfreak, попробовал использовать функцию 10s, мне удалось загрузить ее, и она заработала! большое спасибо :), @hmppp


1

На самом деле это намного сложнее, чем может показаться на первый взгляд.

Ваш «датчик звука» — это не что иное, как микрофон и усилитель. Он дает вам форму звукового сигнала, тогда как вас интересует пиковая мощность.

Аудиосигнал бывает как положительным, так и отрицательным:

Пик сигнала может быть как положительным (над линией), так и отрицательным (ниже линии).

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

Однако Arduino не может видеть отрицательные значения на АЦП, поэтому вы получаете только верхнюю часть сигнала, что не идеально. На самом деле вам следует добавить смещение постоянного тока к выходу звукового датчика, чтобы довести сигнал до середины диапазона АЦП (добавление делителя напряжения 10 кОм + 10 кОм на входном контакте к +5 В/GND сделает эту работу). /п>

Если вы не добавляете смещение постоянного тока, вы можете быстро выполнить выборку в течение короткого периода времени и определить максимальное значение:

uint16_t getMaximum(uint8_t pin, uint32_t t) {
    uint16_t maximum = 0;
    uint32_t ts = millis();
    while (millis() - ts < t) {
        uint16_t sample = analogRead(pin);
        if (sample > maximum) {
            maximum = sample;
        }
    }
    return maximum;
}

Теперь, чтобы получить максимум за период, скажем, 10 мс, вы можете:

uint16_t maximum = getMaximum(A0, 10);

Однако, если вы добавите смещение постоянного тока, это станет немного сложнее, но результат будет лучше:

uint16_t getMaximum(uint8_t pin, uint32_t t) {
    int16_t maximum = 0;
    int16_t minimum = 0;
    uint32_t ts = millis()
    while (millis() - ts < t) {
        // Здесь -512 удаляет смещение постоянного тока из показаний. 512 это половина
        // диапазон АЦП.
        int16_t sample = analogRead(pin) - 512;
        if (sample > maximum) {
            maximum = sample;
        }
        if (sample < minimum) {
            minimum = sample;
        }
    }

    // Теперь у нас есть положительное значение как максимальное и отрицательное
    // как минимум или ноль, если ни один из них не достиг максимума или минимума
    // область сигнала. Вычесть негатив из позитива
    // это похоже на добавление позитива к позитиву. Но мы хотим только
    // положительный результат, поэтому мы получим абсолютное значение.
    return abs(maximum - minimum);
}

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

  • Звук выше порога?
    • Да: раньше было выше порогового значения?
    • Нет: установите временную метку и флаг, указывающие на превышение порогового значения.
    • Да: прошло ли более 2 минут?
      • Да: зажгите светодиод.
    • Нет. Было ли это раньше выше порогового значения?
    • Да: прошло ли более 2 минут?
      • Да: погасить светодиод.

Здесь важно знать, что вы ищете изменения в состоянии «выше порога», чтобы начать отсчет времени. Простая реализация может выглядеть так:

static uint32_t wentAbove = 0;
static bool isAbove = false;
const uint16_t threshold = 300;

uint16_t maxval = getMaximum(A0, 10);

if (maxval > threshold) {
    if (!isAbove) {
        isAbove = true;
        wentAbove = millis();
    } else {
        if (millis() - wentAbove > 120000) {
            digitalWrite(13, HIGH);
        }
    }
} else {
    if (isAbove) {
        isAbove = false;
        digitalWrite(13, LOW);
    }
}

Примечание: весь код не тестировался.

,

Привет Маженко, спасибо за подробное объяснение. Извините, я новичок в программировании и Arduino, и у меня некоторые проблемы с пониманием. Не могли бы вы просветить меня, что делает uint32_t t в uint16_t getMaximum(uint8_t pin, uint32_t t) и как мне определить getMaximum? :/, @hmppp

беззнаковое 32-битное целое число. Это то же самое, что и «unsigned long», но явное. Вам не нужно «определять» эти функции — я определил их за вас. Просто скопируйте и вставьте., @Majenko

Я попробовал оба кода, пример реализации выдает сообщение об ошибке, что getMaximum не объявлен. :/, @hmppp