Как выцепить первое подходящее значение с аналогового датчика?

hutsi
Offline
Зарегистрирован: 26.03.2016

Доброго времени суток!
В программировании не силен, столкнулся с такой проблемой...
Имеется скетч, выводящий рандомные слова на матрицу, слова выводятся на реакцию с датчика шума.
То есть необходимо при превышении порогового значения с датчика выводить новое рандомное слово.
Проблема в следующем:
порог срабатывания-  >800
хлопок рядом с датчиком
реакция датчика 799-800-801-802-801-800-799
На данный момент выводятся рандомные слова на каждое подряд значение.
Необходимо выцепить первое подходящее по условию т.е. 800 и не обращать внимания на остальные.
Сейчас на один хлопок меняется несколько слов, а надо 1 хлопок-1 слово.
Преполагаю что нужно ставит таймер где то, но не знаю где и как.

Помогите, пожалуйста!
 


#include <SPI.h> 		//библиотека
#include <Adafruit_GFX.h>   //библиотека
#include <Max72xxPanel.h>   //библиотека

#include <WString.h>
#include <time.h>

#define LOUDNESS_SENSOR_PIN A0  //Датчик громкости подключён к пину А0
#define TRESHOLD   800 //Устанавливаем порог срабатывания


int pinCS = 10; // Attach CS to this pin, DIN to MOSI and CLK to SCK (cf http://arduino.cc/en/Reference/SPI )
int numberOfHorizontalDisplays = 2;
int numberOfVerticalDisplays = 1;

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

int delay_sensor = 10;
int wait = 150; //скорость прокрутки строки

int spacer = 1;
int width = 5 + spacer; // The font width is 5 pixels

// max максимальный индекс внутри массива (не забываем, что массив начинается с 0)
int max = 3;
char * messages[4];

void setup() {
    Serial.begin(9600);
    matrix.setIntensity(15); // Use a value between 0 and 15 for brightness

    messages[0] = "You";
    messages[1] = "are";
    messages[2] = "so";
    messages[3] = "good";

    matrix.setRotation(0, 10);    // варианты отображения текста по направлению 1 матрицы
    matrix.setRotation(1, 10);    // варианты отображения текста по направлению 2 матрицы
}

void loop() {
// Считаем текущее значение громкости
  int loudness = analogRead(LOUDNESS_SENSOR_PIN);
  Serial.println(loudness);
  delay (50);
  if (loudness < TRESHOLD) { return; }
  
    // генерим рандомное число от 3 до 0 (в моем примере), чтобы получить произвольное сообщение из массива

    int index = rand() % (max + 1);

    // получаем рандомное сообщение
    char * cur_msg = messages[index];
    int len = strlen(cur_msg);

    for (int i = 0; i < width * len + matrix.width() - 1 - spacer; i++) {
        matrix.fillScreen(LOW);
       

        int letter = i / width;
        int x = (matrix.width() - 1) - i % width;
        int y = (matrix.height() - 8) / 2; // center the text vertically

        while (x + width - spacer >= 0 && letter >= 0) {
            if (letter < len) {
                matrix.drawChar(x, y, cur_msg[letter], HIGH, LOW, 1);
            }

            letter--;
            x -= width;
        }

        matrix.write(); // Send bitmap to display

        delay(wait);
    }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Надо уточнить задачу.

Требуется только один раз вывести слово. Или несколько раз?

Если несколько, то каков (по времени или по количеству сэмлов) должен быть интервал низких (<800) значений, что появление нового значения считать новым сигналом, а не "отголоском" старого?

Олег М.
Олег М. аватар
Offline
Зарегистрирован: 22.11.2015

"Надо уточнить задачу" (С)

Какой звуковой сенсор используется и есть ли в самом сенсоре регулировка порога?
А еще лучше-посмотреть осциллограмму на его выходе при хлопке.
Где-то тут были ссылки типа "осциллограф из звуковой карты" и из самой Ардуинки.

 

hutsi
Offline
Зарегистрирован: 26.03.2016

На каждый новый громкий звук- выводится новое рандомное слово и крутится в цикле пока не будет нового громкого звука.
Например: 
хлопок
крутится слово "good"
хлопок 
крутится "so"

Про интервал... наверное секунды 3.

hutsi
Offline
Зарегистрирован: 26.03.2016

Звуковой сенсор- аналоговый датчик шума из амперки.
Регулировка чувствительности имеется, с этим проблем нет.
Осцилографа не имеется, очень далек от этой темы.
Проблема в отбросе лишних значений с громкого звука или в объединении их в один.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Читайте 10 ( 100 ) раз, суммируйте, делите на 10 ( 100 ).....

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Т.е. логика такова.

Есть два события:

1) шум начался (Ш), т.е. текущее значение >=800 && предыдущее значение < 800

2) шум смолк (Т), т.е. текущее значение < 800 && предыдущее значение >= 800

Есть период игнорирования событий (ПИ). Он отсчитывается от события Т и имеет продолжительность 3 сек.

Наконец, есть два дкйствия:

1) стартовать период ПИ

2) запустить новое слово

Теперь можно расписать логику:

ЕСЛИ событие Ш ТО
     ЕСЛИ НЕ активен ПИ ТО Запустить Слово
ИНАЧЕ ЕСЛИ событие Т ТО стартовать_ПИ

Такая должна быть логика?

Если такая, добавляйте работу с millis (стартовать период ПИ - значит установить начальсное значение millis, а когда текущий миллис станет на 3+ секунды больше начального значение - период закончился.

Вот и всё. Программируется за 5 минут.

hutsi
Offline
Зарегистрирован: 26.03.2016

ЕвгенийП пишет:

Вот и всё. Программируется за 5 минут.

Это довольно сложно для человека, который связался в первый раз с программированием пару дней назад)
Логика ясна, не ясно как это выразить в с++ и в правильном месте, в существующем коде.
Можно попросить Вас помочь в этом деле?

Что вышло написать...

  if (loudness >= TRESHOLD && "как выразить предыдущее значение?" < TRESHOLD)
  
    

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

hutsi пишет:

Логика ясна, не ясно как это выразить в с++ и в правильном месте, в существующем коде.

Можно попросить Вас помочь в этом деле?

Что вышло написать...

Никак не выражайте, просто храните. Типа так

static int oldLoudness = 0;

int loudness = analogRead ...
if (loudness >= 800 && oldLoundess < 80) ...
...
// в конце не забываем
oldLoudness  =  loudness;

 

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Посчитав среднее  и умножив его на какое-то число измерений  мы как-бы знаем что наш "массив" состоит из этого количества измерений и все измерения равны среднему. Поэтому зачем помнить каждое измерение?

Они все равны  среднему...

NeiroN  прав  ,  но более "читабельно и понятно "

[среднее] = ( [среднее] * [число измерений - 1] + [ текущее показание ] ) / ( [число измерений] )

http://arduino.ru/forum/programmirovanie/array-massivy#comment-86084
http://arduino.ru/forum/programmirovanie/array-massivy#comment-86238

Logik
Offline
Зарегистрирован: 05.08.2014

Ну Вы и в дебри полезли, господа! Нужно после вывода очередного слова просто сделать паузу в работе программы, вполне годится delay(200). За это время шум от хлопка утихнет и ждем следующего хлопка.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

Ну Вы и в дебри полезли, господа! Нужно после вывода очередного слова просто сделать паузу в работе программы, вполне годится delay(200). За это время шум от хлопка утихнет и ждем следующего хлопка.

Ну, а я не то же самое написал? Только с миллис вместо делэя.

Logik
Offline
Зарегистрирован: 05.08.2014

ЕвгенийП пишет:

Logik пишет:

Ну Вы и в дебри полезли, господа! Нужно после вывода очередного слова просто сделать паузу в работе программы, вполне годится delay(200). За это время шум от хлопка утихнет и ждем следующего хлопка.

Ну, а я не то же самое написал? Только с миллис вместо делэя.

Да. Тоже. Я как формулы увидел, испугался что ща БПФ кто предложит, и поторопился ))))

hutsi
Offline
Зарегистрирован: 26.03.2016

Logik пишет:

Ну Вы и в дебри полезли, господа! Нужно после вывода очередного слова просто сделать паузу в работе программы, вполне годится delay(200). За это время шум от хлопка утихнет и ждем следующего хлопка.

А не подскажешь где именно delay впихнуть?
И как быть с тем, что слово должно в цикле отображаться до следующего срабатывания?