ARDUINO GyverEncoder 3.1 странные глюки с энкодером в моём коде + странности с nRF24L01+

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
Использую данную библиотеку (GyverEncoder) в своём проекте, в примерах библиотеки мой самодельный энкодер (сам энкодер взят со старой автомагнитолы и к нему была сделана плата с подтягивающими резисторами) работает нормально, но вот в коде проекта энкодер срабатывает поворота наверно со 100500-го. Не могу понять в чём проблема. Прикрепляю файлы с кодом проекта.

И нашел ещё проблему, при передачи в запись массива transmit_data[6] (TX_response.ino) данных (значение 100), на приёмнике (RX_response.ino) в той же записи массива received_data[6] творится какая-то дичь, значения скачут от 10 до 7000+, значения остальных принимаемых данных массива в норме. При обратной передаче тоже какая-то дичь, значение Bat (transmit_data[1] в RX_response.ino) нормальное (к примеру 89), но на передатчик (recieved_data[1] в TX_response.ino) приходит значение 316!

Менять каналы пробовал, зашумлённость проверял. Не помогает.

P.S. Если код Вам покажется убогим и т.д., не кидайте тапками, я привык к написанию программ (для Windows) на Delphi (язык Object Pascal) и переучиваться на C-подобный язык мне сложно.
 

Вложения

Изменено:

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
С nRF24L01+ более-менее разобрался просто добавив в массив ещё одно значение и записав туда ноль, может оно и считывается/передается с глюками, но зато все остальные значения массива теперь передаются нормально.

Но вот вопрос с энкодером так и не решился пока, не могу понять почему в примерах всё работает нормально, а в моём коде нет.

P.S. Пытался задать данный вопрос (из первого поста) на форуме arduino.ru, но там какие-то не адекватные люди сидят, вот моя тема там если кому интересно почему они не адекватные.
 

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
208
Гайверовский энкодер считывает состояние пинов при вызове функций isClick(), isTurn(), isRight() и т.п. Предположу, что эти функции у тебя вызываются слишком редко, и поэтому библиотека пропускает повороты.
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
@Александр Симонов, Я уже пробовал даже просто энкодер читать, без библиотек, что-то все равно не так, кнопки работают нормально, но вот энкодер ни в какую работать не хочет, уже даже не знаю что делать...
 

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
208
Даже без библиотек, если ты слишком редко опрашиваешь пины энкодера, будешь пропускать повороты.
Для проверки сделай вывод в Сериал в момент опроса пинов (только скорость Сериала поставь побольше -- 115200). Включи Отметки времени в Мониторе порта и смотри, сколько времени проходит между опросами.
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
Даже без библиотек, если ты слишком редко опрашиваешь пины энкодера, будешь пропускать повороты.
Для проверки сделай вывод в Сериал в момент опроса пинов (только скорость Сериала поставь побольше -- 115200). Включи Отметки времени в Мониторе порта и смотри, сколько времени проходит между опросами.
Глупый ламерский вопрос. А как это сделать? Ну кроме отметок времени в мониторе порта.
По идее опрос происходит в loop'е, так что задержек по идее не должно быть.
 

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
208
Ты ж вроде вроде сказал, что сам энкодер читаешь? Ну вот где читаешь, там и добавь Serial.println(состояние ног энкодера).
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
Я читаю его так: if (GetEncoderState() == eLeft) { Serial.println("Энкодер повернулся влево!"); }
Там же вместе с Serial.println ещё используется код нужный мне для изменения значений. Прикрепил файлик с моими исходниками. Чтобы быстро найти нужную часть кода используйте поиск по слову ENC_USE.

C-like:
#define pin_CLK 3
#define pin_DT  2
#define pin_Btn 4

unsigned long CurrTime, LastTime;
enum eEncoderState {eNone, eLeft, eRight, eButton};
int EncoderA, EncoderB, EncoderAPrev, counter;
bool ButtonPrev;

eEncoderState GetEncoderState() {
  // Считываем состояние энкодера
  eEncoderState Result = eNone;
  CurrTime = millis();
  if (CurrTime >= (LastTime + 5)) {
    // Считываем не чаще 1 раза в 5 мс для уменьшения ложных срабатываний
    LastTime = CurrTime;
    if (digitalRead(pin_Btn) == LOW ) {
      if (ButtonPrev) {
        Result = eButton; // Нажата кнопка
        ButtonPrev = 0;
      }
    }
    else {
      ButtonPrev = 1;
      EncoderA = digitalRead(pin_DT);
      EncoderB = digitalRead(pin_CLK);
      if ((!EncoderA) && (EncoderAPrev)) { // Сигнал A изменился с 1 на 0
        if (EncoderB) Result = eRight;     // B=1 => энкодер вращается по часовой
        else          Result = eLeft;      // B=0 => энкодер вращается против часовой
      }
      EncoderAPrev = EncoderA; // запомним текущее состояние
    }
  }
  return Result;
}

void setup() {
  pinMode(pin_DT,  INPUT);
  pinMode(pin_CLK, INPUT);
  pinMode(pin_Btn, INPUT_PULLUP); // Кнопка не подтянута к +5 поэтому задействуем внутренний pull-up резистор
  Serial.begin(9600);
  counter = 0;
}

void loop() {

if (GetEncoderState() == eLeft) Serial.println("Left");
if (GetEncoderState() == eRight) Serial.println("Right");


}
 

Вложения

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
Я пытаюсь прокрутить на самой ардуино, но внезапно, я не менял ни чего в коде и даже пытался старую версию кода использовать, но перестало вообще всё компилироваться...
Прикрепил лог.
 

Вложения

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
208
Нет, .ino файлов в папке может быть много. Но у тебя получается, т.к. файлы практически одинаковые, куча переопределений уже существующих переменных, а это уже ошибка.
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
Какую и как посоветуете задержку поставить между операциями, т.к. вроде заработало. Я поставил пока для теста delay(100);, но если можно как-то иначе... И кажись я убил энкодер, он только влево теперь срабатывает)))
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
И почему у Гайвера всё без задержек нормально работает в примере?
C:
#define CLK 6
#define DT 5
#define SW 4

#include "GyverEncoder.h"
Encoder enc1(CLK, DT, SW);

void setup() {
  Serial.begin(9600);
  enc1.setTickMode(AUTO);
}

void loop() {
  // enc1.tick();  // не нужна, в этом режиме (AUTO) она входит в каждую функцию!
 
  if (enc1.isTurn()) {     // если был совершён поворот (индикатор поворота в любую сторону)
    // ваш код
  }
 
  if (enc1.isRight()) Serial.println("Right");         // если был поворот
  if (enc1.isLeft()) Serial.println("Left");
 
  if (enc1.isRightH()) Serial.println("Right holded"); // если было удержание + поворот
  if (enc1.isLeftH()) Serial.println("Left holded");
 
  if (enc1.isPress()) Serial.println("Press");         // нажатие на кнопку (+ дебаунс)
  if (enc1.isRelease()) Serial.println("Release");     // отпускание кнопки (+ дебаунс)
  if (enc1.isHolded()) Serial.println("Holded");       // если была удержана и энк не поворачивался
  //if (enc1.isHold()) Serial.println("Hold");         // возвращает состояние кнопки
}
 

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
208
Я разве советовал ставить задержку? Я предложил подумать головой, что будет, если вызвать твою функцию GetEncoderState() два раза подряд, например, как в строчке
C-like:
    if (butt1 == HIGH || butt2 == HIGH || button1.Loop() == SB_CLICK || GetEncoderState() == eLeft || GetEncoderState() == eRight) {
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
Я уже убрал функции энкодера из этой строки. Но после установки задержки энкодер начал работать, хотя местами глюкова-то, но думаю это уже из-за износа самого энкодера, он же был снят с авто-магнитолы и не известно сколько лет его крутили, сейчас он нормально работает только при повороте влево, при повороте в право он показывает поворот влево и очень редко в право (проверялось примером из GyverEncoder).
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
И так. Всё таки использовал я библиотеку GyverEncoder, только использовал в качестве основы пример под названием timer_isr, и теперь всё работает нормально. Прикрепляю архив с финальной версией и всеми использованными библиотеками, а так же фото пред-окончательной версии того, ради чего я всё это разрабатывал (корпуса пока в стадии разработки).
IMG_20190612_151940.jpg
IMG_20190612_152020.jpg
IMG_20190612_152040.jpg
IMG_20190612_152402.jpg
IMG_20190612_152428.jpg
 

Вложения

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@eXPert, Видимо таки редко вызывалась функция. Также если тебе не нужен полный функционал библиотеки, можешь использовать короткий алгоритм для энкодера, работает на прерываниях. На основном сайте в статье Алгоритмы ардуино
 

eXPert

✩✩✩✩✩✩✩
14 Авг 2018
22
0
@AlexGyver, Уже пробовал схожий алгоритм найденный на другом форуме, тоже криво работает.

Хотел использовать ещё и библиотеку GyverButton для кнопок (включая кнопку энкодера, мне так проще), но по какой то причине она вызывает замедление вывода на экран данных, причем чем больше кнопок тем медленнее, как я понял по такому принципу - button_1.setTimeout(300) + button_2.setTimeout(300) + ... + button_N.setTimeout(300) = время задержки отображения изменений на экране. Не могу точно утверждать с чем это может быть связано. Но используя дополнение/библиотеку sav_button всё работает нормально.

P.S.
короткий алгоритм для энкодера
Находится в статье про библиотеку GyverEncoder, а не в Алгоритмах ардуино))
 
Изменено:

Valerich-tex

✩✩✩✩✩✩✩
7 Авг 2019
21
2
Столкнулся с подобной проблемой, в самом простом коде энкодер выдает значение только 1 или 5 при этом если закоментировать строки 16 и 18 то энкодер будет бегать исправно прибавляя или уменьшая по 1 значения за 1 тик поворота.
Код, который начинается с 20 строки вообще не сработал, хотя подобное я видел в одном из проектов Гайвера (цветная лампа для подсветки)
Вопрос, где костыли?

Енкодер:
#define but1_PIN 7                                             // Объявляю пины кнопок
#define but2_PIN 6
#define but3_PIN 8
#define but4_PIN A3
#include <EncButton.h>
//EncButton2<EB_ENCBTN> enc(INPUT, but1_PIN, but2_PIN, but4_PIN);  // энкодер с кнопкой
EncButton<EB_TICK, but1_PIN, but2_PIN, but4_PIN> enc(INPUT);

void setup() {
  uart.begin(115200);
}
void loop() {
  byte  menu;
  if (enc.tick()) {
    if (enc.right())  menu++;                       //если нажата кноп1 увеличивать значени
    if (menu > 5)     menu = 1;                     //c этим условием выдет только 1
    if (enc.left())   menu--;                       //уменьшать значение
    if (menu < 1)     menu = 5;                     //с этим условием выдает только 5, без них работает исправно
   
    /*if (enc.isTurn())  {
      menu = enc.getDir();                          //с этим условием выдает только 1 или -1 не более
      //   if (menu > 5)     menu = 1;
      //   if (menu < 1)     menu = 5;
      }
*/
    // enc.resetState();   // сбрасываем флаги (очищаем остальные события)
    uart.println(menu);
  }
}
 

kostyamat

★★★★★★✩
29 Окт 2019
1,098
632
@Valerich-tex, потому что static byte menu должно быть, или вынести переменную menu в глобалы, в начале скетча. Еще стоит сразу начальное значение задать
static byte menu = 1;