• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Делюсь опытом Много кнопок - один pin

nikolz

Well-known member
Наиболее часто устройства IoT принимают сигналы от внешних замыкающихся контактов, такие как кнопки,герконы или сенсоры с выходом "сухой контакт"

В данной заметке я расскажу как подключить несколько таких контактов к одному пину и обеспечить распознавание какая кнопка нажата.
-------------------------------
Данный алгоритм может быть применен на любом микроконтроллере.
Более того , можно RC цепочки не включать последовательно, а для каждой кнопки поставить свою цепочку.
последовательное включение позволяет использовать одинаковые цепочки и получить разное время для различных кнопок.
----------------------------------
Пример дан применительно к ESP8266.
Предполагается, что используемые пины имеют подтяжку к 5в. В nodemcu она уже есть,
а в ESP-12 надо припаять подтяжку к 5 в 10 ком для пина 4 и 5.
==========================
Идея .
Надо сделать так, чтобы при нажатии кнопки на пин поступал импульс определенной длительностью, различный для каждой кнопки.

Простейший вариант реализации такой схемы следующий.

Делаем RC цепочки. Т е R=20 ком соединяем параллельно с конденсатором 2.2 мкф.

Такие номиналы использованы в приведенной далее тестовой прошивке.

RC цепочки (в моем варианте их две) соединяем последовательно.

один конец полученного соединения соединяем с землей.

Место соединение RC цепочек с первой кнопкой, а свободный конец RC цепочки - со второй.

кнопки подключаем к пину 4 ESP8266.
Вот функция колбека для обработки кнопок на ESP8266 по прерыванию
==============================
void intr_cb(int *dummy){
ETS_GPIO_INTR_DISABLE();
uint32 status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
if (status & BIT(pinb)) {
if (Level==GPIO_PIN_INTR_LOLEVEL){
LTime=system_get_time(); Level=GPIO_PIN_INTR_HILEVEL;
} else {
LTime=system_get_time()-LTime; Level=GPIO_PIN_INTR_LOLEVEL;
int m=0; while(LenT>m){
if (LTime>T_min[m] && LTime<T_max[m]){ ( button=m; break; }
m++; }
}
}
gpio_pin_intr_state_set(GPIO_ID_PIN(pinb),Level);
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS,status);
ETS_GPIO_INTR_ENABLE();
}

------------------------
функция вызывает всего два раза на нажатие
при втором вызове определяет номер кнопки.
и Все ничего лишнего.
==================================
К пину 5 подключаем реле.

У меня нашлось такое:




вход signal (у реле это in) соединяем с пином 5 ESP через RC цепочку (см ранее)

На реле подаем питание 5 вольт.

К контакту реле 2 подключаем 5 вольт, а на контакт 1 подключаем через резистор светодиод, второй конец которого соединяем с землей.

В fimware прошивка с примером

две кнопки и реле.

Нажатие на кнопку изменяет частоту переключения реле (две кнопки -две частоты)
=====================
P.s:
Отдельно хочу обратиться к любителям засрать темы .
------------------------------
В заголовке темы написано ДЕЛЮСЬ ОПЫТОМ
это значит - что это НЕ ОБСУЖДЕНИЕ или ВОПРОС
или еще что-то либо что требует Вашего непосредственного излияния.
Это значит что Я рассказал свой опыт тем, кому это интересно,
а не тем, кто хочет выпендриваться .
------------------------------
Просьба модераторов соблюдать их собственные правила,
а то не форум, а помойка какая-то.
 

Вложения

Последнее редактирование:

Алексей.

Active member
В данной заметке я расскажу как подключить несколько таких контактов к одному пину и обеспечить распознавание какая кнопка нажата.
Идея простая. Надо сделать так, чтобы при нажатии кнопки на пин поступал импульс определенной длительностью, различный для каждой кнопки.
Подскажите как определить одновременное замыкание 2-х и более контактов по длительности импульса?
 

nikolz

Well-known member
Подскажите как определить одновременное замыкание 2-х и более контактов по длительности импульса?
--------------------------
В данном варианте при нажатии первой кнопки - которая после первой RC цепочки, считая от земли,
длительность импульса на пине будет 18 мс а при нажатии второй 8 мс.
В программе по прерыванию от пина измеряем длительность нажатия т е время от фронта вниз до фронта вверх
и по таблице временных ворот находим номер строки таблицы - это и будет номер кнопки
Для указанного примера заданы ворота для первой кнопки 17-19 мс для второй 7-9 мс.
Все остальные помехи и дребезги будут отбрасываться.
-----------------------
 

Алексей.

Active member
nikolz,
Нет нажатия первой кнопки и нет нажатия второй кнопки, есть одновременное нажатие 2-х и более кнопок, есть два прибора учета воды с выходом геркон, цена деления одного импульса 0,001куб.м.
при интенсивном расходе вероятность одновременного замыкания 2-х контактов велика.
 
Последнее редактирование:

nikolz

Well-known member
nikolz,
Нет нажатия первой кнопки и нет нажатия второй кнопки, есть одновременное нажатие 2-х и более кнопок, есть два прибора учета воды с выходом геркон, цена деления одного импульса 0,001куб.м.
при интенсивном расходе вероятность одновременного замыкания 2-х контактов велика.
данное решение позволяет экономить пины в задачах, где есть несколько кнопок,
которые могут нажиматься в произвольном порядке последовательно.
Если Вы нажмете два кнопки одновременно, то определится самая первая из них относительно земли, так как она закоротит все вышестоящие RC цепочки.
Можно сказать что приоритет кнопок определяется от земли, которая ближе из нажатых к земле та и главная.
----------------------------
Ваша задача другая, не этой темы.
Возможно в ней нет смысла экономить пин.
Но принцип защиты от помех по длительности импульса и временным воротам остается.
--------------------
 

Алексей.

Active member
Снасала вы говорите про герконы или сенсоры с выходом "сухой контакт"
Наиболее часто устройства IoT принимают сигналы от внешних замыкающихся контактов, такие как кнопки,герконы или сенсоры с выходом "сухой контакт"
а потом оказывается с герконами и сенсорами можно работать только если их научить одновременно не замыкаться, а замыкаться по очереди
смешно :)
 

=AK=

New member
RC цепочки (в моем варианте их две) соединяем последовательно.

один конец полученного соединения соединяем с землей.

Место соединение RC цепочек с первой кнопкой, а свободный конец RC цепочки - со второй.

кнопки подключаем к пину 4 ESP8266.
То есть, когда кнопки не нажаты, то пин 4 висит в воздухе? А что при этом с него читается и почему? И какой длины провод до кнопок допускается?
 

nikolz

Well-known member
То есть, когда кнопки не нажаты, то пин 4 висит в воздухе? А что при этом с него читается и почему? И какой длины провод до кнопок допускается?
Нет,там подтяжка в 10 ком. Полагал по умолчанию сейчас добавлю, если не очевидною
 

nikolz

Well-known member
Снасала вы говорите про герконы или сенсоры с выходом "сухой контакт"

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

nikolz

Well-known member
Ну конечно повыпендриваться, когда решаешь конкретную задачу с двумя сенсорами, куда уж без этого.
Вообще-то это решение для случая когда есть две проблемы:
1) нажимает на кнопки герконы человек или его задница.
Т е время удержания кнопки может быть большим и неизвестным.
2) когда кнопок много а пины кончились.
можно подключить таким образом очень много кнопок.
еще меня достал длительный треп на форуме про борьбу с помехами от кнопок.
Поэтому выложил прошивку примера. Потому что у меня никаких помех и дребезга нет.
-----------------------------
В вашем случае нет смысла экономить пины и делать постоянным длительность импульса так как у вас он и так хороший.
Поэтому Ваша задача гораздо проще изложенной мною.
 

Юрий Ботов

Moderator
Команда форума
а потом оказывается с герконами и сенсорами можно работать только если их научить одновременно не замыкаться, а замыкаться по очереди
смешно :)
Вдумайтесь: цифровая входная нога то ОДНА. Через нее ОДНОВРЕМЕННО никак два+ сигнала не пролезут, как программно не изворачивайся.
 

=AK=

New member
Вдумайтесь: цифровая входная нога то ОДНА. Через нее ОДНОВРЕМЕННО никак два+ сигнала не пролезут, как программно не изворачивайся.
Ну почему же? Вполне можно извернуться. Например, одна кнопка подключет конденсатор 1 мкФ, другая кнопка - конденсатор 2 мкФ. А входная нога только и делает, что регулярно меряет подключенную к ней емкость: сначала настраивается на вывод и разряжает ее, а потом настраивается на ввод и ждет, за какое время внешний (или внутренний) подтягивающий резистор зарядит есмкость. Если замерянная емкость близка к нулю - обе кнопке отжаты, если на входе имеется 1 мкФ - нажата кнопка 1, если 2 мкФ - нажата кнопка 2, а если 3 мкФ - нажаты обе кнопки.
 
  • Like
Реакции: 44e

Юрий Ботов

Moderator
Команда форума
=AK=, проблема в том что наиболее вероятный сценарий: одну нажали (допустим 1мкф), пока она еще нажата нажали другую(2мкф), потом отжалась одна из кнопок (фиг ее знает какая первая), и после этого отжалась вторая, в результате "средняя по палате" емкость будет произвольной.
 

nikolz

Well-known member
Ну почему же? Вполне можно извернуться. Например, одна кнопка подключет конденсатор 1 мкФ, другая кнопка - конденсатор 2 мкФ. А входная нога только и делает, что регулярно меряет подключенную к ней емкость: сначала настраивается на вывод и разряжает ее, а потом настраивается на ввод и ждет, за какое время внешний (или внутренний) подтягивающий резистор зарядит есмкость. Если замерянная емкость близка к нулю - обе кнопке отжаты, если на входе имеется 1 мкФ - нажата кнопка 1, если 2 мкФ - нажата кнопка 2, а если 3 мкФ - нажаты обе кнопки.
------------------------------------
можно и в этой схеме.
Но в этом случае надо для каждой кнопки включить свою RC цепь на землю и рассчитать номинал RC так,
чтобы сумма любых двух RC была не равна любой из RС.
 

=AK=

New member
=AK=, проблема в том что наиболее вероятный сценарий: одну нажали (допустим 1мкф), пока она еще нажата нажали другую(2мкф), потом отжалась одна из кнопок (фиг ее знает какая первая), и после этого отжалась вторая, в результате "средняя по палате" емкость будет произвольной.
Человек не может жать кнопки даже с частотой 100 Гц. А для реальных (т.е. низких) скоростей всегда можно посчитать такие параметры RC-цепочек, чтобы уверенно отличать любую комбинацию нажатий и при этом достаточно комфортно (т.е особо не торопясь) отрабатыват описанный алгоритм.
 

nikolz

Well-known member
А вот если нырнуть под воду и там не нажимать кнопки,
то как определить что еще не вечер?
Ну и так далее..
 

pvvx

Активный участник сообщества
Подскажите как определить одновременное замыкание 2-х и более контактов по длительности импульса?
Путем переключения направления пина с входа на выход и анализа постоянной времени заряда/разряда RC-цепи.
Совершенно не подходит для кнопок с дребезгом.
Определить срабатывание 2-х кнопок можно только с приоритетом одной кнопки.
Например, путем включения и отключения внутренней подтяжки:
Снимок47.gif
Без включенной подтяжки ожидаете нулевого уровня. По появлению нуля, включаете подтяжку и считываете значение на пин. Проделываете это N-раз для стабильности определения, на частоте цикла уточнения не менее 1000 раз в сек. Но ESP8266 может не обеспечить такие частоты переключения "подтяжки".
 
Последнее редактирование:

=AK=

New member
Совершенно не подходит для кнопок с дребезгом.
Дребезг не играет никакой рояли. Одно измерение в любом случае может быть испорчено если кнопку нажали где-то в середине процесса измерения. Поэтому измерений надо делать много, а решение принимать "статистически". Это и дребезг убьет напрочь.

Определить срабатывание 2-х кнопок можно только с приоритетом одной кнопки.
Тупите. В сообщении #14 показано, как можно сделать без приоритетов.
 
Сверху Снизу