Секретный код

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Здравствуйте, имею реле и ардуино, после просмотра несколькив видео на ум пришла одна идея.

Кровать у меня железная так что (как я понял) имется возможность сделать из нее "сенсорную кнопку". Так вот, хочу сделать так, чтобы реле срабатывала при определенном "стуке" по кровати. В этом деле я новичок и любая помощь приветствуется))).

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Что-то вроде этого

http://www.youtube.com/watch?nomobile=1&v=ocp8MyvySwU

Borland
Offline
Зарегистрирован: 17.05.2012

Не очень понял как из кровати сделать сенсорную кнопку

На ум приходит только микрофон или датчик удара.

В любом случае нужно устройство приема, и функция дающая какое то значение при ударе, вероятно с фильтром антидребезга. Это полагаю самое сложное.

Далее самое простое, это анализ во временных интервалах поступающих от функции сигналов, с формированием "секретного" кода, или даже нескольких секретных кодов , включающих разные реле, главное чтобы производитель стука, ударов был достаточно музыкален в части выдерживания пауз и воспроизведения стуков, хотя темп (Адажио или престо) тоже можно попробовать отловить.

как то так

 

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

Гуглите "arduino capacitive sensor". Вроде даже готовые библиотеки были.

Естьи  готовые специальные микрухи для этого, типа MPR121, воспользуйтесь поиском, кажишь летом тоже обсуждали подобные датчики. Что-то типа "датчик прикосновения/приближения и т.п." , "что бы ловило через доску/стол"

На хабре такое было: http://habrahabr.ru/post/143928/

Вообщем если есть желание - найти не проблема.

Это "просто ловить нажатие". "Секретный стук" - а вы вначале на обычной кнопке его сделайте. Разберитесь как засекать время нажатие кнопки, паузы между ними и т.п. на обычных digitalRead/millis(), а уж потом в "сенсорность" уходите.

Если же хочется "ну вообще круто и заморочится", то вот "новый спосооб взаимодействия с пользователем". Но там уже не дешовая обвязка потребуется (для генерации частот) и хорошие знание схемотехники (я на этом споткнулся), плюс математику подчитать прийдется (не школьный уровень), ну и потом "закодить" эту математику тоже знаний должно хватить. Возможно UNO/MEGA плата и "не потянет" это и прийдется смотреть в сторону DUE или вообще других процессоров.

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

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

leshak
Offline
Зарегистрирован: 29.09.2011

Ну значит берити обычную кнопку и дуину. Смотрите соседние темы, так как раз обсуждается как замерять время нажатие кнопки. Гуглите, были решения открывать замок на стук и т.п.

Вообщем берите кнопку и учитесь ставить ее в разные сексуальные позиции :) 

А "не робот" решается очень просто :)  Задаете паузы между ударами не "жестко" а интервалами. Что-то типа "короткий стук от 200 до 500 мс.", длинный "от 1000 до 2000" тысяч. И все и кодите свой секрет "короткий-коротки-длиный-короткий-длиный".

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Я вот только не понял, почему, если кнопка "кровать" сенсорная, то нужно ударять? Сенсор должен срабатывать на касание. А если стучать по кровати, то нужно к ней приклеить пьезоэлемент (скорее всего, сигнал придется усиливать) или (если кровать неплохо "тянет ноту", скажем, гитарный звукосниматель, он в отличие от пьезо и микрофона ничего кроме вибраций кровати ловить не будет).

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Кровати буду именно касаться. Это я образно насчет стучать сказал)).А как сделать , чтобы была распознана именно последовательность этих стуков (длинный/короткий)?

leshak
Offline
Зарегистрирован: 29.09.2011

Замеряете время между нажатиями кнопки. Смотрите в какой диапазон попадает "намерянное время". В длинный или короткий.  Где найти как делать замер  - я уже сказал в сообщении #5 - смотрите соседние ветки. Да и просто по форуму поиск - задача замера интервала - уже десятки раз обсуждалась.

Можете даже не лазить по форуму, а пойти в раздел программирование (в шапке сайта) и ознакомится с тем набором функций которые вам доступен. Найти функцию которая возвращает текущие время. Ну а имея "часы" думаю уже банальной логикой можно дойти как вычислить интервал.  Если при первом нажатии кнопки у нас текущие время XXXX, а при втором YYYY, то сколько времени была кнопка нажата? А если следующие нажатие произошло в ZZZZ, то как узнать какая пауза между нажатиями была?

Более того там есть даже специальная готовая функция замеряющая длину импульса (хотя я бы делал через "часы" руками).

Если вы собрались осваивать дуину, то без ознакомление с разделом "Программирование", хотя-бы поверхностного - вам явно не обойтись. А судя по вопросам - вы туда не заглядывали особо.

Borland
Offline
Зарегистрирован: 17.05.2012

leshak пишет:

Более того там есть даже специальная готовая функция замеряющая длину импульса (хотя я бы делал через "часы" руками).

 

Leshak , не просвятите что за функция ? чтото я не в теме

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012
leshak
Offline
Зарегистрирован: 29.09.2011

Угу. Вы думаете я не знал ее название и не мог сразу сказать "имя сестра, имя..."? Так же как и сразу сказать имя "функции возвращающей текущие время". Я ведь явно специально не назвал. Что-бы новичок пошел и проклацал по части функций из http://arduino.ru/Reference хотя-бы бегло. Заняло-бы это минут 5-10-ть. Зато было-бы хотя-бы минимальное знакомство с "огласите весь списк. пжласта" (  (с) "Приключения Шурика").

2kisoft: Это не наезд на вас. Вообщем-то никто не сказал что мое понимание "как нужно отвечать новичку" - самое правильное. Просто объяснил почему я сделал именно так.

2Borland: Пользование PulseIn - желательно избегать по тем же причинам что и delay(). Это - блокирующая функция. В данной задаче - ее можно применить, но брать ее везде и всюда в качестве панацеи для замера импульсов - череповато.

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ответ был для Borlanda ;)
PulseIn к тому же использует таймер, а это не всегда хорошо.
leshak, я вижу Ваш стиль обучения и стараюсь не мешать. Критику воспринимаю нормально, так что нет проблем, к тому же мы уже достаточно давно знакомы.

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:
Ответ был для Borlanda ;)

Ну значит Борладну тоже стоит перечитать первоисточники :)  (я вообще даже очень удивился, что он спросил).

Ну - не важно.

kisoft пишет:
PulseIn к тому же использует таймер, а это не всегда хорошо.

Вы ошибаетесь. Таймер он не использует (или вы не правильно пользуетесь термином "таймер", не в AVR смысле).

А вот поток выполнения - останавливает.

Вот исходник этой функции 

/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
 * or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
 * to 3 minutes in length, but must be called at least a few dozen microseconds
 * before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
	// cache the port and bit of the pin in order to speed up the
	// pulse width measuring loop and achieve finer resolution.  calling
	// digitalRead() instead yields much coarser resolution.
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	uint8_t stateMask = (state ? bit : 0);
	unsigned long width = 0; // keep initialization out of time critical area
	
	// convert the timeout from microseconds to a number of times through
	// the initial loop; it takes 16 clock cycles per iteration.
	unsigned long numloops = 0;
	unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
	
	// wait for any previous pulse to end
	while ((*portInputRegister(port) & bit) == stateMask)
		if (numloops++ == maxloops)
			return 0;
	
	// wait for the pulse to start
	while ((*portInputRegister(port) & bit) != stateMask)
		if (numloops++ == maxloops)
			return 0;
	
	// wait for the pulse to stop
	while ((*portInputRegister(port) & bit) == stateMask) {
		if (numloops++ == maxloops)
			return 0;
		width++;
	}

	// convert the reading to microseconds. The loop has been determined
	// to be 20 clock cycles long and have about 16 clocks between the edge
	// and the start of the loop. There will be some error introduced by
	// the interrupt handlers.
	return clockCyclesToMicroseconds(width * 21 + 16); 
}

Как видите - тупо крутит цикл, с ограничением на "количество раз". Никакими таймерами - не пахнет.

P.S. Кстати - тут можно подсмотреть "полезный прием". Что делать если digitalWrite из-за его тормозючести не хочется использовать, но при этом не хочется переходить на прямую запись в порт и терять переносимость (или банально лениво с разбиратся какая-нога какому порту соотвествует). Я про использование digitalPinToBitMask, digitalPinToPort, *portInputRegister которых не найдешь в документации.

P.S.S. Топик стартеру: не заморпчивайте себе, пока, этим "полезным приемом" голову. Можете смело пользовался digitalWrite. Для "нажимаем пальцем" она вполне шустрая. Ее скорости может не хватать только когда мы за микросекунды начинаем боротся. А в вашем случае будут сотни и тысячи миллисекунд. 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Кстати, про pulseIn, в таком случае перевод у нас на сайте некорректный. Прежде чем написать ответ, я прочитал, что там написано.

Исходник посмотрел, да уж.. точно код для эгоистов, я здесь работаю и "пусть весь мир подождет", теперь я его точно юзать не буду, впрочем и не было нужды и желания в этом :)

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Насчет возвращения времени, как я понял речь идет о ф-ции "millis()", догадываюсь лишь о "return", больше ничего на ум не пришло. пртестировал ее в processing (т.к ардуино придет только через пару дней) ничего не сработало:(

leshak
Offline
Зарегистрирован: 29.09.2011

Lihtelf пишет:

Насчет возвращения времени, как я понял речь идет о ф-ции "millis()", догадываюсь лишь о "return", больше ничего на ум не пришло.

millis() - правильный ответ :)  Подставте ее в "учебную задачу" которую я давал выше "Если при первом нажатии кнопки у нас текущие время XXXX, а при втором YYYY, то сколько...."

Вот рядышком родственное обсуждают: http://arduino.ru/forum/programmirovanie/pomogite-s-knopkami-i-svetom-razobratsya

И еще этих поиском по форуму в разных ракурсках эту задачу 50-ть раз найти можно.

Но, для начала - попробуйте воспользоватся pulseIn, с ней легче стартовать. Быстрее получите работающий результат. Пока задача минимальна "секретный стук поймать" - ее хватить для решения. Ее "проблемность" не проявится.

А уж потом будете разбиратся как это же сделать через millis().

Это как с "миганием диодом". Вначале с помощью delay() делают по простому (правильно делают). Потому возникает желание "добавить еще логики" и тут вылазять "побочные эффекты delay()". Тогда уже millis() приходится осваивать.

В конечном итоге нужно и так и этак уметь. Уметь решить и через pulseIn/delay() и через millis().

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

Lihtelf пишет:

пртестировал ее в processing ничего не сработало:(

Простите - телепаты в отпуске. Значит "что-то не так делаете".

Lihtelf пишет:

 (т.к ардуино придет только через пару дней)

Опять-таки, поиск по форуму (или просто гугл) позволяет найти симуляторы ардуино (хотя, конечно это "немного не то" :(, не тот кайф учится).

 

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:

Кстати, про pulseIn, в таком случае перевод у нас на сайте некорректный. 

Ну "как сказать". И да и нет. Тут скорее выполезла неоднозначность русского языка. В данном случае "включился таймер" используется в значении "начинается отсчет времени", а не "таймер" - как устройство.

В английском оно более четко различается "timer" и "timing".

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:

Исходник посмотрел, да уж.. точно код для эгоистов, я здесь работаю и "пусть весь мир подождет", теперь я его точно юзать не буду, впрочем и не было нужды и желания в этом :)

Да код, как код. Куча функций работает именно по этому принципу. и delay() и библиотека stepper() и т.д. и т.п.

Все-таки "базовое" должно быть максимаьлно простым. Чай у нас не гигабайты памяти. Да и вызывающий код для асинхронной версии - намного сложней. Так что пихать все это в "базовую функцию" - не имеет смысла. А задача "просто дождатся импульса и померять его длину" когда пофиг на небольшую задержку, ведь есть еще и timeout - не так уж и редка. 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Это все круто, более того даже немного понятно)),но я так понимаю в данном проетке мне это мало пригодится, ведь все промежутки и "пароли" я буду задавать вручную на компе. Правильно ли я определю эти промежутки? это уже другой вопрос)). Тут дело в другом. Допустим я знаю эти временные "промежутки", как мне задать сам "пароль" и сделать так, чтобы он распознавался?

Lihtelf
Offline
Зарегистрирован: 24.12.2012

leshak пишет:

Опять-таки, поиск по форуму (или просто гугл) позволяет найти симуляторы ардуино (хотя, конечно это "немного не то" :(, не тот кайф учится).

Как-то раз пробовал найти эмулятор. Ничего не вышло)). Либо платные либо еще что-то. Буду благодарен если подскажете где скачать нормалную програмку

leshak
Offline
Зарегистрирован: 29.09.2011

Lihtelf пишет:

Это все круто, более того даже немного понятно)),но я так понимаю в данном проетке мне это мало пригодится, ведь все промежутки и "пароли" я буду задавать вручную на компе. Правильно ли я определю эти промежутки? это уже другой вопрос)). Тут дело в другом. Допустим я знаю эти временные "промежутки", как мне задать сам "пароль" и сделать так, чтобы он распознавался?

Ну вот поэтому и "пригодится". Слова можно начатьп писать освоив буквы, из них - складывать слова, из них - стихи :)

Невозможно сразу "перепрыгнуть".

Вам нужно уверенно освоить "замеры интервала". Когда это есть (почитаете что такое if, что такое &&)  - будете решать "как серию распознавать". То есть вначале научитесь просто отличать "короткий стук" от "длинного". Пусть будет код в "один удар".

Когда один поняли - начинаете читать про массивы, цикл for и т.п.. И в массив помещаете помещаете "секретную последовательность". Потом проходите по нему и применяете к каждому элементу то что научились на при работе с "один удар". "Секрет" будет зашит в код, для смены кода - нужно будет перезаливать скетч.

Потом озадачитесь "как без перепрошивки командами с компа его менять" - начнете читать про Serial, искать ветки "как прочитать число из Serial" и т.п. - научитесь работе с сериал.

Дальше встанет вопрос, а как сделать что-бы он не "забывал код" при выключении питания - будете про EEPROM читать.

Да. Вот так длинно (хотя когда "Знаешь" - это совсем не сложно и быстро). И ничего не сделать если не освоить "базу". Синтаксис, управляющие операторы, типы данных, логические операторы.

Или вы хотели что-бы "вам все это написали"? Так а толку? Будете смотреть на код как "магию которая работает", а любая попытки изменить выливаться "ой, все поломалось, помогите".

Вообщем нужно осваивать "кубики лего", а уж любой проект, потом, будет из них собиратся.

leshak
Offline
Зарегистрирован: 29.09.2011

Lihtelf пишет:

leshak пишет:

Опять-таки, поиск по форуму (или просто гугл) позволяет найти симуляторы ардуино (хотя, конечно это "немного не то" :(, не тот кайф учится).

Как-то раз пробовал найти эмулятор. Ничего не вышло)). Либо платные либо еще что-то. Буду благодарен если подскажете где скачать нормалную програмку

Да. Либо платные либо еще что-то. Такие они и есть. У меня в работе - так и не прижились поэтому. Гимороя больше чем толку. Вот как раз для случая когда "руки чешутся, а платы нет". Причем "что-то не сложное." Диод и кнопка :)

VirtualBreadBoard, Proteus (вот это серьезно, но слишком большой комбайн), http://www.arduino.com.au/Simulator-for-Arduino.html

Но "идеального решения" - так и не найдено. Но для "пощупать" - должно хватить.

P.S. Последний даже хотел купить, деньги не велики, пусть будет, но что-то заартачилось на мою кредитку, не стал голову морочить :)

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Ну некоторые основы програмирования я знаю, хоть и проходил в школе на паскале. Про массивы я тоже имею некоторые знания, но пока вы не подсказали никак на ум не приходило)). Попробую пока через processing, а затем портирую))

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Короче попробовал тут, но не работает один момент.

int s;
 void setup() {
 size(640, 360); 
}
  void draw()
{
  //background(255);
  int m=millis();
  s=m/1000; //секунды
  println() ;
  print("sec ");
  println(s);
  int[] bit = new int[8];//"пароль" состоящий из 8 битов
  
  if (mousePressed) //если в данную секунду кнопка былы нажата,то ячейке массива под номером данной секунды присвоить 1
   bit[s] = 1 ;
   else
   bit[s] = 0;
   
   println(bit[s]);
  print(bit[0]);print(bit[1]);print(bit[2]);
  print(bit[3]);print(bit[4]);
  print(bit[5]);print(bit[6]);print(bit[7]);
   
}

Значение не присваивается ячейке перманентно,то есть, сразу после того как меняется запись с одной ячейки(соответствующей секунде с начала отсчета) на другую, предыдущая ячека принимает значение "0"

Заранее прошу прощение за корявый код))Но так нагляднее, по крайней мере для меня))))

leshak
Offline
Зарегистрирован: 29.09.2011

>Заранее прошу прощение за корявый код))Но так нагляднее, по крайней мере для меня))))

Да код как код. Собственно на то что раньше вы не давали никакого кода вообще - я и намекал фразой "телепаты в отпуске".

К тому же когда человек пишет много "хочу", но не показывает никакого кода вообще - это вызвает подозрение в "халявщик ищет что-бы ему кто-то все сделал".

А кода "хоть что-то есть", то видно что человек сам пытается. Можно и помочь :)

Так, что-то меня унесло...

По вашему коду:

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

Давайте все-таки "по плану". Не хвататесь за массивы (к тому же явно не почитав про for) Смотрите сообщение #21. Там было "вначале вам нужно освоить замеры интервалов...".

Вот и попробуйте замерятьс колько мышка была нажата. И просто вывести это время. Время удержания кнопки. При этом будет полезно поглядывать на тему "вот родственно обсуждают" (ссылку я давал выше). Особенно обратите внимание на кусочки кода которые я давал :) там.

И еще: держите в уме. Что в процессинге у вас millis() возращает int (поэтому сейчас вы  правильно выбрали тип переменной), но когда начнете писать для ардуины - там millis() уже будет unsigned long. Если, по привычке, напишите int - потом можете поймать очень трудно уловимые баги.

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Короче я так и не понял как замерить интервал, а еще я не понимаю как "зафиксировать" момент millis(), любая переменная сама превращается в функцию, а мне нужна константа

leshak
Offline
Зарегистрирован: 29.09.2011

Lihtelf пишет:

Короче я так и не понял как замерить интервал, а еще я не понимаю как "зафиксировать" момент millis(), любая переменная сама превращается в функцию, а мне нужна константа

М.... честно говоря ничего не понял кроме "не понял как замерить интервал". Все останльное прозвучало как набор слов.

Ладно, давайте еще упростим задачу.

"Вывести время" (значение функции millis()), в момент нажатия и в момент отпускания (смотрите ту ветку. Я там дал кусок код который на 95% и является решением этой задачи).

Кстати, вы разобрались с тем что функци loop()/draw() вызывается постоянно? То есть как только мы дошли до ее конца - опять начинается ее выполнение с начала (но при этом теряются все значения локальных переменныж)?

Как-будто кто-то внешний вызывает ее раз за разом draw();draw();draw();draw();draw();draw();draw();draw(); бесконечно.

Если не выйдет "вывести время в момент нажатия" - откатывайтесь еще на один шаг.

Сделайте просто "постоянно выводить значение millis() и нажата-ли кнопка".  

leshak
Offline
Зарегистрирован: 29.09.2011

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

Смотрите на

http://arduino.ru/forum/programmirovanie/pomogite-s-knopkami-i-svetom-ra...  код в сообщение #25.

Практически готовое решение этой задачки.

Разница только в том что  buttonState=!digitalRead(....) не нужно. В процессинге оно уже есть "готовое". В виде переменной mousePressed.

prevButtonState можно переименовать в "prevMousePressed" (для красоты. что-бы сохранить "единообразие именования").

Ну а там где "... что-то делаем по этому поводу..." - нужно "что-то сделать". В данном случае - вывести текущие время.

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Вот набросал тут кое-что.

float s;
 float h;
 float interval;
 void setup() { 
}
  void draw()
{
  //background(255);
  float m=millis();
  s=m/1000; //секунды
  println() ;
  print("sec ");
  println(s); //текущее время
  if (mousePressed){ 
   h=millis();
  }
println(h/1000);  //секунда на которой была нажата кнопка 
interval = s-h/1000;
print("интервал ");
print(interval);
}

 

 

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

"""экспериментальным""" путем было вычислено, что точка - 50 милисекунд, тире - 100-120. 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

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

leshak
Offline
Зарегистрирован: 29.09.2011

 

Lihtelf пишет:

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

Можно и то и то. Но задача ставилась "длина нажатия". Более того было предложено раздробить и это на еще более мелкие подзадачи.

Возможно я неудачно использовал термин "время нажатия" (многозначность русского языка :( ).  Я имел ввиду "момент нажатия".

Вообщем нужно вывести что-то типа "нажали кнопку в XXXX милессекунд", "отпустили в YYYY миллисекунд".

Если ничего не делаем - ничего не происходит.

В вашем коде есть две ошибки принципиальные:

1. Вы все время обновляете переменную h. То есть пока кнопка держится нажатой - вы туда раз, за разом ложите текущие время. А вам нужно что-бы это происходило только "в момент нажатия". То есть h=millis(), должна вызыватся только в тот момент когда "кнопка была не нажата, а стала нажата". Пока мы держим кнопку - h не должно менятся.
2. Вы все время обновляете переменную m (а за ней s и interval). draw()-то у нас вызывается постоянно. И они у вас все время меняют значения, вне зависимости от того делал что-нибудь с кнопкой пользователь или нет.

Да и вообще, не очень понятно, зачем вы вообще вычисляете "текущую секунду". Единица измерения "миллисекунды" для контроллера - более естественны :) Конвертацией в секунды - вы сами себе создаете проблемы (эфективность, потеря дробной части и т.п.)

Вообещем, попробуйте, все-таки оттолкнутся от того что я написал в #28.  Вначале научимся "ловить нужный момент", а уж потом будет, зная моменты -вычислятьи интервалы.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Длительность, конечно, время между нажатиями не нужно, хотя это то же можно сделать секретной величиной. Но для начала, хватит длительности нажатия

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Если мне нужен МОМЕНТ нажатия, то мне нужен момент перехода состояния кнопки из ненажатой в нажатую?

Попробую снова посмотреть соседнюю ветку, там врде было написано насчет этого.

Lihtelf
Offline
Зарегистрирован: 24.12.2012

 

1 void loop() {
2   if(pin == high){
3     if(prev_pin == low){
4       digitalwrite(led, high);
5       prev_pin = high;
6   }
7

}

Вроде то , что мне надо. Не пойму одного, здесь написано prev_pin. Это предыдущее состояние "кнопки" ? И здесь же prev условная приставка, а как мне сделать в робочем коде, что будет определять предыдущее состояние?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Этот код достаточно специфичный и может совсем сбить с толку. В нужную сторону, но лучше посмотрите примеры, которые идут с ArduinoIDE (не обязательно иметь Arduino, осмотрите исходники), примеры: Button, потом Debounce, StateChangeDetection.

 

leshak
Offline
Зарегистрирован: 29.09.2011

А не хотите, все-таки попытатся сделать именно то что я написал? Именно вот это:

leshak пишет:

 

Смотрите на

http://arduino.ru/forum/programmirovanie/pomogite-s-knopkami-i-svetom-razobratsya#comment-20692  код в сообщение #25.

Практически готовое решение этой задачки.

Разница только в том что  buttonState=!digitalRead(....) не нужно. В процессинге оно уже есть "готовое". В виде переменной mousePressed.

prevButtonState можно переименовать в "prevMousePressed" (для красоты. что-бы сохранить "единообразие именования").

Ну а там где "... что-то делаем по этому поводу..." - нужно "что-то сделать". В данном случае - вывести текущие время.

Пройти именно по указанно ссылке (она именно на тот пост в котором пример брать нужно ведет, даже если "пролистнули", так и номер откуда брать пример - указал). И попытатся сделать именно те замены которые я опять-таки написал.

Ну повсторю чуть другими словами (что-бы еще упростить - даже переменным не будем имена менять)

1. Идем берем именно УКАЗАННЫЙ пример. МОЕ сообщение, под номером #25 в той ветке.  Нажимите для этого там "показать код" - оно свернуто.
2. Вместо buttonState=!digitalRead(PIN_BUTTON) пишем buttonState=mousePressed
3. Читаем коментарии и думаем куда нужно вписать что-то типа print("ON:");println(millis()) и print("OFF:");println(millis()), что-бы выводить время когда нажали кнопку и когда отпустили.

 

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Пока копался в примерах вспомнил одну вещь, не знаю ее ли вы имели в виду, но это работает

int i;
int o;
void setup() {
}

void draw() {
  

  if(mousePressed && o==0){
   i++;
   o=1;
  }
  if(!mousePressed)
   o=0;
  
 
 println(i);
}

Даже не знаю как это все прокомментировать , но i++ работает в том случае, когда кнопка была нажата,а затем прекращает свое действие,чтобы снова запустить i++ нужно отпустить кнопку и снова нажать.

Следовательно все работает именно на изменение состояния.

Lihtelf
Offline
Зарегистрирован: 24.12.2012

попробовал подогнать под processing, возможно наделал много ошибок,а может и нет,но все равно не работет с ошибкой "The operator ! is undefined for the argument type(s) byte"

//#define PIN_BUTTON 2

byte prevButtonState=0;
byte buttonState;

void draw(){
  // читаем состояние кнопки, buttonState==TRUE - кнопка нажата
  if (mousePressed)
       buttonState=1;
     else
       buttonState=0;   // уберите восклицательный знак если кнопка притянута к земле
  
  
  if(!prevButtonState && buttonState==1){
   i++; // перешли из "не нажато", в "нажато"
     // что-то делаем по этому поводу, засекаем момент нажатия и т.п.
  }
  
  if(prevButtonState && !buttonState){
   i++; // перешли из "нажато", в "не нажато"
    // что-то делаем по этому поводу. Обнуляем "момент нажатия", сбрасываем флаги и т.п.
  }
  println(i);
  
  
  prevButtonState=buttonState; // запомнили на следующий проход loop()-а какое у нас было состояние
}

.

 

leshak
Offline
Зарегистрирован: 29.09.2011

Lihtelf пишет:

попробовал подогнать под processing, возможно наделал много ошибок,а может и нет,но все равно не работет с ошибкой "The operator ! is undefined for the argument type(s) byte"

Это уже тонкости/различия процессинга и ардуины начали проявлтся (в ней любой числовой тип - может использоватся как булевский).

Вместо "!prevButtonState" можете писать "prevButtonState==0" - это по смыслу идентично.

Либо, попытатся сменить переменным buttonState и prevButtonState типа с byte на bool (или boolean).

leshak
Offline
Зарегистрирован: 29.09.2011

И зачем у нас тут i++ появилось, если мы говорили про print(millis())?

Lihtelf
Offline
Зарегистрирован: 24.12.2012

i++ для наглядности, поменяю на millis();

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Короче заработало.

byte n=0;
byte p;
 int i;
 int a;
 int b;
void draw(){
  if (mousePressed)
       p=1;
     else
       p=0;   
  if(n==0 && p==1){
   a=millis();     
  }  
  if(n==1 && p==0){
   b=millis();
  }  
  i=b-a;
  println(i);
   n=p;
}

И снова "экспериментальным" путем найден интервал.

Для коротких 80-160 милисекунд
Для длинных 380-420 милисекунд.

Дальше определение и отношение "касаний" к "-" или ",".
Я так понимаю нужно что- то вроде if(i >80 &&  i<160) ?

leshak
Offline
Зарегистрирован: 29.09.2011

Lihtelf пишет:

И снова "экспериментальным" путем найден интервал.

Это не очень здорово. Лучше что-бы "через понимание" (если "эксперементально" вы не имели ввиду узнавание конктретных цифр интервала).

Lihtelf пишет:

Дальше определение и отношение "касаний" к "-" или ",".

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

В первую очередь стиль. Лучше так не привыкать. На 5-ти строчках с ним еще можно разобратся, но когда их будет 100 и больше - мозг взорвется.

Имена переменных n, p, a - это ужас. Глядя на одну строчку - невозможно понять что значит эта переменная, если не найдешь в коде выше как она вычисляется. Через три недели глядя в этот код - вы уже сами не будете помнить "где тут что" (не говоря уже про других), а значит "вникай заново".

Все таки мена вида interval, pressedTime, unpressedTime - гораздо лучше "говорят" что означают эти переменные. Каков их смысл.

Далее, оно у вас "не заработало". Оно у вас "шумит дай-бог" (по крайней мере в дуине будет шуметь).

Вот даже ничего не нажимаете - у вас же все время "цифры бегут".  Строки 17,18,19 выполняются постоянно. А вам достаточно один раз вычислять. И одни раз выводить. В момент отпускание кнопки. То есть все это нужно перенести внутрь второго if-а, после строки 15-ть вставить.

Иначе я нажал кнопку, что-то записалось в a, и полезли "отрицательные интервалы" (так как b, пока ноль. кнопку я еще не отпустил).

Кстати видите как хренов "a", "b" - не глядя в код и не поймешь из текста про что идет речь.

А вот "что-то записалось в pressedTime, и полезли "отрицательные interval" (так как unpressedTime, пока ноль. кнопку я еще не отпустил)" - уже как-то можено понять.

Lihtelf пишет:

Я так понимаю нужно что- то вроде if(i >80 &&  i<160) ?

Верно на 95%. Но давайте вначале, все-таки само вычисление "дожмем". Тем более что "совсем чуть-чуть осталось".

Lihtelf
Offline
Зарегистрирован: 24.12.2012

 

byte n=0;
byte p;
 int i;
 int a;
 int b;
 char j;
void draw(){
  if (mousePressed)
       p=1;
     else
       p=0;   
  if(n==0 && p==1){
   a=millis();     
  }  
  if(n==1 && p==0){
   b=millis();
  }  
  i=b-a;
  n=p;
 /////////////////до этого определялась "длинна нажатия"
 println(i); // "длинна нажатия"
    if(i > 30 &&  i < 230){ //определение короткого сигнала
    println("."); // отображение "точки"
    }
    
    if(i > 250 &&  i < 420){ //определение длинного сигнала
     println("-");// отображение "тире"
    }
    if(i<30||i>250&&i<280||i>420){ // все остальные сигналы
    println(" ");
    }
    
}

Все работает!!!!

Теперь он определяет "." и "-".

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

leshak пишет:

 

Это не очень здорово. Лучше что-бы "через понимание" (если "эксперементально" вы не имели ввиду узнавание конктретных цифр интервала).

Это именно узнавание конкретных цифр))

leshak пишет:

Имена переменных n, p, a - это ужас. Глядя на одну строчку - невозможно понять что значит эта переменная, если не найдешь в коде выше как она вычисляется. Через три недели глядя в этот код - вы уже сами не будете помнить "где тут что" (не говоря уже про других), а значит "вникай заново".

Да, так и есть , но яне знаю что меня приводит в больший ужас: переменные (которые могут быть подписанны в одном месте) или мноого букв означающих переменную)))))

leshak пишет:

Далее, оно у вас "не заработало". Оно у вас "шумит дай-бог" (по крайней мере в дуине будет шуметь).

Вот даже ничего не нажимаете - у вас же все время "цифры бегут".  Строки 17,18,19 выполняются постоянно. А вам достаточно один раз вычислять. И одни раз выводить. В момент отпускание кнопки. То есть все это нужно перенести внутрь второго if-а, после строки 15-ть вставить.

Иначе я нажал кнопку, что-то записалось в a, и полезли "отрицательные интервалы" (так как b, пока ноль. кнопку я еще не отпустил).

Отрицптельные интервалы мне никак не мешают)) ведь они не подходят под условие if

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Вот, работает как часы.
Опять же для наглядности сделал "визуализацию".
Точка = круг, тире = квадрат.

byte n=0;// предыдущее состояние
byte p; //состояние кнопки
 int i; //интервал 
 int a; //момент нажатия кнопкb 
 int b; //момент отпускания кнопки
 int x; //координаты фигуры относительно оси "Х"
 int j; // определяет круг и квадрат
 void setup() {
  size(1024, 768);
 }
void draw(){
  if (mousePressed){
       p=1;
      
  }
     else
       p=0;   
  if(n==0 && p==1){
   a=millis(); 
    
  }  
  if(n==1 && p==0){
   b=millis();
   x++;
  }  
  i=b-a;
  n=p;
 /////////////////до этого определялась "длинна нажатия"
 println(i); // "длинна нажатия"
    if(i > 30 &&  i < 230){ //определение короткого сигнала
    println("."); // отображение "точки"
    j = 1; // для "визуализации"
    }  
    if(i > 250 &&  i < 420){ //определение длинного сигнала
     println("-");// отображение "тире"
     j = 2; // для "визуализации"
    }
    if(i<30||i>250&&i<280||i>420){ // все остальные сигналы
    println(" ");
    }
////////////////////// здесь находится "визуализация "
    switch (j){
      case 1 : //короткий сигнал
    ellipse(x*60+15,195,30,30);
    break;
      case 2 : //длинный сигнал
    rect(x*60,180,30,30);
    break;
    }
    
}

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Немного перенастроил интервалы.
Теперь :
- Точка - (30-130)
- Тире   - (170-420)

byte n=0;// предыдущее состояние
byte p; //состояние кнопки
 int i; //интервал 
 int a; //момент нажатия кнопкb 
 int b; //момент отпускания кнопки
 int x; //координаты фигуры относительно оси "Х"
 int j; // определяет круг и квадрат
 void setup() {
  size(1024, 768);
 }
void draw(){
  if (mousePressed){
       p=1;
      
  }
     else
       p=0;   
  if(n==0 && p==1){
   a=millis(); 
    
  }  
  if(n==1 && p==0){
   b=millis();
   x++;
  }  
  i=b-a;
  n=p;
 /////////////////до этого определялась "длинна нажатия"
 println(i); // "длинна нажатия"
    if(i > 30 &&  i < 130){ //определение короткого сигнала
    println("."); // отображение "точки"
    j = 1; // для "визуализации"
    }  
    if(i > 170 &&  i < 420){ //определение длинного сигнала
     println("-");// отображение "тире"
     j = 2; // для "визуализации"
    }
    if(i<30||i>130&&i<170||i>420){ // все остальные сигналы
    println(" ");
    }
////////////////////// здесь находится "визуализация "
    switch (j){
      case 1 : //короткий сигнал
    ellipse(x*60+15,195,30,30);
    break;
      case 2 : //длинный сигнал
    rect(x*60,180,30,30);
    break;
    }
    
}

 

Lihtelf
Offline
Зарегистрирован: 24.12.2012

Теперь надо разобраться с массивом пароля.
Думаю надо задать что то типа
int[] pass = {1,2,1,2,1,2,0}; - искомый пароль
int[] input = new int[7]; - пароль который будет введен
Пока что не могу понять как будет производится запись пароля в массив.

switch (j){
  case 0 :
  input[x-1]=0:
  case 1 :
  input[x-1]=1;
  case 2 :
  input[x-1]=2;

Где j-тип сигнала, а "х" отвечает за порядок ячеек, то есть при первом нажатии х будет равен 1, а при втором 2.
Столкнулся с той же проблемой, при переходе на другую ячейку, значение предыдущей стирается.

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012