Настраиваемый обратный таймер на Arduino и 4-разрядном 7-сегментном индикаторе
Компоненты и материалы
| Arduino Mega 2560 (любой Arduino подойдёт) | 1 | |
| 4-разрядный 7-сегментный индикатор (общий анод/катод) | 1 | |
| Тактильные кнопки | 4 | Старт/Стоп, +, -, Сброс |
| Пьезоизлучатель (зуммер) | 1 | |
| Перемычки | ~21 | |
| Бредоборд полноразмерный | 1 |
О проекте
Много проектов таймеров, но мало — удобных автономных с настройкой кнопками без перепрошивки. Этот проект заполняет пробел: независимый обратный отсчёт 0–9999 сек, настройка кнопками, звуковой сигнал в конце.
Код содержит универсальную функцию PrintNumber(n, time) — выводит 4-значное число на динамический индикатор заданное время. Удобно для других проектов.
Алгоритм работы
- При включении — режим настройки: кнопки +/- меняют время (ускорение при удержании >30 циклов), Старт — запуск отсчёта.
- Во время отсчёта: Стоп — пауза/возврат в настройку.
- По достижении 0 — звуковой сигнал 1 сек, ожидание нажатия Стоп для нового цикла.
- Динамическая индикация: по одному разряду за 5 мс, цикл ~20 мс.
Распиновка (пример)
- Сегменты A–G: D2–D8 (A0 для E)
- Разряды (PWM): D6, D9, D10, D11 (слева направо)
- Кнопки: D13, D12, D16, D17 (с INPUT_PULLUP)
- Зуммер: D15
Код (C/C++)
#include <math.h>
int digit_pin[] = {6, 9, 10, 11}; // PWM-пины разрядов
int speakerPin = 15;
#define DIGIT_ON LOW
#define DIGIT_OFF HIGH
int segA = 2, segB = 3, segC = 4, segD = 5, segE = A0, segF = 7, segG = 8;
int btnStart = 13, btnStop = 12, btnMinus = 16, btnPlus = 17;
int countdown_time = 60; // начальное значение по умолчанию
struct Digits { int d[4]; };
void setup() {
pinMode(segA, OUTPUT); pinMode(segB, OUTPUT); pinMode(segC, OUTPUT);
pinMode(segD, OUTPUT); pinMode(segE, OUTPUT); pinMode(segF, OUTPUT); pinMode(segG, OUTPUT);
for (int i = 0; i < 4; i++) pinMode(digit_pin[i], OUTPUT);
pinMode(speakerPin, OUTPUT);
pinMode(btnStart, INPUT_PULLUP);
pinMode(btnStop, INPUT_PULLUP);
pinMode(btnMinus, INPUT_PULLUP);
pinMode(btnPlus, INPUT_PULLUP);
}
void playTone(int tone, int duration) {
for (long k = 0; k < duration * 1000L; k += tone * 2) {
digitalWrite(speakerPin, HIGH); delayMicroseconds(tone);
digitalWrite(speakerPin, LOW); delayMicroseconds(tone);
}
}
void lightNumber(int n) {
#define SEG_ON HIGH
#define SEG_OFF LOW
switch (n) {
case 0: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_ON); digitalWrite(segF,SEG_ON); digitalWrite(segG,SEG_OFF); break;
case 1: digitalWrite(segA,SEG_OFF); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_OFF); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_OFF); digitalWrite(segG,SEG_OFF); break;
case 2: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_OFF); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_ON); digitalWrite(segF,SEG_OFF); digitalWrite(segG,SEG_ON); break;
case 3: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_OFF); digitalWrite(segG,SEG_ON); break;
case 4: digitalWrite(segA,SEG_OFF); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_OFF); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_ON); digitalWrite(segG,SEG_ON); break;
case 5: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_OFF); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_ON); digitalWrite(segG,SEG_ON); break;
case 6: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_OFF); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_ON); digitalWrite(segF,SEG_ON); digitalWrite(segG,SEG_ON); break;
case 7: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_OFF); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_OFF); digitalWrite(segG,SEG_OFF); break;
case 8: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_ON); digitalWrite(segF,SEG_ON); digitalWrite(segG,SEG_ON); break;
case 9: digitalWrite(segA,SEG_ON); digitalWrite(segB,SEG_ON); digitalWrite(segC,SEG_ON); digitalWrite(segD,SEG_ON); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_ON); digitalWrite(segG,SEG_ON); break;
case 10: digitalWrite(segA,SEG_OFF); digitalWrite(segB,SEG_OFF); digitalWrite(segC,SEG_OFF); digitalWrite(segD,SEG_OFF); digitalWrite(segE,SEG_OFF); digitalWrite(segF,SEG_OFF); digitalWrite(segG,SEG_OFF); break;
}
}
void switchDigit(int d) {
for (int i = 0; i < 4; i++)
digitalWrite(digit_pin[i], (i == d) ? DIGIT_ON : DIGIT_OFF);
}
Digits intToDigits(int n) {
Digits dig; int zeros = 0, d;
for (int i = 0; i < 4; i++) {
d = n / pow(10, 3 - i);
zeros += d;
n -= d * pow(10, 3 - i);
dig.d[i] = (zeros != 0 || i == 3) ? d : 10; // 10 = пусто
}
return dig;
}
void printNumber(int n, int timeMs) {
Digits dig = intToDigits(n);
for (int i = 0; i <= timeMs / 20; i++) {
if (digitalRead(btnStop) == LOW) return; // прервать
for (int j = 0; j < 4; j++) {
switchDigit(j);
lightNumber(dig.d[j]);
delay(5);
}
}
}
bool countdown(int n, int tickMs) {
for (int q = n; q > 0; q--) {
printNumber(q, tickMs);
if (digitalRead(btnStop) == LOW) return false;
}
printNumber(0, 0);
playTone(1519, 1000);
return true;
}
void adjustTime() {
int pressedMinus = 0, pressedPlus = 0;
Digits dig = intToDigits(countdown_time);
while (digitalRead(btnStart) == HIGH) { // ждём Старт
for (int j = 0; j < 4; j++) { switchDigit(j); lightNumber(dig.d[j]); delay(5); }
if (digitalRead(btnMinus) == LOW) {
if (pressedMinus == 0 || pressedMinus > 30) { if (countdown_time > 0) countdown_time--; dig = intToDigits(countdown_time); }
pressedMinus++;
} else if (digitalRead(btnPlus) == LOW) {
if (pressedPlus == 0 || pressedPlus > 30) { if (countdown_time < 9999) countdown_time++; dig = intToDigits(countdown_time); }
pressedPlus++;
}
if (digitalRead(btnMinus) == HIGH) pressedMinus = 0;
if (digitalRead(btnPlus) == HIGH) pressedPlus = 0;
}
}
void loop() {
adjustTime();
while (!countdown(countdown_time, 962)) adjustTime();
while (digitalRead(btnStop) == HIGH) {} // ждём Стоп для нового цикла
}
Схема подключения
Схема (PNG) в разделе Schematics: индикатор, кнопки, зуммер, Arduino.
Производственный процесс
- Жидкокристаллические дисплеи (LCD): технология, производство и перспективы
- Освоение перегрузки методов в C#: концепции, примеры и лучшие практики
- Primal Display: создайте монитор температуры на Raspberry Pi с LCD
- Установка дисплея Kuman 3.5″ TFT на RetroPie — Пошаговое руководство
- Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение
- Создание классической игры Pong на Arduino UNO с OLED-дисплеем: пошаговый урок
- Watchdog Timer на Arduino: как предотвратить зависание микроконтроллера
- Набор «Инопланетный слот-машин» на ATmega328P — DIY игровой автомат с NeoPixel и I2C дисплеем
- Интерактивный HMI-проект на Nextion с Arduino Mega и датчиками
- Регулируемые амортизаторы: повышение клиренса и производительности