Давно было намерение сделать универсальный таймер, который можно было бы использовать для разных процессов, где требуется выдержка определённого времени и, который бы мог включать/отключать, по истечении времени, различную нагрузку, вплоть до устройств на ~220 В. Время пришло. Схема и программа разработаны. Основой этого таймера послужили проекты Таймер для катушки Мишина и МТР-1.2 (термометр-регулятор).
Как часто бывает, начальный проект всегда имеет какие-то недостатки и более оптимальное решение приходит уже после того, как углубляешься в тему. Так и в этом случае с таймером. После проверки первой версии, пришёл к написанию второй, которую считаю гораздо лучше, оптимальнее и имеющую большие возможности.
Начиная с версии v2.2 дополнительно применена условная компиляция, что позволило легко выбирать вариант логики управления кнопками: HIGH или LOW.
Начиная с версии v2.4 появилась возможность выбирать количество разрядов в индикаторе (3 или 4).
Начиная с версии v3 появился циклический режим работы. Можно задавать время паузы.
Кнопкой [Часы] устанавливаются часы до 99 часов (чуть больше 4-х суток), в первых двух разрядах таймера.
Кнопкой [Минуты] устанавливаются минуты до 59, в третьем и четвёртом разрядах. Часы и минуты разделены точкой второго разряда.
Кнопкой [Старт/Стоп] производится пуск и остановка таймера. Если таймер запущен, то разделительная точка второго разряда мигает. Если таймер остановлен, то точка второго разряда светится постоянно. Точка четвёртого разряда указывает на подключение модуля реле. Если модуль реле отключен, то точка четвёртого разряда не светится.
При одновременно нажатии на кнопки [Часы] и [Минуты] производится сброс установленного времени и на индикаторе выводится [0.00], первый незначащий 0 гасится.
При одновременно нажатии на кнопки [Минуты] и [Старт/Стоп] производится подключение [0.00.] или отключение [0.00] модуля реле, так как бывает, что не всегда необходимо управлять какой-то нагрузкой, поэтому сделал так, чтобы модуль реле можно было бы отключить программно, сигнал же об окончании работы таймера осуществляется звуком через буззер.
Таймер v2
Управляется таймер так же тремя кнопками, но их значение другое:
MODE – Выбор параметра настройки
MINUS – Убавить [–]
PLUS – Прибавить [+]
С помощью этих кнопок теперь возможно устанавливать время в двух режимах:
hh.mm(.) – часы.минуты(.)
mm.ss(.) – минуты.секунды(.)
Возможно через меню настроек:
Включение/Отключение звука
Включение/Отключение активности модуля реле
Установка яркости индикатора [0...7]
По нажатию на кнопку MODE происходит переход в настройки. Каждое нажатие – переход к следующему параметру. В крайнем левом разряде выводится номер пункта меню настройки. Так на индикаторе будет выводится следующая информация:
Индикация текущего времени*: hh.mm(.) | mm.ss(.)
Выбран режим hh.mm (часы.минуты) - на индикаторе: 10.00(.)[1.00(.)]
Выбран режим mm.ss (минуты.секунды) - на индикаторе: 10.01(.)[1.01(.)]
Установка часов|минут – на индикаторе: 20.хх [2.xx(.)], где хх = 0...99
Установка минут|секунд – на индикаторе: 30.хх [3.xx(.)], где хх = 0...59
Активность реле включена – на индикаторе: 40.01. [4.00.] - свечение точки DIG4*
Активность реле отключена – на индикаторе: 40.00 [4.00] - точка DIG4* не светится
Активность зуммера включена – на индикаторе: 50.01(.)[5.01(.)]
Активность зуммера отключена – на индикаторе: 50.00(.)[5.00(.)]
Яркость индикатора – на индикаторе: 60.0х[6.0x(.)], где х = 0...7
Запуск таймера производится кнопкой PLUS.
Остановка запущенного таймера на паузу производится кнопками PLUS, MINUS. При работе таймера кнопка MODE блокируется. Настройка таймера возможна только при остановленном таймере.
В момент сигнала об окончании работы таймера, остановить сигнал можно нажатием на любую кнопку.
Управление достаточно интуитивное и позволяет легко настраивать и пользоваться таймером.
Таймер v3
Эта версия имеет некоторое дополнение для активизации циклического режима работы, поэтому добавлены ещё три пункта в меню настройки. Для совместимости с трёхразрядным индикатором, в меню настроек значение mode выводится во втором разряде для 4-х разрядного индикатора и в первом разряде трёх разрядного индикатора. Теперь на индикаторе выводится следующая информация:
Индикация текущего времени*: hh.mm(.) | mm.ss(.)
Выбран режим hh.mm (часы.минуты) - на индикаторе: 1.00(.)
Выбран режим mm.ss (минуты.секунды) - на индикаторе: 1.01(.)
Установка часов|минут – на индикаторе: 2.xx(.), где хх = 0...99
Установка минут|секунд – на индикаторе: 3.xx(.), где хх = 0...59
Активность реле включена – на индикаторе: 4.00. - свечение точки DIG4*
Активность реле отключена – на индикаторе: 4.00 - точка DIG4* не светится
Активность зуммера включена – на индикаторе: 5.01(.)
Активность зуммера отключена – на индикаторе: 5.00(.)
Яркость индикатора – на индикаторе: 6.0x(.), где х = 0...7
Активность циклического режима включена – на индикаторе: 7.01(.)
Активность циклического режима отключена – на индикаторе: 7.00(.)
Установка* часов|минут – на индикаторе: 8.хх, где хх = 0...99
Установка* минут|секунд – на индикаторе: 9.xx(.), где хх = 0...59
Схема
Основой универсального таймера является плата Ардуино (Arduino Uno, Arduino Nano, Arduino Pro Mini и подобные). Управление осуществляется сенсорными кнопками TTP223, конечно можно вместо них использовать и обычные кнопки.
Индикация таймера осуществляется на четырёх разрядном семисегментном светодиодном индикаторе. В первом варианте схемы (только для версии v1) используется индикатор с общим катодом, который управляется сдвиговым регистром SN74HC595N. В настоящее время это вполне рабочий бюджетный вариант.
Исполнительным устройство является модуль реле K1, с управляющим сигналом высокого уровня (только для версии v1). У меня самодельный модуль, но возможно использование любого модуля и покупного в том числе.
По окончании работы таймера выдаётся звуковой сигнал через буззер активного типа BA1. Выключатель SA2 позволяет отключать звук окончания работы таймера, к примеру, когда окончание работы таймера приходится на ночное время.
Питание таймера осуществляется от внешнего источника питания +5В.
Второй вариант схемы в качестве индикатора использует модуль на TM1637. Для контроллера TM1637 используются светодиодные семисегментные индикаторы с общим анодом. В данном случае модуль самодельный, если использовать покупной модуль, то в нём должна быть возможность управления точками разрядов.
В версии v2 программы таймера используется логика управления низким уровнем выходными устройствами. Кнопки имеют несколько другие функции, поэтому схема изменилась. Попутно отпала необходимость в выключателе звука SA2. Для совместимости вариантов, управляющие пины остались прежними. Исходя из логики управления низким уровнем выходными устройствами, изготовил модуль реле, который управляется (включается) подачей на вход сигнала низкого уровня - LOW.
С версии v2.2 программы таймера сделана возможность выбирать логику управления кнопками. Возможно использовать сенсорные кнопки типа TTP223 (с логикой HIGH), или обычные кнопки (с логикой LOW). Так же для совместимости вариантов, управляющие пины остались прежними. Реализация совместимости программная.
В версии v3.1 программы таймера использован покупной 4-х разрядный индикатор часового типа. Поэтому для индикации активности реле используется дополнительный светодиод HL1. Схема подключения немного упрощена. Подключения идут на пины последовательно.
Ниже вариант схемы с использование обычных кнопок и логикой управления LOW. Описание смотрите ниже на странице Таймер v3.1.
Макетирование схемы
Вначале программа отлаживалась на макете. Ниже фото макета схемы 1. На фото модуль с кнопками снят. Программа проверялась на Arduino Pro Mini.
Далее отлаживалась программа для схемы 2. Модуль индикатора собран на четырёх разрядном индикаторе LN-5644-11Q(общий анод). Микросхема TM1637 припаяна к плате стенда проверки индикаторов. В момент запуска таймера включается модуль реле. На фото видно свечение зелёного светодиода на модуле реле (управление высоким уровнем). Подключение модуля реле указывается свечением точки четвёртого разряда (DIG4).
Скетч
Ниже приводится скетч версии v1 второго варианта схемы с индикатором на TM1637. Скетч версии v1 первого варианта схемы на индикаторе с управлением через сдвиговый регистр SN74HC595N можно скачать в Приложении.
/*************************************************************
2022-03-11 Mr.ALB Универсальный таймер на TM1637
Индикатор 7-сегментный 4-х разрядный
LN5644 - общий анод! Можно любой другой,
но с общим анодом!
Кнопки TP223 - сенсорные.
Кнопки:
1. HOUR – Установка часов
2. MIN – Установка минут
3. START – Старт/Стоп
С помощью кнопки HOUR устанавливаются часы до 99 (чуть больше 4-х суток).
С помощью кнопки MIN устанавливаются минуты до 59.
Кнопкой START осуществляется пуск и остановка таймера.
Кнопки MIN и START нажать одновременно для
включения/выключения активности реле.
Индикация активности реле – светящаяся точка 4-го разряда.
Кнопки MIN и HOUR нажать одновременно для обнуления
установленного времени.
Работа таймера – мигание точки 2-го разряда.
Таймер в режиме паузы или ожидания пуска –
постоянно светящаяся точка 2-го разряда.
Ранее установленное время после окончания работы
таймера сохраняется и новый пуск таймера
осуществляется только нажатием кнопки START.
****************************************************************/#include<TimerOne.h>// Подключение библиотеки Таймер1#include"TM1637_mralb2.h"// Библиотека для TM1637#define BT_HOUR 10
#define BT_MIN 11
#define BT_START 12
#define BUZZER 9
#define OUT 8
#define CLK 3
#define DIO 2
TM1637 disp(CLK, DIO); // Создание объекта индикатора// Массив символовstaticint8_t simb[] =
{
0x3f, 0x06, 0x5b, 0x4f,// 0, 1, 2, 3
0x66, 0x6d, 0x7d, 0x07,// 4, 5, 6, 7
0x7f, 0x6f, 0x00, 0x80 // 8, 9, 10 - пусто, 11 - точка
};
#define BUZZER 9 // Зуммер#define MAXALARM 9 // Сколько раз бикнет буззер/* Глобальные переменные для времени */uint32_t t1, dt;
byte hour_time = 0, hour_set;
int min_time = 0, min_set;
bool flag_run =false; // Флаг работы таймераbool flag_rele =true; // Флаг подключения реле// Переменная для прерывания, мигание точекvolatileboolean flag_point;
/***********************
* Функция настройки
************************/voidsetup()
{
//Serial.begin(9600);pinMode(BT_HOUR,INPUT); // Установка часовpinMode(BT_MIN,INPUT); // Установка минутpinMode(BT_START,INPUT); // Старт/стоп таймераpinMode(OUT,OUTPUT); // Управляющий выходdigitalWrite(OUT,LOW); // Отключим выходpinMode(BUZZER,OUTPUT); // ЗуммерdigitalWrite(BUZZER,HIGH); // Отключим выход
disp.clear();
// Яркость минимум=0, стандарт=2, максимум=7)
disp.brightness(5);
// Для Ардуино Уно, загасить светодиод на пин13
// В других Ардуино не нужноpinMode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
pinMode(BUZZER,OUTPUT); // ЗуммерdigitalWrite(BUZZER,LOW); // Отключим выход// Инициализация прерывания на 500 мс
// Для мигания точекTimer1.initialize(500000);
flag_run =false;
// Проверка сегментов и зумера
fnTestSeg();
} // End setup
/***************************
* Рабочая программа
**************************/voidloop()
{
t1 =millis(); // Текущее время работы программы в мс// Если нажать две кнопки, то обнуляем значение времениwhile (digitalRead(BT_HOUR) &&digitalRead(BT_MIN))
{
if (millis() - t1 >= 2000)
{ // Удерживать более 2 секунд
hour_time = 0;
min_time = 0;
fnStopTimer(); // Стоп таймер
fnPrintTime(); // Вывод текущего времени
fnMyDelay(500); // Задержкаbreak;
}
fnPrintTime(); // Вывод текущего времени
fnMyDelay(100); // Задержка
}
// Если нажать кнопки BT_MIN и BT_START,
// то Влючить/Выключить активность Релеbool statBtStart, statBtMin;
statBtStart = debounce(false, BT_START);
statBtMin = debounce(false, BT_MIN);
while (!flag_run && statBtStart && statBtMin)
{
if (millis() - t1 >= 2000)
{ // Удерживать более 2 секунд
flag_rele =!flag_rele;
flag_point =true;
fnPrintTime(); // Вывод текущего времениbreak;
}
statBtStart = debounce(false, BT_START);
statBtMin = debounce(false, BT_MIN);
fnPrintTime(); // Вывод текущего времени
}
// Было нажатие кнопки СТАРТif
(
debounce(false, BT_START) &&!digitalRead(BT_HOUR) &&!digitalRead(BT_MIN)
)
{
delay(500);
if (flag_run ==false&& (hour_time != 0 || min_time != 0))
{
// Запуск таймера
flag_run =true;
// Подключение прерыванияTimer1.attachInterrupt(blink);
// Включим выход if (flag_rele)digitalWrite(OUT,HIGH);
hour_set = hour_time;
min_set = min_time;
dt = t1;
}
else
{
// Остановим таймер на ПАУЗУ
fnStopTimer();
flag_point =true;
}
}
// Установка часовif
(
flag_run ==false&&digitalRead(BT_HOUR) ==HIGH&&!digitalRead(BT_START)
)
{
hour_time++;
if (hour_time > 99)hour_time = 0;
fnMyDelay(300);
}
// Установка минутif
(
flag_run ==false&&digitalRead(BT_MIN) ==HIGH&&!digitalRead(BT_START)
)
{
min_time++;
if (min_time > 59)min_time = 0;
fnMyDelay(300);
}
fnPrintTime(); // Вывод текущего времени// Проверка пройденной минутыif (flag_run ==true&& ((t1 - dt) >= 60000))
{
min_time--;
if (min_time < 0 && hour_time != 0)
{
min_time = 59;
hour_time--;
}
// Завершение времени таймераif (min_time == 0 && hour_time == 0)
{
fnStopTimer(); // Стоп таймер
fnAlarmTimer(); // Сигнал окончания таймера// Восстановим начальные установки
// для нового запуска
hour_time = hour_set;
min_time = min_set;
flag_point =true;
fnPrintTime(); // Вывод текущего времениdelay(1000);
}
dt = t1;
}
} // End loop
/**********************************
ПОДПРОГРАММЫ
**********************************/
/****************************************
* Функция: Проверка сегментов и буззера
***************************************/void fnTestSeg()
{
flag_point =true;
hour_time = 88;
min_time = 88;
fnPrintTime();
delay(2000);
digitalWrite(BUZZER,HIGH);
delay(100);
digitalWrite(BUZZER,LOW);
//disp.clear();
hour_time = 0;
min_time = 0;
} // End fnTestSeg
/******************************
Функция: Задержка в мс
*****************************/void fnMyDelay(uint32_t mydelay)
{
dt =millis();
while ((millis() - dt) < mydelay)
{
if (digitalRead(BT_START)) break;
}
} // End fnMyDelay
/*************************
Функция мигания точек
************************/voidblink()
{
flag_point =!flag_point;
} // End blink
/******************************
Функция: Стоп таймер
*****************************/void fnStopTimer()
{
flag_run =false;
if (flag_rele)
digitalWrite(OUT,LOW); // Отключим выходTimer1.detachInterrupt(); // Остановка прерывания
} // End fnStopTimer
/***************************
Функция: сигнал таймера
***************************/void fnAlarmTimer()
{
// Включаем сигнал
// Сигнал пульсирующий
// .5 секунды звук
// .5 секунды паузаlong t;
for (byte j = 0; j < MAXALARM; j++)
{
t =millis();
while (millis() - t < 500)
{
// Звук .5 секундыdigitalWrite(BUZZER,HIGH);
//PORTB |= (1 << PB5); // Включаем
fnPrintTime(); // Вывод текущего времени// Если нажата кнопка START
// Выход из цикла while()if (digitalRead(BT_START)) break;
}
t =millis();
while (millis() - t < 500)
{
// Пауза .5 секундыdigitalWrite(BUZZER,LOW);
//PORTB &= ~(1 << PB5); // Выключаем
fnPrintTime(); // Вывод текущего времени// Если нажата кнопка START
// Выход из цикла while()if (digitalRead(BT_START)) break;
}
// Если нажата кнопка START
// Выход из цикла for()if (digitalRead(BT_START)) break;
fnPrintTime(); // Вывод текущего времени
}
} // End fnAlarmTimer
/****************************************
Вывод времени в формате: mm.ss
***************************************/void fnPrintTime()
{
byte dig1 = hour_time / 10,
dig2 = hour_time % 10,
dig3 = min_time / 10,
dig4 = min_time % 10;
byte digit2, digit4;
// Вывод точки 2-го разрядаif (flag_point)
digit2 = simb[dig2] |_dp;
else digit2 = simb[dig2];
// Вывод точки 4-го разрядаif (flag_rele)
digit4 = simb[dig4] |_dp;
else digit4 = simb[dig4];
if (dig1 == 0) dig1 = 10; // Гашение незначащего нуля// Вывод на индикатор
disp.displayByte(simb[dig1], digit2, simb[dig3], digit4);
} // End fnPrintTime
/****************************************
Функция для подавления дребезга
*****************************************/boolean debounce(boolean last,byte buttonPin)
{
// Читаем состояние кнопкиboolean current =digitalRead(buttonPin);
if (last != current)
{
fnMyDelay(5);
current =digitalRead(buttonPin);
}
return current;
} // End debounce
После тестирования первой версии скетча, пришёл к мнению, что требуется значительная переделка управления, чтобы с помощью всего трёх кнопок создать полное управление всеми функциями универсального таймера. Была создана версия v2.
В итоге получилось создать меню настроек в котором 7 пунктов mode =
Индикация текущего времени: hh.mm(.) | mm.ss(.) (зависит от режима 1)
Режим hh.mm (часы.минуты) - 0 | режим mm.ss (минуты.секунды) - 1
Версия v2.4 не имеет циклического режима, просто таймер. Скетч этой версии можно посмотреть ниже по нажатию на соответствующую кнопку (скрыл, чтобы не загромождать страницу). Новинка этой версии: применена условная компиляция, чтобы легко можно было перейти на логику управления кнопками либо LOW, либо HIGH. Дополнительно, используя условную компиляцию, удалось быстро перенастраивать скетч на использование индикатора, имеющего всего три разряда. Модуль индикатора смотрите по ссылке: Модуль на TM1637, модификация платы v4.
/*************************************************************
2022-03-11 Mr.ALB Универсальный таймер на TM1637
Индикатор 7-сегментный 4-х разрядный (можно 3-х)
LN5644 - общий анод! Можно любой другой,
но с общим анодом!
Кнопки TP223 - сенсорные (можно обычные).
https://mralb.ru/sections/programming/arduino_24.php#content_center
В версии v1 Кнопки:
1. HOUR – Установка часов
2. MIN – Установка минут
3. START – Старт/Стоп
С помощью кнопки HOUR устанавливаются часы до 99
(чуть больше 4-х суток).
С помощью кнопки MIN устанавливаются минуты до 59.
Кнопкой START осуществляется пуск и остановка таймера.
Кнопки MIN и START нажать одновременно
для включения/выключения активности реле.
Индикация активности реле – светящаяся точка 4-го разряда.
Кнопки MIN и HOUR нажать одновременно
для обнуления установленного времени.
Работа таймера – мигание точки 2-го разряда.
Таймер в режиме паузы или ожидания пуска – постоянно светящаяся
точка 2-го разряда.
Ранее установленное время после окончания работы таймера сохраняется
и новый пуск таймера осуществляется только нажатием кнопки START.
2022-04-14 Mr.ALB Переделка на полное управление тремя кнопками
2022-04-15 Mr.ALB написана v2.0
- Имеется меню режимов настройки.
- Возможно устанавливать время в двух режимах:
1. hh.mm(.)
2. mm.ss(.)
- Вкл./Откл. звука
- Вкл./Откл. реле
- установка яркости индикатора 0...7
2022-04-16 Mr.ALB v2.1 оптимизация кода
2022-04-17 Mr.ALB v2.2 адаптация под LGT8F + создание
адаптивной компиляции под разную логику кнопок.
Теперь можно использовать кнопки с логикой
управления высоким уровнем HIGH или кнопки с
логикой управления низким уровнем LOW
2022-04-20 Mr.ALB v2.3 предварительный сигнал при остатке
времени 5 мин
2022-04-28 Mr.ALB v2.4 логика управления кнопками TTP223 - LOW
+ отладка + оптимизация + выбор индикатора
на 3 или 4 разряда
Кнопки TTP223 (логика HIGH) или обычные (логика LOW):
1. MODE – Выбор режима
2. PLUS – Прибавить +
3. MINUS – Убавить -
* Примечание: Если у TTP223 замкнута перемычка А, то
* выбрать логику управления #define LOGICA 0
Соединения:
DIO - пин 2
CLK - пин 3
Buzzer - пин 9
MODE - пин 10
MINUS - пин 11
PLUS - пин 12
Реле - пин А0
2022-04-15 Скетч использует 4012 байт
2022-04-16 Скетч использует 3854 байт
2022-04-17 Скетч использует 5596 байт - режим отладки
2022-04-18 Скетч использует 4246 байт - режим откладки отключен
2022-04-19 Скетч использует 4080 байт ARDUINO_UNO
2022-04-20 Скетч использует 4110 байт ARDUINO_UNO
2022-04-28 Скетч использует 4072 байт Индикатор 4 разряда
2022-04-28 Скетч использует 4078 байт Индикатор 3 разряда
Архив с проектом: https://disk.yandex.ru/d/B4miN-and3bNtQ
****************************************************************/#include<TimerOne.h>// Подключение библиотеки Таймер1#include"TM1637_mralb2.h"// Библиотека для TM1637#define OUT A0
#define BUZZER 9
#define BT_MODE 10
#define BT_MINUS 11
#define BT_PLUS 12
#define MAXBEEP 16 // Сколько раз бикнет буззер#define DEF_WAIT_BUTTON 26 // Подтверждение кнопки#define DELAY_CLICK 21 // Время клика#define DELAY_BT 350 // Пауза после нажатия кнопки
// Включение режима отладки
// Если нет надобности, то строку ниже закоментировать
//#define DEBUG
// Определение типа используемой платы#define ARDUINO_UNO
//#define LGT8F
// Установите логику управления кнопками в вашей схеме
// Логика управления 1 - HIGH | 0 - LOW#define LOGICA 1
// Определение символов#define DP 10
#define PUSTO 11
#define CLK 3
#define DIO 2
#define MAXDIGIT 4 // Сколько всего разрядов в индикаторе 3|4TM1637 disp(CLK, DIO); // Создание объекта индикатора
; // Объявление и инициализация
// Массив символовstaticint8_t symb[] =
{
0x3f, 0x06, 0x5b,// 0, 1, 2
0x4f, 0x66, 0x6d,// 3, 4, 5,
0x7d, 0x07, 0x7f,// 6, 7, 8,
0x6f, 0x80, 0x00,// 9, 10 - точка, 11 - пусто,
};
// Структура разрядов дисплеяstruct Disp
{
byte high; // Разряды индикатора DID1, DIG2byte low; // Разряды индикатора DIG3, DIG4byte bright = 3; // Яркость 0...7
};
// Создание переменной типа Disp
Disp sdisp;
/* Глобальные переменные для времени */uint32_t t1, dt;
// Структура переменной времениstruct Tim
{
byte hh;
byte hh_set;
byte mm;
byte mm_set;
byte ss;
byte ss_set;
};
// Создание переменной типа Tim
Tim stime;
// Структура переменной флаговstruct Flag
{
bool runTimer =false; // Флаг работы таймераbool rele =true; // Флаг подключения релеbool buzz =true; // Флаг активности звукаbool modeTime2 =false; // Флаг mm.ss(.)
};
// Создание переменной типа Flag
Flag sflag;
// Переменная для прерывания, мигание точекvolatileboolean flag_point =true;
byte mode = 0; // Пункт меню 0 - вывод времени// Объявление функции сигнала Buzzer-a
// Окончание времени таймераvoid fnAlarmTimer
(
byte max_beep = MAXBEEP,unsignedint delay_beep = 500
);
// Объявление функции сканирования кнопки TTP223boolean fnScanButton
(
byte buttonPin,byte buttonWait = DEF_WAIT_BUTTON
);
// Объявление функции пиканья кнопкиvoid fnClickButton
(
unsignedint delay_ms = DELAY_CLICK
);
/***********************
Функция настройки
************************/voidsetup()
{
#ifdef DEBUG
Serial.begin(115200);
#endif#if (LOGICA == 1)
// Если логика управления кнопками 1 - HIGHpinMode(BT_MODE,INPUT); // Выбор режимаpinMode(BT_PLUS,INPUT); // Прибавить +pinMode(BT_MINUS,INPUT); // Убавить -#else// Если логика управления кнопками 0 - LOWpinMode(BT_MODE,INPUT_PULLUP); // Выбор режимаpinMode(BT_PLUS,INPUT_PULLUP); // Прибавить +pinMode(BT_MINUS,INPUT_PULLUP); // Убавить -#endif// Логика управления реле 0 - LOWpinMode(OUT,OUTPUT); // Управляющий выходdigitalWrite(OUT,HIGH); // Отключим выход// Логика управления звуком 0 - LOWpinMode(BUZZER,OUTPUT); // ЗуммерdigitalWrite(BUZZER,HIGH); // Отключим выход
disp.brightness(sdisp.bright);
// Для Ардуино Уно, загасить светодиод на пин13
// В других Ардуино не нужно#ifdef ARDUINO_UNO
pinMode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
#endif// Инициализация прерывания на 500 мс
// Для мигания точекTimer1.initialize(500000);
// Проверка символов индикатора
// и работы звука буззера
fnDisplayTest();
//flag_point = true;
// Вывод текущего времени
fnPrintDisp(stime.hh, stime.mm);
} // End setup
/***************************
Рабочая программа
**************************/
// Статусы кнопокbool st_bt_minus,
st_bt_plus,
st_bt_mode;
voidloop()
{
// Проверка состояния кнопки BT_MODE
/*******************************************************
Всего 7 пунктов меню:
0 - Индикация текущего времени: hh.mm(.)|mm.ss(.)
1 - Режим hh.mm - 0 | режим mm.ss - 1
2 - Установка часов|минут 0...99
3 - Установка минут|секунд 0...59
4 - Активность реле 0|1 00.00. - точка DIG4
5 - Активность зуммера 0|1
6 - Яркость индикатора 0...7
При запущенном таймере меню заблокировано
*******************************************************/
// Условная компиляция. Выбор логики управления#if (LOGICA == 1)
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_mode &&!sflag.runTimer)
{
st_bt_mode =LOW;
fnMenuMode(); // Меню выбора режима
}
// Текущее время работы программы в мс
t1 =millis();
if (dt > t1) dt = t1; // Защита от переполнения t1// Автоматической возвращение из меню параметров
// к индикации времени через 10 секунд бездействияif ((t1 - dt > 10000) && mode != 0) mode = 0;
// Вывод текущего значения на дисплей
// Выбор установленных значений на индикаторswitch (mode)
{
case 1:// Альтернативное время
sdisp.low = sflag.modeTime2;
break;
case 2:// Значение в разрядах DIG1, DIG2if (sflag.modeTime2)
sdisp.low = stime.mm;
else
sdisp.low = stime.hh;
break;
case 3:// Значение в разрядах DIG3, DIG4if (sflag.modeTime2)
sdisp.low = stime.ss;
else
sdisp.low = stime.mm;
break;
case 4:// Активность реле
sdisp.low = sflag.rele;
break;
case 5:// Активность буззера
sdisp.low = sflag.buzz;
break;
case 6:// Уровень яркости 0...7
sdisp.low = sdisp.bright;
}
fnPrintTime(mode); // Выводим текущее время
/******************** setting *********************/
// Настройка альтернативного времени mm.ss(.)if (mode == 1)
{
sflag.modeTime2 = fnSetParamMode(sflag.modeTime2,false,true);
sdisp.low = sflag.modeTime2;
#if(MAXDIGIT==3)
if (sflag.modeTime2 && stime.mm_set > 9)stime.mm_set = 9;
#endif
sdisp.high = mode;
}
// Установка часов - hours|minitsif (mode == 2)
{
if (sflag.modeTime2)
{
#if(MAXDIGIT==4)
stime.mm_set = fnSetParamMode(stime.mm_set, 0, 99);
#elif(MAXDIGIT==3)
stime.mm_set = fnSetParamMode(stime.mm_set, 0, 9);
#endif
}
else
{
#if(MAXDIGIT==4)
stime.hh_set = fnSetParamMode(stime.hh_set, 0, 99);
#elif(MAXDIGIT==3)
stime.hh_set = fnSetParamMode(stime.hh_set, 0, 9);
#endif
}
// Установка минут - minits|secondsif (mode == 3)
{
if (sflag.modeTime2)
stime.ss_set = fnSetParamMode(stime.ss_set, 0, 59);
else
stime.mm_set = fnSetParamMode(stime.mm_set, 0, 59);
// Установим текущее время, если таймер не запущенif (!sflag.runTimer)
{
if (sflag.modeTime2)
{
stime.ss = stime.ss_set;
sdisp.low = stime.ss_set;
}
else
{
stime.mm = stime.mm_set;
sdisp.low = stime.mm_set;
}
}
sdisp.high = mode;
}
// Настройка активности реле - releif (mode == 4)
{
sflag.rele = fnSetParamMode(sflag.rele,false,true);
// Выключим выходif (!sflag.rele)digitalWrite(OUT,HIGH);
sdisp.low = sflag.rele;
sdisp.high = mode;
}
// Настройка активности звука - buzz/click/alarmif (mode == 5)
{
sflag.buzz = fnSetParamMode(sflag.buzz,false,true);
sdisp.low = sflag.buzz;
sdisp.high = mode;
}
// Настройка яркости индикатора - brightnessif (mode == 6)
{
sdisp.bright = fnSetParamMode(sdisp.bright, 0, 7);
disp.brightness(sdisp.bright);
sdisp.low = sdisp.bright;
sdisp.high = mode;
}
/****************** End setting ******************/
/****************** START TIMER ******************/
st_bt_plus =LOW;
st_bt_minus =LOW;
// Условная компиляция. Выбор логики управления#if (LOGICA == 1)
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
#elseif (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
#endif// Если таймер ещё не запущенif (!sflag.runTimer && st_bt_plus)
{ // Было нажатие кнопки BT_PLUS - старт таймераif
(
mode == 0 &&
(
(
(stime.hh_set != 0 || stime.mm_set != 0) &&!sflag.modeTime2
) ||
(
(stime.mm_set != 0 || stime.ss_set != 0) &&
sflag.modeTime2
)
)
)
{
delay(500);
// Запуск таймера
sflag.runTimer =true;
fnClickButton();
// Подключение прерыванияTimer1.attachInterrupt(blink_point);
// Включим выходif (sflag.rele)digitalWrite(OUT,LOW);
stime.mm_set = stime.mm;
stime.hh_set = stime.hh;
if (sflag.modeTime2)
stime.ss_set = stime.ss;
dt = t1;
}
}
else
{
#if (LOGICA == 1)
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
#elseif (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
#endifif
( // Если таймер запущен, то
// кнопками BT_MINUS, BT_PLUS
// остановить на паузу
sflag.runTimer ==true&&
(st_bt_plus || st_bt_minus)
)
{ // Остановим таймер на ПАУЗУ
st_bt_plus =LOW;
fnStopTimer();
// Установим новые значения
stime.mm_set = stime.mm;
stime.hh_set = stime.hh;
if (sflag.modeTime2)
stime.ss_set = stime.ss;
flag_point =true;
}
}
/**************** END START TIMER ****************/
/**************** CONTROL TIMING ****************/
// Проверка пройденной минутыif
(
(sflag.runTimer ==true&&
((t1 - dt) >= 60000) &&!sflag.modeTime2) ||
(sflag.runTimer ==true&&
((t1 - dt) >= 1000) &&
sflag.modeTime2)
)
{
if (sflag.modeTime2)
{
#ifdef DEBUG
Serial.print(stime.mm);
Serial.print(":");
if (stime.ss < 10)Serial.print("0");
Serial.println(stime.ss);
#endifif (stime.ss != 0) stime.ss--;
else
{
if (stime.mm != 0)
{
stime.ss = 59;
stime.mm--;
}
}
}
else
{
#ifdef DEBUG
Serial.print(stime.hh);
Serial.print(":");
if (stime.mm < 10)Serial.print("0");
Serial.println(stime.mm);
#endifif (stime.mm != 0) stime.mm--;
else
{
if (stime.hh != 0)
{
stime.mm = 59;
stime.hh--;
}
}
}
// beep-beep если осталось 5 минif
(
(stime.hh == 0 && stime.mm == 5 &&!sflag.modeTime2) ||
(stime.mm == 5 && stime.ss == 0 && sflag.modeTime2)
)
{
fnClickButton();
delay(300);
fnClickButton();
}
if
(
(stime.hh == 0 && stime.mm == 0 &&!sflag.modeTime2) ||
(stime.mm == 0 && stime.ss == 0 && sflag.modeTime2)
)
{ // Завершение времени таймера
fnStopTimer(); // Стоп таймер
fnAlarmTimer(); // Сигнал окончания таймера
// Восстановим начальные установки
// для нового запуска
stime.mm = stime.mm_set;
stime.hh = stime.hh_set;
if (sflag.modeTime2)
stime.ss = stime.ss_set;
flag_point =true;
}
dt = t1; // Установка отсчёта новой минуты
}
/************* END CONTROL TIMING ***************/
// Выводим текущее время
fnPrintTime(mode);
} // End loop
/******************************************
*********** ПОДПРОГРАММЫ **************
******************************************/
/*************************
Функция мигания точек
************************/void blink_point()
{
flag_point =!flag_point;
}
/******************************
Функция: Стоп таймер
*****************************/void fnStopTimer()
{
sflag.runTimer =false;
if (sflag.buzz)fnClickButton();
if (sflag.rele)
digitalWrite(OUT,HIGH); // Отключим выходTimer1.detachInterrupt(); // Остановка прерыванияdelay(300);
}
/***********************************************
Функция: сигнал таймера
Включаем сигнал, если активен звук
Сигнал пульсирующий:
.5 секунды звук
.5 секунды пауза
2022-04-16 Mr.ALB v2
2022-04-20 Mr.ALB v2.2 добавлены аргументы:
max_beep - сколько раз бикнет,
delay_beep - время звука
***********************************************/void fnAlarmTimer
(
byte max_beep = MAXBEEP,unsignedint delay_beep = 500
)
{
long t;
// Если активен звукif (sflag.buzz)
{
fnPrintDisp(0, 0);
for (byte j = 0; j < max_beep; j++)
{
t =millis();
// Вывод текущего времени
//fnPrintDisp(stime.hh, stime.mm);while (millis() - t < delay_beep)
{
// Звук .5 секундыdigitalWrite(BUZZER,LOW);
// Если нажата любая кнопка
// Выход из цикла while()#if (LOGICA == 1)
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_minus || st_bt_plus || st_bt_mode)
{
st_bt_minus =LOW;
st_bt_plus =LOW;
st_bt_mode =LOW;
break;
}
}
t =millis();
while (millis() - t < delay_beep)
{
// Пауза .5 секундыdigitalWrite(BUZZER,HIGH);
// Если нажата любая кнопка
// Выход из цикла while()#if (LOGICA == 1)
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_minus || st_bt_plus || st_bt_mode)
{
st_bt_minus =LOW;
st_bt_plus =LOW;
st_bt_mode =LOW;
break;
}
}
// Если нажата любая кнопка
// Выход из цикла for()#if (LOGICA == 1)
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_minus || st_bt_plus || st_bt_mode)
{
st_bt_minus =LOW;
st_bt_plus =LOW;
st_bt_mode =LOW;
break;
}
}
fnClickButton();
delay(DELAY_BT);
}
} // End fnAlarmTimer
/********************************************
Вывод на индикатор в формате: 00.00(.)
2022-04-16 Mr.ALB v1.2
dig_high - число в разрядах DIG1, DIG2
dig_low - число в разрядах DIG3, DIG4
******************************************/void fnPrintDisp(byte dig_high,byte dig_low)
{
byte dig1 = dig_high / 10,
dig2 = dig_high % 10,
dig3 = dig_low / 10,
dig4 = dig_low % 10;
byte digit2, digit4;
// Вывод точки 2-го разрядаif (flag_point)
digit2 = symb[dig2] | symb[DP];
else digit2 = symb[dig2];
// Вывод точки 4-го разрядаif (sflag.rele)
digit4 = symb[dig4] | symb[DP];
else digit4 = symb[dig4];
// Вывод на индикатор#if (MAXDIGIT==4) // Если в индикаторе 4-е разрядаif (dig1 == 0) dig1 = PUSTO; // Гашение незначащего нуля
disp.displayByte(symb[dig1], digit2, symb[dig3], digit4);
#elif (MAXDIGIT == 3) // Если в индикаторе 3-и разряда
disp.displayByte(digit2, symb[dig3], digit4, symb[PUSTO]);
#endif
} // End fnPrintDisp
/*************************************************
Функция проверки всех сегментов
тест сегментов, поджигаем все на 2 сек
2022-01-02 Константин К.
2022-04-11 Mr.ALB переделка на вывод символов
************************************************/void fnDisplayTest()
{
// Проверка символов индикатораfor (byte i = 0; i <sizeof(symb); i++)
{
disp.displayByte(symb[i], symb[i], symb[i], symb[i]);
delay(DELAY_BT);
}
fnClickButton(30);
}
/**************************************
Функция звука нажатия кнопки
2022-04-12 Mr.ALB
2022-04-20 Mr.ALB v2.3
delay_ms - продолжительность звука
**************************************/void fnClickButton(unsignedint delay_ms = DELAY_CLICK)
{
if (sflag.buzz)
{
digitalWrite(BUZZER,LOW); // Звукdelay(DELAY_CLICK); // ЗадержкаdigitalWrite(BUZZER,HIGH); // Откл. звук
}
}
/***************************************************
Функция сканирования состояния кнопки
Кнопка TTP223 (сенсорная)
Активное состояние HIGH, но
если на TTP223 замкнута перемычка А,
то активное состояние LOW
2022-04-14 Mr.ALB
but_pin - номер пина кнопки
but_wait - ожидание устойчивого состояния
***************************************************/boolean fnScanButton(byte buttonPin,byte buttonWait = DEF_WAIT_BUTTON)
{
boolean current;
byte count = 0;
for (byte i = 0; i < buttonWait; i++)
{
// Опрос состояния кнопки#if (LOGICA == 1)
current =digitalRead(buttonPin);
#else
current =!digitalRead(buttonPin);
#endifif (current ==LOW&& count != 0) count--;
if (current ==HIGH) count++;
delay(2);
}
// Возвращаем истину, если подтверждений > 0return ((count > 0) ?true:false);
}
/**************************************************
Функция: установка параметра в mode
2022-04-16 Mr.ALB v1
*************************************************/byte fnSetParamMode
(
byte mode_param,// Устанавливаемый параметрbyte mode_param_min,// Минимальное значениеbyte mode_param_max // Максимальное значение
)
{
if (fnScanButton(BT_PLUS))
{ // Нажата кнопка "Плюс"if (mode_param != mode_param_max) mode_param++;
fnClickButton(21);
}
if (fnScanButton(BT_MINUS))
{ // Нажата кнопка "Минус"if (mode_param != mode_param_min) mode_param--;
fnClickButton(21);
}
delay(21);
return mode_param;
}
/*********************************************
Функция вывода времени
********************************************/void fnPrintTime(byte mode)
{
if (mode == 0)
{ // Выводим текущее времяif (sflag.modeTime2)
fnPrintDisp(stime.mm, stime.ss);
else
fnPrintDisp(stime.hh, stime.mm);
}
else// Иначе выводим значение параметра
fnPrintDisp(sdisp.high, sdisp.low);
}
/******************************************
Функция меню выбора режима
*****************************************/void fnMenuMode()
{
delay(DELAY_BT);
// Было нажатие кнопку "mode"
// Переходим на следующий пункт
mode++;
fnClickButton();
if (mode > 6) mode = 0;
sdisp.high = mode;
// Установка автоматического выхода
// в режим индикации времениif (mode != 0) dt = t1;
#ifdef DEBUG // ОтладкаSerial.print("mode= ");
Serial.println(mode);
#endif
}
Версия v3
Как и хотел, сделал новую версию v3, в которой реализован циклический режим работы.
В меню настроек добавилось ещё три пункта и теперь всего 10 пунктов mode =
Индикация текущего времени: hh.mm(.) | mm.ss(.) (зависит от режима 1)
Режим hh.mm (часы.минуты) - 0 | режим mm.ss (минуты.секунды) - 1
Установка паузы: часов|минут – 0...99 (при mode=7 и выбрано 1)
Установка паузы: минут|секунд – 0...59 (при mode=7 и выбрано 1)
Стоит отметить, что если в пункте 7 не установлена активность циклического режима, то пункты 8 и 9 не выводятся. Если в пункте 7 установлена активность циклического режима, но значения времени для паузы не установлены, то при запуске таймера значения времени для паузы будут как и в активном режиме, т.е. длительность паузы будет равна длительности активного режима.
Скетч v3 можно посмотреть ниже по нажатию на соответствующую кнопку.
/*************************************************************
2022-03-11 Mr.ALB Универсальный таймер на TM1637
Индикатор 7-сегментный 4-х разрядный (можно 3-х)
LN5644 - общий анод! Можно любой другой,
но с общим анодом!
Кнопки TP223 - сенсорные (можно обычные).
https://mralb.ru/sections/programming/arduino_24.php#content_center
В версии v1 Кнопки:
1. HOUR – Установка часов
2. MIN – Установка минут
3. START – Старт/Стоп
С помощью кнопки HOUR устанавливаются часы до 99
(чуть больше 4-х суток).
С помощью кнопки MIN устанавливаются минуты до 59.
Кнопкой START осуществляется пуск и остановка таймера.
Кнопки MIN и START нажать одновременно
для включения/выключения активности реле.
Индикация активности реле – светящаяся точка 4-го разряда.
Кнопки MIN и HOUR нажать одновременно
для обнуления установленного времени.
Работа таймера – мигание точки 2-го разряда.
Таймер в режиме паузы или ожидания пуска – постоянно светящаяся
точка 2-го разряда.
Ранее установленное время после окончания работы таймера сохраняется
и новый пуск таймера осуществляется только нажатием кнопки START.
2022-04-14 Mr.ALB Переделка на полное управление тремя кнопками
2022-04-15 Mr.ALB написана v2.0
- Имеется меню режимов настройки.
- Возможно устанавливать время в двух режимах:
1. hh.mm(.)
2. mm.ss(.)
- Вкл./Откл. звука
- Вкл./Откл. реле
- установка яркости индикатора 0...7
2022-04-16 Mr.ALB v2.1 оптимизация кода
2022-04-17 Mr.ALB v2.2 адаптация под LGT8F + создание
адаптивной компиляции под разную логику кнопок.
Теперь можно использовать кнопки с логикой
управления высоким уровнем HIGH или кнопки с
логикой управления низким уровнем LOW
2022-04-20 Mr.ALB v2.3 предварительный сигнал при остатке
времени 5 мин
2022-04-28 Mr.ALB v2.4 логика управления кнопками TTP223 - LOW
+ отладка + оптимизация + выбор индикатора
на 3 или 4 разряда
2022-05-26 Mr.ALB v2.5 Запись параметров в EEPROM
2022-05-28 Mr.ALB v3.0 Циклический режим
Кнопки TTP223 (логика HIGH) или обычные (логика LOW):
1. MODE – Выбор режима
2. MINUS – Убавить -
3. PLUS – Прибавить +
Примечание: Если у TTP223 замкнута перемычка А, то
выбрать логику управления #define LOGICA 0
Соединения:
DIO - пин 2
CLK - пин 3
Buzzer - пин 9
MODE - пин 10
MINUS - пин 11
PLUS - пин 12
Реле - пин А0
2022-04-15 Скетч использует 4012 байт
2022-04-16 Скетч использует 3854 байт
2022-04-17 Скетч использует 5596 байт - режим отладки
2022-04-18 Скетч использует 4246 байт - режим откладки отключен
2022-04-19 Скетч использует 4080 байт ARDUINO_UNO
2022-04-20 Скетч использует 4110 байт ARDUINO_UNO
2022-04-28 Скетч использует 4072 байт Индикатор 4 разряда
2022-04-28 Скетч использует 4078 байт Индикатор 3 разряда
2022-05-26 v2.5 Скетч использует 4294 байт +EEPROM
2022-05-28 v3.0 Скетч использует 4798 байт +циклический режим
Архив с проектом: https://disk.yandex.ru/d/KeRrmf0r7zUHmA
****************************************************************/#include<TimerOne.h>// Подключение библиотеки Таймер1#include<EEPROM.h>// Для EEPROM, запись яркости#include"TM1637_mralb2.h"// Библиотека для TM1637// Контакты I/O#define OUT A0
#define BUZZER 9
#define BT_MODE 10
#define BT_MINUS 11
#define BT_PLUS 12
#define MAXBEEP 16 // Сколько раз бикнет буззер#define DEF_WAIT_BUTTON 26 // Подтверждение кнопки#define DELAY_CLICK 21 // Время клика#define DELAY_BT 350 // Пауза после нажатия кнопкиbyte max_menu = 7; // Кол-во пунктов меню
/******************************************************
Включение режима отладки
Если нет надобности, то строку ниже закоментировать
*****************************************************/
//#define DEBUG
/*****************************************************
Определение типа используемой платы
****************************************************/#define MK 0 // Определяем тип микроконтроллера
; // 0 - Arduino Uno R3
; // 1 - Arduino Nano, Arduino Pro Mini
; // 2 - LGT8F328P, WAVGAT Pro Mini
; // 3 - WAVGAT Nano - Китайская подделка_
; // под Arduino Nano ATMega328// Выбор микроконтроллера#if (MK == 0)
#define ARDUINO_UNO // AVR ATMega328#endif#if (MK == 1)
#define AVR
#endif#if (MK == 2)
#define LGT8F // Китайский аналог ATMega328#endif#if (MK == 3)
#define WAVGAT_NANO // Китайская подделка_
; // под Nano AVR ATMega328#endif/******************************************************
Установите логику управления кнопками в вашей схеме
Логика управления 1 - HIGH | 0 - LOW
Для кнопок TTP223 лучше 1 - HIGH
Для обычных кнопок лучше 0 - LOW
******************************************************/#define LOGICA 1
/*****************************
ИНДИКАТОР
4-х разрядный 7 сигментный
под управлением TM1637
*****************************/
// Подключение управления#define DIO 2
#define CLK 3
// Сколько всего разрядов в индикаторе 3|4#define MAXDIGIT 4
TM1637 disp(CLK, DIO); // Создание объекта индикатора
; // Объявление и инициализация// Массив символов на индикатореstaticint8_t symb[] =
{ //GFEDCBA
0x3f, 0x06, 0x5b, 0x4f,//0, 1, 2, 3
0x66, 0x6d, 0x7d, 0x07,//4, 5, 6, 7 1100110, 1101101, 1111101,
0x7f, 0x6f, 0x77, 0x7c,//8, 9, A, b (A-10, b-11)
0x39, 0x5e, 0x79, 0x71,//C, d, E, F (C-12, d-13, E-14, F-15)
0x63, 0x73, 0x00,//°, P, , - (°-16, P-17, Пусто-18),
0x40, 0x80 //-, . (минус-19, .-20)
};
// Определение символов на индикаторе#define CELSIUM 12
#define DEGREE 16
#define SPRESS 17
#define PUSTO 18
#define MINUS 19
#define DP 20
// Структура разрядов дисплеяstruct myDisp
{
byte high; // Разряды индикатора DID1, DIG2byte low; // Разряды индикатора DIG3, DIG4byte bright = 3; // Яркость 0...7
};
// Создание переменной типа Disp
myDisp sdisp;
/* Глобальные переменные для времени */uint32_t t1, dt;
// Структура переменной времениstruct myTim
{
byte hh; // Текущее времяbyte mm;
byte ss;
byte hh_set; // Время действияbyte mm_set;
byte ss_set;
byte hhp_set; // Время паузыbyte mmp_set;
byte ssp_set;
};
// Создание переменной типа Tim
myTim stime;
// Структура переменной флаговstruct sFlag
{
bool runTimer =false; // Флаг работы таймераbool rele =true; // Флаг подключения релеbool buzz =true; // Флаг активности звукаbool modeTime2 =false; // Флаг mm.ss(.)bool cycl =false; // Флаг циклического режимаbool pause =false; // Флаг паузы цикла
};
// Создание переменной типа Flag
sFlag flag;
// Переменная для прерывания, мигание точекvolatileboolean flag_point =true;
byte mode = 0; // Пункт меню: 0 - вывод времени// Структура переменной адресов для EEPROMstruct myAddress
{
int br = 3; // Адрес яркости 3int rele = 5; // Адрес реле 5int cycl = 8; // Адрес циклического режима
};
// Создание переменной типа myAddress
myAddress addrEEPROM;
/*******************************************
* Оъявление функций
******************************************/
// Объявление функции сигнала Buzzer-a
// Окончание времени таймераvoid fnAlarmTimer
(
byte max_beep = MAXBEEP,unsignedint delay_beep = 500
);
// Объявление функции сканирования кнопки TTP223boolean fnScanButton
(
byte buttonPin,byte buttonWait = DEF_WAIT_BUTTON
);
// Объявление функции пиканья кнопкиvoid fnClickButton
(
unsignedint delay_ms = DELAY_CLICK
);
/*=======================
Функция настройки
========================*/voidsetup()
{
#ifdef DEBUG
Serial.begin(9600);
#endif#ifdef WAVGAT_NANO
Serial.begin(9600); // Последовательный пор для отладки
// Bits of CLKPR#define CLKOE1 6
#define CLKOE0 5
#define CLKOE 5
bool BIT;
CLKPR |= (1 << 7);
CLKPR &=~(1 << 1); // CLKPS0 установим в 0Serial.println(F(" Test - CLKPR: 0x03"));
Serial.print(F("CLKPCE CLKPOEN1 CLKOEN0 -"));
Serial.println(F("CLKPS3 CLKPS2 CLKPS1 CLKPS0"));
Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKPCE)));
Serial.print(BIT); Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKOE1)));
Serial.print(BIT); Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKOE0)));
Serial.print(BIT); Serial.print(F(" "));
Serial.print("-"); Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKPS3)));
Serial.print(BIT); Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKPS2)));
Serial.print(BIT); Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKPS1)));
Serial.print(BIT); Serial.print(F(" "));
BIT = (CLKPR & (bit(CLKPS0)));
Serial.println(BIT);
Serial.println();
#endif#if (LOGICA == 1)
// Если логика управления кнопками 1 - HIGHpinMode(BT_MODE,INPUT); // Выбор режимаpinMode(BT_PLUS,INPUT); // Прибавить +pinMode(BT_MINUS,INPUT); // Убавить -#else// Если логика управления кнопками 0 - LOWpinMode(BT_MODE,INPUT_PULLUP); // Выбор режимаpinMode(BT_PLUS,INPUT_PULLUP); // Прибавить +pinMode(BT_MINUS,INPUT_PULLUP); // Убавить -#endif// Логика управления реле 0 - LOWpinMode(OUT,OUTPUT); // Управляющий выходdigitalWrite(OUT,HIGH); // Отключим выход// Логика управления звуком 0 - LOWpinMode(BUZZER,OUTPUT); // ЗуммерdigitalWrite(BUZZER,HIGH); // Отключим выход#if (MK==0 || MK == 1 || MK == 2)
// Установка значений из EEPROM
// Считывание яркости из EEPROM
// Для AVR & LGT8Fbyte b;
// Получим значение из EEPROMEEPROM.get(addrEEPROM.br, b);
if
(
b >= 0 &&
b < 8 &&
b != sdisp.bright
)
sdisp.bright = b; // Установим яркость из EEPROM#endif
disp.brightness(sdisp.bright);
// Для Ардуино Уно, загасить светодиод на пин13
// В других Ардуино не нужно#ifdef ARDUINO_UNO
pinMode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
#endif// Инициализация прерывания на 500 мс
// Для мигания точекTimer1.initialize(500000);
// Получим значение из EEPROMEEPROM.get(addrEEPROM.rele, b);
if
(
(b ==false|| b ==true) &&
b != flag.rele
)
flag.rele = b; // Установим флаг реле из EEPROM
// Получим значение из EEPROMEEPROM.get(addrEEPROM.cycl, b);
if
(
(b ==false|| b ==true) &&
b != flag.cycl
)
flag.cycl = b; // Установим флаг цикла из EEPROM// Кол-во пунктов меню
// Если не циклический режим, то max_menu = 7if (flag.cycl) max_menu = 9;
// Проверка символов индикатора
// и работы звука буззера
fnDisplayTest();
// Вывод текущего времени
fnPrintDisp(stime.hh, stime.mm);
} // End setup
/***************************
Рабочая программа
**************************/
// Статусы кнопокbool st_bt_minus,
st_bt_plus,
st_bt_mode;
voidloop()
{
/*******************************************************
Проверка состояния кнопки BT_MODE
Всего 7 пунктов меню:
0 - Индикация текущего времени: hh.mm(.)|mm.ss(.)
1 - Режим hh.mm - 0 | режим mm.ss - 1
2 - Установка часов|минут 0...99
3 - Установка минут|секунд 0...59
4 - Активность реле 0|1 00.00. - точка DIG4
5 - Активность зуммера 0|1
6 - Яркость индикатора 0...7
7 - Активность циклического таймера
8 - Установка паузы часов|минут 0...99
9 - Установка минут|секунд 0...59
При запущенном таймере меню заблокировано
*******************************************************/
// Условная компиляция. Выбор логики управления#if (LOGICA == 1)
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_mode &&!flag.runTimer)
{
st_bt_mode =LOW;
fnMenuMode(); // Меню выбора режима
}
// Текущее время работы программы в мс
t1 =millis();
if (dt > t1) dt = t1; // Защита от переполнения t1// Автоматической возвращение из меню параметров
// к индикации времени через 10 секунд бездействияif ((t1 - dt > 16000) && mode != 0) mode = 0;
// Выбор установленных значений на индикаторswitch (mode)
{
case 1:// Альтернативное время 0|1
sdisp.low = flag.modeTime2;
break;
case 2:// Значение в разрядах DIG1, DIG2if (flag.modeTime2)
sdisp.low = stime.mm_set;
else
sdisp.low = stime.hh_set;
break;
case 3:// Значение в разрядах DIG3, DIG4if (flag.modeTime2)
sdisp.low = stime.ss_set;
else
sdisp.low = stime.mm_set;
break;
case 4:// Активность реле
sdisp.low = flag.rele;
break;
case 5:// Активность буззера
sdisp.low = flag.buzz;
break;
case 6:// Уровень яркости 0...7
sdisp.low = sdisp.bright;
break;
case 7:// Активность циклического режима
sdisp.low = flag.cycl;
break;
case 8:// Время паузы в разрядах DIG1, DIG2if (flag.modeTime2)
sdisp.low = stime.mmp_set;
else
sdisp.low = stime.hhp_set;
break;
case 9:// Время паузы в разрядах DIG3, DIG4if (flag.modeTime2)
sdisp.low = stime.ssp_set;
else
sdisp.low = stime.mmp_set;
}
fnPrintTime(mode); // Выводим текущее время
/******************** setting *********************/byte m; // Вспомогательная переменная
// Настройка альтернативного времени mm.ss(.)if (mode == 1)
{
flag.modeTime2 = fnSetParamMode(flag.modeTime2,false,true);
sdisp.low = flag.modeTime2;
#if(MAXDIGIT==3) // Индикатор 3 разрядаif (flag.modeTime2 && stime.mm_set > 9)stime.mm_set = 9;
#endif
} // end mode=1
// Установка часов - hours|minitsif (mode == 2)
{
if (flag.modeTime2)
{
#if(MAXDIGIT==4)
stime.mm_set = fnSetParamMode(stime.mm_set, 0, 99);
#elif(MAXDIGIT==3)
stime.mm_set = fnSetParamMode(stime.mm_set, 0, 9);
#endif
}
else
{
#if(MAXDIGIT==4)
stime.hh_set = fnSetParamMode(stime.hh_set, 0, 99);
#elif(MAXDIGIT==3)
stime.hh_set = fnSetParamMode(stime.hh_set, 0, 9);
#endif
}
//===============================================================
// Установим текущее время, если таймер не запущенif (!flag.runTimer &&!flag.pause)
{
if (flag.modeTime2)
{
stime.mm = stime.mm_set;
sdisp.low = stime.mm_set;
}
else
{
stime.hh = stime.hh_set;
sdisp.low = stime.hh_set;
}
}
//===============================================================
} // end mode=2
// Установка минут - minits|secondsif (mode == 3)
{
if (flag.modeTime2)
stime.ss_set = fnSetParamMode(stime.ss_set, 0, 59);
else
stime.mm_set = fnSetParamMode(stime.mm_set, 0, 59);
// Установим текущее время, если таймер не запущенif (!flag.runTimer)
{
if (flag.modeTime2)
{
stime.ss = stime.ss_set;
sdisp.low = stime.ss_set;
}
else
{
stime.mm = stime.mm_set;
sdisp.low = stime.mm_set;
}
}
} // end mode=3
// Настройка активности реле - releif (mode == 4)
{
m = flag.rele;
flag.rele = fnSetParamMode(flag.rele,false,true);
// Выключим выходif (!flag.rele)digitalWrite(OUT,HIGH);
sdisp.low = flag.rele;
if (m != flag.rele) // Запись в EEPROMEEPROM.put(addrEEPROM.rele, flag.rele);
} // end mode=4
// Настройка активности звука - buzz/click/alarmif (mode == 5)
{
flag.buzz = fnSetParamMode(flag.buzz,false,true);
sdisp.low = flag.buzz;
} // end mode=5
// Настройка яркости индикатора - brightnessif (mode == 6)
{
m = sdisp.bright;
sdisp.bright = fnSetParamMode(sdisp.bright, 0, 7);
sdisp.low = sdisp.bright;
if (m != sdisp.bright)
{
disp.brightness(sdisp.bright); // Установка яркости
// Запись в EEPROMEEPROM.put(addrEEPROM.br, sdisp.bright);
}
} // end mode=6
// Настройка активности циклического режимаif (mode == 7)
{
m = flag.cycl;
flag.cycl = fnSetParamMode(flag.cycl,false,true);
// Выключим выходif (!flag.cycl)
{
digitalWrite(OUT,HIGH);
max_menu = 7;
}
else
max_menu = 9;
sdisp.low = flag.cycl;
if (m != flag.cycl) // Запись в EEPROMEEPROM.put(addrEEPROM.cycl, flag.cycl);
} // end mode=7
// Установка часов паузы - hours|minitsif (mode == 8)
{
if (flag.modeTime2)
{
#if(MAXDIGIT==4)
m = 99;
#elif(MAXDIGIT==3)
m = 9;
#endif
stime.mmp_set = fnSetParamMode(stime.mmp_set, 0, m);
}
else
{
#if(MAXDIGIT==4)
m = 99;
#elif(MAXDIGIT==3)
m = 9;
#endif
stime.hhp_set = fnSetParamMode(stime.hhp_set, 0, m);
}
} // end mode=8
// Установка минут паузы - minits|secondsif (mode == 9)
{
if (flag.modeTime2)
stime.ssp_set = fnSetParamMode(stime.ssp_set, 0, 59);
else
stime.mmp_set = fnSetParamMode(stime.mmp_set, 0, 59);
} // end mode=9
/******************* End setting *******************/
/************* Проверка текущего режима ************/if (mode != 0)
{ // Если настройка в менюTimer1.detachInterrupt();
flag.runTimer =false;
flag_point =true; // Включить точки
sdisp.high = mode;
}
else// (mode=0)
{ // Вывод информации на индикатор
// Обнулим состояние кнопок
st_bt_plus =LOW;
st_bt_minus =LOW;
// Условная компиляция. Выбор логики управления#if (LOGICA == 1)
if (digitalRead(BT_PLUS)) st_bt_plus =HIGH;
#elseif (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
#endif/****************** START TIMER ******************/
// Если таймер ещё не запущен нажата кнопка Плюс+
// Запустим таймерif (!flag.runTimer &&!flag.pause && st_bt_plus)
{ // Было нажатие кнопки BT_PLUS - старт таймераif
(
(
(stime.hh_set != 0 || stime.mm_set != 0) &&!flag.modeTime2
) ||
(
(stime.mm_set != 0 || stime.ss_set != 0) &&
flag.modeTime2
)
)
{
delay(500);
fnStartTimer(); // Запуск таймера
dt = t1;
}
}
else
{ // Таймер запущен
// Проверим нажатие на кнопки Минус- или Плюс+#if (LOGICA == 1)
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
#elseif (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
#endif// Нажата кнопка Минус- или Плюс+if (st_bt_plus || st_bt_minus)
{
if (flag.buzz)fnClickButton(); // Клик кнопкиif (flag.runTimer)
{
// Установка нового времени действия
stime.mm_set = stime.mm;
stime.hh_set = stime.hh;
if (flag.modeTime2)
stime.ss_set = stime.ss;
}
else flag.pause =false;
fnStopTimer(); // Остановим таймерdelay(300);
dt = t1;
}
} // end else
/**************** END START TIMER ****************/
/**************** CONTROL TIMING *****************/
// Проверка пройденной минуты/секундыif (flag.runTimer || flag.cycl && flag.pause)
{
if
(
// Прошла минута
(((t1 - dt) >= 60000) &&!flag.modeTime2) ||// Прошла секунда
(((t1 - dt) >= 1000) && flag.modeTime2)
)
{
if (flag.modeTime2)
{ // Время: mm.ssif (stime.ss != 0) stime.ss--;
else
{
if (stime.mm != 0)
{
stime.ss = 59;
stime.mm--;
}
}
}
else// !flag.modeTime2
{ // Время: hh.mmif (stime.mm != 0) stime.mm--;
else
{
if (stime.hh != 0)
{
stime.mm = 59;
stime.hh--;
}
}
}
dt = t1; // Установка отсчёта новой минуты
}
if// Закончилось время
(
(stime.hh == 0 && stime.mm == 0 &&!flag.modeTime2) ||
(stime.ss == 0 && stime.mm == 0 && flag.modeTime2)
)
{
if (flag.runTimer)
{
fnStopTimer(); // Остановим таймерif (flag.cycl)
fnStartPause(); // Запустим паузу
}
else
{
if (flag.pause)flag.pause =false;
fnStartTimer();
}
if (!flag.cycl)
{
// Установка времени действия
stime.mm = stime.mm_set;
stime.hh = stime.hh_set;
if (flag.modeTime2)
stime.ss = stime.ss_set;
fnAlarmTimer(); // Сигнал окончания времени
}
}
} // end контроль пройденной минуты/секунды
/************* END CONTROL TIMING ****************/
} // end else (mode=0)
/********** end Проверка текущего режима ***********/
// Выводим текущее время
fnPrintTime(mode);
} // End loop
/******************************************
*********** ПОДПРОГРАММЫ **************
******************************************/
/*************************
Функция мигания точек
************************/void blink_point()
{
flag_point =!flag_point;
}
/**************************************
Функция звука нажатия кнопки
2022-04-12 Mr.ALB
2022-04-20 Mr.ALB v2.3
delay_ms - продолжительность звука
**************************************/void fnClickButton(unsignedint delay_ms = DELAY_CLICK)
{
if (flag.buzz)
{
digitalWrite(BUZZER,LOW); // Звукdelay(DELAY_CLICK); // ЗадержкаdigitalWrite(BUZZER,HIGH); // Откл. звук
}
}
/********************************************
Функция: Старт пауза циклического режима
2022-05-28 Mr.ALB
*******************************************/void fnStartPause()
{
flag.pause =true;
// Подключение прерыванияTimer1.attachInterrupt(blink_point);
// Установим значения паузыif
(
(stime.hhp_set == 0 && stime.mmp_set == 0 &&!flag.modeTime2) ||
(stime.ssp_set == 0 && stime.mmp_set == 0 && flag.modeTime2)
)
{
// Если значения паузы не выставлены, то
// паузу делаем равной времени активности
stime.mm = stime.mm_set;
if (flag.modeTime2)
stime.ss = stime.ss_set;
else
stime.hh = stime.hh_set;
}
else
{
// Если есть значения паузы
stime.mm = stime.mmp_set;
if (flag.modeTime2)
stime.ss = stime.ssp_set;
else
stime.hh = stime.hhp_set;
}
if (flag.rele)
digitalWrite(OUT,HIGH); // Отключим выход
}
/********************************************
Функция: Старт таймер
2022-05-28 Mr.ALB
*******************************************/void fnStartTimer()
{
flag.runTimer =true;
// Подключение прерыванияTimer1.attachInterrupt(blink_point);
if (flag.buzz)fnClickButton(); // Клик кнопкиif (flag.rele)
digitalWrite(OUT,LOW); // Включим выход, если реле
// Установка времени действия
stime.mm = stime.mm_set;
stime.hh = stime.hh_set;
if (flag.modeTime2)
stime.ss = stime.ss_set;
}
/********************************************
Функция: Стоп таймер
2022-05-28 Mr.ALB
*******************************************/void fnStopTimer()
{
flag.runTimer =false;
flag_point =true;
Timer1.detachInterrupt(); // Остановка прерыванияif (flag.buzz)fnClickButton(); // Клик кнопкиif (flag.rele)
digitalWrite(OUT,HIGH); // Отключим выходdelay(300);
}
/***********************************************
Функция: сигнал таймера
Включаем сигнал, если активен звук
Сигнал пульсирующий:
.5 секунды звук
.5 секунды пауза
2022-04-16 Mr.ALB v2
2022-04-20 Mr.ALB v2.2 добавлены аргументы:
max_beep - сколько раз бикнет,
delay_beep - время звука
***********************************************/void fnAlarmTimer
(
byte max_beep = MAXBEEP,unsignedint delay_beep = 500
)
{
long t;
// Если активен звукif (flag.buzz)
{
fnPrintDisp(0, 0);
for (byte j = 0; j < max_beep; j++)
{
t =millis();
// Вывод текущего времени
//fnPrintDisp(stime.hh, stime.mm);while (millis() - t < delay_beep)
{
// Звук .5 секундыdigitalWrite(BUZZER,LOW);
// Если нажата любая кнопка
// Выход из цикла while()#if (LOGICA == 1)
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_minus || st_bt_plus || st_bt_mode)
{
st_bt_minus =LOW;
st_bt_plus =LOW;
st_bt_mode =LOW;
break;
}
}
t =millis();
while (millis() - t < delay_beep)
{
// Пауза .5 секунды
digitalWrite(BUZZER,HIGH);
// Если нажата любая кнопка
// Выход из цикла while()#if (LOGICA == 1)
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_minus || st_bt_plus || st_bt_mode)
{
st_bt_minus =LOW;
st_bt_plus =LOW;
st_bt_mode =LOW;
break;
}
}
// Если нажата любая кнопка
// Выход из цикла for()#if (LOGICA == 1)
if (digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (digitalRead(BT_MODE))st_bt_mode =HIGH;
#elseif (!digitalRead(BT_MINUS))st_bt_minus =HIGH;
if (!digitalRead(BT_PLUS))st_bt_plus =HIGH;
if (!digitalRead(BT_MODE))st_bt_mode =HIGH;
#endifif (st_bt_minus || st_bt_plus || st_bt_mode)
{
st_bt_minus =LOW;
st_bt_plus =LOW;
st_bt_mode =LOW;
break;
}
}
fnClickButton();
delay(DELAY_BT);
}
} // End fnAlarmTimer
/********************************************
Вывод на индикатор в формате: 00.00(.)
2022-04-16 Mr.ALB v1.2
dig_high - число в разрядах DIG1, DIG2
dig_low - число в разрядах DIG3, DIG4
******************************************/void fnPrintDisp(byte dig_high,byte dig_low)
{
byte dig1 = dig_high / 10,
dig2 = dig_high % 10,
dig3 = dig_low / 10,
dig4 = dig_low % 10;
byte digit2, digit4;
// Вывод точки 2-го разрядаif (flag_point)
digit2 = symb[dig2] | symb[DP];
else digit2 = symb[dig2];
// Вывод точки 4-го разрядаif (flag.rele)
digit4 = symb[dig4] | symb[DP];
else digit4 = symb[dig4];
// Вывод на индикатор#if (MAXDIGIT==4) // Если в индикаторе 4-е разрядаif (dig1 == 0) dig1 = PUSTO; // Гашение незначащего нуля
disp.displayByte(symb[dig1], digit2, symb[dig3], digit4);
#elif (MAXDIGIT == 3) // Если в индикаторе 3-и разряда
disp.displayByte(digit2, symb[dig3], digit4, symb[PUSTO]);
#endif
} // End fnPrintDisp
/*************************************************
Функция проверки всех сегментов
тест сегментов, поджигаем все на 2 сек
2022-01-02 Константин К.
2022-04-11 Mr.ALB переделка на вывод символов
************************************************/void fnDisplayTest()
{
// Проверка символов индикатораfor (byte i = 0; i <sizeof(symb); i++)
{
disp.displayByte(symb[i], symb[i], symb[i], symb[i]);
delay(DELAY_BT);
}
fnClickButton(30);
}
/***************************************************
Функция сканирования состояния кнопки
Кнопка TTP223 (сенсорная)
Активное состояние HIGH, но
если на TTP223 замкнута перемычка А,
то активное состояние LOW
2022-04-14 Mr.ALB
but_pin - номер пина кнопки
but_wait - ожидание устойчивого состояния
***************************************************/boolean fnScanButton
(byte buttonPin,byte buttonWait = DEF_WAIT_BUTTON)
{
boolean current;
byte count = 0;
for (byte i = 0; i < buttonWait; i++)
{
// Опрос состояния кнопки#if (LOGICA == 1)
current =digitalRead(buttonPin);
#else
current =!digitalRead(buttonPin);
#endifif (current ==LOW&& count != 0) count--;
if (current ==HIGH) count++;
delay(2);
}
// Возвращаем истину, если подтверждений > 0return ((count > 0) ?true:false);
}
/**************************************************
Функция: установка параметра в mode
2022-04-16 Mr.ALB v1
*************************************************/byte fnSetParamMode
(
byte mode_param,// Устанавливаемый параметрbyte mode_param_min,// Минимальное значениеbyte mode_param_max // Максимальное значение
)
{
if (fnScanButton(BT_PLUS))
{ // Нажата кнопка "Плюс"if (mode_param != mode_param_max) mode_param++;
fnClickButton(21);
}
if (fnScanButton(BT_MINUS))
{ // Нажата кнопка "Минус"if (mode_param != mode_param_min) mode_param--;
fnClickButton(21);
}
delay(21);
return mode_param;
}
/*********************************************
Функция вывода времени
mode - режим индикации
********************************************/void fnPrintTime(byte mode)
{
if (mode == 0)
{ // Выводим текущее время
// В зависимости от уставки в mode=1if (flag.modeTime2)
fnPrintDisp(stime.mm, stime.ss);
else
fnPrintDisp(stime.hh, stime.mm);
}
else// Иначе выводим значение:
// mode и его параметра
fnPrintDisp(sdisp.high, sdisp.low);
}
/******************************************
Функция меню выбора режима
*****************************************/void fnMenuMode()
{
delay(DELAY_BT);
// Было нажатие кнопку "mode"
// Переходим на следующий пункт
mode++;
fnClickButton();
if (mode > max_menu) mode = 0;
sdisp.high = mode;
// Установка автоматического выхода
// в режим индикации времениif (mode != 0) dt = t1;
}
Конструкция v3.0
Завершением проекта всегда будет законченная конструкция устройства. После чего любое устройство может свободно использоваться потребителем.
Конструкция таймера представляет из себя модуль электроники, где собраны в этажерку плата с модулем индикатора и плата с Arduino. В моём варианте использовал плату WAVGAT Pro Mini. Обращу внимание, что контакты для программирования у неё зеркальные по сравнению с Arduino Pro Mini на контроллере AVR ATMega328P. На основной плате установлен зуммер и небольшая плата с панелькой для сенсорных кнопок. Отдельно от основной платы имеется модуль реле. Он закреплён на держателе из пластика ABS. Соединения между модулями и платой с кнопками с помощью шлейфов на разъёмах. Корпус сделал из пластмассы ABS толщиной 2 мм. Он состоит из двух частей: нижней и верхней. Соединяются они между собой защёлками.
К модулю электроники подпаяна плата с разъёмом microUSB, через который осуществляется питание таймера.
Опробовал таймер. Установил в параметре 4 активность реле. На фото ниже видно, что при работе таймера светится индикатор включения реле в нижнем правом углу.
Для удобного пользования наклеил поясняющие этикетки. Файл с этикетками смотрите в Приложении.
С левой стороны таймера есть отверстия под контакты программирования и под питание +5В через разъём microUSB.
Проверка работы Универсального таймера v3.0
Продолжительность фильма 3:59 [мм:сс]
Проверка работы таймера в сборе. Питание осуществляется от зарядного устройства на 5В для телефона через разъём microUSB. Описание параметров см. выше в подразделе Версия v3. Осталось наклеить этикетки с надписями.
Таймер v3.1
Попользовавшись таймером пришёл к мнению, что требуется выделить параметр каким-то образом, поэтому в первом разряде выводится нижнее подчёркивание (сегмент D), что позволяет характерно выделить номер параметра от установленного в первых разрядах времени.
Так как этот таймер ещё писал и под свою Ардуино на микроконтроллере ATTiny44A, в которой применял разные ухищрения по снижению размера кода и оптимальности его написания, то решил и версию v3.1 написать аналогично, используя для управления индикатором оптимизированные функции.
Ещё можно отметить, что в данной версии использовал покупной индикатор часового типа, что позволяет легко купить и использовать без всяких самоделок.
На данный момент проект закончен, но можно чего-нибудь потом и доработать. Пока нужно попользоваться и уже в ходе использования может быть выявятся неудобства или недостатки. Время покажет. А пока спасибо за внимание.
Анатолий Беляев.
На развитие сайта и проектов Arduino
Ниже на форме выберите/укажите сумму и источник перевода: Кошелёк Ю-money или Карта банка: Visa, MasterCard, МИР, Alfa-bank