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

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

pvvx

Активный участник сообщества
Дребезг не играет никакой рояли. Одно измерение в любом случае может быть испорчено если кнопку нажали где-то в середине процесса измерения. Поэтому измерений надо делать много, а решение принимать "статистически". Это и дребезг убьет напрочь.
Тут вы опять ошиблись. :) FAQ пополняется.
Тупите. В сообщении #14 показано, как можно сделать без приоритетов.
Ну да, туплю, т.к. можно поставить готовый внешний контроллер и передавать коды 104 кнопок...
 

=AK=

New member
"Это точно" (с)

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

Алгоритм тот же что и ранее, но распишу его более подробно:
  1. Опрос производится циклически, длительность полного цикла 10 мс. Можно и по прерываниям, но будет сложнее.
  2. Цикл исполняется с шагом 0.5 мс. Для другого шага надо пересчитать номиналы деталей в схеме
  3. В начале цикла настраиваем GPIO пин на вывод и подаем на него "единицу", чтобы зарядить С1.
  4. Первый шаг цикла (после 0.5 мс с начала цикла). С1 заряжен. Настраиваем GPIO пин на ввод, обнуляем счетчик cnt.
  5. В шагах 2...19 проверяем сигнал на GPIO пине. Если там высокий уровень (т.е. "единица"), то инкрементируем счетчик cnt.
  6. После 19-го шага (это 10 мс с начала цикла) проверяем состояние счетчика cnt:
    - если там число менее 9 - то обе кнопки нажаты (С1 разряжен через параллельно соединенные R1 и R2)
    - если там число от 9 до 13 - нажата кнопка SW1 (С1 разряжен через R1)
    - если там число от 14 до 18 - нажата кнопка SW2 (С1 разряжен через R2)
    - если там число более 18 - то обе кнопки отжаты (С1 вообще не успел разрядиться)
  7. Повторяем цикл (п. 3)
Окончательное принятие решения о том, какие кнопки нажаты, производится, скажем, по результатам последних 10 циклов. Если все результаты одинаковые, они принимаются достоверными.

Оптимальное отношение сопротивлений R2 к R1 равно 1.618, что есть "золотое сечение". Что означает, что вместо 47к лучше использовать 51к, но это менее популярный номинал из ряда Е24, тогда как 33к и 47к - из ряда Е12.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Это уже было:
Путем переключения направления пина с входа на выход и анализа постоянной времени заряда/разряда RC-цепи.
Совершенно не подходит для кнопок с дребезгом.
Причина в малом и нестабильном гистерезисе входов у ESP8266 и требуемой большой частоте опроса и переключения пинов, что не всегда возможно c помощью стандартных либ в Arduino и влиянию на опрос работающего драйвера WiFi.
Та и размер и потребление кучи элементов превышает готовые микросхемы (хоть MCU) в SOT-23-6. :)
 
Последнее редактирование:

nikolz

Well-known member
"Это точно" (с)


Не меняя сути моего предложения, слегка модифицированный и оптимизированный вариант:
Такая схема, при всей простоте, обеспечивает прекрасную помехоустойчивость. Кнопки можно выносить на несколько метров, а все резисторы надо располагать поближе к микроконтроллеру.

Алгоритм тот же что и ранее, но распишу его более подробно:
  1. Опрос производится циклически, длительность полного цикла 10 мс. Можно и по прерываниям, но будет сложнее.
  2. Цикл исполняется с шагом 0.5 мс. Для другого шага надо пересчитать номиналы деталей в схеме
  3. В начале цикла настраиваем GPIO пин на вывод и подаем на него "единицу", чтобы зарядить С1.
  4. Первый шаг цикла (после 0.5 мс с начала цикла). С1 заряжен. Настраиваем GPIO пин на ввод, обнуляем счетчик cnt.
  5. В шагах 2...19 проверяем сигнал на GPIO пине. Если там высокий уровень (т.е. "единица"), то инкрементируем счетчик cnt.
  6. После 19-го шага (это 10 мс с начала цикла) проверяем состояние счетчика cnt:
    - если там число менее 9 - то обе кнопки нажаты (С1 разряжен через параллельно соединенные R1 и R2)
    - если там число от 9 до 13 - нажата кнопка SW1 (С1 разряжен через R1)
    - если там число от 14 до 18 - нажата кнопка SW2 (С1 разряжен через R2)
    - если там число более 18 - то обе кнопки отжаты (С1 вообще не успел разрядиться)
  7. Повторяем цикл (п. 3)
Окончательное принятие решения о том, какие кнопки нажаты, производится, скажем, по результатам последних 10 циклов. Если все результаты одинаковые, они принимаются достоверными.

Оптимальное отношение сопротивлений R2 к R1 равно 1.618, что есть "золотое сечение". Что означает, что вместо 47к лучше использовать 51к, но это менее популярный номинал из ряда Е24, тогда как 33к и 47к - из ряда Е12.
это существенно сложнее чем мой вариант.
Вот колбек в моем варианте который не зависит от количества кнопок и работает в десятки раз быстрее вашего.
----------------------
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();
}
------------------------
т е вызывает всего два раза на нажатие
при втором вызове определяет номер кнопки.
и Все ничего лишнего.
--------------------------
Успехов в творчестве!!!
 

=AK=

New member
Причина в малом и нестабильном гистерезисе входов у ESP8266 и требуемой большой частоте опроса и переключения пинов, что не всегда возможно c помощью стандартных либ в Arduino и влиянию на опрос работающего драйвера WiFi.
Та и размер и потребление кучи элементов превышает готовые микросхемы (хоть MCU) в SOT-23-6. :)
Гистерезис входа ESP8266 такой же, как у большинства других микросхем. Например, у RTL8711 мало чем отличается. Вы бы лучше RTFM, чем гнать голословную пургу. :D
Мелкие динамические вариации порогового напряжения "нуля", вызванные колебаниями тока потребления, укладываются в разброс допускаемых значений и/или устраняются предложенным алгоритмом.
"Куча элементов" так или иначе необходима для защиты микросхемы от помех, как бы мала она ни была. Поэтому хоть к MCU в SOT-23-6 - все равно придется навесить снаружи резисторы и конденсаторы. Некоторые еще и дорогие, но ненужные варисторы привешивают от недоумия. :cool:
 

=AK=

New member
это существенно сложнее чем мой вариант.
Вот колбек в моем варианте который не зависит от количества кнопок и работает в десятки раз быстрее вашего.
Ваш вариант подвержен влиянию помех.

Непонятно какая "скорость работы" вас заботит. Если вы о времени реакции на нажатие, то наоборот, требуется замедленная реакция, чтобы задавить дребезг контактов. При этом человек не замечает внесенную задержку обработки если она меньше 200 мс, поэтому мой алгоритм, с его 100 мс, абсолютно незаметен для человека. Уменьшать его далее не нимеет никакого смысла.

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

pvvx

Активный участник сообщества
Гистерезис входа ESP8266 такой же, как у большинства других микросхем. Например, у RTL8711 мало чем отличается. Вы бы лучше RTFM, чем гнать голословную пургу. :D
Зачем мне байки от Espressif. Наелся вдоволь. Тестер другое кажет.
Мелкие динамические вариации порогового напряжения "нуля", вызванные колебаниями тока потребления, укладываются в разброс допускаемых значений и/или устраняются предложенным алгоритмом.
Угу - как отношение резисторов 33 к 47 на ваши 0.5 мс, где дрова WiF постоянно дают прерывание процессов с запретом прерываний на более 140 мкс.
"Куча элементов" так или иначе необходима для защиты микросхемы от помех, как бы мала она ни была. Поэтому хоть к MCU в SOT-23-6 - все равно придется навесить снаружи резисторы и конденсаторы.
Тут вы не угадали. Есть специализированные, со всем встроенным. И уровень обработки дребезга у них получше...
Некоторые еще и дорогие, но ненужные варисторы привешивают от недоумия. :cool:
Варисторы нужны для защиты от Ардуинщиков. Они тыкают проводки куда не попадя. :)
Непонятно какая "скорость работы" вас заботит. Если вы о времени реакции на нажатие, то наоборот, требуется замедленная реакция, чтобы задавить дребезг контактов. При этом человек не замечает внесенную задержку обработки если она меньше 200 мс, поэтому мой алгоритм, с его 100 мс, абсолютно незаметен для человека. Уменьшать его далее не нимеет никакого смысла.
Больным, с заторможенной реакцией, всё равно. Классические выведенные многолетними пробами параметры другие и описаны в литературе.
Если же вы озабочены затратами процессорного времени, то для кнопок вообще очень мало вычислений требуется.
Совсем бир-бар. Но на процесс измерения задержки влияет:
На фоне производительности процессора и затрат на обслуживание WiFi просто смешно сравнивать. Но если уж хотите меряться, то уверенно скажу, что приведенный вами код требует для исполнения больше процессорного времени, чем это нужно для любого шага описанного выше алгоритма.
Это не мой код и не я его притянул в форум...
Вдобавок в вашем случае будкт притормаживаться обработка других прерываний, что крайне нежелательно.
В цикле loop() то Arduino - та и пофиг. :) Тому алгоритму джиттер опроса не страшен, хоть 400%.
Итого: раз =AK= начал визжать, значит дело с его вариантом совсем плохо...
Много кнопок, один пин с приемника и полная защита от помех :) :
 
Последнее редактирование:

pvvx

Активный участник сообщества
Пруф в студию. А то опять буду бить канделябром по вашей лживой роже. В который уж раз =:D=
Тестер, осциллограф и всё сопутствующее возьмите в магазине.
Когда предъявите, скажу как измерить.
 
Сверху Снизу