Вопрос по скетчу в проекте

Тема в разделе "Arduino & Shields", создана пользователем Droban, 20 ноя 2016.

  1. Droban

    Droban Нуб

    Делаю по статье http://cxem.net/arduino/arduino148.php включение/выключение ПК. Всё исправно работает, но, цитата из статьи "Последовательность хлопков по умолчанию в проверочном коде напоминает «собачий вальс»." Прослушать как она звучит можно в видео в конце статьи. Я хочу переписать код на простые 3 последовательных хлопка.
    Скетч прикреплен. Я так понял секретный код записывается в этот массив: int secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    Но что то я не вижу общего между этой записью и этим «собачий вальсом». Попробовал переписать на ... {50, 50, 50...} или ... {25, 25, 25...} - не срабатывает. Объясните пожалуйста этот принцип записи секретного стука. Спасибо.
     

    Вложения:

    Последнее редактирование: 24 ноя 2016
  2. Droban

    Droban Нуб

    Секретный-код перепрограммировать можно, но только если добавить в схему выключатель(в статье это есть), но это делается уже после того как в Arduino залит скетч. Мне же надо заранее знать, какой секретный стук я залью в него. Помогите пожалуйста. Сроки поджимают. Спасибо.
     
  3. ostrov

    ostrov Гуру

    Насколько я понимаю, цифры в коде это паузы между хлопками. Причем, их можно менять, записывая свой код хлопками нажав на кнопку. Попробуйте эталонно похлопать как вам надо или вручную поставить одинаковые паузы и ограничив кол-во хлопков в соответствующей переменной.

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

    qwone Гик

    Как сказал Карабас Барабас это просто П***Ц. (смотри

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

    Droban Нуб

    Прежде чем тролить, было бы не плохо статью просмотреть и уточнить почему конкретно интересуюсь. Ну так объясняю, для записи хлопков, необходимо допаивать на схему элементы дополнительные, проект же упакован в герметичный куб на клей, дабы не производить полный демонтаж(т.к. доступ у меня только к usb-входу arduino), собственно и был поднят вопрос.
     
  6. ostrov

    ostrov Гуру

    Мельком посмотрев программу, обнаружил, что время регистрируется в миллисекундах, что странно. Чтобы хлопать с периодом 25-50 мс надо быть если не колибри, то хотя бы воробьем. Не удивительно, что выхлопать такое почти невозможно. Попробуйте хотя бы интервалы от 200, что уже 5 раз в секунду, и это тоже не каждый сдюжит. Может есть смысл записать звук хлопков и посмотреть периоды комфортных хлопков на любом аудиоредакторе. И гистерезис подкрутить, то есть разброс плюс-минус, 15мс явно мало, не попасть ни за что.
     
  7. Airbus

    Airbus Радиохулиган Модератор

    Спросить проще чем подумать.Если есть доступ к USB значить есть доступ к ардуино и к serial в том числе.Так может правда проще тупо нахлопать посмотреть что выдаст serial и потом эту шнягу записать в массив?
     
    ostrov нравится это.
  8. qwone

    qwone Гик

    программа закручена сильно. Но как-то преобразовал для понимания ее работы. Код не проверял
    Код (C++):
    /* http://cxem.net/arduino/arduino148.php
    Открытие замка по секретной последовательности хлопков
    Подключение :
    Микрофон                                      ->A1 (NoiseSensor_pin)
    переключатель для записи секретной комбинации ->2 (bottom_pin)
    Реле открытия                                 ->3 (Relay_pin  )  1 открыто / 0 закрыто
    Красный светодиод "идет программирование"     ->4 (redLED_pin)   1 горит ( программирование секретного кода) / 0 нет
    Зеленый светодиод                             ->5 (greenLED_pin) 1- нормальная работа
    */

    const int NoiseSensor_pin = 1          ; // нога микрофона
    int       NoiseSensor                  ; // Последнее значение величины сигнала на микрофоне
    const int NoiseSensor_min = 8          ; // Уровень "тишины" на микрофоне
    const int max_between_knocks = 1200    ; // максимальная длительность между хлопками
    const int maximumKnocks = 20           ; // максимальное количество хлопков для записи и прослушивания
    int       Secret_Code  [maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // Секретная последовательность
    int       Reading_Code [maximumKnocks] ; // Массив для записи хлопков с микрофона.
    const int Relay_pin  = 3               ; // Реле замка
    const int bottom_pin = 2               ; // если кнопка в 1 то записать в секретный код
    const int redLED_pin = 4               ; // нога красного светодиода  "идет программирование"
    int       redLED     = 0               ; // 1 - перепрограммирование секретной последовательности / 0 проверяем старую
    const int redLED_blink = 150           ; // время мигания при опозновании хлопка
    const int greenLED_pin = 5             ; // нога зеленого светодиода
    const int rejectValue = 25             ; // Индивидуальное расхождение прочитаного и секретного кода
    const int averageRejectValue = 15      ; // Усредненое расхождение прочитаного и секретного кода  .

    int i                                  ; // вспомогательная переменная
    uint32_t start_Time                    ; //  millis() предыдущего хлопка
    uint32_t now_Time                      ; //  millis() этого хлопка
    //  ---------------------------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      Serial.println("Program start.");
      pinMode      (Relay_pin    , OUTPUT);
      pinMode      (redLED_pin   , OUTPUT);
      pinMode      (greenLED_pin , OUTPUT);
      digitalWrite (greenLED_pin , 1     );
      pinMode      (bottom_pin   , INPUT );
    }
    void loop() {
      digitalWrite(redLED_pin, redLED  = digitalRead(bottom_pin));// если кнопка нажата,
      //  то зажечь светодиод и перевести режим записи секретного кода.
      NoiseSensor    = analogRead(NoiseSensor_pin);  // Записываем уровень на входе микрофона
      if (NoiseSensor    >= NoiseSensor_min)
        Listen_Knock();
    }

    void Listen_Knock()    {       //запись последовательности хлопков с микрофона
      Serial.println("knock starting");   // в сериал "хлопоки начались"
      for (i = 0; i < maximumKnocks; i++) // очистим массив для записи хлопков
        Reading_Code[i] = 0;
      i = 0;                       // начинальный элемент для записи
      start_Time = millis();              // фиксируем начало 1 хлопка
      digitalWrite(greenLED_pin, 0);      // погасим зеленый светодиод
      if (redLED )
        digitalWrite(redLED_pin, 0);       // погасим красным если идет запись
      delay(redLED_blink);
      digitalWrite(greenLED_pin, 1);      // вкл зеленый светодиод
      if (redLED )
        digitalWrite(redLED_pin, 1);      // вкл красным если идет запись
      do   {  //слушаем следующий хлопок или ждем тайм-аута
        NoiseSensor    = analogRead(NoiseSensor_pin);
        if (NoiseSensor    >= NoiseSensor_min)  {     // если звук больше "тишины"
          Serial.println("knock."); // в сериал "хлопок"
          now_Time = millis();
          Reading_Code[i] = now_Time - start_Time; // запишем  время между хлопками
          i ++;                                     //увеличим счетчик
          start_Time = now_Time;                    // сделает стартовым временем теперешнее
          digitalWrite(greenLED_pin, 0);            // погасим зеленый светодиод
          if (redLED )
            digitalWrite(redLED_pin, 0);            // погасим красным если идет запись
          delay(redLED_blink);
          digitalWrite(greenLED_pin, 1);            // вкл зеленый светодиод
          if (redLED )
            digitalWrite(redLED_pin, 1);            // вкл красным если идет запись
        }
        now_Time = millis();
      }
      while ((now_Time - start_Time < max_between_knocks) && (i < maximumKnocks)); //Прекратить цикл если пауза между хлопками больше нужного или кол-во хлопков достигла максимума

      //we've got our knock recorded, lets see if it's valid
      if (! redLED )    {           // только не в режиме программирования секретного кода
        if (Comparison_of_Secret_Reading_Codes() )       // если коды совпали
          Relay_ON ();      //
        else {
          Serial.println("Secret knock failed.");
          digitalWrite(greenLED_pin, 0);          // We didn't trigger Relay_pin  , so blink the red LED as visual feedback.
          for (i = 1; i < 9; i++) {
            digitalWrite(redLED_pin, i%2);
            delay(100);
          }
          digitalWrite(greenLED_pin, 1);
        }
      }
      else  {  // if we're in programming mode we still validate the knock, we just don't do anything with the Relay_pin
        Comparison_of_Secret_Reading_Codes();
        Serial.println("New code stored.");      // and we blink the green and red alternately to show that program is complete.
        digitalWrite(redLED_pin, 0);
        digitalWrite(greenLED_pin, 1);
        for (i = 0; i < 3; i++) {
          delay(100);
          digitalWrite(redLED_pin, 1);
          digitalWrite(greenLED_pin, 0);
          delay(100);
          digitalWrite(redLED_pin, 0);
          digitalWrite(greenLED_pin, 1);
        }
      }
    }

    // отрываваем реле на 10 секунд если успешно
    void Relay_ON  ()   {
      Serial.println("Relay ON");
      digitalWrite(Relay_pin   , 1); // Вкл на время реле
      digitalWrite(greenLED_pin, 1); // Вкл зел светодиод
      delay(10000);
      digitalWrite(Relay_pin   , 0); // Выкл  реле
    }

    // Функция проверки прочитаной послед хлопков с секретной
    boolean Comparison_of_Secret_Reading_Codes() {
      int Current_i = 0;
      int Secret_i = 0;
      int maxKnockInterval = 0;  // максим интервал между хлопками
      for (i = 0; i < maximumKnocks; i++) {
        if (Reading_Code[i] > 0)// если значение в записаной больше 0
          Current_i++;
        if (Secret_Code[i] > 0)   // если значение в секретной больше 0
          Secret_i++;
        if (Reading_Code[i] > maxKnockInterval) {     // collect normalization data while we're looping.
          maxKnockInterval = Reading_Code[i];
        }
      }
      if (redLED) {     // если у нас идет процесс записи нового секретного кода
        for (i = 0; i < maximumKnocks; i++) { // нормируем хлопки
          Secret_Code[i] = map(Reading_Code[i], 0, maxKnockInterval, 0, 100);
        }
        // Мигнем с указанием что программирование успешно
        digitalWrite(greenLED_pin, 0);
        digitalWrite(redLED_pin, 0);
        delay(1000);
        digitalWrite(greenLED_pin, 1);
        digitalWrite(redLED_pin, 1);
        delay(50);
        for (i = 0; i < maximumKnocks ; i++) {
          digitalWrite(greenLED_pin, 0);
          digitalWrite(redLED_pin, 0);
          // only turn it on if there's a delay
          if (Secret_Code[i] > 0) {
            delay( map(Secret_Code[i], 0, 100, 0, maxKnockInterval)); // выведем огрублено на светодиоды секретную запись
            digitalWrite(greenLED_pin, 1);
            digitalWrite(redLED_pin, 1);
          }
          delay(50);
        }
        return 0;     // выйдем из функции
      }
      if (Current_i != Secret_i)    //если кол-во ударов не совпадает
        return 0;                   // выйти указав что есть ошибка
      /*  Теперь мы сравним относительные интервалы наших хлопков, а не абсолютного времени между ними.
           (То есть. А если вы делаете то же шаблон медленно или быстро он должен еще открыть дверь)
           Это делает его менее разборчивы, что, делая его менее безопасным и может сделать это
           меньше боли в использовании, если вы темп немного медленно или быстро.
      */

      int totaltimeDifferences = 0;
      int timeDiff = 0;
      for (i = 0; i < maximumKnocks; i++) {
        Reading_Code[i] = map(Reading_Code[i], 0, maxKnockInterval, 0, 100);    // Normalize the times
        timeDiff = abs(Reading_Code[i] - Secret_Code[i]);
        if (timeDiff > rejectValue)    // Индивидуальное расхождение прочиного и секретного кода
          return 0;
        totaltimeDifferences += timeDiff;
      }
      if (totaltimeDifferences / Secret_i > averageRejectValue) // Усредненое расхождение прочитаного и секретного кода
        return 0;
      return 1; // успешный выход из функции. Прочитаный и успешный кода совпали.
    }
     
    Последнее редактирование: 26 ноя 2016
  9. qwone

    qwone Гик

    Код (C++):
    /* http://cxem.net/arduino/arduino148.php
    Открытие замка по секретной последовательности хлопков
    Подключение :
    Микрофон                                      ->A1 (NoiseSensor_pin)
    переключатель для записи секретной комбинации ->2 (bottom_pin)
    Реле открытия                                 ->3 (Relay_pin  )  1 открыто / 0 закрыто
    Красный светодиод "идет программирование"     ->4 (redLED_pin)   1 горит ( программирование секретного кода) / 0 нет
    Зеленый светодиод                             ->5 (greenLED_pin) 1- нормальная работа
    */

    const int NoiseSensor_pin = 1          ; // нога микрофона
    int       NoiseSensor                  ; // Последнее значение величины сигнала на микрофоне
    const int NoiseSensor_min = 8          ; // Уровень "тишины" на микрофоне
    const int max_between_knocks = 1200    ; // максимальная длительность между хлопками
    const int maximumKnocks = 20           ; // максимальное количество хлопков для записи и прослушивания
    int       Secret_Code  [maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // Секретная последовательность
    int       Reading_Code [maximumKnocks] ; // Массив для записи хлопков с микрофона.
    const int Relay_pin  = 3               ; // Реле замка
    const int bottom_pin = 2               ; // если кнопка в 1 то записать в секретный код
    const int redLED_pin = 4               ; // нога красного светодиода  "идет программирование"
    int       redLED     = 0               ; // 1 - перепрограммирование секретной последовательности / 0 проверяем старую
    const int redLED_blink = 150           ; // время мигания при опозновании хлопка
    const int greenLED_pin = 5             ; // нога зеленого светодиода
    int       maxKnockInterval             ; // максим интервал между хлопками
    const int Max_Time_Diff = 25           ; // максимальная индивидульная ошибка несовпадений.
    int       Time_Diff                    ; // индивидульная ошибка несовпадений.
    const int Average_Total_Time_Diff = 15 ; // Усредненое расхождение прочитаного и секретного кода
    int       Total_Time_Diff              ; // сумма ошибок несовпадение


    int i                                  ; // вспомогательная переменная
    int Current_i                          ; // вспомогательная переменная
    int Secret_i                           ; // вспомогательная переменная
    uint32_t start_Time                    ; //  millis() предыдущего хлопка
    uint32_t now_Time                      ; //  millis() этого хлопка
    //  ---------------------------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      Serial.println("Program start.");
      pinMode      (Relay_pin    , OUTPUT);
      pinMode      (redLED_pin   , OUTPUT);
      pinMode      (greenLED_pin , OUTPUT);
      digitalWrite (greenLED_pin , 1     );
      pinMode      (bottom_pin   , INPUT );
    }
    void loop() {
      digitalWrite(redLED_pin, redLED  = digitalRead(bottom_pin));// если кнопка нажата,
      //  то зажечь светодиод и перевести режим записи секретного кода.
      NoiseSensor    = analogRead(NoiseSensor_pin);  // Записываем уровень на входе микрофона
      if (NoiseSensor    >= NoiseSensor_min)
        Listen_Knock();
    }

    void Listen_Knock()    {       //запись последовательности хлопков с микрофона
      Serial.println("knock starting");   // в сериал "хлопоки начались"
      for (i = 0; i < maximumKnocks; i++) // очистим массив для записи хлопков
        Reading_Code[i] = 0;
      i = 0;                       // начинальный элемент для записи
      start_Time = millis();              // фиксируем начало 1 хлопка
      digitalWrite(greenLED_pin, 0);      // погасим зеленый светодиод
      if (redLED )
        digitalWrite(redLED_pin, 0);       // погасим красным если идет запись
      delay(redLED_blink);
      digitalWrite(greenLED_pin, 1);      // вкл зеленый светодиод
      if (redLED )
        digitalWrite(redLED_pin, 1);      // вкл красным если идет запись
      do   {  //слушаем следующий хлопок или ждем тайм-аута
        NoiseSensor    = analogRead(NoiseSensor_pin);
        if (NoiseSensor    >= NoiseSensor_min)  {     // если звук больше "тишины"
          Serial.println("knock."); // в сериал "хлопок"
          now_Time = millis();
          Reading_Code[i] = now_Time - start_Time; // запишем  время между хлопками
          i ++;                                     //увеличим счетчик
          start_Time = now_Time;                    // сделает стартовым временем теперешнее
          digitalWrite(greenLED_pin, 0);            // погасим зеленый светодиод
          if (redLED )
            digitalWrite(redLED_pin, 0);            // погасим красным если идет запись
          delay(redLED_blink);
          digitalWrite(greenLED_pin, 1);            // вкл зеленый светодиод
          if (redLED )
            digitalWrite(redLED_pin, 1);            // вкл красным если идет запись
        }
        now_Time = millis();
      }
      while ((now_Time - start_Time < max_between_knocks) && (i < maximumKnocks)); //Прекратить цикл если пауза между хлопками больше нужного или кол-во хлопков достигла максимума
      if ( redLED ) { // если у нас программирование секретного кода то запишим его
        Save_Reading_Code_To_Secret();
        Serial.println("New code stored.");      // and we blink the green and red alternately to show that program is complete.
        digitalWrite(redLED_pin, 0);
        digitalWrite(greenLED_pin, 1);
        for (i = 0; i < 3; i++) {
          delay(100);
          digitalWrite(redLED_pin, 1);
          digitalWrite(greenLED_pin, 0);
          delay(100);
          digitalWrite(redLED_pin, 0);
          digitalWrite(greenLED_pin, 1);
        }
      }
      else  {  // иначе у нас режим проверки
        if (Comparison_of_Secret_Reading_Codes() ) // если коды совпали
          Relay_ON ();      //
        else {
          Serial.println("Secret knock failed.");
          digitalWrite(greenLED_pin, 0);          // We didn't trigger Relay_pin  , so blink the red LED as visual feedback.
          for (i = 1; i < 9; i++) {
            digitalWrite(redLED_pin, i % 2);
            delay(100);
          }
          digitalWrite(greenLED_pin, 1);
        }
      }
    }

    // отрываваем реле на 10 секунд если успешно
    void Relay_ON  ()   {
      Serial.println("Relay ON");
      digitalWrite(Relay_pin   , 1); // Вкл на время реле
      digitalWrite(greenLED_pin, 1); // Вкл зел светодиод
      delay(10000);
      digitalWrite(Relay_pin   , 0); // Выкл  реле
    }

    // Функция записи прочитаной послед хлопков в секретную
    void Save_Reading_Code_To_Secret() {
      maxKnockInterval = 0;  // максим интервал между хлопками
      for (i = 0; i < maximumKnocks; i++) {
        if (Reading_Code[i] > maxKnockInterval) {     // определяем максим интервал между хлопками
          maxKnockInterval = Reading_Code[i];
        }
      }
      for (i = 0; i < maximumKnocks; i++) { // нормируем хлопки
        Secret_Code[i] = map(Reading_Code[i], 0, maxKnockInterval, 0, 100);
      }
      // Мигнем с указанием что программирование успешно
      digitalWrite(greenLED_pin, 0);
      digitalWrite(redLED_pin, 0);
      delay(1000);
      digitalWrite(greenLED_pin, 1);
      digitalWrite(redLED_pin, 1);
      delay(50);
      for (i = 0; i < maximumKnocks ; i++) {
        digitalWrite(greenLED_pin, 0);
        digitalWrite(redLED_pin, 0);
        if (Secret_Code[i] > 0) {
          delay( map(Secret_Code[i], 0, 100, 0, maxKnockInterval)); // выведем огрублено на светодиоды секретную запись
          digitalWrite(greenLED_pin, 1);
          digitalWrite(redLED_pin, 1);
        }
        delay(50);
      }
    }

    // Функция проверки прочитаной послед хлопков с секретной
    boolean Comparison_of_Secret_Reading_Codes() {
      maxKnockInterval = 0;  // максим интервал между хлопками
      for (i = 0; i < maximumKnocks; i++) {
        if (Reading_Code[i] > maxKnockInterval) {     // определяем максим интервал между хлопками
          maxKnockInterval = Reading_Code[i];
        }
      }
      Current_i = 0;
      Secret_i = 0;
      for (i = 0; i < maximumKnocks; i++) {
        if (Reading_Code[i] > 0)// если значение в записаной больше 0
          Current_i++;
        if (Secret_Code[i] > 0)   // если значение в секретной больше 0
          Secret_i++;
      }
      if (Current_i != Secret_i)    //если кол-во хлопков не совпадает
        return 0;                   // выйти указав что есть ошибка
      Total_Time_Diff = 0; // сумма ошибок несовпадение
      Time_Diff = 0;// индивидульная ошибка несовпадений
      for (i = 0; i < maximumKnocks; i++) {
        Reading_Code[i] = map(Reading_Code[i], 0, maxKnockInterval, 0, 100);    // Нормализуем время хлопков
        Time_Diff = abs(Reading_Code[i] - Secret_Code[i]);
        if (Time_Diff > Max_Time_Diff)    // если индивидульная ошибка несовпадений больше нормы
          return 0;                    // выйти указав что есть ошибка
        Total_Time_Diff += Time_Diff;
      }
      if (Total_Time_Diff / Secret_i > Average_Total_Time_Diff) // если усредненая ошибка несовпадений больше нормы
        return 0;                   // выйти указав что есть ошибка
      return 1; // успешный выход из функции. Прочитаный и успешный кода совпали.
    }
     
  10. Droban

    Droban Нуб

    Ну что ж вы придирчивые то такие все, доступ только к USB, потому что в коробке есть вырез под вход, что-бы питание из вне производить.
    Спасибо за помощь всем, меня интересовал только вопрос записи кода в массив. Т.к. мне уже подсказали что цифры это задержки, то запись ...{100,100,0,0,0.....} сразу же и сработала(на три хлопка), все отлично работает. Всем спасибо за помощь!
     
  11. Yevgen

    Yevgen Нуб

    А можете скинуть окончательный скетч, который у вас получился?