класс титановый велосипед для тактовой кнопки.

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

Angbor пишет:

удивляет не количество пальцев на ногах, а количество Клапауци-ев на форуме :)

един в тысяче ликов.

или, всегда не больше одного.

Гриша
Онлайн
Зарегистрирован: 27.04.2014

офф. топ

Angbor пишет:

 но так и не знаю, как подписаться на этом фоуме на тему, не оставив сообщение

я так и пишу: - "подписался" :) ... я другое не нашел, как искать (поиском) среди тем за которыми следишь...

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

Гриша пишет:

я так и пишу: - "подписался" :) ... я другое не нашел, как искать (поиском) среди тем за которыми следишь...

ну, подписались, и чего?
класс в глухом финальном тупике.
новых идей, какие ещё события можно вытащить из алгоритма юзания кнопки, нет.
Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

лучше не подписывайтся, потом отписаться невозможно.

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

Tomasina пишет:

лучше не подписывайтся, потом отписаться невозможно.

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

Гриша
Онлайн
Зарегистрирован: 27.04.2014

ОФФ.ТОП.

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

Tomasina пишет:

лучше не подписывайтся, потом отписаться невозможно.

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

1) эта тема закреплена и ее не потеряешь, подписываться нет смысла
2) просто убираешь галочку ниже окна "ответить" - (Уведомлять меня о новых комментариях) и писем не будет
3) слежу через профиль вкладка следить, там же они хранятся. Искать проще – только для этого и подписываюсь.
ЗЫ ну как-то так…
 

Angbor
Angbor аватар
Offline
Зарегистрирован: 26.10.2015

Клапауций 322 пишет:
ну, подписались, и чего?

класс в глухом финальном тупике.
новых идей, какие ещё события можно вытащить из алгоритма юзания кнопки, нет.
депрессия? искусство ради искусства?
Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Angbor пишет:

депрессия? искусство ради искусства?

я не гуманитарий и в таком контексте технические вопросы вообще не рассматриваю.

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

адептам титанового велосипеда, следующая модель

класс титановый велосипед для delay без delay().

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

Всем привет.
Вроде, просмотрел все ветки, но если моя тема баян-прошу не пинать ногами.
Я попробовал давить дребезг кнопок без несчастной delay() дедовским методом совпадений.
Для начала от балды задается некоторое количество (N) опросов кнопки, и если последовательно все N опросов дают один результат-кнопка считается нажатой. Если хоть один раз обнаружено несовпадение-опрос начинается сначала.

/*
 DigitalReadSerial
 Reads a digital input on pin 2, prints the result to the serial monitor
 This example code is in the public domain.
 */

// digital pin 2 has a pushbutton attached to it. Give it a name:

// Подавление дребезга кнопки методом совпадений.
// Состояние кнопки многоратно "N" раз считывается digitalRead()
// Если последующее чтение не совпадает с предыдущим - цикл обнуляется
// и повторяется с самого начала
// На печать выведено количество циклов полседовательного чтения
// и суммарное время всех циклов в мсек
// 

#define RESET_ALL 12                                        // пин кнопки "СБРОС"
const boolean reset_all_State = false ;                     // исходное состояние нормально разомкнутой кнопки
                                                            // RESET_ALL с подтягиванием к земле
int numberOfCycles = 32767 ;                                // максимальное число циклов чтения состояния кнопки digitalRead()
unsigned long startTime ;                                   // начальное время цикла измерений [msec]
unsigned int duration = 0 ;                                 // длительность цикла измерений [msec]


// 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:
  Serial.println("Duration\tThe number") ;
  Serial.println("msec    \tof cycles") ;
}
            
void loop() {                                               // the loop routine runs over and over again Forever!
  for ( int i = 2; i <= numberOfCycles; i = i*2 ) {
    if (reset_all_State == !readOneDelay(RESET_ALL, i-1)) { // PUSH ON
      Serial.print(duration) ;                              // print out the duration of cycles
      Serial.print("\t\t") ;
      Serial.println(i-1) ;                                 // print out out the number of cycles  
    } 
  }
}


// Function digitalread one delay
 
boolean readOneDelay(int nomberPin, int numberOfCycles) {
  int numberOfMatches =0 ; 
  boolean newState = digitalRead(nomberPin) ;
  startTime = millis() ;                                    // глобальная переменная
  while (numberOfMatches < numberOfCycles) {
    if (newState == digitalRead(nomberPin))
      {
      numberOfMatches = numberOfMatches + 1 ;
      newState = true ;
    }
    else {
      numberOfMatches = 0 ;
      newState = !true ;
    }   
  } ;
  duration = millis() - startTime ;                         // глобальная переменная
  return newState ;
}


/* Один из результатов прогона 09.02.2016
 *  
Duration  The number
msec      of cycles
0         1
0         3
0         7
0         15
0         31
0         63
0         127
1         255
2         511
5         1023
11        2047
19        4095
39        8191
78        16383
154       32767

 */

По предварительной оценке за 1 мсек пин опрашивается 200 раз, т.е. частота опроса 200 кГц.
Поэтому получается, что задавая, допустим, 200 раз без перерыва опросить датчик я потрачу всего 1 мсек времени.
Может, у меня кнопка хорошая  и провода пока короткие, но проблем я не нашел. Да и осциллографа тоже нет, чтобы посмотреть реальный сигнал на контактах.
Хотелось бы узнать мнение мудрейших относительно такого способа подавления дребезга да и заодно получить не злую критику.

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

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

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

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

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

свой велосипед всегда лучше.
Чем лучше? Чем остальные ;)

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

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

Я попробовал давить дребезг кнопок без несчастной delay() дедовским методом совпадений.

Тема дребезга давно обсосана и закрыта. Нахрена велосипед изобретать?

Вот, читайте - http://www.eng.utah.edu/~cs5780/debouncing.pdf

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

Tomasina пишет:

свой велосипед всегда лучше.
Чем лучше? Чем остальные ;)

где я такое утверждал?

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

это я утверждаю.
Согласны? Флаг в руки и на передовую. Несогласны? А мне пофиг. :)

vvadim
Offline
Зарегистрирован: 23.05.2012

Клапауций, зачем так нервничать и всё принимать близко к сердцу))))

тебе за твою работу спасибо и поклон.

только форум не засирай матюками и грёбанной политикой...

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

Во первых, уважаемый Евгений П. я сразу сказал, что использую старинный дедовский метод совпадений, а не изобретаю лисапет.
Во вторых, я применил только стандартные ардуиновские языковые конструкции без недокументированных возможностей ардуины, внутренних таймеров, механизмов ООП и наследования и т.п.
В третьих, я испытываю внутреннее сопротивление при использовании непонятных мне и недокументированных программных инструкций.
В четвертых, предварительная проверка показала достаточную устойчивость предложенного решения и его быстродействие. Проверка в поле на длинных линиях будет проведена позже.
В пятых, зачем вы изобрели свою кнопку, если тема давно обоссана и закрыта? Я по вашей ссылке навскидку не нашел моего примера, а мне ведь тоже хочется изобретать :)
В шестых, как-то в прошлой жизни одна интересная фирма привезла интересный маленький прибор с большими механическими кнопками. На мой вопрос почему они не применяют модные нынче сенсорные кнопки, был получен достойный ответ. Этот прибор по заданию военных заказчиков должен управляться в том числе и в зимних условиях в толстых перчатках, поэтому необходимы большие кнопки с четкой фиксацией. И там категорически непремлемы двойные, тройные клики и прочие экзерсисы.
В седьмых, нет предела совершенству.
К сожалению, у меня не хватает знаний и оборудования, чтобы сравнить быстродействие, расход памяти прочие параметры с другими вариантами подавления дребезга.

Так что внимательно жду вашу конструктивную критику по существу. Но не холивар.
Как-то так.
Всем удачи.
 

vvadim
Offline
Зарегистрирован: 23.05.2012

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

Во первых, уважаемый Евгений П. я сразу сказал, что использую старинный дедовский метод совпадений, а не изобретаю лисапет.
Во вторых, я применил только стандартные ардуиновские языковые конструкции без недокументированных возможностей ардуины, внутренних таймеров, механизмов ООП и наследования и т.п.
В третьих, я испытываю внутреннее сопротивление при использовании непонятных мне и недокументированных программных инструкций.
В четвертых, предварительная проверка показала достаточную устойчивость предложенного решения и его быстродействие. Проверка в поле на длинных линиях будет проведена позже.
В пятых, зачем вы изобрели свою кнопку, если тема давно обоссана и закрыта? Я по вашей ссылке навскидку не нашел моего примера, а мне ведь тоже хочется изобретать :)
В шестых, как-то в прошлой жизни одна интересная фирма привезла интересный маленький прибор с большими механическими кнопками. На мой вопрос почему они не применяют модные нынче сенсорные кнопки, был получен достойный ответ. Этот прибор по заданию военных заказчиков должен управляться в том числе и в зимних условиях в толстых перчатках, поэтому необходимы большие кнопки с четкой фиксацией. И там категорически непремлемы двойные, тройные клики и прочие экзерсисы.
В седьмых, нет предела совершенству.
К сожалению, у меня не хватает знаний и оборудования, чтобы сравнить быстродействие, расход памяти прочие параметры с другими вариантами подавления дребезга.

Так что внимательно жду вашу конструктивную критику по существу. Но не холивар.
Как-то так.
Всем удачи.
 

 

не засерай чужую тему

открой свою

skif
Offline
Зарегистрирован: 24.03.2015

Как я вас всех люблю!

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

skif пишет:

Как я вас всех люблю!

Нетрадиционный? Чур меня! Сгинь! :)

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

vvadim пишет:

не засерай чужую тему

открой свою

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

разберём по винтикам его метод и саму ситуацию.

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

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

Во первых, уважаемый Евгений П. я сразу сказал, что использую старинный дедовский метод совпадений, а не изобретаю лисапет.
Во вторых, я применил только стандартные ардуиновские языковые конструкции без недокументированных возможностей ардуины, внутренних таймеров, механизмов ООП и наследования и т.п.
В третьих, я испытываю внутреннее сопротивление при использовании непонятных мне и недокументированных программных инструкций.
В четвертых, предварительная проверка показала достаточную устойчивость предложенного решения и его быстродействие. Проверка в поле на длинных линиях будет проведена позже.
В пятых, зачем вы изобрели свою кнопку, если тема давно обоссана и закрыта? Я по вашей ссылке навскидку не нашел моего примера, а мне ведь тоже хочется изобретать :)
В шестых, как-то в прошлой жизни одна интересная фирма привезла интересный маленький прибор с большими механическими кнопками. На мой вопрос почему они не применяют модные нынче сенсорные кнопки, был получен достойный ответ. Этот прибор по заданию военных заказчиков должен управляться в том числе и в зимних условиях в толстых перчатках, поэтому необходимы большие кнопки с четкой фиксацией. И там категорически непремлемы двойные, тройные клики и прочие экзерсисы.
В седьмых, нет предела совершенству.
К сожалению, у меня не хватает знаний и оборудования, чтобы сравнить быстродействие, расход памяти прочие параметры с другими вариантами подавления дребезга.

Так что внимательно жду вашу конструктивную критику по существу. Но не холивар.
Как-то так.
Всем удачи.

Уважаемый Олег М:

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

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

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

4. автор класс титановый велосипед для тактовой кнопки спрашивал, но не получил ответ: "а нахуа?".

5. автор класс титановый велосипед для тактовой кнопки желает ознакомиться с кнопкой Евгений П.

6. класс титановый велосипед для тактовой кнопки позволяет использовать исключительно события нажатия кнопки.

7. см. пункт 4. с поправкой: чем метод совпадений лучше метода, используемого в класс титановый велосипед для тактовой кнопки?

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

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

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

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

исходные данные:
тактовая кнопка классической конструкции(далее "кнопка") - нормально разомкнутые контакты.
процесс дребезга кнопки начинается при нажатии кнопки и длится, обусловленное конструкцией кнопки, время.
процесс дребезга при отпускании кнопки физически невозможен.
 
решение:
программная фиксация события нажатия кнопки в течении времени дребезга.
 
*всё.
Олег М.
Олег М. аватар
Offline
Зарегистрирован: 22.11.2015

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

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

Спасибо уважаемому Клапауцию 322 за ответ, к которому у меня есть только один встречный вопрос по поводу сообщения «...класс титановый велосипед для тактовой кнопки использует только стандартные ардуиновские языковые конструкции без недокументированных возможностей ардуины, внутренних таймеров, механизмов ООП и наследования и т.п.".
В самом первом сообщении темы #1 в скетче записано:
 

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// класс титановый велосипед для тактовой кнопки.
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.

class BUTTON {
public:

В сообщении #2 присутствует фраза "...каждый объявленный объект класса..."

В "Справочнике языка Ардуино" я не нашел определения "класс", ни "объект класса" .
Подскажите, пожалуйста, где про ЭТО описано в"Справочнике..." . Я только недавно познакомился с языком Ардуино, и всех его конструкций и тонкостей не знаю :(

К сожалению, уважаемый Клапауций 322, который просит "...опишите читателям темы алгоритм метода совпадений...", скорее всего не смотрел мой скетч (но осуждает :) ), потому что в кетче в комментах в строках 09-13 это описано.
Поэтому повторю алгоритм.
В отличие от скетча #1 уважаемого Клапауция 999

//================================================================
static const byte bounce_              =   50; // длительность отслеживания дребезга.
static const byte doubleclick_         =  200; // длительность отслеживания двойного клика.
static const unsigned long timer_      = 5000; // длительность отслеживания неактивности.
static const unsigned int retention_   = 2000; // длительность отслеживания нажатия и удержания.
//================================================================

я заранее не знаю для конкретного экземпляра кнопки конкретного типа кнопок, сколько времени (50 мсек или больше, или меньше) длится переходной процесс  (дребезг) "...обусловленный конструкцией кнопки...". Поэтому запускаю серию N измерений состояния кнопки.
Если вновь измеренное состояние совпадает с предыдущим - плюс в карму. И продолжаю до тех пор, пока не получу подряд N совпадений. Если хотя бы один раз в цикле будет несовпадение - начинаю серию с начала. Вот и весь алгоритм.
Таким образом, за 50 мсек я могу получить примерно 10 000 совпадений. Пока я себе поставил по умолчанию 255 совпадений за время около 1 мсек. Проблем пока не нашел.

Может, правильнее назвать это не «старинным дедовским методом совпадений», а банальной цифровой фильтрацией, но это уж дело вкуса.
Удачи всем!

PS. Жаль, что никаких конкретных и конструктивных замечаний по скетчу так и не поступило. И пусть будет больше кнопок хороших и разных!

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

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

В "Справочнике языка Ардуино" я не нашел определения "класс", ни "объект класса" .
Подскажите, пожалуйста, где про ЭТО описано в"Справочнике..." .

там же и написано первой же строкой:

Язык программирования устройств Ардуино основан на C/C++.

далее написано Создание библиотек для Arduino

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

скорее всего не смотрел мой скетч (но осуждает :) )

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

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

Может, правильнее назвать это не «старинным дедовским методом совпадений», а банальной цифровой фильтрацией

пожалуйста, всё тоже самое, но кратче  - иначе, я возможно неправильно понимаю сути вашего алгоритма:

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

ок. но:

1. это же равно моему предположению, что дребезг никак не может быть длиннее, допустим 50 миллисекунд или, как в вашем случае 1-й.

можно установить в классе static const byte bounce_              =   1; // длительность отслеживания дребезга.

и чем это будет отличаться от вашей дидовской фильтрации?

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

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

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

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Клапауций 322, по просьбе публикую скриншоты дребезга на обычной тактовой кнопке.  Дребезг бывает не каждый раз, на новой кнопке в среднем 1 нажатие из 10, на старой больше, -уже каждое второе. Вот примеры дребезга без конденсатора, по клику должно увеличиваться:

 

С конденсатором практически все осцилограммы идеальны, один раз из 100 выпал вот такой:

Все остальные 99 раз были почти идеальны :)

PS это всё фронты отпускания кнопки, а фронт нажатия  (1 -> 0)  почти всегда хороший, даже нечего толком показать. Вот самый плохой фронт что получилось сделать (без конденсатора).

 

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

Привет всем!
И юным нубам, и старым чайникам (к которым я себя отношу), и продвинутым знатокам С/С++.
И даже "Клапауцию 322", который вместо "шото про дидов..." хотел написать "щось про дідів" ;)

На пальцАх разница между моей кнопкой и кнопкой от титанового лисапета в самом простейшем случае следующая.

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

Остальная требуха типа выставления "флага" в длинном лупе и прочие способы фиксации срабатывания кнопки-это уже кто как хочет.
Еще преимущество моей кнопки без delay() в том, что она реализована только конструкциями языка Arduino, который является подмножеством C/C++, но знание последнего уже слишком напрЯжно для новичков. Тем более напряжны призывы изучить раздел "Создание библиотеки для Arduino". Тут бы в простых конструкциях разобраться.

Отдельное спсибо dimax за хорошие осциллограммы и терпение при "ловле" передних и задних фронтов.
Последние две картинки хорошо показывают "работу" аналоговой фильтрации обычным конденсатором.
А все наши алгоритмы обработки digitalRead() уже являются цифровыми фильтрами. Простыми и не очень.
Как то так.
Возможно, я не совсем не прав.

Удачи всем!

PS. Мне не нужен алгоритм фиксации факта окончания дребезга!
Если моя кнопка не может 255 раз подряд внятно сказать "Да" и тем самым зафиксировать срабатывание - значит её нужно лечить.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Олег М., так по рисункам выходит что не нужно убеждаться в том, что кнопка нажата. Если пришёл "звоночек" что кнопку нажали -значит её точно нажали, и можно обрабатывать это действие. А вот когда пришёл звонок что кнопку отпустили -значит её отпустили, и тоже обрабатывать это действие, но при этом поставить флажок и больше не реагировать на изменения сигнала порядка 500uS . Это конечно всё голые рассуждения, сам я обычно либо ставлю конденсатор  на простую кнопку, либо использую переключающую кнопку и бездребезговую схему на RS-триггере.

Гриша
Онлайн
Зарегистрирован: 27.04.2014

ИМХО. рассуждения о кнопке

ПЕРВОЕ. Беречь ресурс процессора считаю необходимым и опрашивать кнопку более 10 раз - расточительство. Нам известно примерное время переходного процесса и нечего проверять в этот момент.

ВТОРОЕ. О "плохих" кнопках уже сказано и ориентироваться, что нам "досталась" такая кнопка решая вопрос в коде - не оптимально.

О КОДАХ. Код уважаемого Клапауций 322  я просто поместил где-то (типа как библиотеку) объявил кнопки и работаю с ними т.е. КОД - готов к употреблению. А вот код уважаемого Олег М. еще нужно причесывать.

О АРДУИНО. Мне, как ползателю :), не имеет значение в какой среде написан код (хоть в ASM), если все необходимые значения (параметры, переменные) доступны (можно изменить и  они понятны). Перед использованием какой-либо библиотеки с устройством, всегда запускаешь тестовый скетч и, либо пишешь сам, либо ищешь подходящий. Очень редко встречаются энтузиасты, исправляющие чужие косяки.

ЛИЧНО. Автору топика Клапауций 322 - не будьте так строги к новичкам, никакого бульдозера лично я не увидел.  Олег М.  мое личное мнение, не уместно было размещать код на обсуждение, в теме готового велосипеда. Нужно было создать свой топик, а в этой теме принимается критика велосипеда.

З.Ы. ну не мог пройти мимо, хот и понимаю, что половина оффтопа. 

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

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

от титанового лисапета

смешно - два раза ХА.

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

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

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

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

Олег М. пишет:
Еще преимущество моей кнопки без delay() в том, что она реализована только конструкциями языка Arduino, который является подмножеством C/C++

те же яйца - вид сбоку:

класститановый велосипед для тактовой кнопки

Олег М. пишет:
Мне не нужен алгоритм фиксации факта окончания дребезга!

Если моя кнопка не может 255 раз подряд внятно сказать "Да" и тем самым зафиксировать срабатывание - значит её нужно лечить.

так и я могу сказать, что если кнопка дребезжит при static const byte bounce_ = 50; то её нужно лечить.

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

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

здесь #125 ступил

#include "class_BUTTON.h"

так работает и в arduino-1.0.6

хм. теперь не работает в arduino-1.0.6 никак.

...как же раньше работало.

skif
Offline
Зарегистрирован: 24.03.2015

ЕвгенийП пишет:

skif пишет:

Как я вас всех люблю!

Нетрадиционный? Чур меня! Сгинь! :)

бедненький.. У тебя кроме секса никаких мыслей? Я тебя боюсь

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

skif пишет:

У тебя кроме секса никаких мыслей?

Как это никаких? Пиво!!! Клеветать изволите!

skalinas
Offline
Зарегистрирован: 13.01.2016

Добрый день.

Реализовал антидребезг  для шилда (LCD+ кнопки) так. Постоянно происходит опрос  аналогового входа кнопок в теле программы и происходит сравнение между двумя замерами (интервал между замерами можно выставить от  5 до 30 мс - это оптимальное время для антидребезга) уровня напряжения (от 0 до 1024 ед.) на аналоговом входе кнопок. Если уровни совпадают, то интерпретируется нажатие определенной кнопки, если нет, то происходит повторный замер и сравнение уровней (разницу между замеренными уровнями можно установить от 0 до 10 ед.). Если разницу установить в ноль, то ложных срабатываний не бывает.

Реализовал 3 режима нажатия кнопки;  

1. Однократное нажатие (длительностью менее 750 мс)

2. Удержание кнопки (более 750 мс.)

3. Длительное нажатие (более 5 с.), можно реализовать и другие режимы.

Если есть интерес, выложу готовый скетч с перебором цифр от кнопок на экране LCD для UNO.

Гриша
Онлайн
Зарегистрирован: 27.04.2014

skalinas пишет:

Если есть интерес, выложу готовый скетч с перебором цифр от кнопок на экране LCD для UNO.

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

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

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

в версии Дуино ИДЕ arduino-1.6.6 класс можно подключить как библиотеку:

#include <class_BUTTON.h>
- копируем код #1 в файл class_BUTTON.h
- копируем файл class_BUTTON.h в папку class_BUTTON.
- папку class_BUTTON размещаем в *\Мои документы\Arduino\libraries\

*работает только в версии arduino-1.6.7

что бы работало в версиях младше вплоть до Arduino 1.0, нужно в код #1 добавить первой строкой

#include <Arduino.h>

**проверяем.

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

подписчикам титанового велосипеда:

класс титановый велосипед StopWatch.

класс считает количество миллисекунд между двумя последними событиями.
mrtester
Offline
Зарегистрирован: 26.02.2015

Здравствуйте

Почитал все титановые ветки, попробовал работает, но не понял как релизовать такой алгоритм

При нажатие 1 кнопки (на А0 ноль), на выходе 2 и 4 ноль, на выходе 5 ноль после 1 сек. единица и т. д. (моргает)

При повторном нажатие через 5 сек. кнопку 1 (на А0 ноль) на выходе 2, 3, 5, 6 единица и после 100 сек. на выходе 4 единица

При нажатии кнопки 2 (на А1 ноль) на выходе 3 и 4 ноль на выходе 6 ноль после 1 сел. единица и т. д. (моргает)

При повторном нажатии через 5 сек. кнопку 2 (на А1 ноль), на выходе 2, 3, 5, 6 единица и после 100 сек. на выходе 4 единица

Если на выходе 2 и 4 ноль и выход 5 моргает нажать кнопку 2 (на А1 ноль), то на выходе 6 ноль 1 сек. единица и т. д. (моргает),

на выходе 5 единица, на выходе 3 ноль, через 2 сек. на выходе 2 единица

Если на выходе 3 и 4 ноль и выход 6 моргает нажать кнопку 1 (на А0 ноль), то на выходе 5 ноль 1 сек. единица (моргает),

на выходе 6 единица, на выходе 2 ноль, через 2 сек. на выходе 3 единица

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

mrtester пишет:

Почитал все титановые ветки, попробовал работает, но не понял как релизовать такой алгоритм

ок. всё прочитал, но ничего не понял и не написал ни строчки своего кода - бывает. тебе сюда Ищу исполнителя

mrtester
Offline
Зарегистрирован: 26.02.2015

////////////////////////
BUTTON BUTTON_01(A0);
BUTTON BUTTON_02(A1);
////////////////////////

void setup() 
{


pinMode(2, OUTPUT);
digitalWrite(2, 1);
pinMode(3, OUTPUT);
digitalWrite(3, 1);
pinMode(4, OUTPUT);
digitalWrite(4, 1);
pinMode(5, OUTPUT);
digitalWrite(5, 1);
pinMode(6, OUTPUT);
digitalWrite(6, 1);

}

void loop() {

BUTTON_01.read();
BUTTON_02.read();


if (BUTTON_01.click_down) 
  {
  digitalWrite(3, 0);
  digitalWrite(4, 0);
  digitalWrite(2, 1);
  } // светодиод включается при нажатии кнопки.
  //моргает 5
  
 if (BUTTON_02.click_down) 

  {
  digitalWrite(3, 1);
  digitalWrite(4, 0);
  digitalWrite(2, 0);
   } // светодиод включается при нажатии кнопки.
   // моргает 6
    //дальше задумался

if (BUTTON_01.timer) 
{
  digitalWrite(4, 1);
  digitalWrite(3, 1);
  digitalWrite(2, 1);
} // светодиод выключается через timer_ = 10000 (10 сек.) неактивности кнопки.
//if (BUTTON_01.click_up)
//{
//digitalWrite(3, 1);
//digitalWrite(4, 1);
//} // светодиод выключается при нажатии кнопки.
//if (BUTTON_01.retention) {digitalWrite(2, 0);} // светодиод выключается при удержании кнопки через retention_ = 1000 (1 сек.)


}

 

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

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

удачи.

Гриша
Онлайн
Зарегистрирован: 27.04.2014

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

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

удачи.

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

Гриша
Онлайн
Зарегистрирован: 27.04.2014

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

Гриша пишет:

потом добавляй ноги.

затем - руки и голову. потому, как:

mrtester пишет:
При повторном нажатие через 5 сек. кнопку 1

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

предполагалось, что они уже подключены к процессу :), а ноги от МК...

по второму вопросу: это просто 2 условия - если было нажато и уже  прошло указанное время. А то будет, как немногим раньше - когда МК, по замыслу автора, должен был угадывать, чего хочет пользователь (один раз нажать или дважды до факта нажатия).

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

Гриша пишет:

по второму вопросу: это просто 2 условия - если было нажато и уже  прошло указанное время.

склоняюсь к версии, что это "ещё не прошло указанное время" - просто длинный даблклик для людей с ограниченными возможностями.
 
*или заказчика нужно послать разминировать взрывное устройство по написанному им алгоритму, что бы он проклял самого себя за глупость перед смертью.
*или заказчику нужно нанять переводчика с русского гуманитарного на русский человеческий.
DIYMan
DIYMan аватар
Онлайн
Зарегистрирован: 23.11.2015

С позволения автора - дописал под свои нужды указанный класс: взял за основу приведённый код, сделал так, чтобы можно было юзать кнопку на аналоговом пине, плюс добавил поддержку событий. Особо не вылизывал, так что местами не очень.

Файл PushButton.h:

#ifndef _PUSHBUTTON_H
#define _PUSHBUTTON_H
//--------------------------------------------------------------------------------------------------
#include <Arduino.h>
//--------------------------------------------------------------------------------------------------
#define TWO_VOLTS_BORDER 410 // down interval for mapping the analog value (0-1023) to the HIGH constant
#define BOUNCE_INTERVAL  70 // длительность отслеживания дребезга.
#define DOUBLECLICK_INTERVAL 200 // длительность отслеживания двойного клика.
#define INACTIVITY_INTERVAL 5000 // длительность отслеживания неактивности.
#define RETENTION_INTERVAL 2000 // длительность отслеживания нажатия и удержания.
//--------------------------------------------------------------------------------------------------
class PushButton;
typedef void (*PushButtonEvent)(const PushButton& Sender, void* UserData);
//--------------------------------------------------------------------------------------------------
class PushButton
{
 public:
  
    PushButton(uint8_t _pin);

    // инициализируем, в параметрах можем передать указатель на любые пользовательские данные,
    // плюс указатели на функции-обработчики событий, если это необходимо
    void init(void* _userData = NULL
    , PushButtonEvent _onClick = NULL
    , PushButtonEvent _onPress = NULL
    , PushButtonEvent _onDoubleClick = NULL
    , PushButtonEvent _onInactive = NULL
    , PushButtonEvent _onRetention = NULL
    );    
    void update(); // обновляем внутреннее состояние
    
    bool isPressed() { return click_down; }
    bool isClicked() { return click_up; }
    bool isDoubleClicked() { return doubleclick; }
    bool isInactive() { return timer; }
    bool isRetention() { return retention; }


 private:

  void* userData;
  PushButtonEvent OnClick; // событие - кнопка нажата и отпущена
  PushButtonEvent OnPress; // событие - кнопка нажата
  PushButtonEvent OnDoubleClick; // событие - кнопка нажата дважды
  PushButtonEvent OnInactive; // событие - кнопка неактивна в течение настроенного интервала
  PushButtonEvent OnRetention; // событие - кнопка нажата и удерживается определённое время
  
  
  unsigned long lastMillis;
  uint8_t  lastButtonState;
  bool  lastBounce;
  bool lastDoubleClick;
  uint8_t     clickCounter;
  bool  lastTimer;
  bool  lastRetention;
  bool atLeastOneStateChangesFound;

  byte buttonPin; // пин, на котором висит кнопка

  bool click_down; // нажата?
  bool click_up; // нажата и отпущена?
  bool doubleclick; // два раза нажата и отпущена?
  bool timer; // неактивна в течение установленного интервала?
  bool retention; // нажата и удерживается в течение установленного интервала?


 protected:   
    
    virtual void do_init(uint8_t pin) = 0;
    virtual uint8_t readButtonState(uint8_t pin) = 0;
    
 };
//--------------------------------------------------------------------------------------------------
class DigitalPushButton : public PushButton
{
protected:
    virtual uint8_t readButtonState(uint8_t pin)
    {
      return digitalRead(pin);
    };
    virtual void do_init(uint8_t pin)
    {
      digitalWrite(pin,HIGH); // включаем подтягивающий к питанию резистор
    }

public:
  DigitalPushButton(uint8_t pin) : PushButton(pin) {}
};
//--------------------------------------------------------------------------------------------------
class AnalogPushButton : public PushButton
{
protected:

    virtual uint8_t readButtonState(uint8_t pin)
    {
      uint16_t val = analogRead(pin);
      if(val < TWO_VOLTS_BORDER) // less than 2 volts
        return LOW;
      else
        return HIGH;

    };
    
    virtual void do_init(uint8_t pin)
    {
    }

public:
  AnalogPushButton(uint8_t pin) : PushButton(pin) {}
};
//--------------------------------------------------------------------------------------------------
#endif

Файл PushButton.cpp:

#include "PushButton.h"
//--------------------------------------------------------------------------------------------------
PushButton::PushButton(uint8_t _pin)
{
  buttonPin = _pin;
  pinMode(buttonPin, INPUT);
  
  userData = NULL;
  OnClick = NULL;
  OnPress = NULL;
  OnDoubleClick = NULL;
  OnInactive = NULL;
  OnRetention = NULL;
  
  atLeastOneStateChangesFound = false;

  click_down      = false;
  click_up        = false;
  doubleclick     = false;
  timer           = false;
  retention       = false;

  clickCounter  =     0;
  
  lastBounce  =      false;
  lastDoubleClick =  false;
  lastTimer  =        false;
  lastRetention  =    false;
  
  lastMillis  =      millis();
}
//--------------------------------------------------------------------------------------------------
void PushButton::init(void* _userData  
    , PushButtonEvent _onClick
    , PushButtonEvent _onPress
    , PushButtonEvent _onDoubleClick
    , PushButtonEvent _onInactive
    , PushButtonEvent _onRetention)
{
  userData = _userData;
  OnClick = _onClick;
  OnPress = _onPress;
  OnDoubleClick = _onDoubleClick;
  OnInactive = _onInactive;
  OnRetention = _onRetention;
  
  do_init(buttonPin);   
  lastButtonState  = readButtonState(buttonPin);
}
//--------------------------------------------------------------------------------------------------
void PushButton::update()
{

  // обновляем внутреннее состояние
  bool curBounce  = false;
  bool curDoubleClick = false;
  bool curTimer  = false;
  bool curRetention  = false;

  // сбрасываем все флаги
  click_down  = false;
  click_up    = false;
  doubleclick = false;
  timer       = false;
  retention   = false;


  unsigned long curMillis = millis();
  unsigned long millisDelta = curMillis - lastMillis;
  uint8_t curButtonState = readButtonState(buttonPin); // читаем текущее состояние

 if (curButtonState != lastButtonState) // состояние изменилось
  {
    atLeastOneStateChangesFound = true; // было хотя бы одно изменение в состоянии (нужно для того, чтобы не было события "clicked", когда кнопку не нажимали ни разу)
    lastButtonState = curButtonState; // сохраняем его
    lastMillis = curMillis; // и время последнего обновления
  }

  if (millisDelta > BOUNCE_INTERVAL)  // надо проверить на дребезг
    curBounce = true;

  if (millisDelta > DOUBLECLICK_INTERVAL) // надо проверить на даблклик
    curDoubleClick = true;

  if (curDoubleClick != lastDoubleClick) // состояние даблклика с момента последней проверки изменилось
  {
    lastDoubleClick = curDoubleClick; // сохраняем текущее
    if (lastDoubleClick) // проверяем - если кнопка не нажата, то сбрасываем счётчик нажатий 
      clickCounter = 0;
  }

  if (curBounce != lastBounce) // состояние проверки дребезга изменилось
  {
    lastBounce = curBounce; // сохраняем текущее

    if (!lastButtonState && !curBounce) // если кнопка была нажата в момент последнего замера и сейчас - значит, дребезг прошёл и мы можем сохранять состояние
    {
      click_down = true; // выставляем флаг, что кнопка нажата

      if(OnPress)
        OnPress(*this,userData);
      
      ++clickCounter; // увеличиваем счётчик кликов
      
      if (clickCounter == 2) // если кликнули два раза
      {
        clickCounter = 0;  // сбрасываем счётчик кликов
        doubleclick = true; // и выставляем флаг двойного нажатия
        
        if(OnDoubleClick)
          OnDoubleClick(*this,userData);
      }
    }

    click_up = lastButtonState && lastBounce && atLeastOneStateChangesFound; // кнопка отпущена тогда, когда последний замер и текущий - равны 1 (пин подтянут к питанию!), и был хотя бы один клик на кнопке
    
    if(click_up && OnClick)
      OnClick(*this,userData);

  }

  if (millisDelta > INACTIVITY_INTERVAL) // пора проверять неактивность
    curTimer = true;
    
  if (curTimer != lastTimer) // состояние неактивности изменилось с момента последнего замера?
  {
    lastTimer = curTimer; // сохраняем текущее
    timer = lastButtonState && lastTimer && atLeastOneStateChangesFound; // кнопка неактивна тогда, когда не была нажата с момента последнего опроса этого состояния

    if(timer && OnInactive)
      OnInactive(*this,userData);
  }

  if (millisDelta > RETENTION_INTERVAL) // пора проверять удержание
    curRetention = true;

  if (curRetention != lastRetention) // если состояние изменилось
  {
    lastRetention = curRetention; // сохраняем его
    retention = !lastButtonState && lastRetention && atLeastOneStateChangesFound; // и считаем кнопку удерживаемой, когда она нажата сейчас и была нажата до этого
    
    if(retention && OnRetention)
      OnRetention(*this,userData); 
  }
  
}
//--------------------------------------------------------------------------------------------------

Использование:

#include "PushButton.h"

DigitalPushButton button(8); // кнопка на цифровом пине 8
AnalogPushButton button2(A1); // кнопка на аналоговом A1

// обработчик события клика на кнопке.
void OnButtonClick(const PushButton& Sender, void* UserData)
{
  Serial.print("Button clicked: ");
  Serial.println((int)UserData);
}

void setup()
{
 button.init((void*)100,OnButtonClick); // инициализируем, можно привязывать свои данные и обработчики событий

// можно тупо инициализировать
button2.init();
}

void loop()
{
button.update();
 if(button.isPressed())
  Serial.println("pressed");

 if(button.isClicked())
  Serial.println("clicked");
 
 if(button.isDoubleClicked())
  Serial.println("double clicked");

if(button.isInactive())
  Serial.println("inactive");

 if(button.isRetention())
  Serial.println("retention");
}

Ещё раз подчёркиваю - за основу взят код ТС, я лишь немного дописал под свои нужды, плюс избавился от пары досадных мелочей, вроде засчитывания клика и неактивности, когда с кнопкой не делали вообще ничего после старта скетча: в варианте автора у кнопки взводились флаги timer и click_up.

 

DIYMan
DIYMan аватар
Онлайн
Зарегистрирован: 23.11.2015

Вдогонку: расово верное подключение кнопки - указано в теме, т.е., как минимум - пин дуины подтянут к питанию резистором.

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

DIYMan пишет:

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

как-то мимо меня прошло - пролетало где-то что на некоторых ревизиях AVR аналоговые пины не получается заюзать как цифровые. так и есть? нельзя сделать на аналоговом пине digitalRead?

добавлено после внимайтельного рассмотрения кода:

// ура! кто-то написал велосипед для аналоговой кнопки.
#define TWO_VOLTS_BORDER 410 // down interval for mapping the analog value (0-1023) to the HIGH constant
analogRead(pin);

// блин! расходимся - нас наепали. :D
digitalRead(pin);

DIYMan пишет:

плюс избавился от пары досадных мелочей, вроде засчитывания клика и неактивности, когда с кнопкой не делали вообще ничего после старта скетча: в варианте автора у кнопки взводились флаги timer и click_up.

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

и, наоборот - если девайс включен с нажатой кнопкой...

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

 

karl2233
karl2233 аватар
Offline
Зарегистрирован: 05.07.2015

ооо! как полезно.

спасибо!

DIYMan
DIYMan аватар
Онлайн
Зарегистрирован: 23.11.2015

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

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

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

Насчёт аналоговых пинов: там виртуальная функция в базовом классе определена, и если создаётся экземпляр класса AnalogPushButton - он будет читать из пина вызовом analogRead, если создаётся DigitalPushButton - там старый добрый digitalRead, так что с поведением кнопки на аналоговом пине всё нормально, проверял - если напруга на ней выше двух вольт, то считается, что на выходе HIGH, иначе - LOW.

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

 

 

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

DIYMan пишет:

Насчёт аналоговых пинов: там виртуальная функция в базовом классе определена, и если создаётся экземпляр класса AnalogPushButton - он будет читать из пина вызовом analogRead, если создаётся DigitalPushButton - там старый добрый digitalRead, так что с поведением кнопки на аналоговом пине всё нормально, проверял - если напруга на ней выше двух вольт, то считается, что на выходе HIGH, иначе - LOW.

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