первый

This commit is contained in:
2020-11-28 23:20:52 +03:00
commit de59e62d68
5 changed files with 1364 additions and 0 deletions

167
GyverEncoder.h Normal file
View File

@@ -0,0 +1,167 @@
#pragma once
#include "mbed.h"
/*
GyverEncoder - библиотека для отработки энкодера. Возможности:
- Отработка поворота энкодера
- Отработка "нажатого поворота"
- Отработка "быстрого поворота"
- Несколько алгоритмов опроса энкодера
- Выбор подтяжки подключения энкодера
- Работа с двумя типами экнодеров
- Работа с внешним энкодером (через расширитель пинов и т.п.)
- Отработка нажатия/удержания кнопки с антидребезгом
Документацию читай здесь: https://alexgyver.ru/encoder/
Для максимально быстрого (в 2 раза быстрее) опроса энкодера рекомендуется использовать ядро GyverCore https://alexgyver.ru/gyvercore/
Версии:
- 3.6 от 16.09.2019 - Возвращены дефайны настроек
- 4.0 от 13.11.2019
- Оптимизирован код
- Исправлены баги
- Добавлены другие алгоритмы опроса
- Добавлена возможность полностью убрать кнопку (экономия памяти)
- Добавлена возможность подключения внешнего энкодера
- Добавлена настройка подтяжки пинов
- 4.1
- Исправлено изменение подтяжек
- 4.2
- Добавлена поддержка TYPE1 для алгоритма PRECISE_ALGORITHM
- Добавлена отработка двойного клика: isSingle / isDouble
*/
// ========= КОНСТАНТЫ ==========
#define ENC_NO_BUTTON -1 // константа для работы без пина
#define TYPE1 0 // полушаговый энкодер
#define TYPE2 1 // полношаговый
#define NORM 0 // направление вращения обычное
#define REVERSE 1 // обратное
#define MANUAL 0 // нужно вызывать функцию tick() вручную
#define AUTO 1 // tick() входит во все остальные функции и опрашивается сама!
#define HIGH_PULL 0 // внутренняя подтяжка к питанию (pinMode INPUT_PULLUP)
#define LOW_PULL 1 // внешняя подтяжка к GND (pinMode INPUT)
// =========== НАСТРОЙКИ ===========
// закомментируй строку, чтобы полностью убрать отработку кнопки из кода
#define ENC_WITH_BUTTON
// тип подключения энкодера по умолчанию (LOW_PULL или HIGH_PULL)
//#define DEFAULT_ENC_PULL LOW_PULL
#define DEFAULT_ENC_PULL HIGH_PULL
// тип подключения кнопки энкодера по умолчанию (LOW_PULL или HIGH_PULL)
//#define DEFAULT_BTN_PULL LOW_PULL
#define DEFAULT_BTN_PULL HIGH_PULL
// алгоритмы опроса энкодера (раскомментировать нужный)
//#define FAST_ALGORITHM // тик 10 мкс, быстрый, не справляется с люфтами
//#define BINARY_ALGORITHM // тик 14 мкс, лучше справляется с люфтами
#define PRECISE_ALGORITHM // тик 16 мкс, медленнее, но работает даже с убитым энкодером (по мотивам https://github.com/mathertel/RotaryEncoder)
// настройка антидребезга энкодера, кнопки, таймаута удержания и таймаута двойного клика
#define ENC_DEBOUNCE_TURN 1ms
#define ENC_DEBOUNCE_BUTTON 10ms
#define ENC_HOLD_TIMEOUT 700ms
#define ENC_DOUBLE_TIMEOUT 300ms
// The sample time in ms.
const int SAMPLE_TIME = 1;
// The number of samples that must agree before a key state change is recognised.
// 50 = 50ms for 1ms sample time.
const int DEBOUNCE_COUNT = 50;
// The number of samples that must agree before a key held state is recognised.
// 1000 = 1s for 1ms sample time.
const int HOLD_COUNT = 1000;
// The number of samples that must agree before a key repeat state is recognised.
// 200 = 200ms for 1ms sample time.
const int REPEAT_COUNT = 200;
#pragma pack(push, 1)
typedef struct
{
bool hold_flag : 1;
bool butt_flag : 1;
bool turn_flag : 1;
bool isTurn_f : 1;
bool isPress_f : 1;
bool isRelease_f : 1;
bool isHolded_f : 1;
bool isFastR_f : 1;
bool isFastL_f : 1;
bool isReleaseHold_f : 1;
bool enc_tick_mode : 1;
bool enc_type : 1;
bool use_button : 1;
bool extCLK : 1;
bool extDT : 1;
bool extSW : 1;
bool invBtn : 1;
bool isSingle_f : 1;
bool isDouble_f : 1;
bool countFlag : 1;
bool doubleFlag : 1;
bool doubleAllow : 1;
} GyverEncoderFlags;
#pragma pack(pop)
// Варианты инициализации:
// Encoder enc; // не привязан к пину
// Encoder enc(пин CLK, пин DT); // энкодер без кнопки (ускоренный опрос)
// Encoder enc(пин CLK, пин DT, пин SW); // энкодер с кнопкой
// Encoder enc(пин CLK, пин DT, пин SW, тип); // энкодер с кнопкой и указанием типа
// Encoder enc(пин CLK, пин DT, ENC_NO_BUTTON, тип); // энкодер без кнопкой и с указанием типа
class Encoder {
public:
Encoder(); // для непривязанного к пинам энкодера
Encoder(PinName clk, PinName dt, PinName sw, bool type = false); // CLK, DT, SW, тип (TYPE1 / TYPE2) TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
void tick(); // опрос энкодера, нужно вызывать постоянно или в прерывании
void tick(bool clk, bool dt, bool sw = 0); // опрос "внешнего" энкодера
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(Kernel::Clock::duration timeout); // установка таймаута быстрого поворота
bool isTurn(); // возвращает true при любом повороте, сама сбрасывается в false
bool isRight(); // возвращает true при повороте направо, сама сбрасывается в false
bool isLeft(); // возвращает true при повороте налево, сама сбрасывается в false
bool isRightH(); // возвращает true при удержании кнопки и повороте направо, сама сбрасывается в false
bool isLeftH(); // возвращает true при удержании кнопки и повороте налево, сама сбрасывается в false
bool isFastR(); // возвращает true при быстром повороте
bool isFastL(); // возвращает true при быстром повороте
bool isPress(); // возвращает true при нажатии кнопки, сама сбрасывается в false
bool isRelease(); // возвращает true при отпускании кнопки, сама сбрасывается в false
bool isClick(); // возвращает true при нажатии и отпускании кнопки, сама сбрасывается в false
bool isHolded(); // возвращает true при удержании кнопки, сама сбрасывается в false
bool isHold(); // возвращает true при удержании кнопки, НЕ СБРАСЫВАЕТСЯ
bool isSingle(); // возвращает true при одиночном клике (после таймаута), сама сбрасывается в false
bool isDouble(); // возвращает true при двойном клике, сама сбрасывается в false
void start();
void stop();
private:
Thread* encThread;
GyverEncoderFlags flags;
Kernel::Clock::duration _fast_timeout = 50ms; // таймаут быстрого поворота
uint8_t prevState = 0;
uint8_t encState = 0; // 0 не крутился, 1 лево, 2 право, 3 лево нажат, 4 право нажат
Kernel::Clock::time_point debounce_timer;
Kernel::Clock::time_point fast_timer;
DigitalIn* _CLK;
DigitalIn* _DT;
DigitalIn* _SW;
Kernel::Clock::duration debounceDelta;
Kernel::Clock::time_point thisMls;
bool turnFlag = false, extTick = false, SW_state = false;
void encoderThread();
};