Кнопка-существительное женского рода

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

«Есть у Льва Николаевича Толстого, среди множества алмазов народной речи, в одном из произведений такая поговорка: "Баба с печи летит, семьдесят семь дум передумает. Сколько там с той печи лететь? И то — семьдесят семь дум!" Михалевич, Высокие низы. [Матрена:

Если, например, возьмем высоту печи 1,5 м (поправьте, кто лучше знает), то по формуле школьного учебника физики получается, что лететь Матрене всего t=sqrt(2*h/g) = sqrt(2*1.5/9.8) = 0.6 сек.

Отсюда легко посчитать, что на одну думу затрачивается t=0,6/77 = 0.008 сек, или примерно восемь миллисекунд.

Кнопка - она женского рода, поэтому даже самые идеальные кнопки в первые мгновения на ласковое нажатие и простой и прямой вопрос ДА? начинают суетиться  и дергаться, лихорадочно менять свое состояние, тоже, может быть, сто раз за секунду, чтобы, в конце концов, вынести мОзги, так ничего внятного не ответив :(((
Это явление в технике называется "дребезг" и обычно с ним предлагают бороться следующим образом.

Опрашивают состояние кнопки, и если оно ДА, через какое-то время опрашивают снова. Если получен утвердительный ответ ДА во второй раз - нужно немедленно действовать. Если получено НЕТ – задавать вопрос сначала уже в следующем цикле.

Промежуток времени между двумя запросами каждый определяет самостоятельно. Одни засекают время, запускают таймер и продолжают заниматься своими делами пока не подойдет время второго запроса. Другие бросают все дела, тупо зависают на время задержки (см. функцию delay()), и только потом задают второй вопрос.

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

Второй способ подойдет тем, кому некуда торопиться.  Например, в системе полива цветов ±10 сек или даже минут никакой роли не играют.

Я предлагаю еще один способ опроса состояния кнопки.

Если первый ответ отрицательный - дальше не имеет смысла опрашивать, и продолжаем выполнять луп.

Если вдруг прозвучало "ДА" - бросаем все дела и снова и снова (допустим, 255 раз) спрашиваем: "ты действительно говоришь ДА?". Если все ответы подряд положительны и кнопка твердо согласна - начинаем обрабатывать согласие. Если хоть один ответ был отрицательный - ловить нам нечего, бросаем окучивать кнопку и продолжаем луп.

Собственно, здесь приложен скетч тестового примера.

/*
 * DigitalReadSerial
 * Reads a digital input on pin 2, prints the result to the serial monitor
 * This example code is in the public domain.
 *
 * Среда разработки {The Arduino Integrated Development Environment - or Arduino Software (IDE)}
 * идентифицирует плату как Arduino Uno/Genuino Uno
 * 
*/

/*                        ТЕСТОВЫЙ ПРИМЕР
   Подавление дребезга кнопки методом последовательных совпадений
   Состояние кнопки многократно "N" раз считывается digitalRead()
   Если последующее чтение не совпадает с предыдущим - цикл обнуляется,
   опрос состояния кнопки прекращается
   Если все N последовательных опросов дают одинаковый результат -
   выводится сообщение о нажатии кнопки,
   на 1000 мсек = 1 сек зажигается LED 13-го пина
*/

#define RESET_ALL 11                                        // пин моей кнопки "RESET_ALL"
const boolean default_RESET_ALL = LOW ;                     // исходное состояние нормально разомкнутой кнопки
                                                            // RESET_ALL с подтягиванием к земле
unsigned int numberOfCycles = 65535 ;                       // максимальное допустимое число повторений digitalRead() 


// the setup routine runs once when you press reset:
// Запуск делается с нажатой кнопкой RESET_ALL

void setup() {
  Serial.begin(9600) ;                                      // initialize serial communication at 9600 bits per second:
  pinMode(RESET_ALL, INPUT) ;                               // make the pushbutton's pin an input:
  pinMode(13, OUTPUT) ;
  digitalWrite(13, LOW) ;
  }

void loop() {                                               // the loop routine runs over and over again Forever!
  if (ladyButton(RESET_ALL,                                 // сравнивается текущее состояние кнопки
                 default_RESET_ALL,                         // с дефолтным
                 255 )                                      // максимальное число повторений в примере
                 == !default_RESET_ALL ) {                  // если состояние стабильно изменилось -
    Serial.println ("Button is pressed !") ;                // выводим сообщение
    digitalWrite(13, HIGH) ;                                // включаем 13 пин,
    delay(1000) ;                                           // смотрим на него 1 сек
    digitalWrite(13, LOW) ;                                 // и выключаем 13 пин     
    }
  }


// Функция многократного непрерывного опроса кнопки

boolean ladyButton(int nomberPin, boolean defaultState, unsigned int numberOfCycles)
  {                                                         // nomberPin номер опрашиваемого цифрового пина
                                                            // defaultState исходное состояние кнопки/пина
                                                            // numberOfCycles число повторений опросов состояния кнопки
  unsigned int i = 0 ;                                      // счетчик текущего номера цикла чтения кнопки
  boolean pushState ;                                       // возвращаемое состояние кнопки
  while (i < numberOfCycles) {                              // запускается циклический опрос
    if (digitalRead(nomberPin) == !defaultState) {          // если кнопка изменила исходное состояние -
      i = i + 1 ;                                           // наращивается счетчик текущего номера цикла
      }
    else {                                                  // если было несовпадение -
      break ;                                               // выходим из проверки
      }                                                     // значит переходной процесс не закончился         
    }                                                       // и незачем тратить время на следующие запросы

  if (i == numberOfCycles) {                                // если все подряд опросы == ДА - нам повезло
    pushState = !defaultState;                              // и кнопка хорошо нажата
    }           
  else {                                                    // если хоть раз НЕТ - ждем следующего случая
    pushState = defaultState;                               // и кнопка не нажата
    }                       
  return pushState ;                                        // возвращаем результат опроса состояния кнопки 
  }

/* Один из результатов прогона 09.02.2016
 
Число     Длительность
опросов   всех опросов
  шт.       мсек
  2         0
  4         0 
  8         0
  16        0
  32        0
  64        0
  128       0
  256       1
  512       2
  1024      5
  2048      11
  4096      19
  9192      39
  16384     78
  32768     154

 */

Моя функция опроса ladyButton(номер_пина, исходное_состояние_контакта, число_чтений) получает три параметра и возвращает значение LOW/HIGH.

Как-то так.

По моей оценке на 255 запросов уходит около 1 мсек, а на 1024 запроса – 5 мсек. Лично я считаю, что информация из 1024 ответов надежнее, чем всего два ответа с интервалом 5 мсек.

Казалось бы, на этом можно закончить.

Но нахрена этот чел, подумаете вы, парил нам мозги своей суперпуперкнопкой, когда эта тема уже давно обсосана. И будете правы.

Но в действительности, все не так, как на самом деле L

Разных кнопок в мире гораздо больше, чем могут охватить наши форумы.

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

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

Другой живой пример. Контакты реле протока перестанут дергаться и будут надежно замкнуты, когда при заполнении трубы все пузырьки и водяные снаряды – есть такой инженерный термин снарядное течение - уже пронеслись и сплошной поток идет полным сечением трубы.

И пока такие реальные переходные процессы не успокоятся, моя система может ничего не делать и тупо ждать несколько секунд или даже десятков секунд до окончательного срабатывания датчика уровня и/или реле протока.

Вот для чего могут понадобиться другие алгоритмы сглаживания/фильтрации/демпфирования сигналов состояния кнопок.

Удачи всем!

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

И к чему это все было?
1. Опрашивать кнопку фиксированное количество раз - бесперспективная идея - дребезг имеет определенную постоянную времени, следовательно, опрашивать кнопку нужно в течение определенного интервала времени, а не по количеству раз.
2. По поводу работы кнопки даже на этом форуме было написано не мало. Автору нее мешало бы ознакомиться с тем, что уже опубликовано. Вероятно, после этого и желание писать данное сообщение не появилось бы, т.к. ничего нового в нем нет. Рекомендую почитать как закрепленные вверху темы, так и некоторые "не удостоенные", например о публикации "Сага о кнопке".
3. Да и как оформлять код - тоже не мешало бы почитать. Или "автор - не читатель, автор - писатель"?

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

andriano пишет:
И к чему это все было? 1. Опрашивать кнопку фиксированное количество раз - бесперспективная идея - дребезг имеет определенную постоянную времени, следовательно, опрашивать кнопку нужно в течение определенного интервала времени, а не по количеству раз. 2. По поводу работы кнопки даже на этом форуме было написано не мало. Автору нее мешало бы ознакомиться с тем, что уже опубликовано. Вероятно, после этого и желание писать данное сообщение не появилось бы, т.к. ничего нового в нем нет. Рекомендую почитать как закрепленные вверху темы, так и некоторые "не удостоенные", например о публикации "Сага о кнопке". 3. Да и как оформлять код - тоже не мешало бы почитать. Или "автор - не читатель, автор - писатель"?

Огорчил меня Andriano своим сообщением. Слов и критики много, но реально в тему только один: "прятать" код скетча в сообщении. Каюсь, грешен, но это я уже научился делать.

А вот то, что "...по поводу работы кнопки даже на этом форуме было написано не мало..." как раз доказывает то,  у проблемы дребезга НЕТ РЕШЕНИЯ, которое бы удовлетворяло большую часть форумчан!
Потому и каждый спец стремится в меру своей начитанности придумать что-нибудь этакое заковыристое, типа чугунных или латунных кнопок, которые ЯКОБЫ лучше иных прочих (естественно, имеется ввиду не сами кнопки, а алгоритмы обработки).
Даже САГИ кнопкам посвящают!

На самом деле, проверить алгоритмы достаточно просто :)
Идея проверки заключается в том, что на вход цифрового пина вместо кнопки подается достаточно длинный искусственно сгенерированный (или записанный в реальных условиях) сигнал с дребезгом, сетевыми наводками, импульсными помехами от реле и коллекторных двигателей и пр. А задача алгоритма - выловить в этом шуме РЕАЛЬНЫЕ нажатия кнопки.
Такой тестовый сигнал можно воспроизводить либо звуковой картой (тут есть проблема с постоянной составляющей), либо тем же дискретным выходом самой платы. Это если хватит ее быстродействия.
Это будет корректное решение поставленной задачи.
И если мой алгоритм (а на самом деле далеко не мой) не справится с такой задачей-тогда мне придется посыпать голову пеплом и рвать волосы. Догадайтесь с трех раз где.

Как то так...

at0mix
at0mix аватар
Offline
Зарегистрирован: 23.11.2015
Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Олег М. пишет:

По моей оценке на 255 запросов уходит около 1 мсек, а на 1024 запроса – 5 мсек. Лично я считаю, что информация из 1024 ответов надежнее, чем всего два ответа с интервалом 5 мсек.

ты так и не ответил на мой вопрос #180

Клапауций 322 пишет:

Олег М. пишет:

Моя кнопка должна 255 раз подряд услышать "Да", и тогда будет считать себя нажатой.

т.е. если нажатием является событие актуальное в течении 1 цикла программы, то твой код превратится в кирпич - ничего не будет происходить.

ты подумал, что кнопкой может рулить не только человек, но и что-то ещё?

ты так и не понял, что не нужно сравнивать все 255 опросов кнопки, если известно, что дребезг длится не более 1 мсек

ты так и не понял, что 255 опросов кнопки не всегда длятся 1 мсек - достаточно функции длиться более 1 мсек и твой код превратится в кирпич. проверь свою балалайку на частотах менее 16 мегагерц

*в очередной раз мне непонятно, зачем ты пытаешься время заменить производным от времени - количеством циклов.

at0mix
at0mix аватар
Offline
Зарегистрирован: 23.11.2015

Клапауций 322 пишет:

*в очередной раз мне непонятно, зачем ты пытаешься время заменить производным от времени - количеством циклов.

Успокойся - детки шалят %( Может когда-нибудь чему-нибудь выучатся......

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

at0mix пишет:

Успокойся - детки шалят %( Может когда-нибудь чему-нибудь выучатся......

чел отметился с неким дедовским методом совпадений в класс титановый велосипед для тактовой кнопки. - оказалось, считает циклы вместо времени.

здесь, это уже не дедовский способ, а баба с печи ёбнулась - снова считаем циклы и приводим тестовые скетчи с делаями.

*думаю, это бабушка Путина с яйцами.

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

Странные вы  люди, мои уважаемые критики. Не признаете или не знаете очевидных и простых вещей :(((

Я по своей дремучести считаю, что кнопка нажата – это когда переходные процессы (дребезг) закончились, и кнопка на протяжении достаточно длительного времени (5 мсек) сохраняет нажатое состояние (true).
Чтобы в этом удостовериться, я на протяжении 5 мсек выполняю примерно 1000 запросов и получаю 1000 подтверждений.
Вы же делаете один запрос и получаете true.  Потом через 5 мсек (с delay()) или без) делаете еще один запрос, и после получения еще одного true считаете кнопку нажатой.
А то, что кнопка могла поменять состояние внутри этого интервала, вы игнорируете.
Сомневаюсь, что кому-то нужно доказывать, что 1000 измерений случайной величины статистически гораздо достовернее всего двух измерений.

Еще одно замечание.
Надеюсь, Вы заметили, что второй параметр вызова функции ladyButton(Pin, defaultState, numberOfCycles) фактически является описанием конкретного исполнения кнопки: нормально замкнутой или нормально разомкнутой. Плюс, конечно, стягивающие или подтягивающие резисторы.
Это свойство кнопки закладывается в проекте системы и переносится в декларативную часть кода.

А вы вынуждены вводить переменную, в которой запоминается какое-то  предыдущее состояние кнопки и сравниваете его с текущим.
Мне же важно только исходное (проектное) состояние кнопки, от которого я отталкиваюсь при определении ее фактического состояния.

Как то так…

PS. Когда нечего возразить, начинается словесный понос и переход на личность.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Олег М. пишет:

Вы же делаете один запрос и получаете true.  Потом через 5 мсек (с delay()) или без) делаете еще один запрос, и после получения еще одного true считаете кнопку нажатой.

неверно: кнопка считается нажатой, если после первого запроса получено TRUE. кнопка считается отжатой, если с момента отжатия прошло время предполагаемого процесса дребезга и за это время логическое состояние кнопки изменилось на FALSE один раз, иначе... смотри ниже.

Олег М. пишет:

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

неправда, если кнопка поменяла своё состояние внутри ожидания интервала, то отсчёт времени ожидания окончания дребезга сдвигается.

*в этом то и суть - от тебя народ и я пытаются добиться, зачем ты время меряешь циклами, если время тебе доступно и так? нафига эти танцы с цыклами, если ты уже прямым текстом пишешь, что работаешь со временем?

Олег М. пишет:

Еще одно замечание.
Надеюсь, Вы заметили, что второй параметр вызова функции ladyButton(Pin, defaultState, numberOfCycles) фактически является описанием конкретного исполнения кнопки: нормально замкнутой или нормально разомкнутой. Плюс, конечно, стягивающие или подтягивающие резисторы.
Это свойство кнопки закладывается в проекте системы и переносится в декларативную часть кода.

это уже не принципиальные плюшки.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

во избежание дребезга, я использую эфект залипания, на 10мс

std
Offline
Зарегистрирован: 05.01.2012

Зачем что-то считать (тем более такое медленное по меркам процессора как кнопки), если можно поставить RC цепочку и 7414?

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Valera19701 пишет:

во избежание дребезга, я использую эфект залипания, на 10мс

откуда дребезг знает, что ты используешь эффект залипания?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

а дребезг и не должен знать :)

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

std пишет:

Зачем что-то считать (тем более такое медленное по меркам процессора как кнопки), если можно поставить RC цепочку и 7414?

точно! а, есчё можно заюзать ртутный переключатель, что б уж наверняка.

Гриша
Offline
Зарегистрирован: 27.04.2014

присоединюсь таки...

Хотел в посте 4 написать (когда было всего 3 поста): поставить на голосование методы подавления дребезга :), может еще не поздно?   И чем не угоден пост 3 (там ссылки)???????  Вроде наглядно и просто, все в них описано, есть и там обсуждения…  А главное, что мне не очень понятно, зачем напрягать процессор килооперациями  с просто но,  несомненно,  важной кнопкой? Представьте ПК, который молится на нажатие кнопки на клавиатуре 1024 раза (ну, для ровного счета) проверяет, потом еще проверяет – не дай бог нажатие двойное, а вдруг залипание или кнопку специально держат, а кнопок 102 шт :) ))))))

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Гриша пишет:

кнопок 102 шт :) ))))))

и все нажаты одновременно.

Гриша
Offline
Зарегистрирован: 27.04.2014

Клапауций 322 пишет:

Гриша пишет:

кнопок 102 шт :) ))))))

и все нажаты одновременно.

угу... сынок сегодня пролил воду на клавиатуру, а она уже вторая после первого потопа...