GyverEncoder + OLED

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
Ничего понять не могу. Брал пример из гетхаба гайвера с меню. Решил переделать банально кнопки на энкодор. В итоге у этого примера работает только центральная кнопка. Программа отказывается видеть повороты ручки в лево/право. Даже выводил для монитора в сериал. Толку 0.
Это чисто нестыковка библиотеки? Сразу скажу что заливал до этого пример для теста энкодора. Все работатает. Тут же заливают этот скетч и все упало.
Вот тут после условия if (enc1.isLeft()) вывадил в сериал. Толку 0. Отказывается выполнять условие.

C++:
/*
   Пример меню со статическим указателем (перемещаются сами пукты меню)
*/

//#define OLED_SOFT_BUFFER_64     // Буфер на стороне МК
#include <GyverOLED.h>          // Библиотека дисплея
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;


#include "GyverEncoder.h"      // Либа кнопок

#define CLK 2
#define DT 3
#define SW 4
Encoder enc1(CLK, DT, SW);  // для работы c кнопкой

#define ITEMS 12               // Общее кол во пунктов

/* массивы строк с именами пунктов */
const char i0[] PROGMEM = "  Parameter 0:";  // Каждое имя в своей строке, символ переноса не нужен
const char i1[] PROGMEM = "  Parameter 1:";
const char i2[] PROGMEM = "  Parameter 2:";
const char i3[] PROGMEM = "  Parameter 3:";
const char i4[] PROGMEM = "  Parameter 4:";
const char i5[] PROGMEM = "  Parameter 5:";
const char i6[] PROGMEM = "  Parameter 6:";
const char i7[] PROGMEM = "  Parameter 7:";
const char i8[] PROGMEM = "  Parameter 8:";
const char i9[] PROGMEM = "  Parameter 9:";
const char i10[] PROGMEM = "  Parameter 10:";
const char i11[] PROGMEM = "  Parameter 11:";

const char* const names[] PROGMEM =           // Создаем массив ссылок, обращение к названию пунктов по их номеру
{
  i0, i1, i2, i3,
  i4, i5, i6, i7,
  i8, i9, i10, i11
};

void setup() {
  Serial.begin(9600);
  enc1.setType(TYPE2);
  oled.init();
  oled.setContrast(255);
}

void loop() {
  static int8_t pointer = 0; // Переменная указатель

  /* Кнопки */
  enc1.tick();

  if (enc1.isRight()) {          // Нажатие или удержание вверх
    if (--pointer < 1) pointer = ITEMS - 1;   // Уменьшаем указатель на 1 и если он стал меньше 1 -> присваиваем указателю ITEMS - 1
  }

  if (enc1.isLeft()) {      // Нажатие или удержание вниз
    if (++pointer > ITEMS - 1) pointer = 0;   // Увеличиваем указатель на 1 и если он стал больше ITEMS - 1 -> присваиваем указателю 0
  }

  if (enc1.isClick()) {   // Нажатие на ОК - переход в пункт меню
    switch (pointer) {  // По номеру указателей располагаем вложенные функции (можно вложенные меню)
      case 0: func(); break;  // По нажатию на ОК при наведении на 0й пункт вызвать функцию
      case 1: break;
      case 2: break;
      case 3: break;
      case 4: break;
      case 5: break;
      case 6: break;
      case 7: break;
        // И остальные ...
    }
  }

  oled.clear();           // Очищаем буфер
  oled.home();            // Курсор в левый верхний угол

  for (uint8_t i = pointer; i <  pointer + 8; i++) { // Цикл считающий от значения указателя еще 8 раз
    printMenuItem(i > ITEMS - 1 ? i - ITEMS : i);    // Если результат больше ITEMS - 1 -> начинаем сначала, иначе -> продолжаем как обычно
  }

  /* Указатель стоит на месте */
  oled.setCursor(0, 0);
  oled.print(">");
  oled.setCursor(120, 0);
  oled.print("<");

  oled.update();
}

// Функция для печати строки из prm
void printMenuItem(uint8_t num) {
  char buffer[21];                                // Буфер на полную строку
  uint16_t ptr = pgm_read_word(&(names[num]));    // Получаем указатель на первый символ строки
  uint8_t i = 0;                                  // Переменная - счетчик

  do {                                            // Начало цикла
    buffer[i] = (char)(pgm_read_byte(ptr++));     // Прочитать в буфер один символ из PGM и подвинуть указатель на 1
  } while (buffer[i++] != NULL);                  // Если это не конец строки - вернуться в начало цикла

  oled.println(buffer);                           // Вывод готовой строки с переносом на следующую
}


/* пример вложеной функции, которую можно вызвать из под меню */
void func(void) {
  oled.clear();
  oled.home();
  oled.print(F("Press OK to return"));
  oled.update();
  while (1) {
    enc1.tick();
      if (enc1.isClick()) return; // return возвращает нас в предыдущее меню
  }
}
 
Изменено:

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@_Quasar_, Посмотрите детально описание библиотеки, в 42 строке поиграйте с параметром, возможно выбрали не тот тип энкодера
 

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
Я не наше проблему... Начал писать званого с полного 0.. Каждый шаг проверяю в сериал.
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@_Quasar_,

Энкодоры бывают разные, для этого в библиотеки предусмотрено несколько настроек.
Вот выдержка из библиотеки
C++:
    void setType(bool type);                // TYPE1 / TYPE2 - тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
    void setPinMode(bool mode);                // тип подключения энкодера, подтяжка HIGH_PULL (внутренняя) или LOW_PULL (внешняя на GND)
    void setBtnPinMode(bool mode);            // тип подключения кнопки, подтяжка HIGH_PULL (внутренняя) или LOW_PULL (внешняя на GND)
    void setTickMode(bool tickMode);         // MANUAL / AUTO - ручной или автоматический опрос энкодера функцией tick(). (по умолчанию ручной)
    void setDirection(bool direction);        // NORM / REVERSE - направление вращения энкодера
    void setFastTimeout(uint16_t timeout);    // установка таймаута быстрого поворота
Скорее всего Вам просто надо в секции void setup() прописать правильные параметры, поэкспериментируйте. Где то на сайте Алекса было более подробно написано про этот момент. Где то тут https://alexgyver.ru/encoder/
 

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
@DAK, Я прекрасно знаю что у меня тип 2. Я же сказал что заливал пробный скетч на вывод в сериал всех вариаций энкодора.
 

Sergo_ST

★★★★★★✩
15 Мар 2020
959
825
Скорее всего это из-за частого обновления экрана, попробуйте обновлять только по изменению состояния:
C++:
/*
   Пример меню со статическим указателем (перемещаются сами пукты меню)
*/
 
//#define OLED_SOFT_BUFFER_64 // Буфер на стороне МК
#include <GyverOLED.h> // Библиотека дисплея
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;
 
#include "GyverEncoder.h" // Либа кнопок
 
#define CLK 2
#define DT 3
#define SW 4
Encoder enc1(CLK, DT, SW); // для работы c кнопкой
 
#define ITEMS 12 // Общее кол во пунктов
 
/* массивы строк с именами пунктов */
const char i0[] PROGMEM = " Parameter 0:"; // Каждое имя в своей строке, символ переноса не нужен
const char i1[] PROGMEM = " Parameter 1:";
const char i2[] PROGMEM = " Parameter 2:";
const char i3[] PROGMEM = " Parameter 3:";
const char i4[] PROGMEM = " Parameter 4:";
const char i5[] PROGMEM = " Parameter 5:";
const char i6[] PROGMEM = " Parameter 6:";
const char i7[] PROGMEM = " Parameter 7:";
const char i8[] PROGMEM = " Parameter 8:";
const char i9[] PROGMEM = " Parameter 9:";
const char i10[] PROGMEM = " Parameter 10:";
const char i11[] PROGMEM = " Parameter 11:";
 
const char* const names[] PROGMEM = // Создаем массив ссылок, обращение к названию пунктов по их номеру
{
  i0, i1, i2, i3,
  i4, i5, i6, i7,
  i8, i9, i10, i11
};
 
void setup() {
  Serial.begin(9600);
  enc1.setType(TYPE2);
  oled.init();
  oled.setContrast(255);
}
 
void loop() {
  static int8_t pointer = 0; // Переменная указатель
  static boolean upd = 1; // Флаг обновления экрана
 
  /* Кнопки */
  enc1.tick();
 
  if (enc1.isRight()) { // Нажатие или удержание вверх
    if (--pointer < 1) pointer = ITEMS - 1; // Уменьшаем указатель на 1 и если он стал меньше 1 -> присваиваем указателю ITEMS - 1
    upd = 1; // Установили флаг обновления экрана
  }
 
  if (enc1.isLeft()) { // Нажатие или удержание вниз
    if (++pointer > ITEMS - 1) pointer = 0; // Увеличиваем указатель на 1 и если он стал больше ITEMS - 1 -> присваиваем указателю 0
    upd = 1; // Установили флаг обновления экрана
  }
 
  if (enc1.isClick()) { // Нажатие на ОК - переход в пункт меню
    switch (pointer) { // По номеру указателей располагаем вложенные функции (можно вложенные меню)
      case 0: func(); break; // По нажатию на ОК при наведении на 0й пункт вызвать функцию
      case 1: break;
      case 2: break;
      case 3: break;
      case 4: break;
      case 5: break;
      case 6: break;
      case 7: break;
        // И остальные ...
    }
    upd = 1; // Установили флаг обновления экрана
  }
 
  if (upd) { // Если нужно обновить экран
    upd = 0; // Сбросили флаг обновления экрана
    oled.clear(); // Очищаем буфер
    oled.home(); // Курсор в левый верхний угол
 
    for (uint8_t i = pointer; i < pointer + 8; i++) { // Цикл считающий от значения указателя еще 8 раз
      printMenuItem(i > ITEMS - 1 ? i - ITEMS : i); // Если результат больше ITEMS - 1 -> начинаем сначала, иначе -> продолжаем как обычно
    }
 
    /* Указатель стоит на месте */
    oled.setCursor(0, 0);
    oled.print(">");
    oled.setCursor(120, 0);
    oled.print("<");
 
    oled.update();
  }
}
 
// Функция для печати строки из prm
void printMenuItem(uint8_t num) {
  char buffer[21]; // Буфер на полную строку
  uint16_t ptr = pgm_read_word(&(names[num])); // Получаем указатель на первый символ строки
  uint8_t i = 0; // Переменная - счетчик
 
  do { // Начало цикла
    buffer[i] = (char)(pgm_read_byte(ptr++)); // Прочитать в буфер один символ из PGM и подвинуть указатель на 1
  } while (buffer[i++] != NULL); // Если это не конец строки - вернуться в начало цикла
 
  oled.println(buffer); // Вывод готовой строки с переносом на следующую
}
 
/* пример вложеной функции, которую можно вызвать из под меню */
void func(void) {
  oled.clear();
  oled.home();
  oled.print(F("Press OK to return"));
  oled.update();
  while (1) {
    enc1.tick();
    if (enc1.isClick()) return; // return возвращает нас в предыдущее меню
  }
}
 
  • Лойс +1
Реакции: poty

zroman07

✩✩✩✩✩✩✩
12 Мар 2021
1
0
Решил эту проблему прерыванием (была такая же проблема один в один). В примерах к библиотеке есть tickISR