Как заменить энкодер кнопками? Очень просто!

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
Да, заменить энкодер кнопками очень просто. Особенно на библиотеках Гайвера
Что надо понимать:
1) Надо найти все обработчики событий энкодера и заменить их соответствующими событиями кнопок.
2) События обработки энкодера могут быть в разных местах!
Все.
По примеру. есть переменная , которая меняет свое значение от 0 до 255 , после 255 дает 0 - циклично, и так же в обратную сторону.
Поворот энкодера в одну сторону увеличивает на 1 значение переменной, в другую уменьшает. Физическим представлением для переменной может быть пункт меню, значение для яркости светодиода, скорость вращения двигателем и т.п.
Изменение происходит в строках 33 и 34. строка 32 обрабатывает состояние энкодера. Именно эти строки надо заменить на строки обработки кнопок (строки 38 и 39) и на действия по нажатию кнопок (строки 40 и 41). В строках 40 и 41 в условие я еще добавил событие isStep -на мой взгляд очень удобная штука, позволяет менять значение переменных не кликами , а удержанием кнопки. Интервал изменения настраивается в строках 26-27.

Да, пример "за уши притянут" , пины я использую разные у кнопок и энкодера, не обрабатываю кучу событий, типа поворота с нажатием. Поверьте, это не сложно добавить, комбинируя состояния кнопок.

В начале кода стоит 2 строки, которые позволяют отдельно использовать либо кнопки, либо энкодер. Закоментировав любую из них получится полностью удалить выбранные элементы из конечного кода программы.

C++:
#define USE_BUTTON
#define USE_ENCODER
// эта часть отвечает за кнопки
#define BTN_L_PIN 3
#define BTN_R_PIN 9
#include "GyverButton.h"
GButton Btn_L(BTN_L_PIN, HIGH_PULL);
GButton Btn_R(BTN_R_PIN , HIGH_PULL);

// эта часть отвечает за поворот энкодера
#define CLK 4
#define DT 5
#include "GyverEncoder.h"
Encoder enc1(CLK, DT);

uint8_t per = 0;
uint8_t old_per = 1;

void setup() {
  Serial.begin(115200);
 
  // настройка энкодера
  enc1.setType(TYPE2);
 
  // настройка кнопок
  Btn_L.setStepTimeout(100);
  Btn_R.setStepTimeout(100);
}

void loop() {
  // изменение переменной энкодером
  enc1.tick();
  if (enc1.isRight()) per++;
  if (enc1.isLeft()) per--;


  // изменение переменной кнопками
  Btn_R.tick();
  Btn_L.tick();
  if (Btn_R.isClick() || Btn_R.isStep()) per++;
  if (Btn_L.isClick() || Btn_L.isStep()) per--;


  // общая для всех типпо изменения переменной обработка результатов
  if (old_per != per)
  {
    old_per = per;
    Serial.println(per);
  }
}
PS. Такие вопросы встречаются часто. Не знаю стоит ли на них отвечать, но решил ответить. Это только один пример КАК сделать такое. Для других библиотек с энкодером может потребоваться несколько другая тактика, можно попробовать продолжить тему на реальных примерах.
 

Dhorohiy

★✩✩✩✩✩✩
30 Июл 2020
41
10
Да, заменить энкодер кнопками очень просто. Особенно на библиотеках Гайвера ... Только нужно наоборот заменить кнопку энкодером (но от перемены слагаемых результат то не меняется)))
... можно попробовать продолжить тему на реальных примерах.
ДОБРЫЙ ДЕНЬ, вот вопрос с реальным примером( взять лампу Гайвера и крайнюю прошивку gunner47_v1.5.85in1.zip
https://download.ru/files/TXym08IA

я меняю
#ifdef ESP_USE_BUTTON
на
#ifdef ESP_USE_ENCODER;

#include <GyverButton.h>
на
#include "GyverEncoder.h"


в // --- ИНИЦИАЛИЗАЦИЯ ОБЪЕКТОВ ---------- заменить

#ifdef ESP_USE_BUTTON
GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); // для физической (не сенсорной) кнопки нужно поменять LOW_PULL на HIGH_PULL. ну и кнопку нужно ставить без резистора между находящимися рядом пинами D2 и GND
#endif
на
#ifdef ESP_ENC_WITH_BUTTON
#define DEFAULT_BTN_PULL HIGH_PULL

в // --- ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ ------- заменить
bool buttonEnabled = true;
на
bool encoderEnabled = true;
#include "GyverEncoder.h"
#define CLK 13 // S1
#define DT 14 // S2
#define SW 12 // Key=BTN_PIN
Encoder enc(CLK, DT, SW, TYPE2);

в void setup() {

// КНОПКА
#if defined(ESP_USE_BUTTON)
touch.setStepTimeout(BUTTON_STEP_TIMEOUT);
touch.setClickTimeout(BUTTON_CLICK_TIMEOUT);
#if ESP_RESET_ON_START
delay(1000); // ожидание инициализации модуля кнопки ttp223 (по спецификации 250мс)
if (digitalRead(BTN_PIN))
{
wifiManager.resetSettings(); // сброс сохранённых SSID и пароля при старте с зажатой кнопкой, если разрешено
LOG.println(F("Настройки WiFiManager сброшены"));
}
buttonEnabled = true; // при сбросе параметров WiFi сразу после старта с зажатой кнопкой, также разблокируется кнопка, если была заблокирована раньше
EepromManager::SaveButtonEnabled(&buttonEnabled);
ESP.wdtFeed();
#endif
#endif

заменить на (

#if defined(ESP_USE_BUTTON)
touch.setStepTimeout(BUTTON_STEP_TIMEOUT);
touch.setClickTimeout(BUTTON_CLICK_TIMEOUT);
#if ESP_RESET_ON_START
delay(1000); // ожидание инициализации модуля кнопки ttp223 (по спецификации 250мс)
if (digitalRead(BTN_PIN))
{
wifiManager.resetSettings(); // сброс сохранённых SSID и пароля при старте с зажатой кнопкой, если разрешено
LOG.println(F("Настройки WiFiManager сброшены"));
}
buttonEnabled = true; // при сбросе параметров WiFi сразу после старта с зажатой кнопкой, также разблокируется кнопка, если была заблокирована раньше
EepromManager::SaveButtonEnabled(&buttonEnabled);
ESP.wdtFeed();
#endif
#endif


ЗЫ. В программировании вообще не понимаю, а перевести с кнопки на энкодер очень нужно.
 
Изменено:

toric21

✩✩✩✩✩✩✩
7 Фев 2023
15
0
C++:
#define USE_BUTTON
#define USE_ENCODER
#define pin_11 11
#define pin_10 10

// эта часть отвечает за кнопки
#define BTN_L_PIN 3
#define BTN_R_PIN 9
#include "GyverButton.h"
GButton Btn_L(BTN_L_PIN, HIGH_PULL);
GButton Btn_R(BTN_R_PIN , HIGH_PULL);

// эта часть отвечает за поворот энкодера
#define CLK 4
#define DT 5
#include "GyverEncoder.h"
Encoder enc1(CLK, DT);

uint8_t per = 0;
uint8_t old_per = 1;

void setup() {
  Serial.begin(9600);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
 // настройка энкодера
  enc1.setType(TYPE2);
 
  // настройка кнопок
  Btn_L.setStepTimeout(100);
  Btn_R.setStepTimeout(100);
}

void loop() {
  // изменение переменной энкодером
  enc1.tick();
  if (enc1.isRight()) per++;
  if (enc1.isLeft()) per--;

 
  // изменение переменной кнопками
  Btn_R.tick();
  Btn_L.tick();
  if (Btn_R.isClick() || Btn_R.isStep()) per++;
  if (Btn_L.isClick() || Btn_L.isStep()) per--;
 
 

  // общая для всех типпо изменения переменной обработка результатов
  if (old_per != per)
  {
    old_per = per;
    Serial.println(per);
    digitalWrite(pin_11,per++);
    digitalWrite(pin_10,per--);
    
  }
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
2 вопроса:
1) Кто написал эти строки ?
2) Зачем нужно давать сигнал на энкодер ? Он от этого сам крутиться не будет.

Эти строки надо убрать.

В остальном переменная обрабатывается и на нажатие кнопок и на поворот энкодера. Так что работать должно. Работает ли код, если отдельно его использовать для кнопок или отдельно для энкодера ?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
Выход то выходом, но 10 и 11 пины это ВХОД энкодера. С них надо считывать информацию (что делает библиотека энкодера) а если писать в них что попало, то библиотека будет вести себя как попало
 

toric21

✩✩✩✩✩✩✩
7 Фев 2023
15
0
в том то и дело что мне нужно просто убрать энкодер и вывести вместо него кнопки. ну или продублировать его. как то так должно выглядеть)
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
да это я понял.
Но записывая в пины значения это не заставит работать энкодер так просто.
1) Заменить или добавить это разные вещи. Совсем.
Заменить означает физическое удаление энкодера, возможно установка кнопок на его пины. Самое правильное, если код чужой и очень большой, а так же как в примере используется библиотека Гайвера переделать энкодер на вирутальный: вот тут в статье по нему есть раздел https://alexgyver.ru/encoder/
Там уже есть что то подобно записи состояния, но не на пины,а в функцию тик
2) Добавить - новое устройство в виде 2-х кнопок с сохранением полного функционала старого устройство.
Именно так должен работать Ваш код. На 2 устройства одновременно в конечном итоге.
 

toric21

✩✩✩✩✩✩✩
7 Фев 2023
15
0
Я правильно понял, что по второму пункту нужно просто запараллелить ножки энкодера на 4 и 5 контакт и добавить кнопки на 3 и 9 . ?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
По второму надо просто убрать строки, которые я указал. Далее все должно работтать.
Если не работает - проверять отдельно кнопки и отдельно энкодер.
 

toric21

✩✩✩✩✩✩✩
7 Фев 2023
15
0
@Старик Похабыч,
Здравствуйте! Схема и программа работает . На компьютере графики рисует, что от энкодера, что от кнопок . но как соединить её с платой ? какой то выход же должен быть на основную плату с ардуино. подключал эту схему параллельно энкодеру на плате, не работает от кнопок. только от энкодера оно и понятно он в параллели.
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
Я правильно понял, что код в начале, исправлен и подключен по схеме в предыдущем посте ?
При этом работает только энкодер ? А энкодер у Вас голый, как на схеме или на плате, с питанием ?
Тогда в самое начало цикла loop добавьте 2 строки:
C++:
if (!digitalRead(BTN_L_PIN)) digitalWrite(13,1);
if (!digitalRead(BTN_R_PIN)) digitalWrite(13,0);
Эти строки будут работать так: одна зажигать встроенный светодиод на плате, вторая гасить.


Добавка позже:
Закинул все в эмулятор, код работает
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
Давайте так.
Берете макетную плату, энкодер и 2 кнопки, собираете схему как я дал на ссылке выше и проверяете работоспособность. А уже после этого пробуте переносить на плату.
Т.е. код , который вы сделали, на 99% был рабочий, значит проблема не программиста, а техника. Проверяем правильность подключения кнопок и энкодера. Т.к. кнопки простые как 2 рубля, то проблем скорее всего в подключении энкодера, там можно запутаться в 3-х контактах.
А уже потом , вооружившись мультиметром. проверяет что куда идет на плате.
Т.е. задача скорее всего не соотв. теме - вам надо сделать что то, что будет подключаться к пинам энкодера сторонней платы и эмулировать этот самый энкодер , то тут ее надо будет закрыть, а открыть отдельную, в помощи например и четко описать задачу.
 

toric21

✩✩✩✩✩✩✩
7 Фев 2023
15
0
@Старик Похабыч,
Да, макетная плата полностью работает и отрабатывает на отлично. Только я не понимаю тогда смысл этой сборки , если ее ни к чему не подключить. а использовать как макет.
но все равно спасибо и извините что отвлек.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,220
1,291
Москва
Смысл сборки замена энкодера кнопками на готовом проекте ардуино. Или наоборот. Эмуляция работы энкодера для другой платы - это совсем отдельный проект, и никто не говорит, что его нельзя решить. Так то идея у вас была почти правильная : что то выдавать на 2 пина.
Но для этого надо понимать, как работает заменяемый энкодер на плате . Хотя бы что считать тактом, какой уровень
Если посмотреть на картинку , в правый верхний угол:
1676454373159.png
То видно, что поворот энкодера это 2 сигнала, которые идут с задержкой ,
Если перевести это на язык программирования то будет примерно так:
C++:
 digitalWrite(pin_11,1);
delay(20);
digitalWrite(pin_10,1);
delay(20);
digitalWrite(pin_11,0);
delay(20);
digitalWrite(pin_10,1);
Задержки я чисто интуитивно поставил, может их можно и меньше сделать.
А может быть надо бдуте инвертировать сигнал, сначала включать 0, а потом 1.

Да, код этот по идее должен соотв. вращению в одну сторону, для вращения в другую надо менять местами 10 и 11 пины