<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>http://wikiprometheus.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maya</id>
	<title>WikiPrometheus.ru - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="http://wikiprometheus.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maya"/>
	<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Maya"/>
	<updated>2026-06-15T22:58:44Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=63</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=63"/>
		<updated>2026-05-11T14:47:31Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Код программы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
*Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
*Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
*Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
*Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
*Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
*Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
*Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
*Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
*Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
*Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
*Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
*Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
*Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
==Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
*Микроконтроллер Arduino Nano&lt;br /&gt;
*Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
*Управление Энкодер&lt;br /&gt;
*Кнопки игроков 2 кнопки &lt;br /&gt;
*Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
*Питание от встроенного аккумулятора&lt;br /&gt;
*Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
*Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
*Примечания&lt;br /&gt;
&lt;br /&gt;
*· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
*· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
*· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
==Органы управления==&lt;br /&gt;
*Элемент	Назначение&lt;br /&gt;
*Энкодер (поворот)	Навигация по меню, изменение значений&lt;br /&gt;
*Энкодер (нажатие)	Подтверждение выбора, пауза во время игры&lt;br /&gt;
*Кнопка игрока 1	Ход первого игрока, запуск игры&lt;br /&gt;
*Кнопка игрока 2	Ход второго игрока, запуск игры&lt;br /&gt;
*Обе кнопки (удержание 2 сек)	Полный сброс всех настроек&lt;br /&gt;
&lt;br /&gt;
==ГЛАВНОЕ МЕНЮ==&lt;br /&gt;
*При включении часы показывают главное меню. На дисплеях отображается номер текущего пункта (от 1 до 6).&lt;br /&gt;
&lt;br /&gt;
*Навигация: поворот энкодера — перемещение по пунктам, нажатие энкодера — вход в выбранный пункт.&lt;br /&gt;
&lt;br /&gt;
*Пункт 1 — установка времени. Диапазон 1–999 минут. При быстром вращении энкодера шаг увеличивается до 5 минут. На дисплее 1 отображается значение минут, на дисплее 2 — цифра 1.&lt;br /&gt;
&lt;br /&gt;
*Пункт 2 — выбор режима игры. 0 = CLS (классический), 1 = ADD (с добавкой), 2 = DLY (с задержкой). На дисплее 1 отображается название режима, на дисплее 2 — его номер.&lt;br /&gt;
&lt;br /&gt;
*Пункт 3 — настройка добавки или задержки. В режиме ADD: добавка 0–60 секунд. В режиме DLY: задержка 1–60 секунд. В режиме CLS: настройка не используется. На дисплее 2 отображается тип настройки: Add или dLY.&lt;br /&gt;
&lt;br /&gt;
*Пункт 4 — старт игры. Запуск отсчёта времени.&lt;br /&gt;
&lt;br /&gt;
*Пункт 5 — яркость дисплеев. Диапазон 0–7 (0 — минимум, 7 — максимум). На дисплее 1 отображается brI, на дисплее 2 — значение.&lt;br /&gt;
&lt;br /&gt;
*Пункт 6 — громкость звука. Диапазон 0–100 (0 — звук выключен, 100 — максимум). На дисплее 1 отображается VoL, на дисплее 2 — значение, делённое на 10.&lt;br /&gt;
&lt;br /&gt;
==Режимы игры==&lt;br /&gt;
&lt;br /&gt;
*CLS (классический) — обычный контроль времени. Время каждого игрока уменьшается только во время его хода. Без добавки и задержки. Применение: стандартные партии, классические турниры.&lt;br /&gt;
&lt;br /&gt;
*ADD (с добавкой) — после каждого хода к оставшемуся времени добавляется указанное количество секунд (0–60). Пример: начальное время 5 минут, добавка 3 секунды — после каждого хода игрок получает +3 секунды. Применение: блиц, рапид с добавлением времени (инкремент по Фишеру).&lt;br /&gt;
&lt;br /&gt;
*DLY (с задержкой) — время не уменьшается в течение указанной задержки (1–60 секунд) после нажатия кнопки соперником. Пример: задержка 5 секунд — после хода соперника у вас есть 5 секунд на обдумывание без потери основного времени. Применение: традиционные турниры, игра с задержкой Бронштейна.&lt;br /&gt;
&lt;br /&gt;
==Игровой процесс==&lt;br /&gt;
&lt;br /&gt;
*Запуск игры: настройте параметры в меню, перейдите в пункт 4 (Старт), нажмите кнопку игрока, который ходит первым (кнопка 1 — игрок 1, кнопка 2 — игрок 2).&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода и переключение времени на соперника. Нажатие энкодера — пауза или снятие с паузы. Удержание энкодера (2 секунды) — показ статистики ходов (на дисплее 1 — ходы игрока 1, на дисплее 2 — ходы игрока 2).&lt;br /&gt;
&lt;br /&gt;
*Окончание игры: когда у одного из игроков истекает время, дисплей проигравшего мигает, звучит длинный звуковой сигнал, часы возвращаются в главное меню.&lt;br /&gt;
&lt;br /&gt;
*Пауза: нажмите энкодер — на дисплеях отображается PUSE, время останавливается, кнопки игроков блокируются. Повторное нажатие энкодера снимает паузу.&lt;br /&gt;
&lt;br /&gt;
==Звуковые сигналы==&lt;br /&gt;
&lt;br /&gt;
*Поворот энкодера — 5 мс, 4000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие кнопки игрока — 20 мс, 3000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие энкодера — 30 мс, 2800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Старт игры — 50 мс, 2500 Гц.&lt;br /&gt;
&lt;br /&gt;
*Пауза — 100 мс, 2200 Гц.&lt;br /&gt;
&lt;br /&gt;
*Снятие с паузы — 100 мс, 2400 Гц.&lt;br /&gt;
&lt;br /&gt;
*Сброс настроек — 100 мс, 2000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Длинное удержание — 100 мс, 1800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Конец игры — 1000 мс, 1500 Гц.&lt;br /&gt;
&lt;br /&gt;
==Формат отображения времени==&lt;br /&gt;
&lt;br /&gt;
*Обычный режим (ММ:СС) — когда время меньше 99 минут. Дисплей показывает минуты и секунды, двоеточие мигает.&lt;br /&gt;
&lt;br /&gt;
*Часовой режим (ЧЧ:ММ) — когда время достигает 99 минут (5940 секунд) и более. Дисплей автоматически переключается на часы и минуты. Максимальное отображение — 99 часов 59 минут.&lt;br /&gt;
&lt;br /&gt;
==Пасхалки==&lt;br /&gt;
&lt;br /&gt;
«К Элизе» Бетховена. Активация: зайдите в настройки громкости (пункт 6), установите громкость 0, в течение 3 секунд установите 100, снова установите 0, и наконец 100. На дисплеях появится ELIS, затем заиграет мелодия.&lt;br /&gt;
&lt;br /&gt;
==Краткое руководство (памятка)==&lt;br /&gt;
&lt;br /&gt;
*Навигация по меню: вращение энкодера — выбор пункта, нажатие — вход.&lt;br /&gt;
&lt;br /&gt;
*Пункты меню: 1 — время партии, 2 — режим игры, 3 — добавка/задержка, 4 — старт, 5 — яркость, 6 — громкость.&lt;br /&gt;
&lt;br /&gt;
*Режимы игры: CLS — классический, ADD — с добавкой, DLY — с задержкой.&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода, нажатие энкодера — пауза, удержание энкодера — статистика ходов, удержание обеих кнопок (2 секунды) — полный сброс.&lt;br /&gt;
&lt;br /&gt;
==Код программы ==&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
==Руководитель==&lt;br /&gt;
Бизяев Алексей Анатольевич-старший преподаватель кафедры конструирования и технологии радиоэлектронных средств, научный сотрудник  научно-исследовательской лаборатории перспективных космических  разработок НГТУ НЭТИ&lt;br /&gt;
&lt;br /&gt;
== Команда проекта ==&lt;br /&gt;
*Козырев Андрей-электронщик&lt;br /&gt;
*Хавкунова Екатерина-конструктор&lt;br /&gt;
*Тельпухова Майя-журналист&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=62</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=62"/>
		<updated>2026-05-05T13:10:48Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Руководитель */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
*Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
*Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
*Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
*Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
*Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
*Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
*Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
*Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
*Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
*Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
*Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
*Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
*Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
==Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
*Микроконтроллер Arduino Nano&lt;br /&gt;
*Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
*Управление Энкодер&lt;br /&gt;
*Кнопки игроков 2 кнопки &lt;br /&gt;
*Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
*Питание от встроенного аккумулятора&lt;br /&gt;
*Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
*Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
*Примечания&lt;br /&gt;
&lt;br /&gt;
*· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
*· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
*· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
==Органы управления==&lt;br /&gt;
*Элемент	Назначение&lt;br /&gt;
*Энкодер (поворот)	Навигация по меню, изменение значений&lt;br /&gt;
*Энкодер (нажатие)	Подтверждение выбора, пауза во время игры&lt;br /&gt;
*Кнопка игрока 1	Ход первого игрока, запуск игры&lt;br /&gt;
*Кнопка игрока 2	Ход второго игрока, запуск игры&lt;br /&gt;
*Обе кнопки (удержание 2 сек)	Полный сброс всех настроек&lt;br /&gt;
&lt;br /&gt;
==ГЛАВНОЕ МЕНЮ==&lt;br /&gt;
*При включении часы показывают главное меню. На дисплеях отображается номер текущего пункта (от 1 до 6).&lt;br /&gt;
&lt;br /&gt;
*Навигация: поворот энкодера — перемещение по пунктам, нажатие энкодера — вход в выбранный пункт.&lt;br /&gt;
&lt;br /&gt;
*Пункт 1 — установка времени. Диапазон 1–999 минут. При быстром вращении энкодера шаг увеличивается до 5 минут. На дисплее 1 отображается значение минут, на дисплее 2 — цифра 1.&lt;br /&gt;
&lt;br /&gt;
*Пункт 2 — выбор режима игры. 0 = CLS (классический), 1 = ADD (с добавкой), 2 = DLY (с задержкой). На дисплее 1 отображается название режима, на дисплее 2 — его номер.&lt;br /&gt;
&lt;br /&gt;
*Пункт 3 — настройка добавки или задержки. В режиме ADD: добавка 0–60 секунд. В режиме DLY: задержка 1–60 секунд. В режиме CLS: настройка не используется. На дисплее 2 отображается тип настройки: Add или dLY.&lt;br /&gt;
&lt;br /&gt;
*Пункт 4 — старт игры. Запуск отсчёта времени.&lt;br /&gt;
&lt;br /&gt;
*Пункт 5 — яркость дисплеев. Диапазон 0–7 (0 — минимум, 7 — максимум). На дисплее 1 отображается brI, на дисплее 2 — значение.&lt;br /&gt;
&lt;br /&gt;
*Пункт 6 — громкость звука. Диапазон 0–100 (0 — звук выключен, 100 — максимум). На дисплее 1 отображается VoL, на дисплее 2 — значение, делённое на 10.&lt;br /&gt;
&lt;br /&gt;
==Режимы игры==&lt;br /&gt;
&lt;br /&gt;
*CLS (классический) — обычный контроль времени. Время каждого игрока уменьшается только во время его хода. Без добавки и задержки. Применение: стандартные партии, классические турниры.&lt;br /&gt;
&lt;br /&gt;
*ADD (с добавкой) — после каждого хода к оставшемуся времени добавляется указанное количество секунд (0–60). Пример: начальное время 5 минут, добавка 3 секунды — после каждого хода игрок получает +3 секунды. Применение: блиц, рапид с добавлением времени (инкремент по Фишеру).&lt;br /&gt;
&lt;br /&gt;
*DLY (с задержкой) — время не уменьшается в течение указанной задержки (1–60 секунд) после нажатия кнопки соперником. Пример: задержка 5 секунд — после хода соперника у вас есть 5 секунд на обдумывание без потери основного времени. Применение: традиционные турниры, игра с задержкой Бронштейна.&lt;br /&gt;
&lt;br /&gt;
==Игровой процесс==&lt;br /&gt;
&lt;br /&gt;
*Запуск игры: настройте параметры в меню, перейдите в пункт 4 (Старт), нажмите кнопку игрока, который ходит первым (кнопка 1 — игрок 1, кнопка 2 — игрок 2).&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода и переключение времени на соперника. Нажатие энкодера — пауза или снятие с паузы. Удержание энкодера (2 секунды) — показ статистики ходов (на дисплее 1 — ходы игрока 1, на дисплее 2 — ходы игрока 2).&lt;br /&gt;
&lt;br /&gt;
*Окончание игры: когда у одного из игроков истекает время, дисплей проигравшего мигает, звучит длинный звуковой сигнал, часы возвращаются в главное меню.&lt;br /&gt;
&lt;br /&gt;
*Пауза: нажмите энкодер — на дисплеях отображается PUSE, время останавливается, кнопки игроков блокируются. Повторное нажатие энкодера снимает паузу.&lt;br /&gt;
&lt;br /&gt;
==Звуковые сигналы==&lt;br /&gt;
&lt;br /&gt;
*Поворот энкодера — 5 мс, 4000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие кнопки игрока — 20 мс, 3000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие энкодера — 30 мс, 2800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Старт игры — 50 мс, 2500 Гц.&lt;br /&gt;
&lt;br /&gt;
*Пауза — 100 мс, 2200 Гц.&lt;br /&gt;
&lt;br /&gt;
*Снятие с паузы — 100 мс, 2400 Гц.&lt;br /&gt;
&lt;br /&gt;
*Сброс настроек — 100 мс, 2000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Длинное удержание — 100 мс, 1800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Конец игры — 1000 мс, 1500 Гц.&lt;br /&gt;
&lt;br /&gt;
==Формат отображения времени==&lt;br /&gt;
&lt;br /&gt;
*Обычный режим (ММ:СС) — когда время меньше 99 минут. Дисплей показывает минуты и секунды, двоеточие мигает.&lt;br /&gt;
&lt;br /&gt;
*Часовой режим (ЧЧ:ММ) — когда время достигает 99 минут (5940 секунд) и более. Дисплей автоматически переключается на часы и минуты. Максимальное отображение — 99 часов 59 минут.&lt;br /&gt;
&lt;br /&gt;
==Пасхалки==&lt;br /&gt;
&lt;br /&gt;
«К Элизе» Бетховена. Активация: зайдите в настройки громкости (пункт 6), установите громкость 0, в течение 3 секунд установите 100, снова установите 0, и наконец 100. На дисплеях появится ELIS, затем заиграет мелодия.&lt;br /&gt;
&lt;br /&gt;
==Краткое руководство (памятка)==&lt;br /&gt;
&lt;br /&gt;
*Навигация по меню: вращение энкодера — выбор пункта, нажатие — вход.&lt;br /&gt;
&lt;br /&gt;
*Пункты меню: 1 — время партии, 2 — режим игры, 3 — добавка/задержка, 4 — старт, 5 — яркость, 6 — громкость.&lt;br /&gt;
&lt;br /&gt;
*Режимы игры: CLS — классический, ADD — с добавкой, DLY — с задержкой.&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода, нажатие энкодера — пауза, удержание энкодера — статистика ходов, удержание обеих кнопок (2 секунды) — полный сброс.&lt;br /&gt;
&lt;br /&gt;
==Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
==Руководитель==&lt;br /&gt;
Бизяев Алексей Анатольевич-старший преподаватель кафедры конструирования и технологии радиоэлектронных средств, научный сотрудник  научно-исследовательской лаборатории перспективных космических  разработок НГТУ НЭТИ&lt;br /&gt;
&lt;br /&gt;
== Команда проекта ==&lt;br /&gt;
*Козырев Андрей-электронщик&lt;br /&gt;
*Хавкунова Екатерина-конструктор&lt;br /&gt;
*Тельпухова Майя-журналист&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=61</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=61"/>
		<updated>2026-05-05T13:07:34Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Руководитель */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
*Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
*Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
*Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
*Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
*Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
*Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
*Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
*Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
*Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
*Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
*Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
*Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
*Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
==Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
*Микроконтроллер Arduino Nano&lt;br /&gt;
*Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
*Управление Энкодер&lt;br /&gt;
*Кнопки игроков 2 кнопки &lt;br /&gt;
*Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
*Питание от встроенного аккумулятора&lt;br /&gt;
*Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
*Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
*Примечания&lt;br /&gt;
&lt;br /&gt;
*· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
*· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
*· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
==Органы управления==&lt;br /&gt;
*Элемент	Назначение&lt;br /&gt;
*Энкодер (поворот)	Навигация по меню, изменение значений&lt;br /&gt;
*Энкодер (нажатие)	Подтверждение выбора, пауза во время игры&lt;br /&gt;
*Кнопка игрока 1	Ход первого игрока, запуск игры&lt;br /&gt;
*Кнопка игрока 2	Ход второго игрока, запуск игры&lt;br /&gt;
*Обе кнопки (удержание 2 сек)	Полный сброс всех настроек&lt;br /&gt;
&lt;br /&gt;
==ГЛАВНОЕ МЕНЮ==&lt;br /&gt;
*При включении часы показывают главное меню. На дисплеях отображается номер текущего пункта (от 1 до 6).&lt;br /&gt;
&lt;br /&gt;
*Навигация: поворот энкодера — перемещение по пунктам, нажатие энкодера — вход в выбранный пункт.&lt;br /&gt;
&lt;br /&gt;
*Пункт 1 — установка времени. Диапазон 1–999 минут. При быстром вращении энкодера шаг увеличивается до 5 минут. На дисплее 1 отображается значение минут, на дисплее 2 — цифра 1.&lt;br /&gt;
&lt;br /&gt;
*Пункт 2 — выбор режима игры. 0 = CLS (классический), 1 = ADD (с добавкой), 2 = DLY (с задержкой). На дисплее 1 отображается название режима, на дисплее 2 — его номер.&lt;br /&gt;
&lt;br /&gt;
*Пункт 3 — настройка добавки или задержки. В режиме ADD: добавка 0–60 секунд. В режиме DLY: задержка 1–60 секунд. В режиме CLS: настройка не используется. На дисплее 2 отображается тип настройки: Add или dLY.&lt;br /&gt;
&lt;br /&gt;
*Пункт 4 — старт игры. Запуск отсчёта времени.&lt;br /&gt;
&lt;br /&gt;
*Пункт 5 — яркость дисплеев. Диапазон 0–7 (0 — минимум, 7 — максимум). На дисплее 1 отображается brI, на дисплее 2 — значение.&lt;br /&gt;
&lt;br /&gt;
*Пункт 6 — громкость звука. Диапазон 0–100 (0 — звук выключен, 100 — максимум). На дисплее 1 отображается VoL, на дисплее 2 — значение, делённое на 10.&lt;br /&gt;
&lt;br /&gt;
==Режимы игры==&lt;br /&gt;
&lt;br /&gt;
*CLS (классический) — обычный контроль времени. Время каждого игрока уменьшается только во время его хода. Без добавки и задержки. Применение: стандартные партии, классические турниры.&lt;br /&gt;
&lt;br /&gt;
*ADD (с добавкой) — после каждого хода к оставшемуся времени добавляется указанное количество секунд (0–60). Пример: начальное время 5 минут, добавка 3 секунды — после каждого хода игрок получает +3 секунды. Применение: блиц, рапид с добавлением времени (инкремент по Фишеру).&lt;br /&gt;
&lt;br /&gt;
*DLY (с задержкой) — время не уменьшается в течение указанной задержки (1–60 секунд) после нажатия кнопки соперником. Пример: задержка 5 секунд — после хода соперника у вас есть 5 секунд на обдумывание без потери основного времени. Применение: традиционные турниры, игра с задержкой Бронштейна.&lt;br /&gt;
&lt;br /&gt;
==Игровой процесс==&lt;br /&gt;
&lt;br /&gt;
*Запуск игры: настройте параметры в меню, перейдите в пункт 4 (Старт), нажмите кнопку игрока, который ходит первым (кнопка 1 — игрок 1, кнопка 2 — игрок 2).&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода и переключение времени на соперника. Нажатие энкодера — пауза или снятие с паузы. Удержание энкодера (2 секунды) — показ статистики ходов (на дисплее 1 — ходы игрока 1, на дисплее 2 — ходы игрока 2).&lt;br /&gt;
&lt;br /&gt;
*Окончание игры: когда у одного из игроков истекает время, дисплей проигравшего мигает, звучит длинный звуковой сигнал, часы возвращаются в главное меню.&lt;br /&gt;
&lt;br /&gt;
*Пауза: нажмите энкодер — на дисплеях отображается PUSE, время останавливается, кнопки игроков блокируются. Повторное нажатие энкодера снимает паузу.&lt;br /&gt;
&lt;br /&gt;
==Звуковые сигналы==&lt;br /&gt;
&lt;br /&gt;
*Поворот энкодера — 5 мс, 4000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие кнопки игрока — 20 мс, 3000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие энкодера — 30 мс, 2800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Старт игры — 50 мс, 2500 Гц.&lt;br /&gt;
&lt;br /&gt;
*Пауза — 100 мс, 2200 Гц.&lt;br /&gt;
&lt;br /&gt;
*Снятие с паузы — 100 мс, 2400 Гц.&lt;br /&gt;
&lt;br /&gt;
*Сброс настроек — 100 мс, 2000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Длинное удержание — 100 мс, 1800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Конец игры — 1000 мс, 1500 Гц.&lt;br /&gt;
&lt;br /&gt;
==Формат отображения времени==&lt;br /&gt;
&lt;br /&gt;
*Обычный режим (ММ:СС) — когда время меньше 99 минут. Дисплей показывает минуты и секунды, двоеточие мигает.&lt;br /&gt;
&lt;br /&gt;
*Часовой режим (ЧЧ:ММ) — когда время достигает 99 минут (5940 секунд) и более. Дисплей автоматически переключается на часы и минуты. Максимальное отображение — 99 часов 59 минут.&lt;br /&gt;
&lt;br /&gt;
==Пасхалки==&lt;br /&gt;
&lt;br /&gt;
«К Элизе» Бетховена. Активация: зайдите в настройки громкости (пункт 6), установите громкость 0, в течение 3 секунд установите 100, снова установите 0, и наконец 100. На дисплеях появится ELIS, затем заиграет мелодия.&lt;br /&gt;
&lt;br /&gt;
==Краткое руководство (памятка)==&lt;br /&gt;
&lt;br /&gt;
*Навигация по меню: вращение энкодера — выбор пункта, нажатие — вход.&lt;br /&gt;
&lt;br /&gt;
*Пункты меню: 1 — время партии, 2 — режим игры, 3 — добавка/задержка, 4 — старт, 5 — яркость, 6 — громкость.&lt;br /&gt;
&lt;br /&gt;
*Режимы игры: CLS — классический, ADD — с добавкой, DLY — с задержкой.&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода, нажатие энкодера — пауза, удержание энкодера — статистика ходов, удержание обеих кнопок (2 секунды) — полный сброс.&lt;br /&gt;
&lt;br /&gt;
==Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
==Руководитель==&lt;br /&gt;
Бизяев Алексей Анатольевич-старший преподаватель НГТУ НЭТИ&lt;br /&gt;
&lt;br /&gt;
== Команда проекта ==&lt;br /&gt;
*Козырев Андрей-электронщик&lt;br /&gt;
*Хавкунова Екатерина-конструктор&lt;br /&gt;
*Тельпухова Майя-журналист&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=60</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=60"/>
		<updated>2026-05-05T13:03:54Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
*Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
*Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
*Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
*Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
*Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
*Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
*Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
*Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
*Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
*Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
*Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
*Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
*Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
==Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
*Микроконтроллер Arduino Nano&lt;br /&gt;
*Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
*Управление Энкодер&lt;br /&gt;
*Кнопки игроков 2 кнопки &lt;br /&gt;
*Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
*Питание от встроенного аккумулятора&lt;br /&gt;
*Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
*Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
*Примечания&lt;br /&gt;
&lt;br /&gt;
*· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
*· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
*· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
==Органы управления==&lt;br /&gt;
*Элемент	Назначение&lt;br /&gt;
*Энкодер (поворот)	Навигация по меню, изменение значений&lt;br /&gt;
*Энкодер (нажатие)	Подтверждение выбора, пауза во время игры&lt;br /&gt;
*Кнопка игрока 1	Ход первого игрока, запуск игры&lt;br /&gt;
*Кнопка игрока 2	Ход второго игрока, запуск игры&lt;br /&gt;
*Обе кнопки (удержание 2 сек)	Полный сброс всех настроек&lt;br /&gt;
&lt;br /&gt;
==ГЛАВНОЕ МЕНЮ==&lt;br /&gt;
*При включении часы показывают главное меню. На дисплеях отображается номер текущего пункта (от 1 до 6).&lt;br /&gt;
&lt;br /&gt;
*Навигация: поворот энкодера — перемещение по пунктам, нажатие энкодера — вход в выбранный пункт.&lt;br /&gt;
&lt;br /&gt;
*Пункт 1 — установка времени. Диапазон 1–999 минут. При быстром вращении энкодера шаг увеличивается до 5 минут. На дисплее 1 отображается значение минут, на дисплее 2 — цифра 1.&lt;br /&gt;
&lt;br /&gt;
*Пункт 2 — выбор режима игры. 0 = CLS (классический), 1 = ADD (с добавкой), 2 = DLY (с задержкой). На дисплее 1 отображается название режима, на дисплее 2 — его номер.&lt;br /&gt;
&lt;br /&gt;
*Пункт 3 — настройка добавки или задержки. В режиме ADD: добавка 0–60 секунд. В режиме DLY: задержка 1–60 секунд. В режиме CLS: настройка не используется. На дисплее 2 отображается тип настройки: Add или dLY.&lt;br /&gt;
&lt;br /&gt;
*Пункт 4 — старт игры. Запуск отсчёта времени.&lt;br /&gt;
&lt;br /&gt;
*Пункт 5 — яркость дисплеев. Диапазон 0–7 (0 — минимум, 7 — максимум). На дисплее 1 отображается brI, на дисплее 2 — значение.&lt;br /&gt;
&lt;br /&gt;
*Пункт 6 — громкость звука. Диапазон 0–100 (0 — звук выключен, 100 — максимум). На дисплее 1 отображается VoL, на дисплее 2 — значение, делённое на 10.&lt;br /&gt;
&lt;br /&gt;
==Режимы игры==&lt;br /&gt;
&lt;br /&gt;
*CLS (классический) — обычный контроль времени. Время каждого игрока уменьшается только во время его хода. Без добавки и задержки. Применение: стандартные партии, классические турниры.&lt;br /&gt;
&lt;br /&gt;
*ADD (с добавкой) — после каждого хода к оставшемуся времени добавляется указанное количество секунд (0–60). Пример: начальное время 5 минут, добавка 3 секунды — после каждого хода игрок получает +3 секунды. Применение: блиц, рапид с добавлением времени (инкремент по Фишеру).&lt;br /&gt;
&lt;br /&gt;
*DLY (с задержкой) — время не уменьшается в течение указанной задержки (1–60 секунд) после нажатия кнопки соперником. Пример: задержка 5 секунд — после хода соперника у вас есть 5 секунд на обдумывание без потери основного времени. Применение: традиционные турниры, игра с задержкой Бронштейна.&lt;br /&gt;
&lt;br /&gt;
==Игровой процесс==&lt;br /&gt;
&lt;br /&gt;
*Запуск игры: настройте параметры в меню, перейдите в пункт 4 (Старт), нажмите кнопку игрока, который ходит первым (кнопка 1 — игрок 1, кнопка 2 — игрок 2).&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода и переключение времени на соперника. Нажатие энкодера — пауза или снятие с паузы. Удержание энкодера (2 секунды) — показ статистики ходов (на дисплее 1 — ходы игрока 1, на дисплее 2 — ходы игрока 2).&lt;br /&gt;
&lt;br /&gt;
*Окончание игры: когда у одного из игроков истекает время, дисплей проигравшего мигает, звучит длинный звуковой сигнал, часы возвращаются в главное меню.&lt;br /&gt;
&lt;br /&gt;
*Пауза: нажмите энкодер — на дисплеях отображается PUSE, время останавливается, кнопки игроков блокируются. Повторное нажатие энкодера снимает паузу.&lt;br /&gt;
&lt;br /&gt;
==Звуковые сигналы==&lt;br /&gt;
&lt;br /&gt;
*Поворот энкодера — 5 мс, 4000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие кнопки игрока — 20 мс, 3000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие энкодера — 30 мс, 2800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Старт игры — 50 мс, 2500 Гц.&lt;br /&gt;
&lt;br /&gt;
*Пауза — 100 мс, 2200 Гц.&lt;br /&gt;
&lt;br /&gt;
*Снятие с паузы — 100 мс, 2400 Гц.&lt;br /&gt;
&lt;br /&gt;
*Сброс настроек — 100 мс, 2000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Длинное удержание — 100 мс, 1800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Конец игры — 1000 мс, 1500 Гц.&lt;br /&gt;
&lt;br /&gt;
==Формат отображения времени==&lt;br /&gt;
&lt;br /&gt;
*Обычный режим (ММ:СС) — когда время меньше 99 минут. Дисплей показывает минуты и секунды, двоеточие мигает.&lt;br /&gt;
&lt;br /&gt;
*Часовой режим (ЧЧ:ММ) — когда время достигает 99 минут (5940 секунд) и более. Дисплей автоматически переключается на часы и минуты. Максимальное отображение — 99 часов 59 минут.&lt;br /&gt;
&lt;br /&gt;
==Пасхалки==&lt;br /&gt;
&lt;br /&gt;
«К Элизе» Бетховена. Активация: зайдите в настройки громкости (пункт 6), установите громкость 0, в течение 3 секунд установите 100, снова установите 0, и наконец 100. На дисплеях появится ELIS, затем заиграет мелодия.&lt;br /&gt;
&lt;br /&gt;
==Краткое руководство (памятка)==&lt;br /&gt;
&lt;br /&gt;
*Навигация по меню: вращение энкодера — выбор пункта, нажатие — вход.&lt;br /&gt;
&lt;br /&gt;
*Пункты меню: 1 — время партии, 2 — режим игры, 3 — добавка/задержка, 4 — старт, 5 — яркость, 6 — громкость.&lt;br /&gt;
&lt;br /&gt;
*Режимы игры: CLS — классический, ADD — с добавкой, DLY — с задержкой.&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода, нажатие энкодера — пауза, удержание энкодера — статистика ходов, удержание обеих кнопок (2 секунды) — полный сброс.&lt;br /&gt;
&lt;br /&gt;
==Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
==Руководитель==&lt;br /&gt;
Бизяев Алексей Анатольевич&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
*Козырев Андрей-электронщик&lt;br /&gt;
*Хавкунова Екатерина-конструктор&lt;br /&gt;
*Тельпухова Майя-журналист&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=59</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=59"/>
		<updated>2026-05-04T02:25:37Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Технические характеристики */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
*Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
*Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
*Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
*Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
*Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
*Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
*Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
*Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
*Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
*Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
*Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
*Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
*Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
==Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
*Микроконтроллер Arduino Nano&lt;br /&gt;
*Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
*Управление Энкодер&lt;br /&gt;
*Кнопки игроков 2 кнопки &lt;br /&gt;
*Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
*Питание от встроенного аккумулятора&lt;br /&gt;
*Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
*Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
*Примечания&lt;br /&gt;
&lt;br /&gt;
*· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
*· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
*· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
==Органы управления==&lt;br /&gt;
*Элемент	Назначение&lt;br /&gt;
*Энкодер (поворот)	Навигация по меню, изменение значений&lt;br /&gt;
*Энкодер (нажатие)	Подтверждение выбора, пауза во время игры&lt;br /&gt;
*Кнопка игрока 1	Ход первого игрока, запуск игры&lt;br /&gt;
*Кнопка игрока 2	Ход второго игрока, запуск игры&lt;br /&gt;
*Обе кнопки (удержание 2 сек)	Полный сброс всех настроек&lt;br /&gt;
&lt;br /&gt;
==ГЛАВНОЕ МЕНЮ==&lt;br /&gt;
*При включении часы показывают главное меню. На дисплеях отображается номер текущего пункта (от 1 до 6).&lt;br /&gt;
&lt;br /&gt;
*Навигация: поворот энкодера — перемещение по пунктам, нажатие энкодера — вход в выбранный пункт.&lt;br /&gt;
&lt;br /&gt;
*Пункт 1 — установка времени. Диапазон 1–999 минут. При быстром вращении энкодера шаг увеличивается до 5 минут. На дисплее 1 отображается значение минут, на дисплее 2 — цифра 1.&lt;br /&gt;
&lt;br /&gt;
*Пункт 2 — выбор режима игры. 0 = CLS (классический), 1 = ADD (с добавкой), 2 = DLY (с задержкой). На дисплее 1 отображается название режима, на дисплее 2 — его номер.&lt;br /&gt;
&lt;br /&gt;
*Пункт 3 — настройка добавки или задержки. В режиме ADD: добавка 0–60 секунд. В режиме DLY: задержка 1–60 секунд. В режиме CLS: настройка не используется. На дисплее 2 отображается тип настройки: Add или dLY.&lt;br /&gt;
&lt;br /&gt;
*Пункт 4 — старт игры. Запуск отсчёта времени.&lt;br /&gt;
&lt;br /&gt;
*Пункт 5 — яркость дисплеев. Диапазон 0–7 (0 — минимум, 7 — максимум). На дисплее 1 отображается brI, на дисплее 2 — значение.&lt;br /&gt;
&lt;br /&gt;
*Пункт 6 — громкость звука. Диапазон 0–100 (0 — звук выключен, 100 — максимум). На дисплее 1 отображается VoL, на дисплее 2 — значение, делённое на 10.&lt;br /&gt;
&lt;br /&gt;
==Режимы игры==&lt;br /&gt;
&lt;br /&gt;
*CLS (классический) — обычный контроль времени. Время каждого игрока уменьшается только во время его хода. Без добавки и задержки. Применение: стандартные партии, классические турниры.&lt;br /&gt;
&lt;br /&gt;
*ADD (с добавкой) — после каждого хода к оставшемуся времени добавляется указанное количество секунд (0–60). Пример: начальное время 5 минут, добавка 3 секунды — после каждого хода игрок получает +3 секунды. Применение: блиц, рапид с добавлением времени (инкремент по Фишеру).&lt;br /&gt;
&lt;br /&gt;
*DLY (с задержкой) — время не уменьшается в течение указанной задержки (1–60 секунд) после нажатия кнопки соперником. Пример: задержка 5 секунд — после хода соперника у вас есть 5 секунд на обдумывание без потери основного времени. Применение: традиционные турниры, игра с задержкой Бронштейна.&lt;br /&gt;
&lt;br /&gt;
==Игровой процесс==&lt;br /&gt;
&lt;br /&gt;
*Запуск игры: настройте параметры в меню, перейдите в пункт 4 (Старт), нажмите кнопку игрока, который ходит первым (кнопка 1 — игрок 1, кнопка 2 — игрок 2).&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода и переключение времени на соперника. Нажатие энкодера — пауза или снятие с паузы. Удержание энкодера (2 секунды) — показ статистики ходов (на дисплее 1 — ходы игрока 1, на дисплее 2 — ходы игрока 2).&lt;br /&gt;
&lt;br /&gt;
*Окончание игры: когда у одного из игроков истекает время, дисплей проигравшего мигает, звучит длинный звуковой сигнал, часы возвращаются в главное меню.&lt;br /&gt;
&lt;br /&gt;
*Пауза: нажмите энкодер — на дисплеях отображается PUSE, время останавливается, кнопки игроков блокируются. Повторное нажатие энкодера снимает паузу.&lt;br /&gt;
&lt;br /&gt;
==Звуковые сигналы==&lt;br /&gt;
&lt;br /&gt;
*Поворот энкодера — 5 мс, 4000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие кнопки игрока — 20 мс, 3000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие энкодера — 30 мс, 2800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Старт игры — 50 мс, 2500 Гц.&lt;br /&gt;
&lt;br /&gt;
*Пауза — 100 мс, 2200 Гц.&lt;br /&gt;
&lt;br /&gt;
*Снятие с паузы — 100 мс, 2400 Гц.&lt;br /&gt;
&lt;br /&gt;
*Сброс настроек — 100 мс, 2000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Длинное удержание — 100 мс, 1800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Конец игры — 1000 мс, 1500 Гц.&lt;br /&gt;
&lt;br /&gt;
==Формат отображения времени==&lt;br /&gt;
&lt;br /&gt;
*Обычный режим (ММ:СС) — когда время меньше 99 минут. Дисплей показывает минуты и секунды, двоеточие мигает.&lt;br /&gt;
&lt;br /&gt;
*Часовой режим (ЧЧ:ММ) — когда время достигает 99 минут (5940 секунд) и более. Дисплей автоматически переключается на часы и минуты. Максимальное отображение — 99 часов 59 минут.&lt;br /&gt;
&lt;br /&gt;
==Пасхалки==&lt;br /&gt;
&lt;br /&gt;
«К Элизе» Бетховена. Активация: зайдите в настройки громкости (пункт 6), установите громкость 0, в течение 3 секунд установите 100, снова установите 0, и наконец 100. На дисплеях появится ELIS, затем заиграет мелодия.&lt;br /&gt;
&lt;br /&gt;
==Краткое руководство (памятка)==&lt;br /&gt;
&lt;br /&gt;
*Навигация по меню: вращение энкодера — выбор пункта, нажатие — вход.&lt;br /&gt;
&lt;br /&gt;
*Пункты меню: 1 — время партии, 2 — режим игры, 3 — добавка/задержка, 4 — старт, 5 — яркость, 6 — громкость.&lt;br /&gt;
&lt;br /&gt;
*Режимы игры: CLS — классический, ADD — с добавкой, DLY — с задержкой.&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода, нажатие энкодера — пауза, удержание энкодера — статистика ходов, удержание обеих кнопок (2 секунды) — полный сброс.&lt;br /&gt;
&lt;br /&gt;
==Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
*Козырев Андрей-электронщик&lt;br /&gt;
*Хавкунова Екатерина-конструктор&lt;br /&gt;
*Тельпухова Майя-журналист&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=58</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=58"/>
		<updated>2026-05-03T02:01:16Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
*Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
*Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
*Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
*Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
*Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
*Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
*Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
*Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
*Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
*Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
*Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
*Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
*Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
==Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
==Органы управления==&lt;br /&gt;
*Элемент	Назначение&lt;br /&gt;
*Энкодер (поворот)	Навигация по меню, изменение значений&lt;br /&gt;
*Энкодер (нажатие)	Подтверждение выбора, пауза во время игры&lt;br /&gt;
*Кнопка игрока 1	Ход первого игрока, запуск игры&lt;br /&gt;
*Кнопка игрока 2	Ход второго игрока, запуск игры&lt;br /&gt;
*Обе кнопки (удержание 2 сек)	Полный сброс всех настроек&lt;br /&gt;
&lt;br /&gt;
==ГЛАВНОЕ МЕНЮ==&lt;br /&gt;
*При включении часы показывают главное меню. На дисплеях отображается номер текущего пункта (от 1 до 6).&lt;br /&gt;
&lt;br /&gt;
*Навигация: поворот энкодера — перемещение по пунктам, нажатие энкодера — вход в выбранный пункт.&lt;br /&gt;
&lt;br /&gt;
*Пункт 1 — установка времени. Диапазон 1–999 минут. При быстром вращении энкодера шаг увеличивается до 5 минут. На дисплее 1 отображается значение минут, на дисплее 2 — цифра 1.&lt;br /&gt;
&lt;br /&gt;
*Пункт 2 — выбор режима игры. 0 = CLS (классический), 1 = ADD (с добавкой), 2 = DLY (с задержкой). На дисплее 1 отображается название режима, на дисплее 2 — его номер.&lt;br /&gt;
&lt;br /&gt;
*Пункт 3 — настройка добавки или задержки. В режиме ADD: добавка 0–60 секунд. В режиме DLY: задержка 1–60 секунд. В режиме CLS: настройка не используется. На дисплее 2 отображается тип настройки: Add или dLY.&lt;br /&gt;
&lt;br /&gt;
*Пункт 4 — старт игры. Запуск отсчёта времени.&lt;br /&gt;
&lt;br /&gt;
*Пункт 5 — яркость дисплеев. Диапазон 0–7 (0 — минимум, 7 — максимум). На дисплее 1 отображается brI, на дисплее 2 — значение.&lt;br /&gt;
&lt;br /&gt;
*Пункт 6 — громкость звука. Диапазон 0–100 (0 — звук выключен, 100 — максимум). На дисплее 1 отображается VoL, на дисплее 2 — значение, делённое на 10.&lt;br /&gt;
&lt;br /&gt;
==Режимы игры==&lt;br /&gt;
&lt;br /&gt;
*CLS (классический) — обычный контроль времени. Время каждого игрока уменьшается только во время его хода. Без добавки и задержки. Применение: стандартные партии, классические турниры.&lt;br /&gt;
&lt;br /&gt;
*ADD (с добавкой) — после каждого хода к оставшемуся времени добавляется указанное количество секунд (0–60). Пример: начальное время 5 минут, добавка 3 секунды — после каждого хода игрок получает +3 секунды. Применение: блиц, рапид с добавлением времени (инкремент по Фишеру).&lt;br /&gt;
&lt;br /&gt;
*DLY (с задержкой) — время не уменьшается в течение указанной задержки (1–60 секунд) после нажатия кнопки соперником. Пример: задержка 5 секунд — после хода соперника у вас есть 5 секунд на обдумывание без потери основного времени. Применение: традиционные турниры, игра с задержкой Бронштейна.&lt;br /&gt;
&lt;br /&gt;
==Игровой процесс==&lt;br /&gt;
&lt;br /&gt;
*Запуск игры: настройте параметры в меню, перейдите в пункт 4 (Старт), нажмите кнопку игрока, который ходит первым (кнопка 1 — игрок 1, кнопка 2 — игрок 2).&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода и переключение времени на соперника. Нажатие энкодера — пауза или снятие с паузы. Удержание энкодера (2 секунды) — показ статистики ходов (на дисплее 1 — ходы игрока 1, на дисплее 2 — ходы игрока 2).&lt;br /&gt;
&lt;br /&gt;
*Окончание игры: когда у одного из игроков истекает время, дисплей проигравшего мигает, звучит длинный звуковой сигнал, часы возвращаются в главное меню.&lt;br /&gt;
&lt;br /&gt;
*Пауза: нажмите энкодер — на дисплеях отображается PUSE, время останавливается, кнопки игроков блокируются. Повторное нажатие энкодера снимает паузу.&lt;br /&gt;
&lt;br /&gt;
==Звуковые сигналы==&lt;br /&gt;
&lt;br /&gt;
*Поворот энкодера — 5 мс, 4000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие кнопки игрока — 20 мс, 3000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Нажатие энкодера — 30 мс, 2800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Старт игры — 50 мс, 2500 Гц.&lt;br /&gt;
&lt;br /&gt;
*Пауза — 100 мс, 2200 Гц.&lt;br /&gt;
&lt;br /&gt;
*Снятие с паузы — 100 мс, 2400 Гц.&lt;br /&gt;
&lt;br /&gt;
*Сброс настроек — 100 мс, 2000 Гц.&lt;br /&gt;
&lt;br /&gt;
*Длинное удержание — 100 мс, 1800 Гц.&lt;br /&gt;
&lt;br /&gt;
*Конец игры — 1000 мс, 1500 Гц.&lt;br /&gt;
&lt;br /&gt;
==Формат отображения времени==&lt;br /&gt;
&lt;br /&gt;
*Обычный режим (ММ:СС) — когда время меньше 99 минут. Дисплей показывает минуты и секунды, двоеточие мигает.&lt;br /&gt;
&lt;br /&gt;
*Часовой режим (ЧЧ:ММ) — когда время достигает 99 минут (5940 секунд) и более. Дисплей автоматически переключается на часы и минуты. Максимальное отображение — 99 часов 59 минут.&lt;br /&gt;
&lt;br /&gt;
==Пасхалки==&lt;br /&gt;
&lt;br /&gt;
«К Элизе» Бетховена. Активация: зайдите в настройки громкости (пункт 6), установите громкость 0, в течение 3 секунд установите 100, снова установите 0, и наконец 100. На дисплеях появится ELIS, затем заиграет мелодия.&lt;br /&gt;
&lt;br /&gt;
==Краткое руководство (памятка)==&lt;br /&gt;
&lt;br /&gt;
*Навигация по меню: вращение энкодера — выбор пункта, нажатие — вход.&lt;br /&gt;
&lt;br /&gt;
*Пункты меню: 1 — время партии, 2 — режим игры, 3 — добавка/задержка, 4 — старт, 5 — яркость, 6 — громкость.&lt;br /&gt;
&lt;br /&gt;
*Режимы игры: CLS — классический, ADD — с добавкой, DLY — с задержкой.&lt;br /&gt;
&lt;br /&gt;
*Во время партии: нажатие своей кнопки — завершение хода, нажатие энкодера — пауза, удержание энкодера — статистика ходов, удержание обеих кнопок (2 секунды) — полный сброс.&lt;br /&gt;
&lt;br /&gt;
==Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
*Козырев Андрей-электронщик&lt;br /&gt;
*Хавкунова Екатерина-конструктор&lt;br /&gt;
*Тельпухова Майя-журналист&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=57</id>
		<title>Заглавная страница</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=57"/>
		<updated>2026-05-02T08:44:18Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Проекты СКБ &amp;quot;Прометей&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Конструкторское бюро &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
&#039;&#039;&#039;Конструкторское бюро &amp;quot;Прометей&amp;quot; (изначально студенческое конструкторское бюро &amp;quot;Прометей&amp;quot;)&#039;&#039;&#039; – основано на базе Новосибирского государственного технического университета 17.11.2017 года. Причиной основания бюро явилась реформа высшего образования, результатом которого многократно сократились специальные дисциплины в вузах. Руководители, из числа преподавателей вуза, стало жалко смотреть на утопическую реформу и решило организовать место для собственного роста и развития. На базе конструкторского бюро ведутся различные учебные проекты у которых есть перспектива роста и развития в собственный бизнес. Основной упор делается на саморазвитие, но с привлечением внимания специалистов. На базе конструкторского бюро ведется развитие по следующим компетенциям:&lt;br /&gt;
* Электронщик - специалист, в область деятельности которого входит разработка электрических принципиальных схем, настройка и отладка электронного оборудования, ремонт электронных узлов;&lt;br /&gt;
* Конструктор - специалист, который разрабатывает конструкции блоков, элементов креплений, корпусов под электронные изделия с элементами дизайна;&lt;br /&gt;
* Программист нижнего уровня - специалист, который занимается программированием микроконтроллеров, настройкой оборудования, проведением пуско-наладочных работ, отладкой электронных блоков с микроконтроллерами;&lt;br /&gt;
* Программист верхнего уровня - специалист, который программирует многопоточные настольные приложения с интерфейсом пользователя, с аппаратными интерфейсами;&lt;br /&gt;
* Программист базы данных - специалист, который создает базы данных и обеспечивает доступ к ним, пишет хранимые процедуры. &lt;br /&gt;
* Администратор сети - специалист, обеспечивающий доступ к серверу, к различному программному обеспечению, следит за безопасностью в сети.&lt;br /&gt;
* Дизайнер - специалист, который работает с публикациями, разрабатывает стендовые плакаты, презентации.&lt;br /&gt;
* Технический дизайнер - разрабатывает уникальный дизайн изделий вместе с конструктором, проводят макетирование.&lt;br /&gt;
* Журналист - публикует статьи о разработках в сети и поддерживает связь с общественностью. &lt;br /&gt;
* Служба безопасности - специалисты, которые разносят в пух и прах врагов конструкторского бюро в информационном поле, следит за угрозами из вне. &lt;br /&gt;
&lt;br /&gt;
Конструкторское бюро поддерживает связь с специалистами, которые могут консультировать &lt;br /&gt;
обеспечивающее рабочее место радиоэлектронщика, конструктора, технолога дизайнера, где студенты, желающие развиваться по направлению, приобретало практические навыки проектирования радиоэлектронной аппаратуры. Основное направление развития навыков проектирования велось из практических задач, которые выбирались из задач решаемых для предпринимателей, малого и среднего бизнеса, задач предприятий. Студенты, участвующие в работах, выполняли задания несущий прикладной характер и попутно развивались в профессиональной сфере. Всю ответственность на себя брали руководители СКБ &amp;quot;Прометей&amp;quot; из числа преподавателей и опытных студентов. &lt;br /&gt;
&lt;br /&gt;
== Сотрудники конструкторского бюро ==&lt;br /&gt;
* Преподавателей кафедры &amp;quot;Конструирования и технологии радиоэлектронных средств&amp;quot; и коллеги с других кафедр и факультетов;&lt;br /&gt;
* Студентов, обучающих на радиотехнических направлениях, желающих участвовать в разработках;&lt;br /&gt;
* Школьников 17 Гимназии города Новосибирска, проходящих профильное образование в НГТУ;&lt;br /&gt;
* Некоторых школьников из разных школ города Новосибирска, желающих саморазвиваться по техническим направлениям. &lt;br /&gt;
&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya Тельпухова Майя Максимовна ]&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:MandzykS Мандзюк Степан Иванович]&lt;br /&gt;
&lt;br /&gt;
== Проекты СКБ &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
* Качели с водопадом - система управления аттракциона качели с водопадом;&lt;br /&gt;
* Регистратор электромагнитного излучения - предназначен для прогнозирования динамических проявлений горного давления;&lt;br /&gt;
* Автоматизированная система определения глубины промерзания грунта и включения холодильной системы;&lt;br /&gt;
* Система определения эмоционального состояния у детей с расстройством аутистического спектра.&lt;br /&gt;
&lt;br /&gt;
Информацию по работе с этой вики можно найти в [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents справочном руководстве].&lt;br /&gt;
&lt;br /&gt;
* [[Шахматные часы с тремя режимами контроля времени]]&lt;br /&gt;
* [[Шахматные часы самодельные]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
== Начало работы ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список возможных настроек];&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Manual:FAQ/ru Часто задаваемые вопросы и ответы по MediaWiki];&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ Рассылка уведомлений о выходе новых версий MediaWiki].&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Перевод MediaWiki на свой язык]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Узнайте, как бороться со спамом в вашей вики]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Сотрудники]]&lt;br /&gt;
[[Категория:Радиолюбители]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=56</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=56"/>
		<updated>2026-05-02T08:35:18Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=55</id>
		<title>Заглавная страница</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=55"/>
		<updated>2026-05-02T08:34:08Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Проекты СКБ &amp;quot;Прометей&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Конструкторское бюро &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
&#039;&#039;&#039;Конструкторское бюро &amp;quot;Прометей&amp;quot; (изначально студенческое конструкторское бюро &amp;quot;Прометей&amp;quot;)&#039;&#039;&#039; – основано на базе Новосибирского государственного технического университета 17.11.2017 года. Причиной основания бюро явилась реформа высшего образования, результатом которого многократно сократились специальные дисциплины в вузах. Руководители, из числа преподавателей вуза, стало жалко смотреть на утопическую реформу и решило организовать место для собственного роста и развития. На базе конструкторского бюро ведутся различные учебные проекты у которых есть перспектива роста и развития в собственный бизнес. Основной упор делается на саморазвитие, но с привлечением внимания специалистов. На базе конструкторского бюро ведется развитие по следующим компетенциям:&lt;br /&gt;
* Электронщик - специалист, в область деятельности которого входит разработка электрических принципиальных схем, настройка и отладка электронного оборудования, ремонт электронных узлов;&lt;br /&gt;
* Конструктор - специалист, который разрабатывает конструкции блоков, элементов креплений, корпусов под электронные изделия с элементами дизайна;&lt;br /&gt;
* Программист нижнего уровня - специалист, который занимается программированием микроконтроллеров, настройкой оборудования, проведением пуско-наладочных работ, отладкой электронных блоков с микроконтроллерами;&lt;br /&gt;
* Программист верхнего уровня - специалист, который программирует многопоточные настольные приложения с интерфейсом пользователя, с аппаратными интерфейсами;&lt;br /&gt;
* Программист базы данных - специалист, который создает базы данных и обеспечивает доступ к ним, пишет хранимые процедуры. &lt;br /&gt;
* Администратор сети - специалист, обеспечивающий доступ к серверу, к различному программному обеспечению, следит за безопасностью в сети.&lt;br /&gt;
* Дизайнер - специалист, который работает с публикациями, разрабатывает стендовые плакаты, презентации.&lt;br /&gt;
* Технический дизайнер - разрабатывает уникальный дизайн изделий вместе с конструктором, проводят макетирование.&lt;br /&gt;
* Журналист - публикует статьи о разработках в сети и поддерживает связь с общественностью. &lt;br /&gt;
* Служба безопасности - специалисты, которые разносят в пух и прах врагов конструкторского бюро в информационном поле, следит за угрозами из вне. &lt;br /&gt;
&lt;br /&gt;
Конструкторское бюро поддерживает связь с специалистами, которые могут консультировать &lt;br /&gt;
обеспечивающее рабочее место радиоэлектронщика, конструктора, технолога дизайнера, где студенты, желающие развиваться по направлению, приобретало практические навыки проектирования радиоэлектронной аппаратуры. Основное направление развития навыков проектирования велось из практических задач, которые выбирались из задач решаемых для предпринимателей, малого и среднего бизнеса, задач предприятий. Студенты, участвующие в работах, выполняли задания несущий прикладной характер и попутно развивались в профессиональной сфере. Всю ответственность на себя брали руководители СКБ &amp;quot;Прометей&amp;quot; из числа преподавателей и опытных студентов. &lt;br /&gt;
&lt;br /&gt;
== Сотрудники конструкторского бюро ==&lt;br /&gt;
* Преподавателей кафедры &amp;quot;Конструирования и технологии радиоэлектронных средств&amp;quot; и коллеги с других кафедр и факультетов;&lt;br /&gt;
* Студентов, обучающих на радиотехнических направлениях, желающих участвовать в разработках;&lt;br /&gt;
* Школьников 17 Гимназии города Новосибирска, проходящих профильное образование в НГТУ;&lt;br /&gt;
* Некоторых школьников из разных школ города Новосибирска, желающих саморазвиваться по техническим направлениям. &lt;br /&gt;
&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya Тельпухова Майя Максимовна ]&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:MandzykS Мандзюк Степан Иванович]&lt;br /&gt;
&lt;br /&gt;
== Проекты СКБ &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
* Качели с водопадом - система управления аттракциона качели с водопадом;&lt;br /&gt;
* Регистратор электромагнитного излучения - предназначен для прогнозирования динамических проявлений горного давления;&lt;br /&gt;
* Автоматизированная система определения глубины промерзания грунта и включения холодильной системы;&lt;br /&gt;
* Система определения эмоционального состояния у детей с расстройством аутистического спектра.&lt;br /&gt;
&lt;br /&gt;
Информацию по работе с этой вики можно найти в [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents справочном руководстве].&lt;br /&gt;
&lt;br /&gt;
* [[Шахматные часы]]&lt;br /&gt;
* [[Шахматные часы с тремя режимами контроля времени]]&lt;br /&gt;
* [[Шахматные часы самодельные]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
== Начало работы ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список возможных настроек];&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Manual:FAQ/ru Часто задаваемые вопросы и ответы по MediaWiki];&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ Рассылка уведомлений о выходе новых версий MediaWiki].&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Перевод MediaWiki на свой язык]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Узнайте, как бороться со спамом в вашей вики]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Сотрудники]]&lt;br /&gt;
[[Категория:Радиолюбители]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=54</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=54"/>
		<updated>2026-05-02T08:32:56Z</updated>

		<summary type="html">&lt;p&gt;Maya: Удалено перенаправление на Трёхрежимные шахматные часы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__ИНДЕКС__&lt;br /&gt;
__ССЫЛКА_НА_НОВЫЙ_РАЗДЕЛ__&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=53</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=53"/>
		<updated>2026-05-02T08:29:54Z</updated>

		<summary type="html">&lt;p&gt;Maya: Отмена версии 52, сделанной Maya (обсуждение)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#перенаправление [[Трёхрежимные шахматные часы]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=52</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=52"/>
		<updated>2026-05-02T08:27:00Z</updated>

		<summary type="html">&lt;p&gt;Maya: Полностью удалено содержимое страницы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A2%D1%80%D1%91%D1%85%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%BD%D1%8B%D0%B5_%D1%88%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B&amp;diff=51</id>
		<title>Трёхрежимные шахматные часы</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A2%D1%80%D1%91%D1%85%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%BD%D1%8B%D0%B5_%D1%88%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B&amp;diff=51"/>
		<updated>2026-05-02T08:19:35Z</updated>

		<summary type="html">&lt;p&gt;Maya: Maya переименовал страницу Трёхрежимные шахматные часы в Шахматные часы самодельные2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#перенаправление [[Шахматные часы самодельные2]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=50</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=50"/>
		<updated>2026-05-02T08:19:35Z</updated>

		<summary type="html">&lt;p&gt;Maya: Maya переименовал страницу Трёхрежимные шахматные часы в Шахматные часы самодельные2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=49</id>
		<title>Шахматные часы с тремя режимами контроля времени</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81_%D1%82%D1%80%D0%B5%D0%BC%D1%8F_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0%D0%BC%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8&amp;diff=49"/>
		<updated>2026-05-02T08:17:12Z</updated>

		<summary type="html">&lt;p&gt;Maya: Maya переименовал страницу Шахматные часы с тремя режимами контроля времени в Трёхрежимные шахматные часы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#перенаправление [[Трёхрежимные шахматные часы]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=48</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=48"/>
		<updated>2026-05-02T08:17:12Z</updated>

		<summary type="html">&lt;p&gt;Maya: Maya переименовал страницу Шахматные часы с тремя режимами контроля времени в Трёхрежимные шахматные часы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B&amp;diff=47</id>
		<title>Шахматные часы</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B&amp;diff=47"/>
		<updated>2026-05-02T08:15:35Z</updated>

		<summary type="html">&lt;p&gt;Maya: Maya переименовал страницу Шахматные часы в Шахматные часы с тремя режимами контроля времени&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#перенаправление [[Шахматные часы с тремя режимами контроля времени]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=46</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=46"/>
		<updated>2026-05-02T08:15:35Z</updated>

		<summary type="html">&lt;p&gt;Maya: Maya переименовал страницу Шахматные часы в Шахматные часы с тремя режимами контроля времени&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=45</id>
		<title>Заглавная страница</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=45"/>
		<updated>2026-05-02T08:15:10Z</updated>

		<summary type="html">&lt;p&gt;Maya: Отмена версии 44, сделанной Maya (обсуждение)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Конструкторское бюро &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
&#039;&#039;&#039;Конструкторское бюро &amp;quot;Прометей&amp;quot; (изначально студенческое конструкторское бюро &amp;quot;Прометей&amp;quot;)&#039;&#039;&#039; – основано на базе Новосибирского государственного технического университета 17.11.2017 года. Причиной основания бюро явилась реформа высшего образования, результатом которого многократно сократились специальные дисциплины в вузах. Руководители, из числа преподавателей вуза, стало жалко смотреть на утопическую реформу и решило организовать место для собственного роста и развития. На базе конструкторского бюро ведутся различные учебные проекты у которых есть перспектива роста и развития в собственный бизнес. Основной упор делается на саморазвитие, но с привлечением внимания специалистов. На базе конструкторского бюро ведется развитие по следующим компетенциям:&lt;br /&gt;
* Электронщик - специалист, в область деятельности которого входит разработка электрических принципиальных схем, настройка и отладка электронного оборудования, ремонт электронных узлов;&lt;br /&gt;
* Конструктор - специалист, который разрабатывает конструкции блоков, элементов креплений, корпусов под электронные изделия с элементами дизайна;&lt;br /&gt;
* Программист нижнего уровня - специалист, который занимается программированием микроконтроллеров, настройкой оборудования, проведением пуско-наладочных работ, отладкой электронных блоков с микроконтроллерами;&lt;br /&gt;
* Программист верхнего уровня - специалист, который программирует многопоточные настольные приложения с интерфейсом пользователя, с аппаратными интерфейсами;&lt;br /&gt;
* Программист базы данных - специалист, который создает базы данных и обеспечивает доступ к ним, пишет хранимые процедуры. &lt;br /&gt;
* Администратор сети - специалист, обеспечивающий доступ к серверу, к различному программному обеспечению, следит за безопасностью в сети.&lt;br /&gt;
* Дизайнер - специалист, который работает с публикациями, разрабатывает стендовые плакаты, презентации.&lt;br /&gt;
* Технический дизайнер - разрабатывает уникальный дизайн изделий вместе с конструктором, проводят макетирование.&lt;br /&gt;
* Журналист - публикует статьи о разработках в сети и поддерживает связь с общественностью. &lt;br /&gt;
* Служба безопасности - специалисты, которые разносят в пух и прах врагов конструкторского бюро в информационном поле, следит за угрозами из вне. &lt;br /&gt;
&lt;br /&gt;
Конструкторское бюро поддерживает связь с специалистами, которые могут консультировать &lt;br /&gt;
обеспечивающее рабочее место радиоэлектронщика, конструктора, технолога дизайнера, где студенты, желающие развиваться по направлению, приобретало практические навыки проектирования радиоэлектронной аппаратуры. Основное направление развития навыков проектирования велось из практических задач, которые выбирались из задач решаемых для предпринимателей, малого и среднего бизнеса, задач предприятий. Студенты, участвующие в работах, выполняли задания несущий прикладной характер и попутно развивались в профессиональной сфере. Всю ответственность на себя брали руководители СКБ &amp;quot;Прометей&amp;quot; из числа преподавателей и опытных студентов. &lt;br /&gt;
&lt;br /&gt;
== Сотрудники конструкторского бюро ==&lt;br /&gt;
* Преподавателей кафедры &amp;quot;Конструирования и технологии радиоэлектронных средств&amp;quot; и коллеги с других кафедр и факультетов;&lt;br /&gt;
* Студентов, обучающих на радиотехнических направлениях, желающих участвовать в разработках;&lt;br /&gt;
* Школьников 17 Гимназии города Новосибирска, проходящих профильное образование в НГТУ;&lt;br /&gt;
* Некоторых школьников из разных школ города Новосибирска, желающих саморазвиваться по техническим направлениям. &lt;br /&gt;
&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya Тельпухова Майя Максимовна ]&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:MandzykS Мандзюк Степан Иванович]&lt;br /&gt;
&lt;br /&gt;
== Проекты СКБ &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
* Качели с водопадом - система управления аттракциона качели с водопадом;&lt;br /&gt;
* Регистратор электромагнитного излучения - предназначен для прогнозирования динамических проявлений горного давления;&lt;br /&gt;
* Автоматизированная система определения глубины промерзания грунта и включения холодильной системы;&lt;br /&gt;
* Система определения эмоционального состояния у детей с расстройством аутистического спектра.&lt;br /&gt;
&lt;br /&gt;
Информацию по работе с этой вики можно найти в [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents справочном руководстве].&lt;br /&gt;
&lt;br /&gt;
* [[Шахматные часы]]&lt;br /&gt;
* [[Шахматные часы самодельные]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
== Начало работы ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список возможных настроек];&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Manual:FAQ/ru Часто задаваемые вопросы и ответы по MediaWiki];&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ Рассылка уведомлений о выходе новых версий MediaWiki].&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Перевод MediaWiki на свой язык]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Узнайте, как бороться со спамом в вашей вики]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Сотрудники]]&lt;br /&gt;
[[Категория:Радиолюбители]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=44</id>
		<title>Заглавная страница</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=44"/>
		<updated>2026-05-02T08:13:00Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Проекты СКБ &amp;quot;Прометей&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Конструкторское бюро &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
&#039;&#039;&#039;Конструкторское бюро &amp;quot;Прометей&amp;quot; (изначально студенческое конструкторское бюро &amp;quot;Прометей&amp;quot;)&#039;&#039;&#039; – основано на базе Новосибирского государственного технического университета 17.11.2017 года. Причиной основания бюро явилась реформа высшего образования, результатом которого многократно сократились специальные дисциплины в вузах. Руководители, из числа преподавателей вуза, стало жалко смотреть на утопическую реформу и решило организовать место для собственного роста и развития. На базе конструкторского бюро ведутся различные учебные проекты у которых есть перспектива роста и развития в собственный бизнес. Основной упор делается на саморазвитие, но с привлечением внимания специалистов. На базе конструкторского бюро ведется развитие по следующим компетенциям:&lt;br /&gt;
* Электронщик - специалист, в область деятельности которого входит разработка электрических принципиальных схем, настройка и отладка электронного оборудования, ремонт электронных узлов;&lt;br /&gt;
* Конструктор - специалист, который разрабатывает конструкции блоков, элементов креплений, корпусов под электронные изделия с элементами дизайна;&lt;br /&gt;
* Программист нижнего уровня - специалист, который занимается программированием микроконтроллеров, настройкой оборудования, проведением пуско-наладочных работ, отладкой электронных блоков с микроконтроллерами;&lt;br /&gt;
* Программист верхнего уровня - специалист, который программирует многопоточные настольные приложения с интерфейсом пользователя, с аппаратными интерфейсами;&lt;br /&gt;
* Программист базы данных - специалист, который создает базы данных и обеспечивает доступ к ним, пишет хранимые процедуры. &lt;br /&gt;
* Администратор сети - специалист, обеспечивающий доступ к серверу, к различному программному обеспечению, следит за безопасностью в сети.&lt;br /&gt;
* Дизайнер - специалист, который работает с публикациями, разрабатывает стендовые плакаты, презентации.&lt;br /&gt;
* Технический дизайнер - разрабатывает уникальный дизайн изделий вместе с конструктором, проводят макетирование.&lt;br /&gt;
* Журналист - публикует статьи о разработках в сети и поддерживает связь с общественностью. &lt;br /&gt;
* Служба безопасности - специалисты, которые разносят в пух и прах врагов конструкторского бюро в информационном поле, следит за угрозами из вне. &lt;br /&gt;
&lt;br /&gt;
Конструкторское бюро поддерживает связь с специалистами, которые могут консультировать &lt;br /&gt;
обеспечивающее рабочее место радиоэлектронщика, конструктора, технолога дизайнера, где студенты, желающие развиваться по направлению, приобретало практические навыки проектирования радиоэлектронной аппаратуры. Основное направление развития навыков проектирования велось из практических задач, которые выбирались из задач решаемых для предпринимателей, малого и среднего бизнеса, задач предприятий. Студенты, участвующие в работах, выполняли задания несущий прикладной характер и попутно развивались в профессиональной сфере. Всю ответственность на себя брали руководители СКБ &amp;quot;Прометей&amp;quot; из числа преподавателей и опытных студентов. &lt;br /&gt;
&lt;br /&gt;
== Сотрудники конструкторского бюро ==&lt;br /&gt;
* Преподавателей кафедры &amp;quot;Конструирования и технологии радиоэлектронных средств&amp;quot; и коллеги с других кафедр и факультетов;&lt;br /&gt;
* Студентов, обучающих на радиотехнических направлениях, желающих участвовать в разработках;&lt;br /&gt;
* Школьников 17 Гимназии города Новосибирска, проходящих профильное образование в НГТУ;&lt;br /&gt;
* Некоторых школьников из разных школ города Новосибирска, желающих саморазвиваться по техническим направлениям. &lt;br /&gt;
&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya Тельпухова Майя Максимовна ]&lt;br /&gt;
* [http://wikiprometheus.ru/index.php/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:MandzykS Мандзюк Степан Иванович]&lt;br /&gt;
&lt;br /&gt;
== Проекты СКБ &amp;quot;Прометей&amp;quot; ==&lt;br /&gt;
* Качели с водопадом - система управления аттракциона качели с водопадом;&lt;br /&gt;
* Регистратор электромагнитного излучения - предназначен для прогнозирования динамических проявлений горного давления;&lt;br /&gt;
* Автоматизированная система определения глубины промерзания грунта и включения холодильной системы;&lt;br /&gt;
* Система определения эмоционального состояния у детей с расстройством аутистического спектра.&lt;br /&gt;
&lt;br /&gt;
Информацию по работе с этой вики можно найти в [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents справочном руководстве].&lt;br /&gt;
&lt;br /&gt;
* [[Шахматные часы с тремя режимами контроля времени]]&lt;br /&gt;
* [[Шахматные часы самодельные]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
== Начало работы ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список возможных настроек];&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Manual:FAQ/ru Часто задаваемые вопросы и ответы по MediaWiki];&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ Рассылка уведомлений о выходе новых версий MediaWiki].&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Перевод MediaWiki на свой язык]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Узнайте, как бороться со спамом в вашей вики]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Сотрудники]]&lt;br /&gt;
[[Категория:Радиолюбители]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=43</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=43"/>
		<updated>2026-05-02T02:51:59Z</updated>

		<summary type="html">&lt;p&gt;Maya: код&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
/*&lt;br /&gt;
  Шахматные часы на Arduino Nano&lt;br /&gt;
  Упрощенные режимы: Классика, С добавкой, С задержкой&lt;br /&gt;
  Исправлены проблемы с паузой и форматом времени&lt;br /&gt;
  Добавлена пасхалка &amp;quot;К Элизе&amp;quot; (исправленная версия)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;TM1637Display.h&amp;gt;&lt;br /&gt;
#include &amp;lt;GyverEncoder.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// ==================== ПИНЫ ====================&lt;br /&gt;
#define ENC_S1 11&lt;br /&gt;
#define ENC_S2 10&lt;br /&gt;
#define ENC_KEY 9&lt;br /&gt;
#define BTN_P1 7&lt;br /&gt;
#define BTN_P2 8&lt;br /&gt;
#define TM1637_CLK1 6&lt;br /&gt;
#define TM1637_DIO1 5&lt;br /&gt;
#define TM1637_CLK2 4&lt;br /&gt;
#define TM1637_DIO2 3&lt;br /&gt;
#define BUZZER 2&lt;br /&gt;
&lt;br /&gt;
// ==================== НАСТРОЙКИ ====================&lt;br /&gt;
#define DEBOUNCE_DELAY   50&lt;br /&gt;
#define LONG_PRESS_TIME 2000&lt;br /&gt;
#define ENC_DELAY_NORMAL 150&lt;br /&gt;
#define ENC_DELAY_FAST   50&lt;br /&gt;
#define ENC_FAST_THRESHOLD 3&lt;br /&gt;
&lt;br /&gt;
// ==================== ЗВУКОВЫЕ ЧАСТОТЫ ====================&lt;br /&gt;
#define BEEP_ENC        4000&lt;br /&gt;
#define BEEP_BUTTON     3000&lt;br /&gt;
#define BEEP_START      2500&lt;br /&gt;
#define BEEP_CLICK      2800&lt;br /&gt;
#define BEEP_RESET      2000&lt;br /&gt;
#define BEEP_GAME_OVER  1500&lt;br /&gt;
#define BEEP_LONG_PRESS 1800&lt;br /&gt;
#define BEEP_PAUSE      2200&lt;br /&gt;
#define BEEP_UNPAUSE    2400&lt;br /&gt;
&lt;br /&gt;
// ==================== ПРОТОТИПЫ ====================&lt;br /&gt;
void beep(int duration, int frequency);&lt;br /&gt;
void showTime();&lt;br /&gt;
void showMenu();&lt;br /&gt;
void showSetTime();&lt;br /&gt;
void showSetAdd();&lt;br /&gt;
void showSetDelay();&lt;br /&gt;
void showSetMode();&lt;br /&gt;
void showSetBrightness();&lt;br /&gt;
void showSetVolume();&lt;br /&gt;
void handleGame();&lt;br /&gt;
void startGame(int firstPlayer);&lt;br /&gt;
void gameOver(int loser);&lt;br /&gt;
void resetAll();&lt;br /&gt;
void playFurElise();&lt;br /&gt;
void checkVolumeEasterEgg();&lt;br /&gt;
&lt;br /&gt;
// ==================== ПЕРЕМЕННЫЕ ====================&lt;br /&gt;
TM1637Display display1(TM1637_CLK1, TM1637_DIO1);&lt;br /&gt;
TM1637Display display2(TM1637_CLK2, TM1637_DIO2);&lt;br /&gt;
Encoder encoder(ENC_S1, ENC_S2, ENC_KEY);&lt;br /&gt;
&lt;br /&gt;
int mode = 0;&lt;br /&gt;
int gameMode = 0;&lt;br /&gt;
&lt;br /&gt;
long timeP1 = 300;&lt;br /&gt;
long timeP2 = 300;&lt;br /&gt;
long addTime = 3;&lt;br /&gt;
long delaySec = 5;&lt;br /&gt;
&lt;br /&gt;
bool turn = 0;&lt;br /&gt;
bool playing = false;&lt;br /&gt;
bool paused = false;&lt;br /&gt;
unsigned long lastTickTime = 0;&lt;br /&gt;
unsigned long pauseStartTime = 0;&lt;br /&gt;
bool gameStarted = false;&lt;br /&gt;
&lt;br /&gt;
int movesP1 = 0;&lt;br /&gt;
int movesP2 = 0;&lt;br /&gt;
bool showStats = false;&lt;br /&gt;
unsigned long statsShowTime = 0;&lt;br /&gt;
&lt;br /&gt;
int setMinutes = 5;&lt;br /&gt;
int setAdd = 3;&lt;br /&gt;
int setDelay = 5;&lt;br /&gt;
int setMode = 0;&lt;br /&gt;
int setBrightness = 7;&lt;br /&gt;
int setVolume = 100;&lt;br /&gt;
&lt;br /&gt;
// Переменные для пасхалки&lt;br /&gt;
int easterEggStep = 0;&lt;br /&gt;
unsigned long lastEasterEggTime = 0;&lt;br /&gt;
&lt;br /&gt;
bool lastP1 = HIGH, lastP2 = HIGH;&lt;br /&gt;
unsigned long lastP1Time = 0, lastP2Time = 0;&lt;br /&gt;
unsigned long bothStart = 0;&lt;br /&gt;
&lt;br /&gt;
int menuPos = 0;&lt;br /&gt;
unsigned long lastEncTime = 0;&lt;br /&gt;
&lt;br /&gt;
int encFastCounter = 0;&lt;br /&gt;
unsigned long lastEncTurnTime = 0;&lt;br /&gt;
int lastEncDirection = 0;&lt;br /&gt;
&lt;br /&gt;
// ==================== СЕГМЕНТНЫЕ МАСКИ ====================&lt;br /&gt;
const uint8_t MY_SEG_A = 0b01110111;&lt;br /&gt;
const uint8_t MY_SEG_b = 0b01111100;&lt;br /&gt;
const uint8_t MY_SEG_C = 0b00111001;&lt;br /&gt;
const uint8_t MY_SEG_d = 0b01011110;&lt;br /&gt;
const uint8_t MY_SEG_L = 0b00111000;&lt;br /&gt;
const uint8_t MY_SEG_S = 0b01101101;&lt;br /&gt;
const uint8_t MY_SEG_Y = 0b01101110;&lt;br /&gt;
const uint8_t MY_SEG_r = 0b01010000;&lt;br /&gt;
const uint8_t MY_SEG_I = 0b01101100;&lt;br /&gt;
const uint8_t MY_SEG_U = 0b00111110;&lt;br /&gt;
const uint8_t MY_SEG_o = 0b01011100;&lt;br /&gt;
&lt;br /&gt;
const uint8_t MODE_CLS[] = { MY_SEG_C, MY_SEG_L, MY_SEG_S, 0x00 };&lt;br /&gt;
const uint8_t MODE_ADD[] = { MY_SEG_A, MY_SEG_d, MY_SEG_d, 0x00 };&lt;br /&gt;
const uint8_t MODE_DLY[] = { MY_SEG_d, MY_SEG_L, MY_SEG_Y, 0x00 };&lt;br /&gt;
const uint8_t MODE_bRI[] = { MY_SEG_b, MY_SEG_r, MY_SEG_I, 0x00 };&lt;br /&gt;
const uint8_t MODE_Vol[] = { MY_SEG_U, MY_SEG_o, MY_SEG_L, 0x00 };&lt;br /&gt;
const uint8_t PUSE[] = { 0b01110011, 0b01111100, 0b01101101, 0b01111001 };&lt;br /&gt;
const uint8_t ELISE_SEG[] = { 0b01111001, 0b00111000, 0b00110000, 0b01101101 }; // E L I S&lt;br /&gt;
&lt;br /&gt;
// ==================== SETUP ====================&lt;br /&gt;
void setup() {&lt;br /&gt;
    pinMode(BTN_P1, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BTN_P2, INPUT_PULLUP);&lt;br /&gt;
    pinMode(BUZZER, OUTPUT);&lt;br /&gt;
&lt;br /&gt;
    display1.setBrightness(setBrightness);&lt;br /&gt;
    display2.setBrightness(setBrightness);&lt;br /&gt;
&lt;br /&gt;
    display1.showNumberDec(8888);&lt;br /&gt;
    display2.showNumberDec(8888);&lt;br /&gt;
    delay(800);&lt;br /&gt;
&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== LOOP ====================&lt;br /&gt;
void loop() {&lt;br /&gt;
    encoder.tick();&lt;br /&gt;
&lt;br /&gt;
    if (mode == 0) {&lt;br /&gt;
        handleEncoderMenu();&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            if (menuPos == 0) {&lt;br /&gt;
                mode = 3;&lt;br /&gt;
                setMinutes = timeP1 / 60;&lt;br /&gt;
                showSetTime();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 1) {&lt;br /&gt;
                mode = 5;&lt;br /&gt;
                setMode = gameMode;&lt;br /&gt;
                showSetMode();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 2) {&lt;br /&gt;
                if (gameMode == 1) {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                else if (gameMode == 2) {&lt;br /&gt;
                    mode = 7;&lt;br /&gt;
                    setDelay = delaySec;&lt;br /&gt;
                    showSetDelay();&lt;br /&gt;
                }&lt;br /&gt;
                else {&lt;br /&gt;
                    mode = 4;&lt;br /&gt;
                    setAdd = addTime;&lt;br /&gt;
                    showSetAdd();&lt;br /&gt;
                }&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 3) {&lt;br /&gt;
                mode = 1;&lt;br /&gt;
                timeP1 = (long)setMinutes * 60;&lt;br /&gt;
                timeP2 = timeP1;&lt;br /&gt;
                movesP1 = 0;&lt;br /&gt;
                movesP2 = 0;&lt;br /&gt;
                gameStarted = false;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                paused = false;&lt;br /&gt;
                showTime();&lt;br /&gt;
                beep(50, BEEP_START);&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 4) {&lt;br /&gt;
                mode = 6;&lt;br /&gt;
                showSetBrightness();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
            }&lt;br /&gt;
            else if (menuPos == 5) {&lt;br /&gt;
                mode = 8;&lt;br /&gt;
                showSetVolume();&lt;br /&gt;
                lastEncTime = millis();&lt;br /&gt;
                easterEggStep = 0; // Сброс пасхалки при входе&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            resetAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 1) {&lt;br /&gt;
        if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(0);&lt;br /&gt;
        }&lt;br /&gt;
        else if (digitalRead(BTN_P2) == LOW &amp;amp;&amp;amp; !gameStarted) {&lt;br /&gt;
            delay(DEBOUNCE_DELAY);&lt;br /&gt;
            startGame(1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded()) {&lt;br /&gt;
            beep(100, BEEP_LONG_PRESS);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            menuPos = 0;&lt;br /&gt;
            showTime();&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 2) {&lt;br /&gt;
        if (encoder.isClick() &amp;amp;&amp;amp; playing) {&lt;br /&gt;
            if (!paused) {&lt;br /&gt;
                paused = true;&lt;br /&gt;
                pauseStartTime = millis();&lt;br /&gt;
                beep(100, BEEP_PAUSE);&lt;br /&gt;
                display1.setSegments(PUSE, 4, 0);&lt;br /&gt;
                display2.setSegments(PUSE, 4, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                paused = false;&lt;br /&gt;
                unsigned long pauseDuration = millis() - pauseStartTime;&lt;br /&gt;
                lastTickTime += pauseDuration;&lt;br /&gt;
                beep(100, BEEP_UNPAUSE);&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
            delay(200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (encoder.isHolded() &amp;amp;&amp;amp; !showStats) {&lt;br /&gt;
            showStats = true;&lt;br /&gt;
            statsShowTime = millis();&lt;br /&gt;
            display1.showNumberDec(movesP1);&lt;br /&gt;
            display2.showNumberDec(movesP2);&lt;br /&gt;
            beep(50, BEEP_CLICK);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (showStats &amp;amp;&amp;amp; millis() - statsShowTime &amp;gt; 2000) {&lt;br /&gt;
            showStats = false;&lt;br /&gt;
            showTime();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        handleGame();&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 3) {&lt;br /&gt;
        handleEncoderValueDynamic(setMinutes, 1, 999, showSetTime);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 4) {&lt;br /&gt;
        handleEncoderValueDynamic(setAdd, 0, 60, showSetAdd);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            addTime = setAdd;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 5) {&lt;br /&gt;
        handleEncoderValue(setMode, 0, 2, showSetMode);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            gameMode = setMode;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 6) {&lt;br /&gt;
        handleEncoderValue(setBrightness, 0, 7, showSetBrightness);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            display1.setBrightness(setBrightness);&lt;br /&gt;
            display2.setBrightness(setBrightness);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 7) {&lt;br /&gt;
        handleEncoderValueDynamic(setDelay, 1, 60, showSetDelay);&lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            delaySec = setDelay;&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else if (mode == 8) {&lt;br /&gt;
        int oldVolume = setVolume;&lt;br /&gt;
        handleEncoderValueFast(setVolume, 0, 100, showSetVolume, 10);&lt;br /&gt;
        &lt;br /&gt;
        // Проверяем изменение громкости для пасхалки&lt;br /&gt;
        if (oldVolume != setVolume) {&lt;br /&gt;
            checkVolumeEasterEgg();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (encoder.isClick()) {&lt;br /&gt;
            beep(30, BEEP_CLICK);&lt;br /&gt;
            mode = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            easterEggStep = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delay(5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ПАСХАЛКА ====================&lt;br /&gt;
void checkVolumeEasterEgg() {&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
    &lt;br /&gt;
    // Если прошло больше 3 секунд, сбрасываем&lt;br /&gt;
    if (now - lastEasterEggTime &amp;gt; 3000) {&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    lastEasterEggTime = now;&lt;br /&gt;
    &lt;br /&gt;
    // Проверяем последовательность: 0 -&amp;gt; 100 -&amp;gt; 0 -&amp;gt; 100&lt;br /&gt;
    if (easterEggStep == 0 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 1 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        easterEggStep = 2;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 2 &amp;amp;&amp;amp; setVolume == 0) {&lt;br /&gt;
        easterEggStep = 3;&lt;br /&gt;
    }&lt;br /&gt;
    else if (easterEggStep == 3 &amp;amp;&amp;amp; setVolume == 100) {&lt;br /&gt;
        // Пасхалка активирована!&lt;br /&gt;
        easterEggStep = 0;&lt;br /&gt;
        &lt;br /&gt;
        // Показываем ELIS&lt;br /&gt;
        display1.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        display2.setSegments(ELISE_SEG, 4, 0);&lt;br /&gt;
        &lt;br /&gt;
        // Играем мелодию&lt;br /&gt;
        playFurElise();&lt;br /&gt;
        &lt;br /&gt;
        // Возвращаем отображение&lt;br /&gt;
        showSetVolume();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playFurElise() {&lt;br /&gt;
    // Частоты нот&lt;br /&gt;
    const int E5 = 659;&lt;br /&gt;
    const int DS5 = 622;&lt;br /&gt;
    const int E4 = 330;&lt;br /&gt;
    const int B4 = 494;&lt;br /&gt;
    const int D5 = 587;&lt;br /&gt;
    const int C5 = 523;&lt;br /&gt;
    const int A4 = 440;&lt;br /&gt;
    const int REST = 0;&lt;br /&gt;
    &lt;br /&gt;
    // Упрощенная мелодия &amp;quot;К Элизе&amp;quot;&lt;br /&gt;
    int melody[] = {&lt;br /&gt;
        E5, DS5, E5, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, DS5, E5, B4, D5, C5, A4,&lt;br /&gt;
        REST, C5, E4, A4, B4, REST, E4, C5, B4, A4&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int durations[] = {&lt;br /&gt;
        150, 150, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 150, 150, 150, 300,&lt;br /&gt;
        50, 150, 150, 150, 300, 50, 150, 150, 150, 300&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    int notesCount = sizeof(melody) / sizeof(melody[0]);&lt;br /&gt;
    &lt;br /&gt;
    for (int i = 0; i &amp;lt; notesCount; i++) {&lt;br /&gt;
        if (melody[i] != REST) {&lt;br /&gt;
            // Используем громкость, но не меньше 20%&lt;br /&gt;
            int volumePercent = (setVolume &amp;gt; 20) ? setVolume : 50;&lt;br /&gt;
            int adjustedFreq = map(volumePercent, 0, 100, 500, melody[i]);&lt;br /&gt;
            tone(BUZZER, adjustedFreq, durations[i] * 0.9);&lt;br /&gt;
        }&lt;br /&gt;
        delay(durations[i]);&lt;br /&gt;
        noTone(BUZZER);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    delay(300);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОБРАБОТКА ЭНКОДЕРА ====================&lt;br /&gt;
void handleEncoderMenu() {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos++;&lt;br /&gt;
            if (menuPos &amp;gt; 5) menuPos = 0;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            menuPos--;&lt;br /&gt;
            if (menuPos &amp;lt; 0) menuPos = 5;&lt;br /&gt;
            showMenu();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValue(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value++;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value--;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueDynamic(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)()) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) { encFastCounter++; } &lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int step = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? 5 : 1;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void handleEncoderValueFast(int &amp;amp;value, int minVal, int maxVal, void (*updateFunc)(), int step) {&lt;br /&gt;
    if (encoder.isRight()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == 1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = 1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = 1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value += step;&lt;br /&gt;
            if (value &amp;gt; maxVal) value = maxVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (encoder.isLeft()) {&lt;br /&gt;
        unsigned long now = millis();&lt;br /&gt;
        if (now - lastEncTurnTime &amp;lt; 150) {&lt;br /&gt;
            if (lastEncDirection == -1) encFastCounter++;&lt;br /&gt;
            else { encFastCounter = 1; lastEncDirection = -1; }&lt;br /&gt;
        } else { encFastCounter = 0; lastEncDirection = -1; }&lt;br /&gt;
        lastEncTurnTime = now;&lt;br /&gt;
        int currentDelay = (encFastCounter &amp;gt; ENC_FAST_THRESHOLD) ? ENC_DELAY_FAST : ENC_DELAY_NORMAL;&lt;br /&gt;
        if (now - lastEncTime &amp;gt; currentDelay) {&lt;br /&gt;
            beep(5, BEEP_ENC);&lt;br /&gt;
            value -= step;&lt;br /&gt;
            if (value &amp;lt; minVal) value = minVal;&lt;br /&gt;
            updateFunc();&lt;br /&gt;
            beep(20, BEEP_CLICK);&lt;br /&gt;
            lastEncTime = now;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ЛОГИКА ИГРЫ ====================&lt;br /&gt;
void handleGame() {&lt;br /&gt;
    if (!playing) return;&lt;br /&gt;
    unsigned long now = millis();&lt;br /&gt;
&lt;br /&gt;
    if (!paused) {&lt;br /&gt;
        bool p1Pressed = digitalRead(BTN_P1) == LOW;&lt;br /&gt;
        if (p1Pressed &amp;amp;&amp;amp; !lastP1) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 0) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP1 -= secondsElapsed;&lt;br /&gt;
                            if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP1 += addTime;&lt;br /&gt;
                movesP1++;&lt;br /&gt;
                turn = 1;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP1 = p1Pressed;&lt;br /&gt;
&lt;br /&gt;
        bool p2Pressed = digitalRead(BTN_P2) == LOW;&lt;br /&gt;
        if (p2Pressed &amp;amp;&amp;amp; !lastP2) {&lt;br /&gt;
            beep(20, BEEP_BUTTON);&lt;br /&gt;
            if (turn == 1) {&lt;br /&gt;
                long elapsed = now - lastTickTime;&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 2) {&lt;br /&gt;
                    if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                        long extraTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                        int secondsElapsed = extraTime / 1000;&lt;br /&gt;
                        if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                            timeP2 -= secondsElapsed;&lt;br /&gt;
                            if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                            lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime = now;&lt;br /&gt;
                } else {&lt;br /&gt;
                    int secondsElapsed = elapsed / 1000;&lt;br /&gt;
                    if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                        lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                if (gameMode == 1) timeP2 += addTime;&lt;br /&gt;
                movesP2++;&lt;br /&gt;
                turn = 0;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        lastP2 = p2Pressed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (gameStarted &amp;amp;&amp;amp; !paused) {&lt;br /&gt;
        long elapsed = millis() - lastTickTime;&lt;br /&gt;
        &lt;br /&gt;
        if (gameMode == 2) {&lt;br /&gt;
            if (elapsed &amp;gt; delaySec * 1000L) {&lt;br /&gt;
                long activeTime = elapsed - (delaySec * 1000L);&lt;br /&gt;
                int secondsElapsed = activeTime / 1000;&lt;br /&gt;
                if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                    if (turn == 0) {&lt;br /&gt;
                        timeP1 -= secondsElapsed;&lt;br /&gt;
                        if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeP2 -= secondsElapsed;&lt;br /&gt;
                        if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                    }&lt;br /&gt;
                    lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                    showTime();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            int secondsElapsed = elapsed / 1000;&lt;br /&gt;
            if (secondsElapsed &amp;gt; 0) {&lt;br /&gt;
                if (turn == 0) {&lt;br /&gt;
                    timeP1 -= secondsElapsed;&lt;br /&gt;
                    if (timeP1 &amp;lt;= 0) { gameOver(1); return; }&lt;br /&gt;
                } else {&lt;br /&gt;
                    timeP2 -= secondsElapsed;&lt;br /&gt;
                    if (timeP2 &amp;lt;= 0) { gameOver(2); return; }&lt;br /&gt;
                }&lt;br /&gt;
                lastTickTime += secondsElapsed * 1000;&lt;br /&gt;
                showTime();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (digitalRead(BTN_P1) == LOW &amp;amp;&amp;amp; digitalRead(BTN_P2) == LOW) {&lt;br /&gt;
        if (bothStart == 0) bothStart = millis();&lt;br /&gt;
        if (millis() - bothStart &amp;gt; LONG_PRESS_TIME) {&lt;br /&gt;
            resetAll();&lt;br /&gt;
            bothStart = 0;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        bothStart = 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== СТАРТ ====================&lt;br /&gt;
void startGame(int firstPlayer) {&lt;br /&gt;
    mode = 2;&lt;br /&gt;
    playing = true;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = true;&lt;br /&gt;
    bothStart = 0;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
&lt;br /&gt;
    if (firstPlayer == 0) turn = 0;&lt;br /&gt;
    else turn = 1;&lt;br /&gt;
&lt;br /&gt;
    lastTickTime = millis();&lt;br /&gt;
    showTime();&lt;br /&gt;
    beep(50, BEEP_START);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ==================== ОТОБРАЖЕНИЕ ====================&lt;br /&gt;
void showTime() {&lt;br /&gt;
    bool p1Hours = (timeP1 &amp;gt;= 5940);&lt;br /&gt;
    bool p2Hours = (timeP2 &amp;gt;= 5940);&lt;br /&gt;
    &lt;br /&gt;
    if (p1Hours) {&lt;br /&gt;
        int hours = timeP1 / 3600;&lt;br /&gt;
        int minutes = (timeP1 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display1.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP1 / 60;&lt;br /&gt;
        int seconds = timeP1 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display1.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (p2Hours) {&lt;br /&gt;
        int hours = timeP2 / 3600;&lt;br /&gt;
        int minutes = (timeP2 % 3600) / 60;&lt;br /&gt;
        if (hours &amp;gt; 99) hours = 99;&lt;br /&gt;
        if (minutes &amp;gt; 59) minutes = 59;&lt;br /&gt;
        display2.showNumberDecEx(hours * 100 + minutes, 0b01000000, true, 4, 0);&lt;br /&gt;
    } else {&lt;br /&gt;
        int minutes = timeP2 / 60;&lt;br /&gt;
        int seconds = timeP2 % 60;&lt;br /&gt;
        if (minutes &amp;gt; 99) minutes = 99;&lt;br /&gt;
        if (seconds &amp;gt; 59) seconds = 59;&lt;br /&gt;
        display2.showNumberDecEx(minutes * 100 + seconds, 0b01000000, true, 4, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showMenu() {&lt;br /&gt;
    display1.showNumberDec(menuPos + 1);&lt;br /&gt;
    display2.showNumberDec(menuPos + 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetTime() {&lt;br /&gt;
    static int lastMinutes = -1;&lt;br /&gt;
    if (setMinutes &amp;lt; 100) {&lt;br /&gt;
        if (lastMinutes &amp;gt;= 100 &amp;amp;&amp;amp; setMinutes &amp;lt; 100) display1.clear();&lt;br /&gt;
        display1.showNumberDecEx(setMinutes, 0b00000000, true, 2, 2);&lt;br /&gt;
    } else {&lt;br /&gt;
        if (lastMinutes &amp;lt; 100 &amp;amp;&amp;amp; setMinutes &amp;gt;= 100) display1.clear();&lt;br /&gt;
        display1.showNumberDec(setMinutes);&lt;br /&gt;
    }&lt;br /&gt;
    lastMinutes = setMinutes;&lt;br /&gt;
    display2.showNumberDec(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetAdd() {&lt;br /&gt;
    display1.showNumberDecEx(setAdd, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_ADD, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetDelay() {&lt;br /&gt;
    display1.showNumberDecEx(setDelay, 0b00000000, true, 2, 2);&lt;br /&gt;
    display2.setSegments(MODE_DLY, 4, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetMode() {&lt;br /&gt;
    if (setMode == 0) { display1.setSegments(MODE_CLS, 4, 0); display2.showNumberDec(1); }&lt;br /&gt;
    else if (setMode == 1) { display1.setSegments(MODE_ADD, 4, 0); display2.showNumberDec(2); }&lt;br /&gt;
    else if (setMode == 2) { display1.setSegments(MODE_DLY, 4, 0); display2.showNumberDec(3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetBrightness() {&lt;br /&gt;
    display1.setSegments(MODE_bRI, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setBrightness);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void showSetVolume() {&lt;br /&gt;
    display1.setSegments(MODE_Vol, 4, 0);&lt;br /&gt;
    display2.showNumberDec(setVolume / 10);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void gameOver(int loser) {&lt;br /&gt;
    playing = false;&lt;br /&gt;
    beep(1000, BEEP_GAME_OVER);&lt;br /&gt;
    for (int i = 0; i &amp;lt; 6; i++) {&lt;br /&gt;
        if (loser == 1) display1.clear();&lt;br /&gt;
        else display2.clear();&lt;br /&gt;
        delay(200);&lt;br /&gt;
        showTime();&lt;br /&gt;
        delay(200);&lt;br /&gt;
    }&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resetAll() {&lt;br /&gt;
    timeP1 = (long)setMinutes * 60;&lt;br /&gt;
    timeP2 = timeP1;&lt;br /&gt;
    addTime = setAdd;&lt;br /&gt;
    delaySec = setDelay;&lt;br /&gt;
    gameMode = setMode;&lt;br /&gt;
    movesP1 = 0;&lt;br /&gt;
    movesP2 = 0;&lt;br /&gt;
    mode = 0;&lt;br /&gt;
    playing = false;&lt;br /&gt;
    paused = false;&lt;br /&gt;
    gameStarted = false;&lt;br /&gt;
    menuPos = 0;&lt;br /&gt;
    showTime();&lt;br /&gt;
    showMenu();&lt;br /&gt;
    beep(100, BEEP_RESET);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void beep(int duration, int frequency) {&lt;br /&gt;
    if (setVolume == 0) return;&lt;br /&gt;
    int adjustedFreq = map(setVolume, 0, 100, 500, frequency);&lt;br /&gt;
    if (adjustedFreq &amp;lt; 500) adjustedFreq = 500;&lt;br /&gt;
    if (adjustedFreq &amp;gt; frequency) adjustedFreq = frequency;&lt;br /&gt;
    tone(BUZZER, adjustedFreq, duration);&lt;br /&gt;
    delay(duration);&lt;br /&gt;
    noTone(BUZZER);&lt;br /&gt;
}&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya&amp;diff=42</id>
		<title>Участник:Maya</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya&amp;diff=42"/>
		<updated>2026-04-30T01:07:14Z</updated>

		<summary type="html">&lt;p&gt;Maya: /* Тельпухова Майя Максимовна */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Тельпухова Майя Максимовна ==&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=37</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=37"/>
		<updated>2026-04-28T00:58:18Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
Шахматы — это не только стратегия и логика, но и строгий регламент. В соревнованиях любого уровня действует контроль времени: у каждого игрока есть лимит на партию, и превысить его нельзя. Для этого существуют специальные шахматные часы. Они фиксируют ходы, переключают время между соперниками и подают сигнал об окончании партии.&lt;br /&gt;
&lt;br /&gt;
Готовые фабричные часы с полным набором функций стоят относительно дорого, а доступные по цене модели часто оказываются неудобными или ненадёжными. В данном проекте ставится задача разработать собственный вариант шахматных часов — на доступной элементной базе, с понятной схемой и возможностью повторения.&lt;br /&gt;
&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=36</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=36"/>
		<updated>2026-04-28T00:57:29Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Общие сведения ==&lt;br /&gt;
История семьи является микромоделью истории страны. Анализ конкретных, документально подтверждённых судеб позволяет выйти за рамки абстрактных оценок советской эпохи и увидеть её противоречивую сущность на живом материале: с одной стороны — механизм политических репрессий, с другой — мобилизационный потенциал государства в экстремальных условиях. В современной исторической науке сохраняется острый интерес к изучению повседневности и личного опыта людей в тоталитарных и авторитарных системах.&lt;br /&gt;
== Краткая историческая справка ==&lt;br /&gt;
В XIX веке шахматные партии могли длиться бесконечно, и первые попытки контроля времени были кустарными — использовали песочные или карманные часы, которые судья запускал вручную. В 1883 году появились механические часы с двумя циферблатами и перекидным рычагом, а в 1950-х к ним добавили «падающий флажок». Однако такие часы были сложны в производстве и практически не подлежали ремонту — сломавшееся устройство проще выбрасывали. В конце 1980-х фирма DGT выпустила первые цифровые часы с высокой точностью и поддержкой инкремента, но их цена (от 12 000 рублей) сделала их малодоступными для массового пользователя, а дешёвые китайские аналоги (2 000–3 000 рублей) оказались неремонтопригодными.&lt;br /&gt;
&lt;br /&gt;
Наш проект продолжает эту историю, но делает шаг в сторону доступности и открытости. Мы используем современную элементную базу — микроконтроллер, LED-дисплей, энкодер и две кнопки — и собираем часы, которые по функционалу приближаются к профессиональным, а по цене и ремонтопригодности — к самодельным. В отличие от заводских аналогов, наше устройство можно разобрать, заменить любую деталь и починить своими руками.&lt;br /&gt;
&lt;br /&gt;
== Основные требования к современным электронным шахматным часам==&lt;br /&gt;
&lt;br /&gt;
Точность хода — без неё невозможно объективно определить победителя при истечении времени.&lt;br /&gt;
Эргономика — кнопка должна давать чёткий тактильный отклик, чтобы игрок чувствовал переключение хода даже не глядя на часы.&lt;br /&gt;
Видимость — экран должен быть читаем под любым углом и не бликовать, чтобы игрок мгновенно считывал время боковым зрением.&lt;br /&gt;
Интуитивная настройка — интерфейс должен быть понятен без инструкции, чтобы судья мог быстро восстановить время при сбое.&lt;br /&gt;
Устойчивость на столе — часы должны иметь достаточный вес и нескользящее основание, чтобы не сдвигаться при ударах.&lt;br /&gt;
Ремонтопригодность — конструкция должна позволять замену любой детали (кнопки, дисплея, платы) без специального инструмента.&lt;br /&gt;
Надёжность — программа должна корректно обрабатывать дребезг контактов и исключать зависания от случайных нажатий.&lt;br /&gt;
Автономность — часы должны долго работать от доступных источников (AA/AAA или USB), чтобы не отвлекать игроков частой заменой батарей.&lt;br /&gt;
Компактность — часы должны быть удобны для перевозки в сумке с шахматным набором и не иметь хрупких выступающих элементов.&lt;br /&gt;
Доступная цена — стоимость не должна превышать 3000 рублей, чтобы часы были доступны массовому пользователю.&lt;br /&gt;
Минимализм в управлении — управление должно быть сведено к минимуму (старт, стоп, сброс), чтобы часы мог использовать любой человек без инструкции.&lt;br /&gt;
&lt;br /&gt;
== Технические характеристики==&lt;br /&gt;
&lt;br /&gt;
Микроконтроллер Arduino Nano&lt;br /&gt;
Дисплеи 2× TM1637 (4 разряда)&lt;br /&gt;
Управление Энкодер&lt;br /&gt;
Кнопки игроков 2 кнопки &lt;br /&gt;
Звук Пьезоизлучатель (зуммер)&lt;br /&gt;
Питание от встроенного аккумулятора&lt;br /&gt;
Потребление от 50 мА до 250 мА (зависит от яркости)&lt;br /&gt;
Время непрерывной работы: около 18 часов&lt;br /&gt;
&lt;br /&gt;
Примечания&lt;br /&gt;
&lt;br /&gt;
· При быстром вращении энкодера скорость изменения значений автоматически увеличивается&lt;br /&gt;
· Время сохраняется только во время работы устройства, при отключении питания сбрасывается&lt;br /&gt;
· Максимальное время партии: 999 минут (~16.5 часов)&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=35</id>
		<title>Шахматные часы самодельные2</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A8%D0%B0%D1%85%D0%BC%D0%B0%D1%82%D0%BD%D1%8B%D0%B5_%D1%87%D0%B0%D1%81%D1%8B_%D1%81%D0%B0%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B52&amp;diff=35"/>
		<updated>2026-04-27T17:11:58Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Шахматные часы - что это такое  вввыфвфвфывыф&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Шахматные часы - преамбула, назначение.&lt;br /&gt;
Внешний вид ...&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
== Актуальность ==&lt;br /&gt;
&lt;br /&gt;
== Правила игры в шахматы на время ==&lt;br /&gt;
&lt;br /&gt;
== Функуциональная схема ==&lt;br /&gt;
&lt;br /&gt;
== Электрическая схема ==&lt;br /&gt;
&lt;br /&gt;
== Топология печатной платы ==&lt;br /&gt;
&lt;br /&gt;
== Код программы ==&lt;br /&gt;
&lt;br /&gt;
== Примечание ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Группа ==&lt;br /&gt;
* Тельпухова Майя Максимовна &lt;br /&gt;
* вввв&lt;br /&gt;
&lt;br /&gt;
[[Категория:работы студентов]]&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya&amp;diff=20</id>
		<title>Участник:Maya</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya&amp;diff=20"/>
		<updated>2026-04-21T05:07:44Z</updated>

		<summary type="html">&lt;p&gt;Maya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Тельпухова Майя Максимовна ==&lt;br /&gt;
авыаываываыва&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
	<entry>
		<id>http://wikiprometheus.ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya&amp;diff=19</id>
		<title>Участник:Maya</title>
		<link rel="alternate" type="text/html" href="http://wikiprometheus.ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Maya&amp;diff=19"/>
		<updated>2026-04-21T05:07:08Z</updated>

		<summary type="html">&lt;p&gt;Maya: Новая страница: «=== Тельпухова Майя Максимовна === авыаываываыва»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Тельпухова Майя Максимовна ===&lt;br /&gt;
авыаываываыва&lt;/div&gt;</summary>
		<author><name>Maya</name></author>
	</entry>
</feed>