fix display

This commit is contained in:
TheK4n 2021-09-03 20:05:40 +03:00
parent 8b7ee56d09
commit 3245816029
21 changed files with 26 additions and 2709 deletions

View File

@ -20,8 +20,8 @@
int pressure, pressure_low, pressure_high;
bool is_on_pump, is_on_display;
unsigned long last_time1, last_time2;
bool is_on_pump, is_on_display, display_cur_pressure;
unsigned long last_time1, last_time2, last_time3;
EncButton<EB_TICK, S1, S2, KEY> enc;
@ -48,8 +48,9 @@ void setup() {
EEPROM.get(2, pressure_high);
disp.clear();
disp.brightness(7);
disp.brightness(7); // яркость, 0 - 7 (минимум - максимум)
disp.clear();
}
void loop() {
@ -58,6 +59,7 @@ void loop() {
enc.tick();
if (enc.isTurn()) {
disp.clear();
if (enc.isRight()) {
pressure_low = get_constrained_pressure_low(pressure_low+10);
disp.displayInt(pressure_low);
@ -75,9 +77,18 @@ void loop() {
disp.displayInt(pressure_high);
}
is_on_display = true;
display_cur_pressure = false;
last_time2 = millis();
}
// нажать на энкодер - показать текущее давление
if (enc.isClick()) {
display_cur_pressure = true;
is_on_display = true;
last_time2 = millis();
}
// Если энкодер зажат то записать текущие пороги в энергонезависимую память
if (enc.isHolded()) {
EEPROM.put(0, pressure_low);
@ -87,16 +98,18 @@ void loop() {
// Датчик давления 0 - 1000 0 - 10 атмосфер
pressure = analogRead(pressure_port);
// Если прошло 5 сек с момента взаимодействия с энкодером
if (millis() - last_time2 > 5000) {
last_time2 = millis();
is_on_display = false;
// Если прошло 7 сек с момента взаимодействия с энкодером, то отключить дисплей
if (millis() - last_time2 > 7000) {
if (is_on_display) {
last_time2 = millis();
is_on_display = false;
disp.clear();
}
}
// Каждые 850 мс обновляет на дисплее текущее давление, если не бездействие
if (millis() - last_time1 > 350) {
last_time1 = millis();
if (is_on_display) {
if (display_cur_pressure & is_on_display) {
disp.displayInt(pressure);
}
}
@ -109,11 +122,14 @@ void loop() {
}
}
// Иначе если давление выше верхнего порога - выключить мотор
// Иначе если давление выше верхнего порога - выключить насос
else if (pressure > pressure_high) {
if (is_on_pump) {
digitalWrite(relay_port, LOW);
is_on_pump = false;
}
}
Serial.print(pressure_low);
Serial.print(',');
Serial.println(pressure_high);
}

View File

@ -1,21 +0,0 @@
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.

View File

@ -1,194 +0,0 @@
![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)
![author](https://img.shields.io/badge/author-AlexGyver-informational.svg)
# 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**'ов!

View File

@ -1,74 +0,0 @@
// Пример с обработчиками
// Опциональные дефайн-настройки (показаны по умолчанию)
//#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(); // обработка всё равно здесь
}

View File

@ -1,49 +0,0 @@
// Пример с прямой работой библиотеки на прерываниях
// Опциональные дефайн-настройки (показаны по умолчанию)
//#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);
}

View File

@ -1,70 +0,0 @@
// пример с прерываниями pinChangeInterrupt (прерывания на любом пине)
// только для ATmega328 (UNO, Nano, Pro Mini)
#define CLK 4
#define DT 5
#define SW 6
#include <EncButton.h>
EncButton<EB_TICK, CLK, DT, SW> enc;
void setup() {
Serial.begin(9600);
// настроить PCINT
attachPCINT(CLK);
attachPCINT(DT);
}
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");
}
}
// функция для настройки PCINT для ATmega328 (UNO, Nano, Pro Mini)
uint8_t attachPCINT(uint8_t pin) {
if (pin < 8) { // D0-D7 // PCINT2
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << pin);
return 2;
}
else if (pin > 13) { //A0-A5 // PCINT1
PCICR |= (1 << PCIE1);
PCMSK1 |= (1 << pin - 14);
return 1;
}
else { // D8-D13 // PCINT0
PCICR |= (1 << PCIE0);
PCMSK0 |= (1 << pin - 8);
return 0;
}
}
// Векторы PCINT, нужно кинуть сюда тики
// пины 0-7: PCINT2
// пины 8-13: PCINT0
// пины A0-A5: PCINT1
ISR(PCINT0_vect) {
}
ISR(PCINT1_vect) {
}
ISR(PCINT2_vect) {
enc.tick();
}

View File

@ -1,63 +0,0 @@
// Пример с прямой работой библиотеки
// Опциональные дефайн-настройки (показаны по умолчанию)
//#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");
}

View File

@ -1,35 +0,0 @@
#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");
}

View File

@ -1,66 +0,0 @@
#######################################
# 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

View File

@ -1,9 +0,0 @@
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=*

View File

@ -1,383 +0,0 @@
/*
Ультра лёгкая и быстрая библиотека для энкодера, энкодера с кнопкой или просто кнопки
Документация:
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

View File

@ -1,93 +0,0 @@
#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
}

View File

@ -1,13 +0,0 @@
// Быстрый 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

View File

@ -1,21 +0,0 @@
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.

View File

@ -1,337 +0,0 @@
![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)
![author](https://img.shields.io/badge/author-AlexGyver-informational.svg)
# 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**'ов!

View File

@ -1,240 +0,0 @@
/*
Пример вывода на дисплей с регистром 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 это время в миллисекундах!
}

View File

@ -1,182 +0,0 @@
/*
Пример вывода на дисплей с регистром 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 это время в миллисекундах!
}

View File

@ -1,91 +0,0 @@
#######################################
# 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

View File

@ -1,9 +0,0 @@
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=*

View File

@ -1,535 +0,0 @@
#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);
}

View File

@ -1,214 +0,0 @@
/*
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