Энкодер плохо отрабатывает

ValeDeMare

✩✩✩✩✩✩✩
16 Ноя 2022
16
0
Добрый день, прошу помощи. Во всех проектах Энкодер ведёт себя криво. За 1 щелчек 4 смены, при этом чтобы он отловил эти смены приходится крутить ну ооочень медленно, примерно 1 щелчек за секунду, иначе значение изменяемой переменной просто прыгает туда-обратно. более дешевые энкодеры ведут себя примерно также.
Все проекты с использованием библиотек GyverOLED со включенным бубером и EncButton, от задания типа энкодера ничего не меняется.

вот пример скетча, довольно простого, датчик влажности, энкодер, экран и вентилятор, энкодером меняется влажность при которой вентилятор включается.

ТАкое поведение из-за использования буфера, или надо на прерывание переписать работу энкодера (я пока не вникал как но как понимаю это возможно)?

C++:
#include <EncButton.h>

EncButton eb(10, 11, 8);

#include <GyverOLED.h>
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;

#define T_PERIOD 2000
uint32_t timer = 0;//таймер
#include "DHT.h"

#define DHTPIN 2     // what digital pin we're connected to

bool flag=false; //флаг смены процентов

int8_t SetHumidity = 80;
int8_t SetHumidity1 = 70;
int8_t Celsius =0;
int8_t Humidity =0;
int8_t lamp=0;


#define DHTTYPE DHT11   // DHT 11

DHT dht(DHTPIN, DHTTYPE);

void setup() {
eb.setEncType(EB_STEP1);

    eb.setBtnLevel(LOW);
    eb.setClickTimeout(500);
    eb.setDebTimeout(50);
    eb.setHoldTimeout(600);
    eb.setStepTimeout(200);

    eb.setEncReverse(0);
    //eb.setEncType(EB_STEP4_LOW);
    eb.setFastTimeout(30);

// pinMode     (6,    INTUT_PULLDOWN); //крутилка
pinMode     (7,    OUTPUT); //крутилка
pinMode     (4,    OUTPUT); //Led1
pinMode     (5,    OUTPUT); //Led2
digitalWrite (3, HIGH);
digitalWrite (4, LOW);
digitalWrite (5, LOW);
pinMode     (8,    INPUT_PULLUP);

oled.init();        // инициализация
  oled.clear();       // очистка
  oled.setScale(1);   // масштаб текста (1..4)
  oled.home();        // курсор в 0,0
  oled.print("Крабариум 1.0");




  dht.begin();
}

void loop() {

if (millis()-timer > T_PERIOD){
timer=millis();

   Humidity = dht.readHumidity();

   Celsius = dht.readTemperature();




if (Humidity>=SetHumidity){
  digitalWrite (7, HIGH);
}
if (Humidity<SetHumidity1){
  digitalWrite (7, LOW);

}

}



eb.tick();
if (eb.hold()) {
  flag=!flag;
}
if (eb.click()) {
  lamp++;
  if (lamp>=4) {
   lamp=0;
    }
}



switch (lamp) {
        case 0: digitalWrite (4, LOW);digitalWrite (5, LOW);
        break;
         case 1:  digitalWrite (4, LOW);digitalWrite (5, HIGH);
        break;
         case 2:  digitalWrite (4, HIGH);digitalWrite (5, HIGH);
        break;
        case 3:  digitalWrite (4, LOW);digitalWrite (5, HIGH);
        break;
}


if (eb.turn() ) {
if (eb.left()&& flag ) {
SetHumidity-=2;
SetHumidity = constrain (SetHumidity,10,100);
SetHumidity1=SetHumidity-10;
}

if (eb.right()&& flag ) {
SetHumidity+=2;
  SetHumidity = constrain (SetHumidity,10,100);
  SetHumidity1=SetHumidity-10;
}
}
oled.setCursor(0, 2); oled.print("Температура= "); oled.print(Celsius); oled.print("*C");
  oled.setCursor(0, 3); oled.print("Влажность= "); oled.print(Humidity); oled.print("%");
   oled.setCursor(0, 4);oled.print("Включить при"); oled.print(SetHumidity); oled.print("%");
   oled.setCursor(0, 5);oled.print("Флаг"); oled.print(flag);oled.print("ф"); oled.print(lamp);oled.print("ф");oled.print(flag1);oled.print("ф");oled.print(flag2);
   oled.update();
}
 

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

★★★★★★★
14 Авг 2019
4,360
1,331
Москва
Для работы энкодера нужно максимально четко обрабатывать его тики.
Что бы я рекомендовал:
1. Для начала убрать (закомментировать) весь вывод на дисплей - он довольно медленный, а делается он каждый цикл loop. Делать его надо только по изменению параметра, или при получении нового. Ну или по интервалу.
2. Если не пробовались разные типы энкодера , то попробовать их. Но они скорее всего пробовались.
3. по другому организовать проверку энкодера: на крутилку сделать пины 2 и 3 (поменять) и сделать обработку по прерыванию на них. Или организовать прерывание по таймеру скажем 1000 раз в секунду и делать тик энкодера там.
4. Для контроля работы сделать вывод в монитор порта, при этом скорость обмена с монитором порта поставить не менее 115200. В монитор порта выводить отладочные данные по повороту энкодера и посмотреть на сколько четко или нечетко работает энкодер. так же попробовать другой энкодер.
 
  • Лойс +1
Реакции: ValeDeMare

ValeDeMare

✩✩✩✩✩✩✩
16 Ноя 2022
16
0
@Старик Похабыч,
Энкодеры разные пробовал, не влияет, по крайней мере существенно. если отключить буфер на экран то работает лучше. думаю без экрана будет работать совсем хорошо, но задача то и экран чтоб работал..
спасибо за советы, попробую поэкспериментировать.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
668
105
@ValeDeMare, у Гайвера есть объяснения по этому поводу. Первые энкодеры так себя вели, за один щелчок по два тика. Есть другой тип, там добавили элементов и всё нормально.
 

ValeDeMare

✩✩✩✩✩✩✩
16 Ноя 2022
16
0
@VictorArx, я давно смотрел по энкодерам его видео, там 2 типа было, у меня и первого есть и второго, и оба работают плюс-минус одинаково.

Скорее всего проблема в том, что loop каждый раз обновляется полностью экран, это время занимает много и плата просто не видит движение на Энкодере. Перепишу код чтобы экран только на изменения информации обновлялся и скорее всего будет лучше.

@Старик Похабыч,
Большое спасибо за подсказку, переписал код так, чтобы экран обновлялся только при изменении переменных, отображаемых на экране и стало прям на порядок адекватнее работать, возможно даже так оставлю. А может попробую и другие ваши советы.