Переключение режимов Эндодерм

DV73

✩✩✩✩✩✩✩
22 Янв 2020
4
0
Нужно переключать режимы (3 шт) Поочерёдное включение 3 светодиодов, энкодером.
ESP8266 . Набросал скетч из примеров Алекса. Но есть одна проблемка.
Режимы переключается при правом вращении по кругу циклично. То есть 1 - 2 - 3.
А вот при вращение в лево энкодером нет цикличности . Подскажите что не так в коде?
C++:
#define CLK 13 // D7 пин
#define DT 12 // D6 пин
#define SW 14 // D5 пин
#include "GyverEncoder.h"
#define MODE_AM 3 //Количество присетов
Encoder enc1(CLK, DT, SW);
byte mode = 0;
void setup() {
  Serial.begin(9600);
   pinMode(16, OUTPUT); // Красный светоиод D0 пин
   pinMode(5, OUTPUT); //                  D1 пин
   pinMode(4, OUTPUT); //                  D2 пин
   //digitalWrite(16, LOW);
   //digitalWrite(5, LOW);
   //digitalWrite(4, LOW);
    enc1.setType(TYPE2);    // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
}
void loop() {
 // обязательная функция отработки. Должна постоянно опрашиваться
  enc1.tick();

  if (enc1.isRight()){
   if (++mode >= MODE_AM) mode = 0;
   }
    switch (mode) {
    case 0: task_0();
      break;
    case 1: task_1();
      break;
    case 2: task_2();
      break;
}
  if (enc1.isLeft()){
   if (--mode >= MODE_AM) mode = 0;
   }
    switch (mode) {
    case 0: task_0();
      break;
    case 1: task_1();
      break;
    case 2: task_2();
      break;
    }
}
// наши задачи, внутри функций понятное дело может быть всё что угодно
void task_0() {
  digitalWrite(16, HIGH);
  digitalWrite(5, LOW);
  digitalWrite(4, LOW);
}
void task_1() {
 digitalWrite(16, LOW);
 digitalWrite(5, HIGH);
 digitalWrite(4, LOW);
 
}
void task_2() {
 digitalWrite(16, LOW);
 digitalWrite(5, LOW);
 digitalWrite(4, HIGH);
}
 

poty

★★★★★★✩
19 Фев 2020
3,230
940
Потому что сравнение mode в isLeft нужно проводить с нулем (в данном случае Вам повезло и это необязательно, так как переменная mode - беззнаковая) и присваивать mode значение 2.

P.S. Пока в пути - развлекался:
Примерно так:
// Для энкодера
#define CLK 13                // Подключение энкодера
#define DT 12                 // Подключение энкодера
#define SW 14                 // Подключение кнопки энкодера
#include "GyverEncoder.h"
Encoder enc1(CLK, DT, SW);    // Создаём класс Encoder

byte leds[] = { 16, 5, 4 };   // Массив пинов, к которым подключены светодиоды, не более 7

class mtl {                   // Объявляем класс светодиодов
  public:
                              // Конструктор класса
    mtl( byte *pleds, byte lNumber) {
                              // Инициализируем пины, к которым подключены светодиоды, как выходные
      for ( _s_max = 0; _s_max < lNumber; _s_max++ ) pinMode(*(pleds + _s_max), OUTPUT);
      _s_over = 1<<_s_max;    // Запоминаем запредельный битовый сдвиг
      _s_max = _s_over >> 1;  // Запоминаем маску последнего светодиода
      _state = 1;             // Начинаем с первого светодиода
      _pleds = pleds;         // Запоминаем ссылку на массив пинов светодиодов
      _changeState();         // Отображаем текущее состояние
    };
    
    mtl operator++() {        // Движение вправо
      _state <<= 1;           // Смещаем бит в сторону старших разрядов
                              // Если вышли за пределы количества светодиодов - начинаем с первого
      if (_state & _s_over) _state = 1;
      _changeState();         // Отображаем текущее состояние
    };    
    
    mtl operator--() {        // Движение влево
      _state >>= 1;           // Смещаем бит в сторону младших разрядов
                              // Если вышли за пределы количества светодиодов - начинаем с последнего
      if (_state == 0) _state = _s_max;
      _changeState();         // Отображаем текущее состояние
    };
    
  private:
  
    byte _state;              // Текущее состояние светодиодов
    byte _s_max;              // Маска последнего светодиода
    byte _s_over;             // Маска выхода за пределы последнего светодиода
    byte *_pleds;             // Ссылка на массив пинов светодиодов
    
    void _changeState() {     // Отображение текущего состояния
      byte iMask = 1;         // Начинаем проверять с младшего бита
                              // Проверяем до выхода за пределы последнего светодиода
      for( byte iCounter = 0; !(iMask & _s_over); iCounter++) {
                              // Устанавливаем порт в соответствии с состоянием бита
        digitalWrite(*(_pleds + iCounter), _state & iMask);
        iMask <<= 1;          // Смещаемся на следующий бит
      }
    };
};

mtl mtli(leds, sizeof(leds)); // Создаём класс управления светодиодами

void setup() {
  enc1.setType(TYPE2);        // Установка энкодера
}
void loop() {
  enc1.tick();                // опрашиваем энкодер
  if (enc1.isRight()) ++mtli; // обрабатываем вращение вправо
  if (enc1.isLeft()) --mtli;  // обрабатываем вращение влево
}
 
Изменено:
  • Лойс +1
Реакции: DV73

andrew_alpha.mega.project

✩✩✩✩✩✩✩
20 Июл 2020
1
0
просто предложу готовое решение
C++:
#define CLK 13 // D7 пин
#define DT 12 // D6 пин
#define SW 14 // D5 пин
#include "GyverEncoder.h"
#define MODE_AM 3 //Количество присетов
Encoder enc1(CLK, DT, SW);
byte mode = 0;
void setup() {
  Serial.begin(9600);
   pinMode(16, OUTPUT); // Красный светоиод D0 пин
   pinMode(5, OUTPUT); //                  D1 пин
   pinMode(4, OUTPUT); //                  D2 пин
   //digitalWrite(16, LOW);
   //digitalWrite(5, LOW);
   //digitalWrite(4, LOW);
    enc1.setType(TYPE2);    // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
}
void loop() {
 // обязательная функция отработки. Должна постоянно опрашиваться
  enc1.tick();

  if (enc1.isRight()){
   if (mode == MODE_AM) mode = 0 else mode++;
   }
    switch (mode) {
    case 0: task_0();
      break;
    case 1: task_1();
      break;
    case 2: task_2();
      break;
}
  if (enc1.isLeft()){
   if (mode == 0) mode = MODE_AM else mode--;
   }
    switch (mode) {
    case 0: task_0();
      break;
    case 1: task_1();
      break;
    case 2: task_2();
      break;
    }
}
// наши задачи, внутри функций понятное дело может быть всё что угодно
void task_0() {
  digitalWrite(16, HIGH);
  digitalWrite(5, LOW);
  digitalWrite(4, LOW);
}
void task_1() {
 digitalWrite(16, LOW);
 digitalWrite(5, HIGH);
 digitalWrite(4, LOW);
 
}
void task_2() {
 digitalWrite(16, LOW);
 digitalWrite(5, LOW);
 digitalWrite(4, HIGH);
}
попробуйте так
 

kostyamat

★★★★★★✩
29 Окт 2019
1,098
632
@andrew_alpha.mega.project, так у него никогда не получится mode 0, если влево клацать. Лучше тогда уж объявить переменную
char mode;
И проверять ее так
if (mode < 0) mode = MODE_AM else mode--;
 

poty

★★★★★★✩
19 Фев 2020
3,230
940
@kostyamat, не совсем. Изменение mode происходит после проверки. Здесь ошибка в другом: получается, что обрабатывается 4 состояния: 0, 1, 2, 3, а обработчики есть только у 0, 1, 2. Т.е. каждый раз для перехода через границу 0 или 2 потребуется два щелчка энкодером.