add disp
This commit is contained in:
parent
0e1f3c1579
commit
d62ecbc979
23
README.md
23
README.md
@ -0,0 +1,23 @@
|
||||
<h1 align="center">PumpController</h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Pendosv">
|
||||
<img src="https://img.shields.io/github/followers/Pendosv?label=Follow&style=social">
|
||||
</a>
|
||||
<a href="https://github.com/Pendosv/PumpController">
|
||||
<img src="https://img.shields.io/github/stars/Pendosv/PumpController?style=social">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
<p align="center">
|
||||
Contact with me
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://T.me/Pend0s">
|
||||
<img src="https://raw.githubusercontent.com/Pendosv/Pendosv/master/img/telegram.png" width="40" height="40">
|
||||
</a>
|
||||
<a href="mailto:djvlad967891@gmail.com">
|
||||
<img src="https://raw.githubusercontent.com/Pendosv/Pendosv/master/img/mail.png" width="40" height="40">
|
||||
</a>
|
||||
</p>
|
||||
@ -1,29 +1,46 @@
|
||||
#define pressure_Aport 0
|
||||
#define relay_Dport 5
|
||||
|
||||
#define CLK 2
|
||||
#define DT 3
|
||||
#define SW 4
|
||||
#define S1 2
|
||||
#define S2 3
|
||||
#define KEY 4
|
||||
|
||||
#define CLK 6
|
||||
#define DIO 7
|
||||
|
||||
#define const_pressure_min 0
|
||||
#define const_pressure_max 1000
|
||||
|
||||
#include <GyverEncoder.h>
|
||||
#include <EncButton.h>
|
||||
#include <EEPROM.h>
|
||||
#include <GyverTM1637.h>
|
||||
|
||||
|
||||
int pressure, pressure_min, pressure_max;
|
||||
bool flag;
|
||||
unsigned long last_time1, last_time2;
|
||||
|
||||
Encoder enc(CLK, DT, SW);
|
||||
|
||||
EncButton<EB_TICK, S1, S2, KEY> enc;
|
||||
GyverTM1637 disp(CLK, DIO);
|
||||
|
||||
|
||||
|
||||
int constraint_pressure(int pressure_) {
|
||||
return constrain(pressure_, 0, 1000);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc.setType(TYPE2);
|
||||
|
||||
pinMode(relay_Dport, OUTPUT);
|
||||
|
||||
EEPROM.get(0, pressure_min);
|
||||
EEPROM.get(2, pressure_max);
|
||||
|
||||
disp.clear();
|
||||
disp.brightness(7);
|
||||
disp.clear();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -32,20 +49,24 @@ void loop() {
|
||||
enc.tick();
|
||||
if (enc.isTurn()) {
|
||||
if (enc.isRight()) {
|
||||
pressure_min = constrain(pressure_min+10, const_pressure_min, const_pressure_max);
|
||||
pressure_min = constraint_pressure(pressure_min+10);
|
||||
disp.displayInt(pressure_min);
|
||||
}
|
||||
if (enc.isLeft()) {
|
||||
pressure_min = constrain(pressure_min-10, const_pressure_min, const_pressure_max);
|
||||
pressure_min = constraint_pressure(pressure_min-10);
|
||||
disp.displayInt(pressure_min);
|
||||
}
|
||||
if (enc.isRightH()) {
|
||||
pressure_min = constrain(pressure_max+10, const_pressure_min, const_pressure_max);
|
||||
pressure_max = constraint_pressure(pressure_max+10);
|
||||
disp.displayInt(pressure_max);
|
||||
}
|
||||
if (enc.isLeftH()) {
|
||||
pressure_min = constrain(pressure_max-10, const_pressure_min, const_pressure_max);
|
||||
pressure_max = constraint_pressure(pressure_max-10);
|
||||
disp.displayInt(pressure_max);
|
||||
}
|
||||
}
|
||||
|
||||
if (enc.isClick()) {
|
||||
if (enc.isHolded()) {
|
||||
EEPROM.put(0, pressure_min);
|
||||
EEPROM.put(2, pressure_max);
|
||||
}
|
||||
@ -53,6 +74,12 @@ void loop() {
|
||||
|
||||
pressure = analogRead(pressure_Aport);
|
||||
|
||||
if (millis() - last_time1 > 850) {
|
||||
last_time1 = millis();
|
||||
disp.displayInt(pressure);
|
||||
}
|
||||
|
||||
|
||||
if (pressure < pressure_min) {
|
||||
if (!flag) {
|
||||
digitalWrite(relay_Dport, HIGH);
|
||||
|
||||
194
libraries/EncButton/README.md
Normal file
194
libraries/EncButton/README.md
Normal file
@ -0,0 +1,194 @@
|
||||

|
||||

|
||||
# EncButton
|
||||
Ультра лёгкая и быстрая библиотека для энкодера, энкодера с кнопкой или просто кнопки
|
||||
- Максимально быстрое чтение пинов для AVR (ATmega328/ATmega168, ATtiny85/ATtiny13)
|
||||
- Оптимизированный вес
|
||||
- Быстрые и лёгкие алгоритмы кнопки и энкодера
|
||||
- Энкодер: поворот, нажатый поворот, быстрый поворот, счётчик
|
||||
- Кнопка: антидребезг, клик, несколько кликов, счётчик кликов, удержание, режим step
|
||||
- Подключение - **только с подтяжкой к питанию** (внешней или внутренней)!
|
||||
- Опциональный режим callback (+22б SRAM на каждый экземпляр)
|
||||
- Виртуальный режим (кнопка, энк, энк с кнопкой)
|
||||
|
||||
### Совместимость
|
||||
Совместима со всеми Arduino платформами (используются Arduino-функции)
|
||||
|
||||
## Содержание
|
||||
- [Установка](#install)
|
||||
- [Инициализация](#init)
|
||||
- [Использование](#usage)
|
||||
- [Пример](#example)
|
||||
- [Версии](#versions)
|
||||
- [Баги и обратная связь](#feedback)
|
||||
|
||||
<a id="install"></a>
|
||||
## Установка
|
||||
- Библиотеку можно найти по названию **EncButton** и установить через менеджер библиотек в:
|
||||
- Arduino IDE
|
||||
- Arduino IDE v2
|
||||
- PlatformIO
|
||||
- [Скачать библиотеку](https://github.com/GyverLibs/EncButton/archive/refs/heads/main.zip) .zip архивом для ручной установки:
|
||||
- Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64)
|
||||
- Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32)
|
||||
- Распаковать и положить в *Документы/Arduino/libraries/*
|
||||
- (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив
|
||||
- Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
|
||||
|
||||
<a id="init"></a>
|
||||
## Инициализация
|
||||
```cpp
|
||||
EncButton<MODE, A, B, KEY> enc; // энкодер с кнопкой и пинами A, B, KEY
|
||||
EncButton<MODE, A, B> enc; // просто энкодер с пинами A, B
|
||||
EncButton<MODE, KEY> btn; // просто кнопка с пином KEY
|
||||
// MODE: EB_TICK или EB_CALLBACK - режим работы ручной или с обработчиками
|
||||
|
||||
// по умолчанию пины настроены в INPUT_PULLUP
|
||||
// Если используется внешняя подтяжка - лучше перевести в INPUT
|
||||
EncButton<EB_TICK, 2, 3, 4> enc(INPUT);
|
||||
|
||||
// Виртуальный режим:
|
||||
EncButton<MODE, VIRT_BTN> enc; // виртуальная кнопка
|
||||
EncButton<MODE, VIRT_ENCBTN> enc; // виртуальный энк с кнопкой
|
||||
EncButton<MODE, VIRT_ENC> enc; // виртуальный энк
|
||||
// в tick нужно передавать виртуальное значение, см. ниже!
|
||||
```
|
||||
|
||||
<a id="usage"></a>
|
||||
## Использование
|
||||
```cpp
|
||||
void pullUp(); // подтянуть пины внутренней подтяжкой
|
||||
void holdEncButton(bool state); // виртуально зажать кнопку энкодера
|
||||
void setHoldTimeout(int tout); // установить время удержания кнопки, мс (до 30 000)
|
||||
|
||||
// тикер, вызывать как можно чаще или в прерывании
|
||||
// вернёт отличное от нуля значение, если произошло какое то событие
|
||||
uint8_t tick();
|
||||
|
||||
// tick может принимать виртуальный сигнал при режиме VIRT_:
|
||||
// (сигнал кнопки)
|
||||
// (сигнал энкодера А, сигнал энкодера B)
|
||||
// (сигнал энкодера А, сигнал энкодера B, сигнал кнопки)
|
||||
|
||||
uint8_t getState(); // получить статус
|
||||
void resetState(); // сбросить статус
|
||||
|
||||
// обработка энкодера
|
||||
bool isTurn(); // факт поворота
|
||||
bool isRight(); // вправо
|
||||
bool isLeft(); // влево
|
||||
bool isRightH(); // вправо нажатый
|
||||
bool isLeftH(); // влево нажатый
|
||||
bool isFast(); // быстрый
|
||||
int counter; // доступ к счётчику энкодера
|
||||
|
||||
// обработка кнопки
|
||||
bool isPress(); // нажатие
|
||||
bool isRelease(); // отпускание
|
||||
bool isClick(); // клик
|
||||
bool isHolded(); // было удержание (однократное срабатывание)
|
||||
bool isHold(); // удерживается (постоянное срабатывание)
|
||||
bool isStep(); // режим шага
|
||||
bool state(); // текущий статус кнопки
|
||||
bool hasClicks(uint8_t numClicks); // проверка на наличие указанного количества кликов
|
||||
uint8_t hasClicks(); // вернёт количество кликов, если они есть
|
||||
uint8_t clicks; // доступ к счётчику кликов
|
||||
|
||||
// для режима с обработчиком
|
||||
void attach(eb_callback type, void (*handler)()); // подключить обработчик
|
||||
void detach(eb_callback type); // отключить обработчик
|
||||
void attachClicks(uint8_t amount, void (*handler)()); // подключить обработчик на количество кликов (может быть только один!)
|
||||
void detachClicks(); // отключить обработчик на количество кликов
|
||||
|
||||
// eb_callback может быть:
|
||||
TURN_HANDLER
|
||||
RIGHT_HANDLER
|
||||
LEFT_HANDLER
|
||||
RIGHT_H_HANDLER
|
||||
LEFT_H_HANDLER
|
||||
CLICK_HANDLER
|
||||
HOLDED_HANDLER
|
||||
STEP_HANDLER
|
||||
HOLD_HANDLER
|
||||
CLICKS_HANDLER
|
||||
PRESS_HANDLER
|
||||
RELEASE_HANDLER
|
||||
// СМОТРИ ПРИМЕР
|
||||
|
||||
// дефайны настроек (дефайнить ПЕРЕД ПОДКЛЮЧЕНИЕМ БИБЛИОТЕКИ)
|
||||
// показаны значения по умолчанию
|
||||
//#define EB_FAST 30 // таймаут быстрого поворота, мс
|
||||
//#define EB_DEB 80 // дебаунс кнопки, мс
|
||||
//#define EB_HOLD 1000 // таймаут удержания кнопки, мс
|
||||
//#define EB_STEP 500 // период срабатывания степ, мс
|
||||
//#define EB_CLICK 400 // таймаут накликивания, мс
|
||||
```
|
||||
|
||||
<a id="example"></a>
|
||||
## Пример
|
||||
Остальные примеры смотри в **examples**!
|
||||
```cpp
|
||||
// Пример с прямой работой библиотеки
|
||||
|
||||
#include <EncButton.h>
|
||||
EncButton<EB_TICK, 2, 3, 4> enc; // энкодер с кнопкой <A, B, KEY>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc.counter = 100; // изменение счётчика
|
||||
}
|
||||
|
||||
void loop() {
|
||||
enc.tick();
|
||||
|
||||
if (enc.isTurn()) { // любой поворот
|
||||
Serial.print("turn ");
|
||||
Serial.println(enc.counter); // вывод счётчика
|
||||
}
|
||||
|
||||
if (enc.isLeft()) {
|
||||
if (enc.isFast()) Serial.println("fast left");
|
||||
else Serial.println("left");
|
||||
}
|
||||
|
||||
if (enc.isRight()) {
|
||||
if (enc.isFast()) Serial.println("fast right");
|
||||
else Serial.println("right");
|
||||
}
|
||||
|
||||
if (enc.isLeftH()) Serial.println("leftH");
|
||||
if (enc.isRightH()) Serial.println("rightH");
|
||||
if (enc.isClick()) Serial.println("click");
|
||||
if (enc.isHolded()) Serial.println("holded");
|
||||
if (enc.isStep()) Serial.println("step");
|
||||
|
||||
if (enc.isPress()) Serial.println("press");
|
||||
if (enc.isClick()) Serial.println("click");
|
||||
if (enc.isRelease()) Serial.println("release");
|
||||
|
||||
if (enc.hasClicks(1)) Serial.println("1 click");
|
||||
if (enc.hasClicks(2)) Serial.println("2 click");
|
||||
if (enc.hasClicks(3)) Serial.println("3 click");
|
||||
if (enc.hasClicks(5)) Serial.println("5 click");
|
||||
|
||||
if (enc.hasClicks()) Serial.println(enc.clicks);
|
||||
//if (enc.isHold()) Serial.println("hold");
|
||||
}
|
||||
```
|
||||
|
||||
<a id="versions"></a>
|
||||
## Версии
|
||||
- v1.1 - пуллап отдельныи методом
|
||||
- v1.2 - можно передать конструктору параметр INPUT_PULLUP / INPUT(умолч)
|
||||
- v1.3 - виртуальное зажатие кнопки энкодера вынесено в отдельную функцию + мелкие улучшения
|
||||
- v1.4 - обработка нажатия и отпускания кнопки
|
||||
- v1.5 - добавлен виртуальный режим
|
||||
- v1.6 - оптимизация работы в прерывании
|
||||
- v1.6.1 - подтяжка по умолчанию INPUT_PULLUP
|
||||
- v1.7 - большая оптимизация памяти, переделан FastIO
|
||||
- v1.8 - индивидуальная настройка таймаута удержания кнопки (была общая на всех)
|
||||
|
||||
<a id="feedback"></a>
|
||||
## Баги и обратная связь
|
||||
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
|
||||
Библиотека открыта для доработки и ваших **Pull Request**'ов!
|
||||
74
libraries/EncButton/examples/callbackMode/callbackMode.ino
Normal file
74
libraries/EncButton/examples/callbackMode/callbackMode.ino
Normal file
@ -0,0 +1,74 @@
|
||||
// Пример с обработчиками
|
||||
|
||||
// Опциональные дефайн-настройки (показаны по умолчанию)
|
||||
//#define EB_FAST 30 // таймаут быстрого поворота, мс
|
||||
//#define EB_DEB 80 // дебаунс кнопки, мс
|
||||
//#define EB_HOLD 1000 // таймаут удержания кнопки, мс
|
||||
//#define EB_STEP 500 // период срабатывания степ, мс
|
||||
//#define EB_CLICK 400 // таймаут накликивания, мс
|
||||
|
||||
// подключение - только PULL-UP, внешний или внутренний!
|
||||
// для изменения направления энкодера поменяй A и B при инициализации
|
||||
|
||||
#include <EncButton.h>
|
||||
EncButton<EB_CALLBACK, 2, 3, 4> enc; // энкодер с кнопкой <A, B, KEY>
|
||||
//EncButton<EB_CALLBACK, 2, 3> enc; // просто энкодер <A, B>
|
||||
//EncButton<EB_CALLBACK, 4> enc; // просто кнопка <KEY>
|
||||
|
||||
// по умолчанию пины настроены в INPUT_PULLUP
|
||||
// Если используется внешняя подтяжка - лучше перевести в INPUT
|
||||
//EncButton<EB_CALLBACK, 2, 3, 4> enc(INPUT);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc.counter = 100; // изменение счётчика
|
||||
//enc.setHoldTimeout(500); // установка таймаута удержания кнопки
|
||||
|
||||
enc.attach(TURN_HANDLER, myTurn);
|
||||
enc.attach(RIGHT_HANDLER, myRight);
|
||||
enc.attach(CLICK_HANDLER, myClick);
|
||||
enc.attach(HOLDED_HANDLER, myHolded);
|
||||
enc.attach(STEP_HANDLER, myStep);
|
||||
enc.attach(CLICKS_HANDLER, myClicks);
|
||||
enc.attachClicks(5, fiveClicks);
|
||||
}
|
||||
|
||||
void myTurn() {
|
||||
Serial.print("turn ");
|
||||
Serial.println(enc.counter); // вывод счётчика
|
||||
|
||||
// также можно опросить здесь (isRight, isLeft, isRightH, isLeftH)
|
||||
if (enc.isLeft()) {
|
||||
if (enc.isFast()) Serial.println("fast left");
|
||||
else Serial.println("left");
|
||||
}
|
||||
if (enc.isLeftH()) {
|
||||
if (enc.isFast()) Serial.println("fast left hold");
|
||||
else Serial.println("left");
|
||||
}
|
||||
}
|
||||
|
||||
void myRight() {
|
||||
if (enc.isFast()) Serial.println("fast right");
|
||||
else Serial.println("right");
|
||||
}
|
||||
|
||||
void myClick() {
|
||||
Serial.println("click");
|
||||
}
|
||||
void myHolded() {
|
||||
Serial.println("holded");
|
||||
}
|
||||
void myStep() {
|
||||
Serial.println("step");
|
||||
}
|
||||
void myClicks() {
|
||||
Serial.println(enc.clicks);
|
||||
}
|
||||
void fiveClicks() {
|
||||
Serial.println("kek");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
enc.tick(); // обработка всё равно здесь
|
||||
}
|
||||
49
libraries/EncButton/examples/isr/isr.ino
Normal file
49
libraries/EncButton/examples/isr/isr.ino
Normal file
@ -0,0 +1,49 @@
|
||||
// Пример с прямой работой библиотеки на прерываниях
|
||||
|
||||
// Опциональные дефайн-настройки (показаны по умолчанию)
|
||||
//#define EB_FAST 30 // таймаут быстрого поворота, мс
|
||||
//#define EB_DEB 80 // дебаунс кнопки, мс
|
||||
//#define EB_HOLD 1000 // таймаут удержания кнопки, мс
|
||||
//#define EB_STEP 500 // период срабатывания степ, мс
|
||||
//#define EB_CLICK 400 // таймаут накликивания, мс
|
||||
|
||||
// подключение - только PULL-UP, внешний или внутренний!
|
||||
// для изменения направления энкодера поменяй A и B при инициализации
|
||||
|
||||
#include <EncButton.h>
|
||||
EncButton<EB_TICK, 2, 3, 4> enc; // энкодер с кнопкой <A, B, KEY>
|
||||
//EncButton<EB_TICK, 2, 3> enc; // просто энкодер <A, B>
|
||||
//EncButton<EB_TICK, 4> enc; // просто кнопка <KEY>
|
||||
|
||||
// по умолчанию пины настроены в INPUT_PULLUP
|
||||
// Если используется внешняя подтяжка - лучше перевести в INPUT
|
||||
//EncButton<EB_TICK, 2, 3, 4> enc(INPUT);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// желательно подключить оба пина энкодера на внешние прерывания по CHANGE
|
||||
// можно использовать PCINT https://github.com/NicoHood/PinChangeInterrupt
|
||||
attachInterrupt(0, isr, CHANGE); // D2
|
||||
attachInterrupt(1, isr, CHANGE); // D3
|
||||
// подключил оба прерывания на одну функцию
|
||||
}
|
||||
|
||||
// в прерывании вызываем тик
|
||||
void isr() {
|
||||
enc.tick();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// тут тоже вызываем тик, нужен для
|
||||
// корректной работы дебаунсов и прочих таймеров!!!
|
||||
enc.tick();
|
||||
|
||||
if (enc.isTurn()) { // любой поворот
|
||||
Serial.print("turn ");
|
||||
Serial.println(enc.counter); // вывод счётчика
|
||||
}
|
||||
|
||||
// имитация загруженной программы, обработка происходит в прерывании
|
||||
delay(50);
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
// пример с прерываниями pinChangeInterrupt (прерывания на любом пине)
|
||||
// только для ATmega328 (UNO, Nano, Pro Mini)
|
||||
|
||||
#define SW 0
|
||||
#define DT 2
|
||||
#define CLK 3
|
||||
#define CLK 4
|
||||
#define DT 5
|
||||
#define SW 6
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1(CLK, DT, SW);
|
||||
#include <EncButton.h>
|
||||
EncButton<EB_TICK, CLK, DT, SW> enc;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
@ -17,13 +17,23 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
enc1.tick(); // оставляем тут для работы "временных" функций и антидребезга
|
||||
// оставляем тут для работы "временных" функций и антидребезга
|
||||
enc.tick();
|
||||
|
||||
if (enc1.isRight()) Serial.println("Right"); // если был поворот
|
||||
if (enc1.isLeft()) Serial.println("Left");
|
||||
if (enc.isTurn()) { // любой поворот
|
||||
Serial.print("turn ");
|
||||
Serial.println(enc.counter); // вывод счётчика
|
||||
}
|
||||
|
||||
if (enc1.isRightH()) Serial.println("Right holded"); // если было удержание + поворот
|
||||
if (enc1.isLeftH()) Serial.println("Left holded");
|
||||
if (enc.isLeft()) {
|
||||
if (enc.isFast()) Serial.println("fast left");
|
||||
else Serial.println("left");
|
||||
}
|
||||
|
||||
if (enc.isRight()) {
|
||||
if (enc.isFast()) Serial.println("fast right");
|
||||
else Serial.println("right");
|
||||
}
|
||||
}
|
||||
|
||||
// функция для настройки PCINT для ATmega328 (UNO, Nano, Pro Mini)
|
||||
@ -46,16 +56,15 @@ uint8_t attachPCINT(uint8_t pin) {
|
||||
}
|
||||
|
||||
// Векторы PCINT, нужно кинуть сюда тики
|
||||
// не обязательно в каждый вектор, достаточно в тот, который задействован
|
||||
// пины 0-7: PCINT2
|
||||
// пины 8-13: PCINT0
|
||||
// пины A0-A5: PCINT1
|
||||
ISR(PCINT0_vect) {
|
||||
//enc1.tick();
|
||||
|
||||
}
|
||||
ISR(PCINT1_vect) {
|
||||
//enc1.tick();
|
||||
|
||||
}
|
||||
ISR(PCINT2_vect) {
|
||||
enc1.tick();
|
||||
enc.tick();
|
||||
}
|
||||
63
libraries/EncButton/examples/tickMode/tickMode.ino
Normal file
63
libraries/EncButton/examples/tickMode/tickMode.ino
Normal file
@ -0,0 +1,63 @@
|
||||
// Пример с прямой работой библиотеки
|
||||
|
||||
// Опциональные дефайн-настройки (показаны по умолчанию)
|
||||
//#define EB_FAST 30 // таймаут быстрого поворота, мс
|
||||
//#define EB_DEB 80 // дебаунс кнопки, мс
|
||||
//#define EB_HOLD 1000 // таймаут удержания кнопки, мс
|
||||
//#define EB_STEP 500 // период срабатывания степ, мс
|
||||
//#define EB_CLICK 400 // таймаут накликивания, мс
|
||||
|
||||
// подключение - только PULL-UP, внешний или внутренний!
|
||||
// для изменения направления энкодера поменяй A и B при инициализации
|
||||
|
||||
#include <EncButton.h>
|
||||
EncButton<EB_TICK, 2, 3, 4> enc; // энкодер с кнопкой <A, B, KEY>
|
||||
//EncButton<EB_TICK, 2, 3> enc; // просто энкодер <A, B>
|
||||
//EncButton<EB_TICK, 4> enc; // просто кнопка <KEY>
|
||||
|
||||
// по умолчанию пины настроены в INPUT_PULLUP
|
||||
// Если используется внешняя подтяжка - лучше перевести в INPUT
|
||||
//EncButton<EB_TICK, 2, 3, 4> enc(INPUT);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc.counter = 100; // изменение счётчика
|
||||
//enc.setHoldTimeout(500); // установка таймаута удержания кнопки
|
||||
}
|
||||
|
||||
void loop() {
|
||||
enc.tick();
|
||||
|
||||
if (enc.isTurn()) { // любой поворот
|
||||
Serial.print("turn ");
|
||||
Serial.println(enc.counter); // вывод счётчика
|
||||
}
|
||||
|
||||
if (enc.isLeft()) {
|
||||
if (enc.isFast()) Serial.println("fast left");
|
||||
else Serial.println("left");
|
||||
}
|
||||
|
||||
if (enc.isRight()) {
|
||||
if (enc.isFast()) Serial.println("fast right");
|
||||
else Serial.println("right");
|
||||
}
|
||||
|
||||
if (enc.isLeftH()) Serial.println("leftH");
|
||||
if (enc.isRightH()) Serial.println("rightH");
|
||||
if (enc.isClick()) Serial.println("click");
|
||||
if (enc.isHolded()) Serial.println("holded");
|
||||
if (enc.isStep()) Serial.println("step");
|
||||
|
||||
if (enc.isPress()) Serial.println("press");
|
||||
if (enc.isClick()) Serial.println("click");
|
||||
if (enc.isRelease()) Serial.println("release");
|
||||
|
||||
if (enc.hasClicks(1)) Serial.println("1 click");
|
||||
if (enc.hasClicks(2)) Serial.println("2 click");
|
||||
if (enc.hasClicks(3)) Serial.println("3 click");
|
||||
if (enc.hasClicks(5)) Serial.println("5 click");
|
||||
|
||||
if (enc.hasClicks()) Serial.println(enc.clicks);
|
||||
//if (enc.isHold()) Serial.println("hold");
|
||||
}
|
||||
35
libraries/EncButton/examples/virtual/virtual.ino
Normal file
35
libraries/EncButton/examples/virtual/virtual.ino
Normal file
@ -0,0 +1,35 @@
|
||||
#include <EncButton.h>
|
||||
|
||||
EncButton<EB_TICK, VIRT_BTN> enc; // виртуальная кнопка
|
||||
//EncButton<EB_TICK, VIRT_ENCBTN> enc; // виртуальный энк с кнопкой
|
||||
//EncButton<EB_TICK, VIRT_ENC> enc; // виртуальный энк
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
pinMode(4, INPUT_PULLUP); // подтянем пин
|
||||
//enc.setHoldTimeout(500); // установка таймаута удержания кнопки
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// tick может принимать виртуальный сигнал:
|
||||
// (сигнал кнопки)
|
||||
// (сигнал энкодера А, сигнал энкодера B)
|
||||
// (сигнал энкодера А, сигнал энкодера B, сигнал кнопки)
|
||||
enc.tick(!digitalRead(4));
|
||||
|
||||
if (enc.isClick()) Serial.println("click");
|
||||
if (enc.isHolded()) Serial.println("holded");
|
||||
if (enc.isStep()) Serial.println("step");
|
||||
|
||||
if (enc.isPress()) Serial.println("press");
|
||||
if (enc.isClick()) Serial.println("click");
|
||||
if (enc.isRelease()) Serial.println("release");
|
||||
|
||||
if (enc.hasClicks(1)) Serial.println("1 click");
|
||||
if (enc.hasClicks(2)) Serial.println("2 click");
|
||||
if (enc.hasClicks(3)) Serial.println("3 click");
|
||||
if (enc.hasClicks(5)) Serial.println("5 click");
|
||||
|
||||
if (enc.hasClicks()) Serial.println(enc.clicks);
|
||||
//if (enc.isHold()) Serial.println("hold");
|
||||
}
|
||||
66
libraries/EncButton/keywords.txt
Normal file
66
libraries/EncButton/keywords.txt
Normal file
@ -0,0 +1,66 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For EncButton
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
EncButton KEYWORD1
|
||||
|
||||
EB_FAST KEYWORD1
|
||||
EB_DEB KEYWORD1
|
||||
EB_HOLD KEYWORD1
|
||||
EB_STEP KEYWORD1
|
||||
EB_CLICK KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
tick KEYWORD2
|
||||
getState KEYWORD2
|
||||
resetState KEYWORD2
|
||||
isPress KEYWORD2
|
||||
isRelease KEYWORD2
|
||||
isFast KEYWORD2
|
||||
isTurn KEYWORD2
|
||||
isRight KEYWORD2
|
||||
isLeft KEYWORD2
|
||||
isRightH KEYWORD2
|
||||
isLeftH KEYWORD2
|
||||
isClick KEYWORD2
|
||||
isHolded KEYWORD2
|
||||
isHeld KEYWORD2
|
||||
isHold KEYWORD2
|
||||
isStep KEYWORD2
|
||||
counter KEYWORD2
|
||||
state KEYWORD2
|
||||
hasClicks KEYWORD2
|
||||
clicks KEYWORD2
|
||||
attach KEYWORD2
|
||||
detach KEYWORD2
|
||||
attachClicks KEYWORD2
|
||||
detachClicks KEYWORD2
|
||||
pullUp KEYWORD2
|
||||
holdEncButton KEYWORD2
|
||||
setHoldTimeout KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
EB_TICK LITERAL1
|
||||
EB_CALLBACK LITERAL1
|
||||
VIRT_BTN LITERAL1
|
||||
VIRT_ENC LITERAL1
|
||||
VIRT_ENCBTN LITERAL1
|
||||
TURN_HANDLER LITERAL1
|
||||
RIGHT_HANDLER LITERAL1
|
||||
LEFT_HANDLER LITERAL1
|
||||
RIGHT_H_HANDLER LITERAL1
|
||||
LEFT_H_HANDLER LITERAL1
|
||||
CLICK_HANDLER LITERAL1
|
||||
HOLDED_HANDLER LITERAL1
|
||||
STEP_HANDLER LITERAL1
|
||||
HOLD_HANDLER LITERAL1
|
||||
CLICKS_HANDLER LITERAL1
|
||||
PRESS_HANDLER LITERAL1
|
||||
RELEASE_HANDLER LITERAL1
|
||||
9
libraries/EncButton/library.properties
Normal file
9
libraries/EncButton/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=EncButton
|
||||
version=1.8
|
||||
author=AlexGyver <alex@alexgyver.ru>
|
||||
maintainer=AlexGyver <alex@alexgyver.ru>
|
||||
sentence=Light and fast library for button and encoder control
|
||||
paragraph=Light and fast library for button and encoder control
|
||||
category=Sensors
|
||||
url=https://github.com/GyverLibs/EncButton
|
||||
architectures=*
|
||||
383
libraries/EncButton/src/EncButton.h
Normal file
383
libraries/EncButton/src/EncButton.h
Normal file
@ -0,0 +1,383 @@
|
||||
/*
|
||||
Ультра лёгкая и быстрая библиотека для энкодера, энкодера с кнопкой или просто кнопки
|
||||
Документация:
|
||||
GitHub: https://github.com/GyverLibs/EncButton
|
||||
Возможности:
|
||||
- Максимально быстрое чтение пинов для AVR (ATmega328/ATmega168, ATtiny85/ATtiny13)
|
||||
- Оптимизированный вес
|
||||
- Быстрые и лёгкие алгоритмы кнопки и энкодера
|
||||
- Энкодер: поворот, нажатый поворот, быстрый поворот, счётчик
|
||||
- Кнопка: антидребезг, клик, несколько кликов, счётчик кликов, удержание, режим step
|
||||
- Подключение - только HIGH PULL!
|
||||
- Опциональный режим callback (+22б SRAM на каждый экземпляр)
|
||||
|
||||
AlexGyver, alex@alexgyver.ru
|
||||
https://alexgyver.ru/
|
||||
MIT License
|
||||
|
||||
Версии:
|
||||
v1.1 - пуллап отдельныи методом
|
||||
v1.2 - можно передать конструктору параметр INPUT_PULLUP / INPUT(умолч)
|
||||
v1.3 - виртуальное зажатие кнопки энкодера вынесено в отдельную функцию + мелкие улучшения
|
||||
v1.4 - обработка нажатия и отпускания кнопки
|
||||
v1.5 - добавлен виртуальный режим
|
||||
v1.6 - оптимизация работы в прерывании
|
||||
v1.6.1 - PULLUP по умолчанию
|
||||
v1.7 - большая оптимизация памяти, переделан FastIO
|
||||
v1.8 - индивидуальная настройка таймаута удержания кнопки (была общая на всех)
|
||||
*/
|
||||
|
||||
#ifndef EncButton_h
|
||||
#define EncButton_h
|
||||
|
||||
// =========== НАСТРОЙКИ (можно передефайнить из скетча) ============
|
||||
#define _EB_FAST 30 // таймаут быстрого поворота
|
||||
#define _EB_DEB 80 // дебаунс кнопки
|
||||
#define _EB_HOLD 1000 // таймаут удержания кнопки
|
||||
#define _EB_STEP 500 // период срабатывания степ
|
||||
#define _EB_CLICK 400 // таймаут накликивания
|
||||
|
||||
// =========== НЕ ТРОГАЙ ============
|
||||
#include <Arduino.h>
|
||||
#include "FastIO_v2.h"
|
||||
// флаг макро
|
||||
#define _setFlag(x) (flags |= 1 << x)
|
||||
#define _clrFlag(x) (flags &= ~(1 << x))
|
||||
#define _readFlag(x) ((flags >> x) & 1)
|
||||
|
||||
#ifndef EB_FAST
|
||||
#define EB_FAST _EB_FAST
|
||||
#endif
|
||||
#ifndef EB_DEB
|
||||
#define EB_DEB _EB_DEB
|
||||
#endif
|
||||
#ifndef EB_HOLD
|
||||
#define EB_HOLD _EB_HOLD
|
||||
#endif
|
||||
#ifndef EB_STEP
|
||||
#define EB_STEP _EB_STEP
|
||||
#endif
|
||||
#ifndef EB_CLICK
|
||||
#define EB_CLICK _EB_CLICK
|
||||
#endif
|
||||
|
||||
enum eb_callback {
|
||||
TURN_HANDLER,
|
||||
RIGHT_HANDLER,
|
||||
LEFT_HANDLER,
|
||||
RIGHT_H_HANDLER,
|
||||
LEFT_H_HANDLER,
|
||||
CLICK_HANDLER,
|
||||
HOLDED_HANDLER,
|
||||
STEP_HANDLER,
|
||||
HOLD_HANDLER,
|
||||
CLICKS_HANDLER,
|
||||
PRESS_HANDLER,
|
||||
RELEASE_HANDLER,
|
||||
};
|
||||
|
||||
// константы
|
||||
#define EB_TICK 0
|
||||
#define EB_CALLBACK 1
|
||||
|
||||
#define EB_NO_PIN 255
|
||||
|
||||
#define VIRT_ENC 254
|
||||
#define VIRT_ENCBTN 253
|
||||
#define VIRT_BTN 252
|
||||
|
||||
// класс
|
||||
template < uint8_t _EB_MODE, uint8_t _S1 = EB_NO_PIN, uint8_t _S2 = EB_NO_PIN, uint8_t _KEY = EB_NO_PIN >
|
||||
class EncButton {
|
||||
public:
|
||||
// можно указать режим работы пина
|
||||
EncButton(const uint8_t mode = INPUT_PULLUP) {
|
||||
if (_S1 < 252 && mode == INPUT_PULLUP) pullUp();
|
||||
}
|
||||
|
||||
// подтянуть пины внутренней подтяжкой
|
||||
void pullUp() {
|
||||
if (_S1 < 252) { // реальное устройство
|
||||
if (_S2 == EB_NO_PIN) { // обычная кнопка
|
||||
pinMode(_S1, INPUT_PULLUP);
|
||||
} else if (_KEY == EB_NO_PIN) { // энк без кнопки
|
||||
pinMode(_S1, INPUT_PULLUP);
|
||||
pinMode(_S2, INPUT_PULLUP);
|
||||
} else { // энк с кнопкой
|
||||
pinMode(_S1, INPUT_PULLUP);
|
||||
pinMode(_S2, INPUT_PULLUP);
|
||||
pinMode(_KEY, INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// установить таймаут удержания кнопки для isHold(), мс (до 30 000)
|
||||
void setHoldTimeout(int tout) {
|
||||
_holdT = tout >> 7;
|
||||
}
|
||||
|
||||
// виртуально зажать кнопку энкодера
|
||||
void holdEncButton(bool state) {
|
||||
if (state) _setFlag(7);
|
||||
else _clrFlag(7);
|
||||
}
|
||||
|
||||
// тикер, вызывать как можно чаще или в прерывании
|
||||
// вернёт отличное от нуля значение, если произошло какое то событие
|
||||
uint8_t tick(uint8_t s1 = 0, uint8_t s2 = 0, uint8_t key = 0) {
|
||||
if (!_isrFlag) {
|
||||
_isrFlag = 1;
|
||||
|
||||
// обработка энка (компилятор вырежет блок если не используется)
|
||||
// если объявлены два пина или выбран вирт. энкодер или энкодер с кнопкой
|
||||
if ((_S1 < 252 && _S2 < 252) || _S1 == VIRT_ENC || _S1 == VIRT_ENCBTN) {
|
||||
uint8_t state;
|
||||
if (_S1 >= 252) state = s1 | (s2 << 1); // получаем код
|
||||
else state = F_fastRead(_S1) | (F_fastRead(_S2) << 1); // получаем код
|
||||
poolEnc(state);
|
||||
}
|
||||
|
||||
// обработка кнопки (компилятор вырежет блок если не используется)
|
||||
// если S2 не указан (кнопка) или указан KEY или выбран вирт. энкодер с кнопкой или кнопка
|
||||
if ((_S1 < 252 && _S2 == EB_NO_PIN) || _KEY != EB_NO_PIN || _S1 == VIRT_BTN || _S1 == VIRT_ENCBTN) {
|
||||
if (_S1 < 252 && _S2 == EB_NO_PIN) _btnState = !F_fastRead(_S1); // обычная кнопка
|
||||
if (_KEY != EB_NO_PIN) _btnState = !F_fastRead(_KEY); // энк с кнопкой
|
||||
if (_S1 == VIRT_BTN) _btnState = s1; // вирт кнопка
|
||||
if (_S1 == VIRT_ENCBTN) _btnState = key; // вирт энк с кнопкой
|
||||
poolBtn();
|
||||
}
|
||||
|
||||
if (_EB_MODE) {
|
||||
if (*_callback[0] && isTurn()) _callback[0]();
|
||||
switch (EBState) {
|
||||
case 1: if (*_callback[1]) _callback[1](); break; // isRight
|
||||
case 2: if (*_callback[2]) _callback[2](); break; // isLeft
|
||||
case 3: if (*_callback[3]) _callback[3](); break; // isRightH
|
||||
case 4: if (*_callback[4]) _callback[4](); break; // isLeftH
|
||||
case 5: if (*_callback[5]) _callback[5](); break; // isClick
|
||||
case 6: if (*_callback[6]) _callback[6](); break; // isHolded
|
||||
case 7: if (*_callback[7]) _callback[7](); break; // isStep
|
||||
case 8: if (*_callback[11]) _callback[11](); break; // isPress
|
||||
case 9: if (*_callback[12]) _callback[12](); break; // isRelease
|
||||
}
|
||||
EBState = 0;
|
||||
if (*_callback[8] && _readFlag(4)) _callback[8](); // isHold
|
||||
if (_readFlag(6)) {
|
||||
if (*_callback[9]) _callback[9](); // clicks
|
||||
if (*_callback[10] && clicks == _amount) _callback[10]();
|
||||
_clrFlag(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
_isrFlag = 0;
|
||||
return EBState;
|
||||
}
|
||||
|
||||
// подключить обработчик
|
||||
void attach(eb_callback type, void (*handler)()) {
|
||||
_callback[type] = *handler;
|
||||
}
|
||||
|
||||
// отключить обработчик
|
||||
void detach(eb_callback type) {
|
||||
_callback[type] = NULL;
|
||||
}
|
||||
|
||||
// подключить обработчик на количество кликов (может быть только один!)
|
||||
void attachClicks(uint8_t amount, void (*handler)()) {
|
||||
_amount = amount;
|
||||
_callback[10] = *handler;
|
||||
}
|
||||
|
||||
// отключить обработчик на количество кликов
|
||||
void detachClicks() {
|
||||
_callback[10] = NULL;
|
||||
}
|
||||
|
||||
// получить статус
|
||||
uint8_t getState() { return EBState; }
|
||||
|
||||
// сбросить статус
|
||||
void resetState() { EBState = 0; }
|
||||
|
||||
// поворот вправо
|
||||
bool isRight() { return _EB_MODE ? (_dir == 1 ? 1 : 0) : checkState(1); }
|
||||
|
||||
// поворот влево
|
||||
bool isLeft() { return _EB_MODE ? (_dir == 2 ? 1 : 0) : checkState(2); }
|
||||
|
||||
// поворот вправо нажатый
|
||||
bool isRightH() { return _EB_MODE ? (_dir == 3 ? 1 : 0) : checkState(3); }
|
||||
|
||||
// поворот влево нажатый
|
||||
bool isLeftH() { return _EB_MODE ? (_dir == 4 ? 1 : 0) : checkState(4); }
|
||||
|
||||
// быстрый поворот
|
||||
bool isFast() { return _readFlag(1); }
|
||||
|
||||
// энкодер повёрнут
|
||||
bool isTurn() {
|
||||
if (_readFlag(0)) {
|
||||
_clrFlag(0);
|
||||
return true;
|
||||
} return false;
|
||||
}
|
||||
|
||||
// кнопка нажата
|
||||
bool isPress() { return checkState(8); }
|
||||
|
||||
// кнопка отпущена
|
||||
bool isRelease() { return checkState(9); }
|
||||
|
||||
// клик по кнопке
|
||||
bool isClick() { return checkState(5); }
|
||||
|
||||
// кнопка удержана
|
||||
bool isHolded() { return checkState(6); }
|
||||
|
||||
// кнопка удержана (грамотный аналог holded =)
|
||||
bool isHeld() { return checkState(6); }
|
||||
|
||||
// кнопка удерживается
|
||||
bool isHold() { return _readFlag(4); }
|
||||
|
||||
// режим импульсного удержания
|
||||
bool isStep() { return checkState(7); }
|
||||
|
||||
// статус кнопки
|
||||
bool state() { return !F_fastRead(_S1); }
|
||||
|
||||
// имеются клики
|
||||
bool hasClicks(uint8_t numClicks) {
|
||||
if (clicks == numClicks && _readFlag(6)) {
|
||||
_clrFlag(6);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// имеются клики
|
||||
uint8_t hasClicks() {
|
||||
if (_readFlag(6)) {
|
||||
_clrFlag(6);
|
||||
return clicks;
|
||||
} return 0;
|
||||
}
|
||||
|
||||
// счётчик энкодера
|
||||
int counter = 0;
|
||||
|
||||
// счётчик кликов
|
||||
uint8_t clicks = 0;
|
||||
|
||||
private:
|
||||
void poolEnc(uint8_t state) {
|
||||
if (_encRST && state == 0b11) { // ресет и энк защёлкнул позицию
|
||||
if (_S2 == EB_NO_PIN || _KEY != EB_NO_PIN) { // энкодер с кнопкой
|
||||
if (!_readFlag(4)) { // если кнопка не "удерживается"
|
||||
if (_lastState == 0b10) EBState = (_btnState || _readFlag(7)) ? 3 : 1, counter++;
|
||||
else if (_lastState == 0b01) EBState = (_btnState || _readFlag(7)) ? 4 : 2, counter--;
|
||||
}
|
||||
} else { // просто энкодер
|
||||
if (_lastState == 0b10) EBState = 1, counter++;
|
||||
else if (_lastState == 0b01) EBState = 2, counter--;
|
||||
}
|
||||
if (EBState > 0) {
|
||||
if (_EB_MODE) _dir = EBState;
|
||||
if (millis() - _debTimer < EB_FAST) _setFlag(1); // быстрый поворот
|
||||
else _clrFlag(1); // обычный поворот
|
||||
if (EBState < 5) _setFlag(0); // флаг поворота для юзера
|
||||
}
|
||||
|
||||
_encRST = 0;
|
||||
_debTimer = millis();
|
||||
}
|
||||
if (state == 0b00) _encRST = 1;
|
||||
_lastState = state;
|
||||
}
|
||||
|
||||
void poolBtn() {
|
||||
uint32_t thisMls = millis();
|
||||
uint32_t debounce = thisMls - _debTimer;
|
||||
if (_btnState) { // кнопка нажата
|
||||
if (!_readFlag(3)) { // и не была нажата ранее
|
||||
if (debounce > EB_DEB) { // и прошел дебаунс
|
||||
_setFlag(3); // флаг кнопка была нажата
|
||||
_debTimer = thisMls; // сброс таймаутов
|
||||
EBState = 8; // кнопка нажата
|
||||
}
|
||||
if (debounce > EB_CLICK) { // кнопка нажата после EB_CLICK
|
||||
clicks = 0; // сбросить счётчик и флаг кликов
|
||||
flags &= ~0b01100000;
|
||||
}
|
||||
} else { // кнопка уже была нажата
|
||||
if (!_readFlag(4)) { // и удержание ещё не зафиксировано
|
||||
if (debounce < (_holdT << 7)) { // прошло меньше удержания
|
||||
if (EBState != 0 && EBState != 8) _setFlag(2); // но энкодер повёрнут! Запомнили
|
||||
} else { // прошло больше времени удержания
|
||||
if (!_readFlag(2)) { // и энкодер не повёрнут
|
||||
EBState = 6; // значит это удержание (сигнал)
|
||||
_setFlag(4); // запомнили что удерживается
|
||||
_debTimer = thisMls; // сброс таймаута
|
||||
}
|
||||
}
|
||||
} else { // удержание зафиксировано
|
||||
if (debounce > EB_STEP) { // таймер степа
|
||||
EBState = 7; // сигналим
|
||||
_debTimer = thisMls; // сброс таймаута
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // кнопка не нажата
|
||||
if (_readFlag(3)) { // но была нажата
|
||||
if (debounce > EB_DEB && !_readFlag(4) && !_readFlag(2)) { // энкодер не трогали и не удерживали - это клик
|
||||
EBState = 5;
|
||||
clicks++;
|
||||
} else EBState = 9; // кнопка отпущена
|
||||
flags &= ~0b00011100; // clear 2 3 4
|
||||
_debTimer = thisMls; // сброс таймаута
|
||||
} else if (clicks > 0 && debounce > EB_CLICK && !_readFlag(5)) flags |= 0b01100000; // флаг на клики
|
||||
}
|
||||
}
|
||||
|
||||
bool checkState(uint8_t val) {
|
||||
if (EBState == val) {
|
||||
EBState = 0;
|
||||
return 1;
|
||||
} return 0;
|
||||
}
|
||||
uint32_t _debTimer = 0;
|
||||
uint8_t _lastState = 0, EBState = 0;
|
||||
bool _btnState = 0, _encRST = 0, _isrFlag = 0;
|
||||
uint8_t flags = 0;
|
||||
uint8_t _holdT = EB_HOLD >> 7;
|
||||
|
||||
uint8_t _dir = 0;
|
||||
void (*_callback[_EB_MODE ? 13 : 0])() = {};
|
||||
uint8_t _amount = 0;
|
||||
|
||||
|
||||
// flags
|
||||
// 0 - enc turn
|
||||
// 1 - enc fast
|
||||
// 2 - enc был поворот
|
||||
// 3 - флаг кнопки
|
||||
// 4 - hold
|
||||
// 5 - clicks flag
|
||||
// 6 - clicks get
|
||||
// 7 - enc button hold
|
||||
|
||||
// EBState
|
||||
// 0 - idle
|
||||
// 1 - right
|
||||
// 2 - left
|
||||
// 3 - rightH
|
||||
// 4 - leftH
|
||||
// 5 - click
|
||||
// 6 - holded
|
||||
// 7 - step
|
||||
// 8 - press
|
||||
// 9 - release
|
||||
};
|
||||
|
||||
#endif
|
||||
93
libraries/EncButton/src/FastIO_v2.cpp
Normal file
93
libraries/EncButton/src/FastIO_v2.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "FastIO_v2.h"
|
||||
|
||||
bool F_fastRead(const uint8_t pin) {
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||
if (pin < 8) return bitRead(PIND, pin);
|
||||
else if (pin < 14) return bitRead(PINB, pin - 8);
|
||||
else if (pin < 20) return bitRead(PINC, pin - 14);
|
||||
|
||||
#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
|
||||
return bitRead(PINB, pin);
|
||||
|
||||
#elif defined(AVR)
|
||||
uint8_t *_pin_reg = portInputRegister(digitalPinToPort(pin));
|
||||
uint8_t _bit_mask = digitalPinToBitMask(pin);
|
||||
return bool(*_pin_reg & _bit_mask);
|
||||
|
||||
#else
|
||||
return digitalRead(pin);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void F_fastWrite(const uint8_t pin, bool val) {
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||
if (pin < 8) bitWrite(PORTD, pin, val);
|
||||
else if (pin < 14) bitWrite(PORTB, (pin - 8), val);
|
||||
else if (pin < 20) bitWrite(PORTC, (pin - 14), val);
|
||||
|
||||
#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
|
||||
bitWrite(PORTB, pin, val);
|
||||
|
||||
#elif defined(AVR)
|
||||
uint8_t *_port_reg = portInputRegister(digitalPinToPort(pin));
|
||||
uint8_t _bit_mask = digitalPinToBitMask(pin);
|
||||
_port_reg = portOutputRegister(digitalPinToPort(pin));
|
||||
_bit_mask = digitalPinToBitMask(pin);
|
||||
if (val) *_port_reg |= _bit_mask; // HIGH
|
||||
else *_port_reg &= ~_bit_mask; // LOW
|
||||
|
||||
#else
|
||||
digitalWrite(pin, val);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t F_fastShiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
||||
#if defined(AVR)
|
||||
volatile uint8_t *_clk_port = portOutputRegister(digitalPinToPort(clockPin));
|
||||
volatile uint8_t *_dat_port = portInputRegister(digitalPinToPort(dataPin));
|
||||
uint8_t _clk_mask = digitalPinToBitMask(clockPin);
|
||||
uint8_t _dat_mask = digitalPinToBitMask(dataPin);
|
||||
uint8_t data = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
*_clk_port |= _clk_mask;
|
||||
if (bitOrder == MSBFIRST) {
|
||||
data <<= 1;
|
||||
if (bool(*_dat_port & _dat_mask)) data |= 1;
|
||||
} else {
|
||||
data >>= 1;
|
||||
if (bool(*_dat_port & _dat_mask)) data |= 1 << 7;
|
||||
}
|
||||
*_clk_port &= ~_clk_mask;
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
return shiftIn(dataPin, clockPin, bitOrder);
|
||||
#endif
|
||||
}
|
||||
|
||||
void F_fastShiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t data) {
|
||||
#if defined(AVR)
|
||||
volatile uint8_t *_clk_port = portOutputRegister(digitalPinToPort(clockPin));
|
||||
volatile uint8_t *_dat_port = portOutputRegister(digitalPinToPort(dataPin));
|
||||
uint8_t _clk_mask = digitalPinToBitMask(clockPin);
|
||||
uint8_t _dat_mask = digitalPinToBitMask(dataPin);
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (bitOrder == MSBFIRST) {
|
||||
if (data & (1 << 7)) *_dat_port |= _dat_mask;
|
||||
else *_dat_port &= ~_dat_mask;
|
||||
data <<= 1;
|
||||
} else {
|
||||
if (data & 1) *_dat_port |= _dat_mask;
|
||||
else *_dat_port &= ~_dat_mask;
|
||||
data >>= 1;
|
||||
}
|
||||
*_clk_port |= _clk_mask;
|
||||
*_clk_port &= ~_clk_mask;
|
||||
}
|
||||
#else
|
||||
shiftOut(dataPin, clockPin, bitOrder, data);
|
||||
#endif
|
||||
}
|
||||
13
libraries/EncButton/src/FastIO_v2.h
Normal file
13
libraries/EncButton/src/FastIO_v2.h
Normal file
@ -0,0 +1,13 @@
|
||||
// Быстрый IO для AVR (для остальных будет digitalxxxxx)
|
||||
// v1.0
|
||||
|
||||
#ifndef _FastIO_v2_h
|
||||
#define _FastIO_v2_h
|
||||
#include <Arduino.h>
|
||||
|
||||
bool F_fastRead(const uint8_t pin); // быстрое чтение пина
|
||||
void F_fastWrite(const uint8_t pin, bool val); // быстрая запись
|
||||
uint8_t F_fastShiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); // быстрый shiftIn
|
||||
void F_fastShiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t data); // быстрый shiftOut
|
||||
|
||||
#endif
|
||||
@ -1,149 +0,0 @@
|
||||

|
||||

|
||||
# GyverEncoder
|
||||
Библиотека для расширенной работы с энкодером
|
||||
**ВНИМАНИЕ, БИБЛИОТЕКА УСТАРЕЛА! ИСПОЛЬЗУЙ БИБЛИОТЕКУ [EncButton](https://github.com/GyverLibs/EncButton)**
|
||||
- Отработка поворота энкодера
|
||||
- Отработка "нажатого поворота"
|
||||
- Отработка "быстрого поворота"
|
||||
- Несколько алгоритмов опроса энкодера
|
||||
- Выбор подтяжки подключения энкодера
|
||||
- Работа с двумя типами экнодеров
|
||||
- Работа с внешним энкодером (через расширитель пинов и т.п.)
|
||||
- Отработка нажатия/удержания кнопки с антидребезгом
|
||||
|
||||
### Совместимость
|
||||
Совместима со всеми Arduino платформами (используются Arduino-функции)
|
||||
|
||||
### Документация
|
||||
К библиотеке есть [расширенная документация](https://alexgyver.ru/encoder/)
|
||||
|
||||
## Содержание
|
||||
- [Установка](#install)
|
||||
- [Инициализация](#init)
|
||||
- [Использование](#usage)
|
||||
- [Пример](#example)
|
||||
- [Версии](#versions)
|
||||
- [Баги и обратная связь](#feedback)
|
||||
|
||||
<a id="install"></a>
|
||||
## Установка
|
||||
- Библиотеку можно найти по названию **GyverEncoder** и установить через менеджер библиотек в:
|
||||
- Arduino IDE
|
||||
- Arduino IDE v2
|
||||
- PlatformIO
|
||||
- [Скачать библиотеку](https://github.com/GyverLibs/GyverEncoder/archive/refs/heads/main.zip) .zip архивом для ручной установки:
|
||||
- Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64)
|
||||
- Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32)
|
||||
- Распаковать и положить в *Документы/Arduino/libraries/*
|
||||
- (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив
|
||||
- Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
|
||||
|
||||
<a id="init"></a>
|
||||
## Инициализация
|
||||
```cpp
|
||||
Encoder enc; // не привязан к пину
|
||||
Encoder enc(пин CLK, пин DT); // энкодер без кнопки (ускоренный опрос)
|
||||
Encoder enc(пин CLK, пин DT, пин SW); // энкодер с кнопкой
|
||||
Encoder enc(пин CLK, пин DT, пин SW, тип); // энкодер с кнопкой и указанием типа
|
||||
Encoder enc(пин CLK, пин DT, ENC_NO_BUTTON, тип); // энкодер без кнопкой и с указанием типа
|
||||
```
|
||||
|
||||
<a id="usage"></a>
|
||||
## Использование
|
||||
```cpp
|
||||
void tick(); // опрос энкодера, нужно вызывать постоянно или в прерывании
|
||||
void setType(boolean type); // TYPE1 / TYPE2 - тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
|
||||
void setTickMode(boolean tickMode); // MANUAL / AUTO - ручной или автоматический опрос энкодера функцией tick(). (по умолчанию ручной)
|
||||
void setDirection(boolean direction); // NORM / REVERSE - направление вращения энкодера
|
||||
void setFastTimeout(int timeout); // установка таймаута быстрого поворота
|
||||
void setPinMode(bool mode); // тип подключения энкодера, подтяжка HIGH_PULL (внутренняя) или LOW_PULL (внешняя на GND)
|
||||
void setBtnPinMode(bool mode); // тип подключения кнопки, подтяжка HIGH_PULL (внутренняя) или LOW_PULL (внешняя на GND)
|
||||
|
||||
boolean isTurn(); // возвращает true при любом повороте, сама сбрасывается в false
|
||||
boolean isRight(); // возвращает true при повороте направо, сама сбрасывается в false
|
||||
boolean isLeft(); // возвращает true при повороте налево, сама сбрасывается в false
|
||||
boolean isRightH(); // возвращает true при удержании кнопки и повороте направо, сама сбрасывается в false
|
||||
boolean isLeftH(); // возвращает true при удержании кнопки и повороте налево, сама сбрасывается в false
|
||||
boolean isFastR(); // возвращает true при быстром повороте
|
||||
boolean isFastL(); // возвращает true при быстром повороте
|
||||
|
||||
boolean isPress(); // возвращает true при нажатии кнопки, сама сбрасывается в false
|
||||
boolean isRelease(); // возвращает true при отпускании кнопки, сама сбрасывается в false
|
||||
boolean isClick(); // возвращает true при нажатии и отпускании кнопки, сама сбрасывается в false
|
||||
boolean isHolded(); // возвращает true при удержании кнопки, сама сбрасывается в false
|
||||
boolean isHold(); // возвращает true при удержании кнопки, НЕ СБРАСЫВАЕТСЯ
|
||||
boolean isSingle(); // возвращает true при одиночном клике (после таймаута), сама сбрасывается в false
|
||||
boolean isDouble(); // возвращает true при двойном клике, сама сбрасывается в false
|
||||
void resetStates(); // сбрасывает все is-флаги
|
||||
```
|
||||
|
||||
<a id="example"></a>
|
||||
## Пример
|
||||
Остальные примеры смотри в **examples**!
|
||||
```cpp
|
||||
#define CLK 2
|
||||
#define DT 3
|
||||
#define SW 4
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1(CLK, DT, SW); // для работы c кнопкой
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE2);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// обязательная функция отработки. Должна постоянно опрашиваться
|
||||
enc1.tick();
|
||||
|
||||
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"); // то же самое, что isClick
|
||||
|
||||
if (enc1.isClick()) Serial.println("Click"); // одиночный клик
|
||||
if (enc1.isSingle()) Serial.println("Single"); // одиночный клик (с таймаутом для двойного)
|
||||
if (enc1.isDouble()) Serial.println("Double"); // двойной клик
|
||||
|
||||
|
||||
if (enc1.isHolded()) Serial.println("Holded"); // если была удержана и энк не поворачивался
|
||||
//if (enc1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки
|
||||
}
|
||||
```
|
||||
|
||||
<a id="versions"></a>
|
||||
## Версии
|
||||
- v3.6 от 16.09.2019 - Возвращены дефайны настроек
|
||||
- v4.0 от 13.11.2019
|
||||
- Оптимизирован код
|
||||
- Исправлены баги
|
||||
- Добавлены другие алгоритмы опроса
|
||||
- Добавлена возможность полностью убрать кнопку (экономия памяти)
|
||||
- Добавлена возможность подключения внешнего энкодера
|
||||
- Добавлена настройка подтяжки пинов
|
||||
- v4.1: Исправлено изменение подтяжек
|
||||
- v4.2
|
||||
- Добавлена поддержка TYPE1 для алгоритма PRECISE_ALGORITHM
|
||||
- Добавлена отработка двойного клика: isSingle / isDouble
|
||||
- v4.3: Исправлено ложное isSingle
|
||||
- v4.4: Добавлен метод resetStates, сбрасывает все is-флаги и счётчики
|
||||
- v4.5: Улучшен алгоритм BINARY_ALGORITHM (спасибо Ярославу Курусу)
|
||||
- v4.6: BINARY_ALGORITHM пофикшен для TYPE1, добавлена isReleaseHold
|
||||
- v4.7: Исправлен случайный нажатый поворот в BINARY_ALGORITHM
|
||||
- v4.8: увеличена производительность для AVR Arduino
|
||||
- v4.9: быстрый поворот отключен если кнопка удерживается
|
||||
|
||||
<a id="feedback"></a>
|
||||
## Баги и обратная связь
|
||||
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
|
||||
Библиотека открыта для доработки и ваших **Pull Request**'ов!
|
||||
@ -1,28 +0,0 @@
|
||||
/*
|
||||
В последнее время китайцы стали делать одинаковые модули (ку 40)
|
||||
с разными типами энкодеров - полный период и полпериода.
|
||||
Если ваш энкодер ведёт себя странно (один тик считает за два поворота),
|
||||
то смените тип энкодера
|
||||
*/
|
||||
|
||||
#define CLK 4
|
||||
#define DT 3
|
||||
#define SW 2
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1(CLK, DT, SW);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// обязательная функция отработки. Должна постоянно опрашиваться
|
||||
enc1.tick();
|
||||
|
||||
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");
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
#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"); // возвращает состояние кнопки
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
#define CLK 2
|
||||
#define DT 3
|
||||
#define SW 4
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
//Encoder enc1(CLK, DT); // для работы без кнопки
|
||||
Encoder enc1(CLK, DT, SW); // для работы c кнопкой
|
||||
//Encoder enc1(CLK, DT, SW, TYPE2); // для работы c кнопкой и сразу выбираем тип
|
||||
//Encoder enc1(CLK, DT, ENC_NO_BUTTON, TYPE2); // для работы без кнопки и сразу выбираем тип
|
||||
|
||||
// Варианты инициализации:
|
||||
// Encoder enc; // не привязан к пину
|
||||
// Encoder enc(пин CLK, пин DT); // энкодер без кнопки (ускоренный опрос)
|
||||
// Encoder enc(пин CLK, пин DT, пин SW); // энкодер с кнопкой
|
||||
// Encoder enc(пин CLK, пин DT, пин SW, тип); // энкодер с кнопкой и указанием типа
|
||||
// Encoder enc(пин CLK, пин DT, ENC_NO_BUTTON, тип); // энкодер без кнопкой и с указанием типа
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE2);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// обязательная функция отработки. Должна постоянно опрашиваться
|
||||
enc1.tick();
|
||||
|
||||
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"); // то же самое, что isClick
|
||||
|
||||
if (enc1.isClick()) Serial.println("Click"); // одиночный клик
|
||||
if (enc1.isSingle()) Serial.println("Single"); // одиночный клик (с таймаутом для двойного)
|
||||
if (enc1.isDouble()) Serial.println("Double"); // двойной клик
|
||||
|
||||
|
||||
if (enc1.isHolded()) Serial.println("Holded"); // если была удержана и энк не поворачивался
|
||||
//if (enc1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
#define CLK 2
|
||||
#define DT 3
|
||||
#define SW 4
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1(CLK, DT, SW);
|
||||
|
||||
int value = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE1); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип\=
|
||||
enc1.setFastTimeout(40); // таймаут на скорость isFastR. По умолч. 50
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// обязательная функция отработки. Должна постоянно опрашиваться
|
||||
enc1.tick();
|
||||
|
||||
if (enc1.isRight()) value++; // если был поворот направо, увеличиваем на 1
|
||||
if (enc1.isLeft()) value--; // если был поворот налево, уменьшаем на 1
|
||||
|
||||
if (enc1.isRightH()) value += 5; // если было удержание + поворот направо, увеличиваем на 5
|
||||
if (enc1.isLeftH()) value -= 5; // если было удержание + поворот налево, уменьшаем на 5
|
||||
|
||||
if (enc1.isFastR()) value += 10; // если был быстрый поворот направо, увеличиваем на 10
|
||||
if (enc1.isFastL()) value -= 10; // если был быстрый поворот налево, уменьшаем на 10
|
||||
|
||||
if (enc1.isTurn()) { // если был совершён поворот (индикатор поворота в любую сторону)
|
||||
Serial.println(value); // выводим значение при повороте
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
/*
|
||||
Пример работы с энкодером с прерыванием. Максимальная чёткость работы
|
||||
в любом быдлокоде!
|
||||
*/
|
||||
|
||||
#define CLK 2
|
||||
#define DT 3
|
||||
#define SW 4
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1(CLK, DT, SW);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
attachInterrupt(0, isrCLK, CHANGE); // прерывание на 2 пине! CLK у энка
|
||||
attachInterrupt(1, isrDT, CHANGE); // прерывание на 3 пине! DT у энка
|
||||
}
|
||||
|
||||
void isrCLK() {
|
||||
enc1.tick(); // отработка в прерывании
|
||||
}
|
||||
void isrDT() {
|
||||
enc1.tick(); // отработка в прерывании
|
||||
}
|
||||
|
||||
void loop() {
|
||||
enc1.tick();
|
||||
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");
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
// подключаем "внешний" энкодер, для работы с расширителями пинов например
|
||||
|
||||
#define SW 0
|
||||
#define DT 2
|
||||
#define CLK 3
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE2);
|
||||
pinMode(SW, INPUT_PULLUP);
|
||||
pinMode(CLK, INPUT);
|
||||
pinMode(DT, INPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// подаём значения напрямую в tick()
|
||||
// можно подавать лог. величины с любых расширителей пинов!!!
|
||||
// Здесь в качестве примера digitalRead
|
||||
enc1.tick(digitalRead(CLK), digitalRead(DT), !digitalRead(SW));
|
||||
|
||||
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.isClick()) Serial.println("Click"); // отпускание кнопки (+ дебаунс)
|
||||
//if (enc1.isRelease()) Serial.println("Release"); // то же самое, что isClick
|
||||
|
||||
if (enc1.isHolded()) Serial.println("Holded"); // если была удержана и энк не поворачивался
|
||||
//if (enc1.isHold()) Serial.println("Hold"); // возвращает состояние кнопки
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Отработка по прерыванию таймера
|
||||
*/
|
||||
|
||||
#define CLK 7
|
||||
#define DT 8
|
||||
#define SW 9
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
#include "TimerOne.h"
|
||||
Encoder enc1(CLK, DT, SW);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
|
||||
|
||||
Timer1.initialize(1000); // установка таймера на каждые 1000 микросекунд (= 1 мс)
|
||||
Timer1.attachInterrupt(timerIsr); // запуск таймера
|
||||
}
|
||||
|
||||
void timerIsr() { // прерывание таймера
|
||||
enc1.tick(); // отработка теперь находится здесь
|
||||
}
|
||||
|
||||
void loop() {
|
||||
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");
|
||||
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
// два энкодера
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
Encoder enc1(4, 3, 2);
|
||||
Encoder enc2(7, 6, 5);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// обязательная функция отработки. Должна постоянно опрашиваться
|
||||
enc1.tick();
|
||||
enc2.tick();
|
||||
|
||||
if (enc1.isLeft()) Serial.println("enc 1 left");
|
||||
if (enc1.isRight()) Serial.println("enc 1 right");
|
||||
if (enc2.isLeft()) Serial.println("enc 2 left");
|
||||
if (enc2.isRight()) Serial.println("enc 2 right");
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
#define CLK 7
|
||||
#define DT 8
|
||||
#define SW 9
|
||||
|
||||
#include "GyverEncoder.h"
|
||||
//Encoder enc1(CLK, DT); // для работы без кнопки
|
||||
Encoder enc1(CLK, DT, SW); // для работы c кнопкой
|
||||
//Encoder enc1(CLK, DT, SW, TYPE2); // для работы c кнопкой и сразу выбираем тип
|
||||
//Encoder enc1(CLK, DT, ENC_NO_BUTTON, TYPE2); // для работы без кнопки и сразу выбираем тип
|
||||
|
||||
int value = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// обязательная функция отработки. Должна постоянно опрашиваться
|
||||
enc1.tick();
|
||||
|
||||
if (enc1.isRight()) value++; // если был поворот направо, увеличиваем на 1
|
||||
if (enc1.isLeft()) value--; // если был поворот налево, уменьшаем на 1
|
||||
|
||||
if (enc1.isRightH()) value += 5; // если было удержание + поворот направо, увеличиваем на 5
|
||||
if (enc1.isLeftH()) value -= 5; // если было удержание + поворот налево, уменьшаем на 5
|
||||
|
||||
if (enc1.isTurn()) { // если был совершён поворот (индикатор поворота в любую сторону)
|
||||
Serial.println(value); // выводим значение при повороте
|
||||
}
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For GyverEncoder
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Encoder KEYWORD1
|
||||
GyverEncoder KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
tick KEYWORD2
|
||||
setType KEYWORD2
|
||||
setDirection KEYWORD2
|
||||
setFastTimeout KEYWORD2
|
||||
setPinMode KEYWORD2
|
||||
setBtnPinMode KEYWORD2
|
||||
isTurn KEYWORD2
|
||||
isRight KEYWORD2
|
||||
isLeft KEYWORD2
|
||||
isRightH KEYWORD2
|
||||
isLeftH KEYWORD2
|
||||
isFastR KEYWORD2
|
||||
isFastL KEYWORD2
|
||||
|
||||
isPress KEYWORD2
|
||||
isRelease KEYWORD2
|
||||
isReleaseHold KEYWORD2
|
||||
isClick KEYWORD2
|
||||
isSingle KEYWORD2
|
||||
isDouble KEYWORD2
|
||||
isHolded KEYWORD2
|
||||
isHold KEYWORD2
|
||||
resetStates KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
TYPE1 LITERAL1
|
||||
TYPE2 LITERAL1
|
||||
MANUAL LITERAL1
|
||||
AUTO LITERAL1
|
||||
NORM LITERAL1
|
||||
REVERSE LITERAL1
|
||||
HIGH_PULL LITERAL1
|
||||
LOW_PULL LITERAL1
|
||||
ENC_NO_BUTTON LITERAL1
|
||||
@ -1,9 +0,0 @@
|
||||
name=GyverEncoder
|
||||
version=4.9
|
||||
author=AlexGyver <alex@alexgyver.ru>
|
||||
maintainer=AlexGyver <alex@alexgyver.ru>
|
||||
sentence=Advanced encoder control library
|
||||
paragraph=Advanced encoder control library
|
||||
category=Sensors
|
||||
url=https://github.com/GyverLibs/GyverEncoder
|
||||
architectures=*
|
||||
@ -1,352 +0,0 @@
|
||||
#include "GyverEncoder.h"
|
||||
|
||||
#if defined(PRECISE_ALGORITHM)
|
||||
const int8_t KNOBDIR[] = {
|
||||
0, -1, 1, 0,
|
||||
1, 0, 0, -1,
|
||||
-1, 0, 0, 1,
|
||||
0, 1, -1, 0,
|
||||
};
|
||||
int8_t encPos = 0;
|
||||
#endif
|
||||
|
||||
// ================= CONSTRUCTOR =================
|
||||
Encoder::Encoder() {
|
||||
flags.use_button = true;
|
||||
}
|
||||
|
||||
Encoder::Encoder(uint8_t clk, uint8_t dt, int8_t sw, bool type) {
|
||||
_CLK = clk;
|
||||
_DT = dt;
|
||||
if (sw != -1) {
|
||||
_SW = sw;
|
||||
flags.use_button = true;
|
||||
} else {
|
||||
flags.use_button = false;
|
||||
}
|
||||
flags.enc_type = type;
|
||||
|
||||
#if defined(__AVR__)
|
||||
_pin_reg_CLK = portInputRegister(digitalPinToPort(_CLK));
|
||||
_bit_mask_CLK = digitalPinToBitMask(_CLK);
|
||||
_pin_reg_DT = portInputRegister(digitalPinToPort(_DT));
|
||||
_bit_mask_DT = digitalPinToBitMask(_DT);
|
||||
if (sw != -1) {
|
||||
_pin_reg_SW = portInputRegister(digitalPinToPort(_SW));
|
||||
_bit_mask_SW = digitalPinToBitMask(_SW);
|
||||
}
|
||||
#endif
|
||||
|
||||
pinMode(_CLK, (DEFAULT_ENC_PULL ? INPUT : INPUT_PULLUP));
|
||||
pinMode(_DT, (DEFAULT_ENC_PULL ? INPUT : INPUT_PULLUP));
|
||||
if (flags.use_button) pinMode(_SW, (DEFAULT_BTN_PULL ? INPUT : INPUT_PULLUP));
|
||||
flags.invBtn = (DEFAULT_BTN_PULL == HIGH_PULL) ? true : false;
|
||||
|
||||
#if defined(FAST_ALGORITHM)
|
||||
prevState = _readCLK();
|
||||
#else
|
||||
prevState = _readCLK() | (_readDT() << 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ================= SET =================
|
||||
void Encoder::setDirection(bool direction) {
|
||||
if (direction) {
|
||||
uint8_t buf = _CLK;
|
||||
_CLK = _DT;
|
||||
_DT = buf;
|
||||
}
|
||||
}
|
||||
void Encoder::setPinMode(bool mode) {
|
||||
pinMode(_CLK, (mode) ? INPUT : INPUT_PULLUP);
|
||||
pinMode(_DT, (mode) ? INPUT : INPUT_PULLUP);
|
||||
}
|
||||
void Encoder::setBtnPinMode(bool mode) {
|
||||
pinMode(_SW, (mode) ? INPUT : INPUT_PULLUP);
|
||||
flags.invBtn = (mode) ? 0 : 1;
|
||||
}
|
||||
void Encoder::setType(bool type) {
|
||||
flags.enc_type = type;
|
||||
}
|
||||
void Encoder::setTickMode(bool tickMode) {
|
||||
flags.enc_tick_mode = tickMode;
|
||||
}
|
||||
void Encoder::setFastTimeout(uint16_t timeout) {
|
||||
_fast_timeout = timeout;
|
||||
}
|
||||
|
||||
// ================= IS =================
|
||||
// повороты
|
||||
boolean Encoder::isTurn() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isTurn_f) {
|
||||
flags.isTurn_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isRight() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (encState == 2) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isLeft() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (encState == 1) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isRightH() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (encState == 4) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isLeftH() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (encState == 3) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isFastR() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isFastR_f) {
|
||||
flags.isFastR_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isFastL() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isFastL_f) {
|
||||
flags.isFastL_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
// кнопка
|
||||
boolean Encoder::isPress() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isPress_f) {
|
||||
flags.isPress_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isRelease() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isRelease_f) {
|
||||
flags.isRelease_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isReleaseHold() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isReleaseHold_f) {
|
||||
flags.isReleaseHold_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isClick() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isRelease_f) {
|
||||
flags.isRelease_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isHolded() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.hold_flag && flags.isHolded_f) {
|
||||
flags.isHolded_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isSingle() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isSingle_f) {
|
||||
flags.isSingle_f = false;
|
||||
flags.isDouble_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isDouble() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
if (flags.isDouble_f) {
|
||||
flags.isDouble_f = false;
|
||||
flags.isSingle_f = false;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
boolean Encoder::isHold() {
|
||||
if (flags.enc_tick_mode) Encoder::tick();
|
||||
return (SW_state);
|
||||
}
|
||||
|
||||
void Encoder::resetStates() {
|
||||
encState = 0;
|
||||
flags.isTurn_f = false;
|
||||
flags.isFastR_f = false;
|
||||
flags.isFastL_f = false;
|
||||
flags.isPress_f = false;
|
||||
flags.isRelease_f = false;
|
||||
flags.isReleaseHold_f = false;
|
||||
flags.isHolded_f = false;
|
||||
flags.isSingle_f = false;
|
||||
flags.isDouble_f = false;
|
||||
}
|
||||
|
||||
// ================= TICK =================
|
||||
void Encoder::tick(bool clk, bool dt, bool sw) {
|
||||
extTick = true;
|
||||
flags.extCLK = clk;
|
||||
flags.extDT = dt;
|
||||
flags.extSW = sw;
|
||||
Encoder::tick();
|
||||
extTick = false;
|
||||
}
|
||||
|
||||
void Encoder::tick() {
|
||||
uint32_t thisMls = millis();
|
||||
uint32_t debounceDelta = thisMls - debounce_timer;
|
||||
|
||||
#ifdef ENC_WITH_BUTTON
|
||||
if (flags.use_button) {
|
||||
if (!extTick) SW_state = _readSW() ^ flags.invBtn; // читаем состояние кнопки SW
|
||||
else SW_state = flags.extSW;
|
||||
|
||||
if (SW_state && !flags.butt_flag && (debounceDelta > ENC_DEBOUNCE_BUTTON)) {
|
||||
flags.butt_flag = true;
|
||||
flags.turn_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0;
|
||||
flags.isPress_f = true;
|
||||
flags.isHolded_f = true;
|
||||
flags.doubleAllow = true;
|
||||
}
|
||||
if (!SW_state && flags.butt_flag && (debounceDelta > ENC_DEBOUNCE_BUTTON)) {
|
||||
if (!flags.turn_flag && !flags.hold_flag) { // если кнопка отпущена и ручка не поворачивалась
|
||||
flags.turn_flag = false;
|
||||
flags.isRelease_f = true;
|
||||
}
|
||||
if (debounceDelta > ENC_HOLD_TIMEOUT) flags.isReleaseHold_f = true;
|
||||
flags.butt_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0;
|
||||
flags.hold_flag = false;
|
||||
|
||||
if (flags.doubleAllow && !flags.doubleFlag) {
|
||||
flags.doubleFlag = true;
|
||||
flags.countFlag = false;
|
||||
} else {
|
||||
flags.countFlag = true;
|
||||
}
|
||||
}
|
||||
if (flags.doubleFlag && debounceDelta > ENC_DOUBLE_TIMEOUT) {
|
||||
if (!flags.turn_flag) {
|
||||
if (!flags.countFlag) flags.isSingle_f = true;
|
||||
else flags.isDouble_f = true;
|
||||
}
|
||||
flags.doubleFlag = false;
|
||||
}
|
||||
if (flags.butt_flag && debounceDelta > ENC_HOLD_TIMEOUT && !flags.turn_flag) {
|
||||
if (SW_state) {
|
||||
flags.hold_flag = true;
|
||||
flags.doubleAllow = false;
|
||||
} else {
|
||||
flags.butt_flag = false;
|
||||
flags.hold_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FAST_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK) : (_readCLK());
|
||||
|
||||
if (curState != prevState
|
||||
#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
#endif
|
||||
) {
|
||||
encState = 0;
|
||||
turnFlag = !turnFlag;
|
||||
if (turnFlag || !flags.enc_type) {
|
||||
if (( (extTick) ? (flags.extDT) : _readDT() ) != prevState) {
|
||||
encState = 1;
|
||||
} else {
|
||||
encState = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(BINARY_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK | (flags.extDT << 1)) : (_readCLK() | (_readDT() << 1));
|
||||
|
||||
if (curState != prevState
|
||||
#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
#endif
|
||||
) {
|
||||
encState = 0;
|
||||
if (flags.rst_flag) {
|
||||
if (curState == 0b11) {
|
||||
flags.rst_flag = 0;
|
||||
//encState = 3-prevState;
|
||||
switch (prevState) {
|
||||
case 0b10: encState = 1; break; // 2 - 1
|
||||
case 0b01: encState = 2; break; // 1 - 2
|
||||
}
|
||||
} else if (!flags.enc_type && (curState == 0b00)) {
|
||||
flags.rst_flag = 0;
|
||||
//encState = prevState;
|
||||
switch (prevState) {
|
||||
case 0b01: encState = 1; break;
|
||||
case 0b10: encState = 2; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curState == 0b00 || (!flags.enc_type && curState == 0b11)) flags.rst_flag = 1;
|
||||
|
||||
#elif defined(PRECISE_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK | (flags.extDT << 1)) : (_readCLK() | (_readDT() << 1));
|
||||
|
||||
if (curState != prevState
|
||||
#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
#endif
|
||||
) {
|
||||
encState = 0;
|
||||
encPos += KNOBDIR[curState | (prevState << 2)];
|
||||
if (flags.enc_type) {
|
||||
if (curState == 0x3 && encPos != 0) {
|
||||
encState = (encPos == 4) ? 1 : 2;
|
||||
encPos = 0;
|
||||
}
|
||||
} else {
|
||||
if ((curState == 0x3 || !curState) && encPos != 0) {
|
||||
encState = (encPos == 2) ? 1 : 2;
|
||||
encPos = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (encState != 0) {
|
||||
flags.isTurn_f = true;
|
||||
if (!SW_state && thisMls - fast_timer < _fast_timeout) {
|
||||
if (encState == 1) flags.isFastL_f = true;
|
||||
else if (encState == 2) flags.isFastR_f = true;
|
||||
fast_timer = thisMls;
|
||||
} else fast_timer = thisMls;
|
||||
#ifdef ENC_WITH_BUTTON
|
||||
if (flags.use_button && SW_state) encState += 2;
|
||||
#endif
|
||||
}
|
||||
prevState = curState;
|
||||
flags.turn_flag = true;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0;
|
||||
}
|
||||
}
|
||||
@ -1,175 +0,0 @@
|
||||
/*
|
||||
GyverEncoder - библиотека для расширенной работы с энкодером
|
||||
ВНИМАНИЕ, БИБЛИОТЕКА УСТАРЕЛА! ИСПОЛЬЗУЙ БИБЛИОТЕКУ EncButton https://github.com/GyverLibs/EncButton
|
||||
Документация: https://alexgyver.ru/encoder/
|
||||
GitHub: https://github.com/GyverLibs/GyverEncoder
|
||||
Возможности:
|
||||
- Отработка поворота энкодера
|
||||
- Отработка "нажатого поворота"
|
||||
- Отработка "быстрого поворота"
|
||||
- Несколько алгоритмов опроса энкодера
|
||||
- Выбор подтяжки подключения энкодера
|
||||
- Работа с двумя типами экнодеров
|
||||
- Работа с внешним энкодером (через расширитель пинов и т.п.)
|
||||
- Отработка нажатия/удержания кнопки с антидребезгом
|
||||
|
||||
Версии:
|
||||
v3.6 от 16.09.2019 - Возвращены дефайны настроек
|
||||
v4.0 от 13.11.2019
|
||||
- Оптимизирован код
|
||||
- Исправлены баги
|
||||
- Добавлены другие алгоритмы опроса
|
||||
- Добавлена возможность полностью убрать кнопку (экономия памяти)
|
||||
- Добавлена возможность подключения внешнего энкодера
|
||||
- Добавлена настройка подтяжки пинов
|
||||
|
||||
v4.1: Исправлено изменение подтяжек
|
||||
|
||||
v4.2
|
||||
- Добавлена поддержка TYPE1 для алгоритма PRECISE_ALGORITHM
|
||||
- Добавлена отработка двойного клика: isSingle / isDouble
|
||||
|
||||
v4.3: Исправлено ложное isSingle
|
||||
v4.4: Добавлен метод resetStates, сбрасывает все is-флаги и счётчики
|
||||
v4.5: Улучшен алгоритм BINARY_ALGORITHM (спасибо Ярославу Курусу)
|
||||
v4.6: BINARY_ALGORITHM пофикшен для TYPE1, добавлена isReleaseHold
|
||||
v4.7: Исправлен случайный нажатый поворот в BINARY_ALGORITHM
|
||||
v4.8: увеличена производительность для AVR Arduino
|
||||
v4.9: быстрый поворот отключен если кнопка удерживается
|
||||
*/
|
||||
|
||||
#ifndef GyverEncoder_h
|
||||
#define GyverEncoder_h
|
||||
#include <Arduino.h>
|
||||
|
||||
// ========= КОНСТАНТЫ ==========
|
||||
#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 0
|
||||
#define ENC_DEBOUNCE_BUTTON 80
|
||||
#define ENC_HOLD_TIMEOUT 700
|
||||
#define ENC_DOUBLE_TIMEOUT 300
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define _readCLK() bool(*_pin_reg_CLK & _bit_mask_CLK)
|
||||
#define _readDT() bool(*_pin_reg_DT & _bit_mask_DT)
|
||||
#define _readSW() bool(*_pin_reg_SW & _bit_mask_SW)
|
||||
#else
|
||||
#define _readCLK() digitalRead(_CLK)
|
||||
#define _readDT() digitalRead(_DT)
|
||||
#define _readSW() digitalRead(_SW)
|
||||
#endif
|
||||
|
||||
#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 isReleaseHold_f: 1;
|
||||
bool isHolded_f: 1;
|
||||
bool isFastR_f: 1;
|
||||
bool isFastL_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;
|
||||
bool rst_flag : 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(uint8_t clk, uint8_t dt, int8_t sw = -1, 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(uint16_t timeout); // установка таймаута быстрого поворота
|
||||
|
||||
boolean isTurn(); // возвращает true при любом повороте, сама сбрасывается в false
|
||||
boolean isRight(); // возвращает true при повороте направо, сама сбрасывается в false
|
||||
boolean isLeft(); // возвращает true при повороте налево, сама сбрасывается в false
|
||||
boolean isRightH(); // возвращает true при удержании кнопки и повороте направо, сама сбрасывается в false
|
||||
boolean isLeftH(); // возвращает true при удержании кнопки и повороте налево, сама сбрасывается в false
|
||||
boolean isFastR(); // возвращает true при быстром повороте
|
||||
boolean isFastL(); // возвращает true при быстром повороте
|
||||
|
||||
boolean isPress(); // возвращает true при нажатии кнопки, сама сбрасывается в false
|
||||
boolean isRelease(); // возвращает true при отпускании кнопки, сама сбрасывается в false
|
||||
boolean isReleaseHold(); // возвращает true при отпускании кнопки после удержания, сама сбрасывается в false
|
||||
boolean isClick(); // возвращает true при нажатии и отпускании кнопки, сама сбрасывается в false
|
||||
boolean isHolded(); // возвращает true при удержании кнопки, сама сбрасывается в false
|
||||
boolean isHold(); // возвращает true при удержании кнопки, НЕ СБРАСЫВАЕТСЯ
|
||||
boolean isSingle(); // возвращает true при одиночном клике (после таймаута), сама сбрасывается в false
|
||||
boolean isDouble(); // возвращает true при двойном клике, сама сбрасывается в false
|
||||
|
||||
void resetStates(); // сбрасывает все is-флаги и счётчики
|
||||
|
||||
private:
|
||||
GyverEncoderFlags flags;
|
||||
uint8_t _fast_timeout = 50; // таймаут быстрого поворота
|
||||
uint8_t prevState = 0;
|
||||
uint8_t encState = 0; // 0 не крутился, 1 лево, 2 право, 3 лево нажат, 4 право нажат
|
||||
uint32_t debounce_timer = 0, fast_timer = 0;
|
||||
uint8_t _CLK = 0, _DT = 0, _SW = 0;
|
||||
bool turnFlag = false, extTick = false, SW_state = false;
|
||||
#if defined(__AVR__)
|
||||
volatile uint8_t *_pin_reg_CLK;
|
||||
volatile uint8_t _bit_mask_CLK;
|
||||
volatile uint8_t *_pin_reg_DT;
|
||||
volatile uint8_t _bit_mask_DT;
|
||||
volatile uint8_t *_pin_reg_SW;
|
||||
volatile uint8_t _bit_mask_SW;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
21
libraries/GyverTM1637/LICENSE
Normal file
21
libraries/GyverTM1637/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Alex
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
337
libraries/GyverTM1637/README.md
Normal file
337
libraries/GyverTM1637/README.md
Normal file
@ -0,0 +1,337 @@
|
||||

|
||||

|
||||
# GyverTM1637
|
||||
GyverTM1637 - бибилотека для 7 сегментного дисплея на чипе TM1637 с кучей приколюх
|
||||
- Вывод цифр массивом или прицельно
|
||||
- Вывод букв из списка доступных (листай ниже) массивом или прицельно
|
||||
- Отдельная функция вывода часов и минут (часы без нуля слева, минуты с нулём)
|
||||
- Вывод числа от -999 до 9999 с учётом знака
|
||||
- Готовая функция бегущей строки
|
||||
- Функции смены яркости и состояния двоеточия автоматически обновляют дисплей
|
||||
- Функция обновления значения с эффектом вертикальной прокрутки
|
||||
- Функция обновления значения с эффектом скручивания (лучше один раз увидеть)
|
||||
|
||||
### Совместимость
|
||||
Совместима со всеми Arduino платформами (используются Arduino-функции)
|
||||
|
||||
### Документация
|
||||
К библиотеке есть [расширенная документация](https://alexgyver.ru/tm1637_display/)
|
||||
|
||||
## Содержание
|
||||
- [Установка](#install)
|
||||
- [Инициализация](#init)
|
||||
- [Использование](#usage)
|
||||
- [Пример](#example)
|
||||
- [Версии](#versions)
|
||||
- [Баги и обратная связь](#feedback)
|
||||
|
||||
<a id="install"></a>
|
||||
## Установка
|
||||
- Библиотеку можно найти по названию **GyverTM1637** и установить через менеджер библиотек в:
|
||||
- Arduino IDE
|
||||
- Arduino IDE v2
|
||||
- PlatformIO
|
||||
- [Скачать библиотеку](https://github.com/GyverLibs/GyverTM1637/archive/refs/heads/main.zip) .zip архивом для ручной установки:
|
||||
- Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64)
|
||||
- Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32)
|
||||
- Распаковать и положить в *Документы/Arduino/libraries/*
|
||||
- (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив
|
||||
- Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
|
||||
|
||||
<a id="init"></a>
|
||||
## Инициализация
|
||||
```cpp
|
||||
GyverTM1637 disp(CLK, DIO);
|
||||
```
|
||||
|
||||
<a id="usage"></a>
|
||||
## Использование
|
||||
```cpp
|
||||
void display(uint8_t DispData[]); // выводит цифры массивом по ячейкам. От 0 до 9 (byte values[] = {3, 5, 9, 0}; )
|
||||
void display(uint8_t BitAddr, uint8_t DispData); // выводит цифру DispData в указанную ячейку дисплея BitAddr
|
||||
void display(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3); // если лень создавать массив, выводит цифры в ячейки
|
||||
|
||||
void displayByte(uint8_t DispData[]); // выводит байт вида 0xe6 и буквы-константы вида _a , _b .... массивом
|
||||
void displayByte(uint8_t BitAddr, uint8_t DispData); // выводит байт вида 0xe6 и буквы-константы вида _a , _b .... в ячейку
|
||||
void displayByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3); // если лень создавать массив, выводит байты в ячейки
|
||||
|
||||
void displayClock(uint8_t hrs, uint8_t mins); // выводит часы и минуты
|
||||
void displayClockScroll(uint8_t hrs, uint8_t mins, int delayms); // выводит часы и минуты с эффектом прокрутки
|
||||
void displayClockTwist(uint8_t hrs, uint8_t mins, int delayms); // выводит часы и минуты с эффектом скрутки
|
||||
|
||||
void displayInt(int value); // выводит число от -999 до 9999 (да, со знаком минус)
|
||||
void runningString(uint8_t DispData[], byte amount, int delayMs); // бегущая строка (array, sizeof(array), задержка в мс)
|
||||
void clear(void); // очистить дисплей
|
||||
void point(boolean PointFlag); // вкл / выкл точку (POINT_ON / POINT_OFF)
|
||||
void brightness(uint8_t bright, uint8_t = 0x40, uint8_t = 0xc0); // яркость 0 - 7
|
||||
|
||||
void scroll(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение прокруткой (адрес, ЦИФРА, задержка в мс)
|
||||
void scroll(uint8_t DispData[], int delayms); // обновить значение прокруткой (массив ЦИФР, задержка в мс)
|
||||
void scroll(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // прокрутка посимвольно
|
||||
void scrollByte(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение прокруткой (адрес, БАЙТ, задержка в мс)
|
||||
void scrollByte(uint8_t DispData[], int delayms); // обновить значение прокруткой (массив БАЙТ, задержка в мс)
|
||||
void scrollByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // прокрутка посимвольно
|
||||
|
||||
void twist(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение скручиванием (адрес, ЦИФРА, задержка в мс)
|
||||
void twist(uint8_t DispData[], int delayms); // обновить значение скручиванием (массив ЦИФР, задержка в мс)
|
||||
void twist(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // скрутка посимвольно
|
||||
void twistByte(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение скручиванием (адрес, БАЙТ, задержка в мс)
|
||||
void twistByte(uint8_t DispData[], int delayms); // обновить значение скручиванием (массив БАЙТ, задержка в мс)
|
||||
void twistByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // скрутка посимвольно
|
||||
```
|
||||
|
||||
<a id="example"></a>
|
||||
## Пример
|
||||
Остальные примеры смотри в **examples**!
|
||||
```cpp
|
||||
/*
|
||||
Пример вывода на дисплей с регистром TM1637
|
||||
показывает все возможности библиотеки GyverTM1637
|
||||
AlexGyver Technologies http://alexgyver.ru/
|
||||
*/
|
||||
|
||||
#define CLK 2
|
||||
#define DIO 3
|
||||
|
||||
#include "GyverTM1637.h"
|
||||
GyverTM1637 disp(CLK, DIO);
|
||||
|
||||
uint32_t Now, clocktimer;
|
||||
boolean flag;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
disp.clear();
|
||||
disp.brightness(7); // яркость, 0 - 7 (минимум - максимум)
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
runningText();
|
||||
scrolls();
|
||||
scrollClock();
|
||||
twists();
|
||||
twistClock();
|
||||
ints();
|
||||
bytes();
|
||||
fadeBlink();
|
||||
normClock();
|
||||
}
|
||||
|
||||
void twists() {
|
||||
// скручивание массив ЦИФР
|
||||
byte digs[4] = {3, 5, 7, 1};
|
||||
disp.twist(digs, 50); // скорость прокрутки 100
|
||||
delay(1000);
|
||||
|
||||
// скручивание прицельно (ячейка, БАЙТ, скорость)
|
||||
disp.twistByte(0, _1, 50);
|
||||
delay(1000);
|
||||
|
||||
// скручивание прицельно (ячейка, ЦИФРА, скорость)
|
||||
disp.twist(0, 8, 70);
|
||||
delay(1000);
|
||||
|
||||
disp.clear();
|
||||
delay(200);
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
disp.twist(3, i, 20);
|
||||
delay(200);
|
||||
}
|
||||
|
||||
// скручивание массива БАЙТ
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.twistByte(troll, 50);
|
||||
delay(1000);
|
||||
|
||||
// прицельное скручивание БАЙТА (ячейка, байт, скорость)
|
||||
disp.twistByte(2, _G, 50);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void twistClock() {
|
||||
byte hrs = 21, mins = 55;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 10000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
if (flag) {
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClockTwist(hrs, mins, 35); // выводим время
|
||||
}
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void scrolls() {
|
||||
// прокрутка массив ЦИФР
|
||||
byte digs[4] = {3, 5, 7, 1};
|
||||
disp.scroll(digs, 100); // скорость прокрутки 100
|
||||
delay(1000);
|
||||
|
||||
// прокрутка прицельно (ячейка, ЦИФРА, скорость)
|
||||
disp.scroll(0, 8, 200);
|
||||
delay(1000);
|
||||
|
||||
disp.clear();
|
||||
delay(1000);
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
disp.scroll(3, i, 50);
|
||||
delay(400);
|
||||
}
|
||||
|
||||
// прокрутка массива БАЙТ
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.scrollByte(troll, 100);
|
||||
delay(1000);
|
||||
|
||||
// прицельная прокрутка БАЙТА (ячейка, байт, скорость)
|
||||
disp.scrollByte(2, _G, 50);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void bytes() {
|
||||
// выводим байты из массива
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.displayByte(troll);
|
||||
delay(1000);
|
||||
|
||||
// выводим байты напрямую (4 в скобках)
|
||||
disp.displayByte(_L, _O, _L, _empty);
|
||||
delay(1000);
|
||||
|
||||
// выводим байты "прицельно"
|
||||
disp.displayByte(3, _O); // 3 ячейка, буква О
|
||||
delay(1000);
|
||||
|
||||
// выводим цифры из массива
|
||||
byte hell[4] = {6, 6, 6, 6};
|
||||
disp.display(hell);
|
||||
delay(1000);
|
||||
|
||||
// выводим цифры напрямую (4 в скобках)
|
||||
disp.display(1, 2, 3, 4);
|
||||
delay(1000);
|
||||
|
||||
// выводим цифры "прицельно"
|
||||
disp.display(0, 9); // 0 ячейка, цифра 9
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void fadeBlink() {
|
||||
// пишем HELL
|
||||
disp.displayByte(_H, _E, _L, _L);
|
||||
|
||||
Now = millis();
|
||||
while (millis () - Now < 3000) { // 3 секунды
|
||||
for (int i = 7; i > 0; i--) {
|
||||
disp.brightness(i); // меняем яркость
|
||||
delay(40);
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
disp.brightness(i); // меняем яркость
|
||||
delay(40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scrollClock() {
|
||||
byte hrs = 15, mins = 0;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 10000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
if (flag) {
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClockScroll(hrs, mins, 70); // выводим время
|
||||
}
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void normClock() {
|
||||
byte hrs = 15, mins = 0;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 10000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClock(hrs, mins); // выводим время функцией часов
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void ints() {
|
||||
// тупо отправляем цифры
|
||||
disp.displayInt(-999);
|
||||
delay(500);
|
||||
disp.displayInt(-99);
|
||||
delay(500);
|
||||
disp.displayInt(-9);
|
||||
delay(500);
|
||||
disp.displayInt(0);
|
||||
delay(500);
|
||||
disp.displayInt(6);
|
||||
delay(500);
|
||||
disp.displayInt(66);
|
||||
delay(500);
|
||||
disp.displayInt(666);
|
||||
delay(500);
|
||||
disp.displayInt(6666);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void runningText() {
|
||||
byte welcome_banner[] = {_H, _E, _L, _L, _O, _empty, _empty,
|
||||
_e, _n, _j, _o, _y, _empty, _empty,
|
||||
_1, _6, _3, _7, _empty, _d, _i, _S, _P, _l, _a, _y
|
||||
};
|
||||
disp.runningString(welcome_banner, sizeof(welcome_banner), 200); // 200 это время в миллисекундах!
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
<a id="versions"></a>
|
||||
## Версии
|
||||
- v1.4 - поправлены типы данных и ошибки, добавлена совместимость с ESP
|
||||
|
||||
<a id="feedback"></a>
|
||||
## Баги и обратная связь
|
||||
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
|
||||
Библиотека открыта для доработки и ваших **Pull Request**'ов!
|
||||
@ -0,0 +1,240 @@
|
||||
/*
|
||||
Пример вывода на дисплей с регистром TM1637
|
||||
показывает все возможности библиотеки GyverTM1637
|
||||
AlexGyver Technologies http://alexgyver.ru/
|
||||
*/
|
||||
|
||||
#define CLK 2
|
||||
#define DIO 3
|
||||
|
||||
#include "GyverTM1637.h"
|
||||
GyverTM1637 disp(CLK, DIO);
|
||||
|
||||
uint32_t Now, clocktimer;
|
||||
boolean flag;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
disp.clear();
|
||||
disp.brightness(7); // яркость, 0 - 7 (минимум - максимум)
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
runningText();
|
||||
scrolls();
|
||||
scrollClock();
|
||||
twists();
|
||||
twistClock();
|
||||
ints();
|
||||
bytes();
|
||||
fadeBlink();
|
||||
normClock();
|
||||
}
|
||||
|
||||
void twists() {
|
||||
// скручивание массив ЦИФР
|
||||
byte digs[4] = {3, 5, 7, 1};
|
||||
disp.twist(digs, 50); // скорость прокрутки 100
|
||||
delay(1000);
|
||||
|
||||
// скручивание прицельно (ячейка, БАЙТ, скорость)
|
||||
disp.twistByte(0, _1, 50);
|
||||
delay(1000);
|
||||
|
||||
// скручивание прицельно (ячейка, ЦИФРА, скорость)
|
||||
disp.twist(0, 8, 70);
|
||||
delay(1000);
|
||||
|
||||
disp.clear();
|
||||
delay(200);
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
disp.twist(3, i, 20);
|
||||
delay(200);
|
||||
}
|
||||
|
||||
// скручивание массива БАЙТ
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.twistByte(troll, 50);
|
||||
delay(1000);
|
||||
|
||||
// прицельное скручивание БАЙТА (ячейка, байт, скорость)
|
||||
disp.twistByte(2, _G, 50);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void twistClock() {
|
||||
byte hrs = 21, mins = 55;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 10000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
if (flag) {
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClockTwist(hrs, mins, 35); // выводим время
|
||||
}
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void scrolls() {
|
||||
// прокрутка массив ЦИФР
|
||||
byte digs[4] = {3, 5, 7, 1};
|
||||
disp.scroll(digs, 100); // скорость прокрутки 100
|
||||
delay(1000);
|
||||
|
||||
// прокрутка прицельно (ячейка, ЦИФРА, скорость)
|
||||
disp.scroll(0, 8, 200);
|
||||
delay(1000);
|
||||
|
||||
disp.clear();
|
||||
delay(1000);
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
disp.scroll(3, i, 50);
|
||||
delay(400);
|
||||
}
|
||||
|
||||
// прокрутка массива БАЙТ
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.scrollByte(troll, 100);
|
||||
delay(1000);
|
||||
|
||||
// прицельная прокрутка БАЙТА (ячейка, байт, скорость)
|
||||
disp.scrollByte(2, _G, 50);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void bytes() {
|
||||
// выводим байты из массива
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.displayByte(troll);
|
||||
delay(1000);
|
||||
|
||||
// выводим байты напрямую (4 в скобках)
|
||||
disp.displayByte(_L, _O, _L, _empty);
|
||||
delay(1000);
|
||||
|
||||
// выводим байты "прицельно"
|
||||
disp.displayByte(3, _O); // 3 ячейка, буква О
|
||||
delay(1000);
|
||||
|
||||
// выводим цифры из массива
|
||||
byte hell[4] = {6, 6, 6, 6};
|
||||
disp.display(hell);
|
||||
delay(1000);
|
||||
|
||||
// выводим цифры напрямую (4 в скобках)
|
||||
disp.display(1, 2, 3, 4);
|
||||
delay(1000);
|
||||
|
||||
// выводим цифры "прицельно"
|
||||
disp.display(0, 9); // 0 ячейка, цифра 9
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void fadeBlink() {
|
||||
// пишем HELL
|
||||
disp.displayByte(_H, _E, _L, _L);
|
||||
|
||||
Now = millis();
|
||||
while (millis () - Now < 3000) { // 3 секунды
|
||||
for (int i = 7; i > 0; i--) {
|
||||
disp.brightness(i); // меняем яркость
|
||||
delay(40);
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
disp.brightness(i); // меняем яркость
|
||||
delay(40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scrollClock() {
|
||||
byte hrs = 15, mins = 0;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 10000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
if (flag) {
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClockScroll(hrs, mins, 70); // выводим время
|
||||
}
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void normClock() {
|
||||
byte hrs = 15, mins = 0;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 10000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClock(hrs, mins); // выводим время функцией часов
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void ints() {
|
||||
// тупо отправляем цифры
|
||||
disp.displayInt(-999);
|
||||
delay(500);
|
||||
disp.displayInt(-99);
|
||||
delay(500);
|
||||
disp.displayInt(-9);
|
||||
delay(500);
|
||||
disp.displayInt(0);
|
||||
delay(500);
|
||||
disp.displayInt(6);
|
||||
delay(500);
|
||||
disp.displayInt(66);
|
||||
delay(500);
|
||||
disp.displayInt(666);
|
||||
delay(500);
|
||||
disp.displayInt(6666);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void runningText() {
|
||||
byte welcome_banner[] = {_H, _E, _L, _L, _O, _empty, _empty,
|
||||
_e, _n, _j, _o, _y, _empty, _empty,
|
||||
_1, _6, _3, _7, _empty, _d, _i, _S, _P, _l, _a, _y
|
||||
};
|
||||
disp.runningString(welcome_banner, sizeof(welcome_banner), 200); // 200 это время в миллисекундах!
|
||||
}
|
||||
@ -0,0 +1,182 @@
|
||||
/*
|
||||
Пример вывода на дисплей с регистром TM1637
|
||||
показывает все возможности библиотеки GyverTM1637
|
||||
AlexGyver Technologies http://alexgyver.ru/
|
||||
*/
|
||||
|
||||
#define CLK 2
|
||||
#define DIO 3
|
||||
|
||||
#include "GyverTM1637.h"
|
||||
GyverTM1637 disp(CLK, DIO);
|
||||
|
||||
uint32_t Now, clocktimer;
|
||||
boolean flag;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
disp.clear();
|
||||
disp.brightness(7); // яркость, 0 - 7 (минимум - максимум)
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
runningText();
|
||||
normClock();
|
||||
scrollClock();
|
||||
twistClock();
|
||||
scrolls();
|
||||
twists();
|
||||
ints();
|
||||
fadeBlink();
|
||||
}
|
||||
|
||||
void twists() {
|
||||
disp.clear();
|
||||
delay(200);
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
disp.twist(3, i, 20);
|
||||
delay(300);
|
||||
}
|
||||
|
||||
// скрутка массива БАЙТ
|
||||
byte troll[4] = {_L, _O, _L, _empty};
|
||||
disp.scrollByte(troll, 100);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void twistClock() {
|
||||
byte hrs = 21, mins = 55;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 5000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
if (flag) {
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
byte dispTime[] = {(byte)hrs / 10, (byte)hrs % 10, (byte)mins / 10, (byte)mins % 10};
|
||||
disp.twist(dispTime, 35); // выводим время массивом
|
||||
}
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void scrolls() {
|
||||
disp.clear();
|
||||
delay(1000);
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
disp.scroll(3, i, 50);
|
||||
delay(300);
|
||||
}
|
||||
|
||||
// прокрутка массива БАЙТ
|
||||
byte troll[4] = {_t, _r, _o, _l};
|
||||
disp.scrollByte(troll, 100);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void fadeBlink() {
|
||||
// пишем HELL
|
||||
disp.displayByte(_H, _E, _L, _L);
|
||||
|
||||
Now = millis();
|
||||
while (millis () - Now < 3000) { // 3 секунды
|
||||
for (int i = 7; i > 0; i--) {
|
||||
disp.brightness(i); // меняем яркость
|
||||
delay(40);
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
disp.brightness(i); // меняем яркость
|
||||
delay(40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scrollClock() {
|
||||
byte hrs = 15, mins = 0;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 5000) { // каждые 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
if (flag) {
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
byte dispTime[] = {(byte)hrs / 10, (byte)hrs % 10, (byte)mins / 10, (byte)mins % 10};
|
||||
disp.scroll(dispTime, 70); // выводим время массивом
|
||||
}
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void normClock() {
|
||||
byte hrs = 15, mins = 0;
|
||||
uint32_t tmr;
|
||||
Now = millis();
|
||||
while (millis () - Now < 5000) { // 10 секунд
|
||||
if (millis() - tmr > 500) { // каждые полсекунды
|
||||
tmr = millis();
|
||||
flag = !flag;
|
||||
disp.point(flag); // выкл/выкл точки
|
||||
|
||||
// ***** часы! ****
|
||||
mins ++;
|
||||
if (mins > 59) {
|
||||
mins = 0;
|
||||
hrs++;
|
||||
if (hrs > 24) hrs = 0;
|
||||
}
|
||||
// ***** часы! ****
|
||||
disp.displayClock(hrs, mins); // выводим время функцией часов
|
||||
}
|
||||
}
|
||||
disp.point(0); // выкл точки
|
||||
}
|
||||
|
||||
void ints() {
|
||||
// тупо отправляем цифры
|
||||
disp.displayInt(-999);
|
||||
delay(200);
|
||||
disp.displayInt(-99);
|
||||
delay(200);
|
||||
disp.displayInt(-9);
|
||||
delay(200);
|
||||
disp.displayInt(0);
|
||||
delay(200);
|
||||
disp.displayInt(6);
|
||||
delay(200);
|
||||
disp.displayInt(66);
|
||||
delay(200);
|
||||
disp.displayInt(666);
|
||||
delay(200);
|
||||
disp.displayInt(6666);
|
||||
delay(200);
|
||||
}
|
||||
|
||||
void runningText() {
|
||||
byte welcome_banner[] = {_H, _E, _L, _L, _O, _empty, _empty,
|
||||
_T, _M, _1, _6, _3, _7,
|
||||
};
|
||||
disp.runningString(welcome_banner, sizeof(welcome_banner), 150); // 200 это время в миллисекундах!
|
||||
}
|
||||
91
libraries/GyverTM1637/keywords.txt
Normal file
91
libraries/GyverTM1637/keywords.txt
Normal file
@ -0,0 +1,91 @@
|
||||
|
||||
#######################################
|
||||
# Syntax Coloring Map For GyverTM1637
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
GyverTM1637 KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
display KEYWORD2
|
||||
displayByte KEYWORD2
|
||||
displayInt KEYWORD2
|
||||
|
||||
displayClock KEYWORD2
|
||||
displayClockTwist KEYWORD2
|
||||
displayClockScroll KEYWORD2
|
||||
|
||||
runningString KEYWORD2
|
||||
scroll KEYWORD2
|
||||
scrollByte KEYWORD2
|
||||
twist KEYWORD2
|
||||
twistByte KEYWORD2
|
||||
|
||||
clear KEYWORD2
|
||||
point KEYWORD2
|
||||
brightness KEYWORD2
|
||||
digToHEX KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
POINT_ON LITERAL1
|
||||
POINT_OFF LITERAL1
|
||||
|
||||
_A LITERAL1
|
||||
_B LITERAL1
|
||||
_C LITERAL1
|
||||
_D LITERAL1
|
||||
_E LITERAL1
|
||||
_F LITERAL1
|
||||
_G LITERAL1
|
||||
_H LITERAL1
|
||||
_J LITERAL1
|
||||
_L LITERAL1
|
||||
_N LITERAL1
|
||||
_O LITERAL1
|
||||
_P LITERAL1
|
||||
_S LITERAL1
|
||||
_U LITERAL1
|
||||
_Y LITERAL1
|
||||
_a LITERAL1
|
||||
_b LITERAL1
|
||||
_c LITERAL1
|
||||
_d LITERAL1
|
||||
_e LITERAL1
|
||||
_f LITERAL1
|
||||
_h LITERAL1
|
||||
_i LITERAL1
|
||||
_j LITERAL1
|
||||
_l LITERAL1
|
||||
_n LITERAL1
|
||||
_o LITERAL1
|
||||
_q LITERAL1
|
||||
_r LITERAL1
|
||||
_t LITERAL1
|
||||
_u LITERAL1
|
||||
_y LITERAL1
|
||||
|
||||
_dash LITERAL1
|
||||
_under LITERAL1
|
||||
_equal LITERAL1
|
||||
_empty LITERAL1
|
||||
_degree LITERAL1
|
||||
|
||||
_0 LITERAL1
|
||||
_1 LITERAL1
|
||||
_2 LITERAL1
|
||||
_3 LITERAL1
|
||||
_4 LITERAL1
|
||||
_5 LITERAL1
|
||||
_6 LITERAL1
|
||||
_7 LITERAL1
|
||||
_8 LITERAL1
|
||||
_9 LITERAL1
|
||||
9
libraries/GyverTM1637/library.properties
Normal file
9
libraries/GyverTM1637/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=GyverTM1637
|
||||
version=1.4
|
||||
author=AlexGyver <alex@alexgyver.ru>
|
||||
maintainer=AlexGyver <alex@alexgyver.ru>
|
||||
sentence=Library for advanced control of TM1637 7-segment display
|
||||
paragraph=Library for advanced control of TM1637 7-segment display
|
||||
category=Display
|
||||
url=https://github.com/GyverLibs/GyverTM1637
|
||||
architectures=*
|
||||
535
libraries/GyverTM1637/src/GyverTM1637.cpp
Normal file
535
libraries/GyverTM1637/src/GyverTM1637.cpp
Normal file
@ -0,0 +1,535 @@
|
||||
#include "GyverTM1637.h"
|
||||
#include <Arduino.h>
|
||||
const uint8_t digitHEX[] = {0x3f, 0x06, 0x5b, 0x4f,
|
||||
0x66, 0x6d, 0x7d, 0x07,
|
||||
0x7f, 0x6f, 0x00, 0x40
|
||||
};//0~9, ,-
|
||||
|
||||
GyverTM1637::GyverTM1637(uint8_t clk, uint8_t dio)
|
||||
{
|
||||
Clkpin = clk;
|
||||
Datapin = dio;
|
||||
pinMode(Clkpin, OUTPUT);
|
||||
pinMode(Datapin, OUTPUT);
|
||||
}
|
||||
|
||||
uint8_t digToHEX(uint8_t digit) {
|
||||
return digitHEX[digit];
|
||||
}
|
||||
|
||||
int GyverTM1637::writeByte(int8_t wr_data)
|
||||
{
|
||||
uint8_t i, count1;
|
||||
for (i = 0; i < 8; i++) //sent 8bit data
|
||||
{
|
||||
digitalWrite(Clkpin, LOW);
|
||||
if (wr_data & 0x01)digitalWrite(Datapin, HIGH); //LSB first
|
||||
else digitalWrite(Datapin, LOW);
|
||||
wr_data >>= 1;
|
||||
digitalWrite(Clkpin, HIGH);
|
||||
|
||||
}
|
||||
digitalWrite(Clkpin, LOW); //wait for the ACK
|
||||
digitalWrite(Datapin, HIGH);
|
||||
digitalWrite(Clkpin, HIGH);
|
||||
pinMode(Datapin, INPUT);
|
||||
|
||||
delayMicroseconds(50);
|
||||
uint8_t ack = digitalRead(Datapin);
|
||||
if (ack == 0)
|
||||
{
|
||||
pinMode(Datapin, OUTPUT);
|
||||
digitalWrite(Datapin, LOW);
|
||||
}
|
||||
delayMicroseconds(50);
|
||||
pinMode(Datapin, OUTPUT);
|
||||
delayMicroseconds(50);
|
||||
|
||||
return ack;
|
||||
}
|
||||
//send start signal to GyverTM1637
|
||||
void GyverTM1637::start(void)
|
||||
{
|
||||
digitalWrite(Clkpin, HIGH); //send start signal to GyverTM1637
|
||||
digitalWrite(Datapin, HIGH);
|
||||
digitalWrite(Datapin, LOW);
|
||||
digitalWrite(Clkpin, LOW);
|
||||
}
|
||||
//End of transmission
|
||||
void GyverTM1637::stop(void)
|
||||
{
|
||||
digitalWrite(Clkpin, LOW);
|
||||
digitalWrite(Datapin, LOW);
|
||||
digitalWrite(Clkpin, HIGH);
|
||||
digitalWrite(Datapin, HIGH);
|
||||
}
|
||||
|
||||
// ************************** ФОРМИРУЕМ ДАННЫЕ *****************************
|
||||
void GyverTM1637::display(uint8_t DispData[])
|
||||
{
|
||||
uint8_t SegData[4];
|
||||
for (byte i = 0; i < 4; i ++) {
|
||||
//if (DispData[i] == 0x7f) SegData[i] = 0x00;
|
||||
//else
|
||||
//{
|
||||
lastData[i] = digitHEX[DispData[i]];
|
||||
SegData[i] = digitHEX[DispData[i]] + PointData;
|
||||
//}
|
||||
}
|
||||
sendArray(SegData);
|
||||
}
|
||||
void GyverTM1637::displayByte(uint8_t DispData[])
|
||||
{
|
||||
uint8_t SegData[4];
|
||||
for (byte i = 0; i < 4; i ++) {
|
||||
//if (DispData[i] == 0x7f) SegData[i] = 0x00;
|
||||
//else SegData[i] = DispData[i];
|
||||
//{
|
||||
lastData[i] = DispData[i];
|
||||
SegData[i] = DispData[i] + PointData;
|
||||
//}
|
||||
}
|
||||
sendArray(SegData);
|
||||
}
|
||||
|
||||
void GyverTM1637::display(uint8_t BitAddr, uint8_t DispData)
|
||||
{
|
||||
uint8_t SegData;
|
||||
//if (DispData == 0x7f) SegData = 0x00;
|
||||
//else
|
||||
//{
|
||||
lastData[BitAddr] = digitHEX[DispData];
|
||||
SegData = digitHEX[DispData] + PointData;
|
||||
//}
|
||||
sendByte(BitAddr, SegData);
|
||||
}
|
||||
|
||||
void GyverTM1637::displayByte(uint8_t BitAddr, uint8_t DispData)
|
||||
{
|
||||
uint8_t SegData;
|
||||
//if (DispData == 0x7f) SegData = 0x00;
|
||||
//else
|
||||
//{
|
||||
lastData[BitAddr] = DispData;
|
||||
SegData = DispData + PointData;
|
||||
//}
|
||||
sendByte(BitAddr, SegData);
|
||||
}
|
||||
|
||||
// ************************** ОТПРАВКА НА ДИСПЛЕЙ *****************************
|
||||
void GyverTM1637::sendByte(uint8_t BitAddr, int8_t sendData) {
|
||||
start(); //start signal sent to GyverTM1637 from MCU
|
||||
writeByte(ADDR_FIXED);//
|
||||
stop(); //
|
||||
start(); //
|
||||
writeByte(BitAddr | 0xc0); //
|
||||
writeByte(sendData);//
|
||||
stop(); //
|
||||
start(); //
|
||||
writeByte(Cmd_DispCtrl);//
|
||||
stop(); //
|
||||
}
|
||||
|
||||
void GyverTM1637::sendArray(uint8_t sendData[]) {
|
||||
start(); //start signal sent to GyverTM1637 from MCU
|
||||
writeByte(ADDR_AUTO);//
|
||||
stop(); //
|
||||
start(); //
|
||||
writeByte(Cmd_SetAddr);//
|
||||
for (byte i = 0; i < 4; i ++) {
|
||||
writeByte(sendData[i]); //
|
||||
}
|
||||
stop(); //
|
||||
start(); //
|
||||
writeByte(Cmd_DispCtrl);//
|
||||
stop(); //
|
||||
}
|
||||
// ******************************************
|
||||
void GyverTM1637::displayByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3) {
|
||||
uint8_t dispArray[] = {bit0, bit1, bit2, bit3};
|
||||
displayByte(dispArray);
|
||||
}
|
||||
void GyverTM1637::display(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3) {
|
||||
uint8_t dispArray[] = {bit0, bit1, bit2, bit3};
|
||||
display(dispArray);
|
||||
}
|
||||
|
||||
void GyverTM1637::clear(void)
|
||||
{
|
||||
display(0x00, 0x7f);
|
||||
display(0x01, 0x7f);
|
||||
display(0x02, 0x7f);
|
||||
display(0x03, 0x7f);
|
||||
lastData[0] = 0x00;
|
||||
lastData[1] = 0x00;
|
||||
lastData[2] = 0x00;
|
||||
lastData[3] = 0x00;
|
||||
}
|
||||
void GyverTM1637::update(void)
|
||||
{
|
||||
displayByte(lastData);
|
||||
}
|
||||
|
||||
void GyverTM1637::brightness(uint8_t brightness, uint8_t SetData, uint8_t SetAddr)
|
||||
{
|
||||
Cmd_SetData = SetData;
|
||||
Cmd_SetAddr = SetAddr;
|
||||
Cmd_DispCtrl = 0x88 + brightness;//Set the brightness and it takes effect the next time it displays.
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void GyverTM1637::point(boolean PointFlag)
|
||||
{
|
||||
if (PointFlag) PointData = 0x80;
|
||||
else PointData = 0;
|
||||
update();
|
||||
}
|
||||
|
||||
// ************************** ВСЯКИЕ ФУНКЦИИ *****************************
|
||||
void GyverTM1637::displayClock(uint8_t hrs, uint8_t mins) {
|
||||
if (hrs > 99 || mins > 99) return;
|
||||
uint8_t disp_time[4];
|
||||
if ((hrs / 10) == 0) disp_time[0] = 10;
|
||||
else disp_time[0] = (hrs / 10);
|
||||
disp_time[1] = hrs % 10;
|
||||
disp_time[2] = mins / 10;
|
||||
disp_time[3] = mins % 10;
|
||||
GyverTM1637::display(disp_time);
|
||||
}
|
||||
void GyverTM1637::displayClockScroll(uint8_t hrs, uint8_t mins, int delayms) {
|
||||
if (hrs > 99 || mins > 99) return;
|
||||
uint8_t disp_time[4];
|
||||
if ((hrs / 10) == 0) disp_time[0] = 10;
|
||||
else disp_time[0] = (hrs / 10);
|
||||
disp_time[1] = hrs % 10;
|
||||
disp_time[2] = mins / 10;
|
||||
disp_time[3] = mins % 10;
|
||||
scroll(disp_time, delayms);
|
||||
}
|
||||
void GyverTM1637::displayClockTwist(uint8_t hrs, uint8_t mins, int delayms) {
|
||||
if (hrs > 99 || mins > 99) return;
|
||||
uint8_t disp_time[4];
|
||||
if ((hrs / 10) == 0) disp_time[0] = 10;
|
||||
else disp_time[0] = (hrs / 10);
|
||||
disp_time[1] = hrs % 10;
|
||||
disp_time[2] = mins / 10;
|
||||
disp_time[3] = mins % 10;
|
||||
twist(disp_time, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::displayInt(int value) {
|
||||
if (value > 9999 || value < -999) return;
|
||||
boolean negative = false;
|
||||
boolean neg_flag = false;
|
||||
byte digits[4];
|
||||
if (value < 0) negative = true;
|
||||
value = abs(value);
|
||||
digits[0] = (int)value / 1000; // количесто тысяч в числе
|
||||
uint16_t b = (int)digits[0] * 1000; // вспомогательная переменная
|
||||
digits[1] = ((int)value - b) / 100; // получем количество сотен
|
||||
b += digits[1] * 100; // суммируем сотни и тысячи
|
||||
digits[2] = (int)(value - b) / 10; // получем десятки
|
||||
b += digits[2] * 10; // сумма тысяч, сотен и десятков
|
||||
digits[3] = value - b; // получаем количество единиц
|
||||
|
||||
if (!negative) {
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
if (digits[i] == 0) digits[i] = 10;
|
||||
else break;
|
||||
}
|
||||
} else {
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
if (digits[i] == 0) {
|
||||
if (digits[i + 1] == 0){
|
||||
digits[i] = 10;
|
||||
} else {
|
||||
digits[i] = 11;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GyverTM1637::display(digits);
|
||||
}
|
||||
|
||||
void GyverTM1637::runningString(uint8_t DispData[], byte amount, int delayMs) {
|
||||
uint8_t segm_data[amount + 8]; // оставляем место для 4х пустых слотов в начале и в конце
|
||||
for (byte i = 0; i < 4; i++) { // делаем первые 4 символа пустыми
|
||||
segm_data[i] = 0x00;
|
||||
}
|
||||
for (byte i = 0; i < amount; i++) { // далее забиваем тем что на входе (сам текст строки)
|
||||
segm_data[i + 4] = DispData[i];
|
||||
}
|
||||
for (byte i = amount + 4; i < amount + 8; i++) { // и последние 4 тоже забиваем пустыми символами
|
||||
segm_data[i] = 0x00;
|
||||
}
|
||||
for (byte i = 0; i <= amount + 4; i++) { // выводим
|
||||
displayByte(segm_data[i], segm_data[i + 1], segm_data[i + 2], segm_data[i + 3]);
|
||||
delay(delayMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GyverTM1637::scroll(uint8_t DispData[], int delayms) {
|
||||
byte DispDataByte[4];
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
DispDataByte[i] = digitHEX[DispData[i]];
|
||||
}
|
||||
scrollByte(DispDataByte, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::scroll(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms) {
|
||||
byte DispData[] = {digitHEX[bit0], digitHEX[bit1], digitHEX[bit2], digitHEX[bit3]};
|
||||
GyverTM1637::scrollByte(DispData, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::scroll(uint8_t BitAddr, uint8_t DispData, int delayms) {
|
||||
byte DispDataByte = digitHEX[DispData];
|
||||
scrollByte(BitAddr, DispDataByte, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::scrollByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms) {
|
||||
byte DispData[] = {bit0, bit1, bit2, bit3};
|
||||
GyverTM1637::scrollByte(DispData, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::scrollByte(uint8_t DispData[], int delayms) {
|
||||
byte lastBytes[4];
|
||||
byte step;
|
||||
byte stepArray[4];
|
||||
boolean changeByte[4] = {0, 0, 0, 0};
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
if (DispData[i] != lastData[i]) changeByte[i] = 1;
|
||||
lastBytes[i] = lastData[i];
|
||||
}
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
byte lastByte = lastData[i];
|
||||
stepArray[i] = lastByte;
|
||||
|
||||
if (changeByte[i]) {
|
||||
step = 0;
|
||||
swapBytes(&step, lastByte, 6, 0);
|
||||
swapBytes(&step, lastByte, 2, 1);
|
||||
swapBytes(&step, lastByte, 4, 5);
|
||||
swapBytes(&step, lastByte, 3, 6);
|
||||
stepArray[i] = step;
|
||||
}
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
byte lastByte = lastBytes[i];
|
||||
stepArray[i] = lastByte;
|
||||
|
||||
if (changeByte[i]) {
|
||||
step = 0;
|
||||
swapBytes(&step, lastByte, 3, 0);
|
||||
stepArray[i] = step;
|
||||
}
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
if (changeByte[i]) {
|
||||
stepArray[i] = 0;
|
||||
}
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
byte lastByte = lastBytes[i];
|
||||
byte newByte = DispData[i];
|
||||
stepArray[i] = lastByte;
|
||||
|
||||
if (changeByte[i]) {
|
||||
step = 0;
|
||||
swapBytes(&step, newByte, 0, 3);
|
||||
stepArray[i] = step;
|
||||
}
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
byte newByte = DispData[i];
|
||||
stepArray[i] = lastBytes[i];
|
||||
|
||||
if (changeByte[i]) {
|
||||
step = 0;
|
||||
swapBytes(&step, newByte, 0, 6);
|
||||
swapBytes(&step, newByte, 1, 2);
|
||||
swapBytes(&step, newByte, 5, 4);
|
||||
swapBytes(&step, newByte, 6, 3);
|
||||
stepArray[i] = step;
|
||||
}
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
displayByte(DispData);
|
||||
}
|
||||
}
|
||||
|
||||
void GyverTM1637::scrollByte(uint8_t BitAddr, uint8_t DispData, int delayms) {
|
||||
byte oldByte = lastData[BitAddr];
|
||||
byte newByte = DispData;
|
||||
byte step;
|
||||
|
||||
step = 0;
|
||||
swapBytes(&step, oldByte, 6, 0);
|
||||
swapBytes(&step, oldByte, 2, 1);
|
||||
swapBytes(&step, oldByte, 4, 5);
|
||||
swapBytes(&step, oldByte, 3, 6);
|
||||
displayByte(BitAddr, step);
|
||||
delay(delayms);
|
||||
|
||||
step = 0;
|
||||
swapBytes(&step, oldByte, 3, 0);
|
||||
swapBytes(&step, newByte, 0, 3);
|
||||
displayByte(BitAddr, step);
|
||||
delay(delayms);
|
||||
|
||||
step = 0;
|
||||
swapBytes(&step, newByte, 0, 6);
|
||||
swapBytes(&step, newByte, 1, 2);
|
||||
swapBytes(&step, newByte, 5, 4);
|
||||
swapBytes(&step, newByte, 6, 3);
|
||||
displayByte(BitAddr, step);
|
||||
delay(delayms);
|
||||
|
||||
displayByte(BitAddr, newByte);
|
||||
}
|
||||
|
||||
void swapBytes(byte* newByte, byte oldByte, byte newP, byte oldP) {
|
||||
byte newBit = 0;
|
||||
if (oldByte & (1 << oldP)) newBit = 1;
|
||||
else newBit = 0;
|
||||
*newByte = *newByte | (newBit << newP);
|
||||
}
|
||||
|
||||
void GyverTM1637::twist(uint8_t BitAddr, uint8_t DispData, int delayms) {
|
||||
twistByte(BitAddr, digitHEX[DispData], delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::twist(uint8_t DispData[], int delayms) {
|
||||
byte newData[4];
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
newData[i] = digitHEX[DispData[i]];
|
||||
}
|
||||
twistByte(newData, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::twist(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms) {
|
||||
byte DispData[] = {digitHEX[bit0], digitHEX[bit1], digitHEX[bit2], digitHEX[bit3]};
|
||||
GyverTM1637::twistByte(DispData, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::twistByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms) {
|
||||
byte DispData[] = {bit0, bit1, bit2, bit3};
|
||||
GyverTM1637::twistByte(DispData, delayms);
|
||||
}
|
||||
|
||||
void GyverTM1637::twistByte(uint8_t DispData[], int delayms) {
|
||||
byte step;
|
||||
byte stepArray[4];
|
||||
boolean changeByte[4] = {0, 0, 0, 0};
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
if (DispData[i] != lastData[i]) changeByte[i] = 1;
|
||||
stepArray[i] = DispData[i];
|
||||
}
|
||||
|
||||
step = step & 0b00111111; // выкл центральную
|
||||
for (byte i = 0; i < 5; i++) {
|
||||
step |= (1 << i); // зажигаем по одной
|
||||
for (byte k = 0; k < 4; k++) {
|
||||
if (changeByte[k])
|
||||
stepArray[k] = step;
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
}
|
||||
//for (byte r = 0; r < 1; r++) {
|
||||
for (byte i = 0; i < 6; i++) {
|
||||
step = 0b11000000;
|
||||
step = ~(step | (1 << i) | (1 << i + 1)); // бегает дырка
|
||||
for (byte k = 0; k < 4; k++) {
|
||||
if (changeByte[k]) stepArray[k] = step;
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
}
|
||||
//}
|
||||
step = 0b11000000;
|
||||
for (byte i = 0; i < 6; i++) {
|
||||
step |= (1 << i);
|
||||
for (byte k = 0; k < 4; k++) {
|
||||
if (changeByte[k])
|
||||
stepArray[k] = ~step;
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
}
|
||||
for (byte k = 0; k < 4; k++) {
|
||||
if (changeByte[k])
|
||||
stepArray[k] = 0b0000000;
|
||||
}
|
||||
for (byte i = 0; i < 7; i++) {
|
||||
for (byte k = 0; k < 4; k++) {
|
||||
if (changeByte[k]) {
|
||||
byte newBit = 0;
|
||||
if (DispData[k] & (1 << i)) newBit = 1;
|
||||
else newBit = 0;
|
||||
stepArray[k] |= (newBit << i);
|
||||
}
|
||||
}
|
||||
displayByte(stepArray);
|
||||
delay(delayms);
|
||||
}
|
||||
}
|
||||
|
||||
void GyverTM1637::twistByte(uint8_t BitAddr, uint8_t DispData, int delayms) {
|
||||
byte oldByte = lastData[BitAddr];
|
||||
byte newByte = DispData;
|
||||
byte step = oldByte;
|
||||
|
||||
step = step & 0b0111111; // выкл центральную
|
||||
|
||||
for (byte i = 0; i < 5; i++) {
|
||||
step |= (1 << i); // зажигаем по одной
|
||||
displayByte(BitAddr, step);
|
||||
delay(delayms);
|
||||
}
|
||||
//for (byte r = 0; r < 1; r++) {
|
||||
for (byte i = 0; i < 6; i++) {
|
||||
step = 0b1000000;
|
||||
step = ~(step | (1 << i) | (1 << i + 1)); // бегает дырка
|
||||
|
||||
displayByte(BitAddr, step);
|
||||
delay(delayms);
|
||||
}
|
||||
//}
|
||||
step = 0b1000000;
|
||||
for (byte i = 0; i < 6; i++) {
|
||||
step |= (1 << i);
|
||||
displayByte(BitAddr, ~step);
|
||||
delay(delayms);
|
||||
}
|
||||
step = 0;
|
||||
for (byte i = 0; i < 7; i++) {
|
||||
byte newBit = 0;
|
||||
if (newByte & (1 << i)) newBit = 1;
|
||||
else newBit = 0;
|
||||
step |= (newBit << i);
|
||||
displayByte(BitAddr, step);
|
||||
delay(delayms);
|
||||
}
|
||||
displayByte(BitAddr, newByte);
|
||||
}
|
||||
214
libraries/GyverTM1637/src/GyverTM1637.h
Normal file
214
libraries/GyverTM1637/src/GyverTM1637.h
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
GyverTM1637 - бибилотека для 7 сегментного дисплея на чипе TM1637 с кучей приколюх
|
||||
Документация:
|
||||
GitHub: https://github.com/GyverLibs/GyverTM1637
|
||||
Возможности:
|
||||
- Вывод цифр массивом или прицельно
|
||||
- Вывод букв из списка доступных (листай ниже) массивом или прицельно
|
||||
- Отдельная функция вывода часов и минут (часы без нуля слева, минуты с нулём)
|
||||
- Вывод числа от -999 до 9999 с учётом знака
|
||||
- Готовая функция бегущей строки
|
||||
- Функции смены яркости и состояния двоеточия автоматически обновляют дисплей
|
||||
- Функция обновления значения с эффектом вертикальной прокрутки
|
||||
- Функция обновления значения с эффектом скручивания (лучше один раз увидеть)
|
||||
|
||||
AlexGyver, alex@alexgyver.ru
|
||||
https://alexgyver.ru/
|
||||
MIT License
|
||||
|
||||
Основано на оригинальной библиотеке "Grove_4Digital_Display" от Frankie.Chu
|
||||
https://github.com/Seeed-Studio/Grove_4Digital_Display
|
||||
|
||||
Версии:
|
||||
v1.4 - поправлены типы данных и ошибки, добавлена совместимость с ESP
|
||||
*/
|
||||
|
||||
#ifndef GyverTM1637_h
|
||||
#define GyverTM1637_h
|
||||
#include <inttypes.h>
|
||||
#include <Arduino.h>
|
||||
class GyverTM1637 {
|
||||
public:
|
||||
|
||||
GyverTM1637(uint8_t clk, uint8_t dio); // объявление и инициализация
|
||||
|
||||
void display(uint8_t DispData[]); // выводит цифры массивом по ячейкам. От 0 до 9 (byte values[] = {3, 5, 9, 0}; )
|
||||
void display(uint8_t BitAddr, uint8_t DispData); // выводит цифру DispData в указанную ячейку дисплея BitAddr
|
||||
void display(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3); // если лень создавать массив, выводит цифры в ячейки
|
||||
|
||||
void displayByte(uint8_t DispData[]); // выводит байт вида 0xe6 и буквы-константы вида _a , _b .... массивом
|
||||
void displayByte(uint8_t BitAddr, uint8_t DispData); // выводит байт вида 0xe6 и буквы-константы вида _a , _b .... в ячейку
|
||||
void displayByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3); // если лень создавать массив, выводит байты в ячейки
|
||||
|
||||
void displayClock(uint8_t hrs, uint8_t mins); // выводит часы и минуты
|
||||
void displayClockScroll(uint8_t hrs, uint8_t mins, int delayms); // выводит часы и минуты с эффектом прокрутки
|
||||
void displayClockTwist(uint8_t hrs, uint8_t mins, int delayms); // выводит часы и минуты с эффектом скрутки
|
||||
|
||||
void displayInt(int value); // выводит число от -999 до 9999 (да, со знаком минус)
|
||||
|
||||
void runningString(uint8_t DispData[], byte amount, int delayMs); // бегущая строка (array, sizeof(array), задержка в мс)
|
||||
|
||||
void clear(void); // очистить дисплей
|
||||
|
||||
void point(boolean PointFlag); // вкл / выкл точку (POINT_ON / POINT_OFF)
|
||||
|
||||
void brightness(uint8_t bright, uint8_t = 0x40, uint8_t = 0xc0); // яркость 0 - 7
|
||||
|
||||
void scroll(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение прокруткой (адрес, ЦИФРА, задержка в мс)
|
||||
void scroll(uint8_t DispData[], int delayms); // обновить значение прокруткой (массив ЦИФР, задержка в мс)
|
||||
void scroll(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // прокрутка посимвольно
|
||||
void scrollByte(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение прокруткой (адрес, БАЙТ, задержка в мс)
|
||||
void scrollByte(uint8_t DispData[], int delayms); // обновить значение прокруткой (массив БАЙТ, задержка в мс)
|
||||
void scrollByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // прокрутка посимвольно
|
||||
|
||||
void twist(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение скручиванием (адрес, ЦИФРА, задержка в мс)
|
||||
void twist(uint8_t DispData[], int delayms); // обновить значение скручиванием (массив ЦИФР, задержка в мс)
|
||||
void twist(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // скрутка посимвольно
|
||||
void twistByte(uint8_t BitAddr, uint8_t DispData, int delayms); // обновить значение скручиванием (адрес, БАЙТ, задержка в мс)
|
||||
void twistByte(uint8_t DispData[], int delayms); // обновить значение скручиванием (массив БАЙТ, задержка в мс)
|
||||
void twistByte(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, int delayms); // скрутка посимвольно
|
||||
|
||||
private:
|
||||
uint8_t lastData[4];
|
||||
void update();
|
||||
int writeByte(int8_t wr_data);
|
||||
void start(void);
|
||||
void stop(void);
|
||||
|
||||
void sendByte(uint8_t BitAddr, int8_t sendData);
|
||||
void sendArray(uint8_t sendData[]);
|
||||
|
||||
uint8_t Cmd_SetData;
|
||||
uint8_t Cmd_SetAddr;
|
||||
uint8_t Cmd_DispCtrl;
|
||||
uint8_t PointData;
|
||||
|
||||
uint8_t Clkpin;
|
||||
uint8_t Datapin;
|
||||
};
|
||||
|
||||
void swapBytes(byte* newByte, byte oldByte, byte oldP, byte newP);
|
||||
uint8_t digToHEX(uint8_t digit); // вернёт код цифры для displayByte
|
||||
|
||||
//************definitions for TM1637*********************
|
||||
#define ADDR_AUTO 0x40
|
||||
#define ADDR_FIXED 0x44
|
||||
#define STARTADDR 0xc0
|
||||
|
||||
/**** definitions for the clock point of the digit tube *******/
|
||||
#define POINT_ON 1
|
||||
#define POINT_OFF 0
|
||||
|
||||
/**************definitions for brightness***********************/
|
||||
#define BRIGHT_DARKEST 0
|
||||
#define BRIGHT_TYPICAL 2
|
||||
#define BRIGHTEST 7
|
||||
|
||||
/************** БУКВЫ И СИМВОЛЫ *****************/
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define _A 0x77
|
||||
#define _B 0x7f
|
||||
#define _C 0x39
|
||||
#define _D 0x3f
|
||||
#define _E 0x79
|
||||
#define _F 0x71
|
||||
#define _G 0x3d
|
||||
#define _H 0x76
|
||||
#define _J 0x1e
|
||||
#define _L 0x38
|
||||
#define _N 0x37
|
||||
#define _O 0x3f
|
||||
#define _P 0x73
|
||||
#define _S 0x6d
|
||||
#define _U 0x3e
|
||||
#define _Y 0x6e
|
||||
#define _a 0x5f
|
||||
#define _b 0x7c
|
||||
#define _c 0x58
|
||||
#define _d 0x5e
|
||||
#define _e 0x7b
|
||||
#define _f 0x71
|
||||
#define _h 0x74
|
||||
#define _i 0x10
|
||||
#define _j 0x0e
|
||||
#define _l 0x06
|
||||
#define _n 0x54
|
||||
#define _o 0x5c
|
||||
#define _q 0x67
|
||||
#define _r 0x50
|
||||
#define _t 0x78
|
||||
#define _u 0x1c
|
||||
#define _y 0x6e
|
||||
#define _dash 0x40
|
||||
#define _under 0x08
|
||||
#define _equal 0x48
|
||||
#define _empty 0x00
|
||||
#define _degree 0x63
|
||||
|
||||
#define _0 0x3f
|
||||
#define _1 0x06
|
||||
#define _2 0x5b
|
||||
#define _3 0x4f
|
||||
#define _4 0x66
|
||||
#define _5 0x6d
|
||||
#define _6 0x7d
|
||||
#define _7 0x07
|
||||
#define _8 0x7f
|
||||
#define _9 0x6f
|
||||
|
||||
#else
|
||||
|
||||
enum TM1637_letters {
|
||||
_A = 0x77,
|
||||
_B = 0x7f,
|
||||
_C = 0x39,
|
||||
_D = 0x3f,
|
||||
_E = 0x79,
|
||||
_F = 0x71,
|
||||
_G = 0x3d,
|
||||
_H = 0x76,
|
||||
_J = 0x1e,
|
||||
_L = 0x38,
|
||||
_N = 0x37,
|
||||
_O = 0x3f,
|
||||
_P = 0x73,
|
||||
_S = 0x6d,
|
||||
_U = 0x3e,
|
||||
_Y = 0x6e,
|
||||
_a = 0x5f,
|
||||
_b = 0x7c,
|
||||
_c = 0x58,
|
||||
_d = 0x5e,
|
||||
_e = 0x7b,
|
||||
_f = 0x71,
|
||||
_h = 0x74,
|
||||
_i = 0x10,
|
||||
_j = 0x0e,
|
||||
_l = 0x06,
|
||||
_n = 0x54,
|
||||
_o = 0x5c,
|
||||
_q = 0x67,
|
||||
_r = 0x50,
|
||||
_t = 0x78,
|
||||
_u = 0x1c,
|
||||
_y = 0x6e,
|
||||
_dash = 0x40,
|
||||
_under = 0x08,
|
||||
_equal = 0x48,
|
||||
_empty = 0x00,
|
||||
_degree = 0x63,
|
||||
|
||||
_0 = 0x3f,
|
||||
_1 = 0x06,
|
||||
_2 = 0x5b,
|
||||
_3 = 0x4f,
|
||||
_4 = 0x66,
|
||||
_5 = 0x6d,
|
||||
_6 = 0x7d,
|
||||
_7 = 0x07,
|
||||
_8 = 0x7f,
|
||||
_9 = 0x6f,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user