как правильно посчитать время между нажатиями на кнопку
- Войдите на сайт для отправки комментариев
приветствую сообщество.
я только делаю первые шаги в программировании, потому прошу сразу ногами не пинать за вопросы, если они покажутся глупыми.
есть потребность в устройстве, которое будет определять частоту нажатий на кнопку без фиксации. это не вся суть устройства, есть еще индикация, опрос аналогового порта с целью замера сопротивления, общение с другой микросхемой по SPI или I2C.
но пока я только начинаю осваивать МК и потому программа будет усложняться по мере обучения.
для начала нужно просто посчитать время между нажатиями на кнопку. алгоритм представляется такой: зажигаем зеленый светодиод, опрашиваем кнопку, если не была нажата, светодиод продолжает гореть, снова опрашиваем кнопку до тех пор, пока не обнаружится первое нажатие.
если нажатие зафиксировано, ждем следующего нажатия. если прошло 2 секунды, а повторного нажатия не было, зажигаем красный светодиод, если нажатие было, ждем следующего, определяем время, мигаем зеленым светодиодом с частотой нажатий (f=1/t).
собственно вопрос пока в том, как посчитать время между нажатиями? нужно задействовать таймер или функций millis/micros будет достаточно? подскажите, как лучше реализовать. быть может у кого-то есть примеры на данную тему. буду признателен за помощь.
опрос сделать по прерываниям
http://arduino.ru/Reference/AttachInterrupt
вот для примера
а время считать millis
Борьбу с дребезгом контактов как организовали?
Нужно архитектуру программы изначально спроектировать.
С учетом масштабируемости проекта, чтобы ее больше не менять.
Если всё будет вертеться вокруг нажатия кнопок, тогда лучше опрос.
Ну т.е. если программа ждет нажатия кнопок, а потом отрабатывает какое либо действие.
А если программа что то делает, а нажатие кнопки меняет или настройки или исполнение какого то алгоритма, то лучше делать прерываниями, чтобы контроллер меньше нагружать.
Прерываниями вызывающимися по изменению сигнала.
Или если трудности любите преодолевать, то на прерывание от таймера и в нём кнопки опрашивать с необходимой частотой.
В прерывании по таймеру лучше опрашивать порты низкоуровнево, не используя функции digitalRead и analogRead.
Больно уж они медленные, много тактов процессора используют, сажая производительность.
Кстати есть стандартная библиотека для опроса кнопок по таймеру.
У меня, правда, работать отказалась почему то.
С таймерами вообще нужно аккуратнее.
Много стандартных библиотек используют таймеры для своих нужд и когда несколько библиотек проекта используют одни и те же таймеры, возникают хаотичные, неуловимые глюки.
jeka_tm, Motto, спасибо за ваши ответы.
для меня это пока сложно, но я попытаюсь разобраться.
Motto, если под архитектурой понимается блок-схема, то таковую я для себя накидал. но сначала хотел разобраться с блоками: мигания диодами, счет времени, работа по SPI, а потом все соединить.
устройство не ждет нажатия на кнопку, оно функционирует самостоятельно, мк должен менять режим работы устройства, если/когда на кнопку стали нажимать.
принцип работы можно сравнить с метрономом, только метроном тикает с заданной частотой, а мне нужно частоту определить и уже по ней выставить метроном. как бы обратная операция. (ну, это образно и только для примера, в реальности нет никакого метронома)
Шаг за шагом. Опиши подробнее, что за устройство. Вернее сказать, что оно делает в то время, когда кнопки не нажаты.
Сорри за Код, на коленке, Он подразумевает опрос кнопки, что стоит процессорного времени. Но предпочтительнее, потому, что пока ты разберешься с прерываниями пройдет время.
Важно, что бы твоя фунция DoSomething(time); не содержит Delay и не задерживет выполнение процессора.
кратко о функционировании:
1. инициализация: устройство включается (подается питание), считывается состояние перемычек (чтобы задать конфигурацию измерения времени: по 2 нажатиям, по 3 или 4), считывается значение сопротивления на аналоговом порту, по SPI передаются команды в другую ИМС о значении сопротивления, мигаем светодиодом с рассчитанной частотой (выражение заранее известно и зависит от величины сопротивления на аналоговом порту). конец инициализации. этот кусок программы больше выполнять нет смысла.
2. Проверяем, была ли нажата кнопка.
2.1. Если кнопка не была нажата,
3. проверяем, не изменилось ли значение сопротивления:
3.1. если не изменилось, снова проверяем кнопку и сопротивление;
3.2. если изменилось, передает данные о значении сопротивления по SPI, пересчитываем частоту, мигаем светодиодом с новой частотой.
2.2. Если кнопка была нажата, запускаем счет, ждем еще 1 (2 или 3 в зависимости от конфигурации перемычек) нажатие на кнопку, считаем время между нажатиями, (усредняем, если нажатий больше чем 2), мигаем светодиодом с частотой нажатий.
да, фукцию delay хотелось бы обойти, чтобы не было проблем с обработкой прерываний.
наверное, было бы резонно сделать 2 внешних прерывания: одно по нажатию на кнопку, второе по изменению сопротивления на аналоговом порту (только как я пока не знаю), а все остальное время пусть МК спит, чтобы не было потребления.
1- прерывание по изменению аналого входа... Не такого не бывает. т.е. проще поставить еще один микропроцессор под это. Иначе придется городить сложную схему из внешнего АЦП и долго долго мучаться с помехами/дребезгом..
В твоем случае Я не вижу необходимости в прерываниях! Тебе нужно избавиться от Delay в коде, путем перевода кода на Even ориентированное прогаммирование.
Идея: У тебя есть состояние, которое помнит контроллер. В лупе в зависимости от состояния вызываются разные фунции: опрос клавиатуры, включение/выключение светодиода и тп. При этом нигде нельзя использовать Delay. для включения/выкл светодиода используешь функцию millis(), mircros(). расчитываешь время когда надо его выключить, и просто проверяешь,насто время или нет.
Да, это плохо с точки зрения потребления электричества, но мне кажеся важнее сделать так, что бы схема вообще заработала. А если ты в конце лупа добавишь delay(20), то контроллер 80% времени будет спать, а ты задержки в 20 миллисикунд может быть и не заметишь.
Получилось сделать TapTempo?