Делаю по статье 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...} - не срабатывает. Объясните пожалуйста этот принцип записи секретного стука. Спасибо.
Секретный-код перепрограммировать можно, но только если добавить в схему выключатель(в статье это есть), но это делается уже после того как в Arduino залит скетч. Мне же надо заранее знать, какой секретный стук я залью в него. Помогите пожалуйста. Сроки поджимают. Спасибо.
Насколько я понимаю, цифры в коде это паузы между хлопками. Причем, их можно менять, записывая свой код хлопками нажав на кнопку. Попробуйте эталонно похлопать как вам надо или вручную поставить одинаковые паузы и ограничив кол-во хлопков в соответствующей переменной. Не вникал как организован гистерезис при считывании, ведь попасть в заданное время с точности до миллисекунды невозможно, но наверняка это уже предусмотрено.
Как сказал Карабас Барабас это просто П***Ц. (смотри слабо записать хлопки, а потом вывести результат в Сериал. А ну да быстрее спросить, чем мозгой шевилить.
Прежде чем тролить, было бы не плохо статью просмотреть и уточнить почему конкретно интересуюсь. Ну так объясняю, для записи хлопков, необходимо допаивать на схему элементы дополнительные, проект же упакован в герметичный куб на клей, дабы не производить полный демонтаж(т.к. доступ у меня только к usb-входу arduino), собственно и был поднят вопрос.
Мельком посмотрев программу, обнаружил, что время регистрируется в миллисекундах, что странно. Чтобы хлопать с периодом 25-50 мс надо быть если не колибри, то хотя бы воробьем. Не удивительно, что выхлопать такое почти невозможно. Попробуйте хотя бы интервалы от 200, что уже 5 раз в секунду, и это тоже не каждый сдюжит. Может есть смысл записать звук хлопков и посмотреть периоды комфортных хлопков на любом аудиоредакторе. И гистерезис подкрутить, то есть разброс плюс-минус, 15мс явно мало, не попасть ни за что.
Спросить проще чем подумать.Если есть доступ к USB значить есть доступ к ардуино и к serial в том числе.Так может правда проще тупо нахлопать посмотреть что выдаст serial и потом эту шнягу записать в массив?
программа закручена сильно. Но как-то преобразовал для понимания ее работы. Код не проверял Код (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; // успешный выход из функции. Прочитаный и успешный кода совпали. }
Код (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; // успешный выход из функции. Прочитаный и успешный кода совпали. }
Ну что ж вы придирчивые то такие все, доступ только к USB, потому что в коробке есть вырез под вход, что-бы питание из вне производить. Спасибо за помощь всем, меня интересовал только вопрос записи кода в массив. Т.к. мне уже подсказали что цифры это задержки, то запись ...{100,100,0,0,0.....} сразу же и сработала(на три хлопка), все отлично работает. Всем спасибо за помощь!