int digit[4] = {13,12,11,10}; // Пины для разрядов индикатора
int segment[7] = {2,3,4,5,6,7,8}; // Пины для сегментов (A-G)
int colonPin = 1; // Пин для точки (двоеточия)
int buttonPin = 9; // Пин для кнопки
// Коды цифр для семисегментного индикатора (общий катод)
byte digitPattern[10] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
unsigned long previousMillis = 0;
unsigned long displayMillis = 0;
unsigned long colonMillis = 0;
const long interval = 1000; // 1 секунда
const long displayInterval = 5; // 5 мс для обновления дисплея
const long colonInterval = 500; // 500 мс для мигания точки
int totalSeconds = 0; // Общее время в секундах
bool isRunning = false;
bool isReset = true;
bool colonState = false;
// Переменные для обработки кнопки
int buttonState = HIGH;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
bool buttonPressed = false;
void setup() {
// Настройка пинов разрядов как выходов
for (int i = 0; i < 4; i++) {
pinMode(digit[i], OUTPUT);
digitalWrite(digit[i], HIGH); // Выключаем все разряды
}
// Настройка пинов сегментов как выходов
for (int i = 0; i < 7; i++) {
pinMode(segment[i], OUTPUT);
digitalWrite(segment[i], LOW);
}
pinMode(colonPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
// Начальное отображение "00:00"
digitalWrite(colonPin, LOW); // Точка выключена
}
void loop() {
unsigned long currentMillis = millis();
// Улучшенная обработка кнопки
int reading = digitalRead(buttonPin);
// Обнаружение изменения состояния кнопки
if (reading != lastButtonState) {
lastDebounceTime = currentMillis;
}
// Проверка, прошло ли достаточно времени для устранения дребезга
if ((currentMillis - lastDebounceTime) > debounceDelay) {
// Если состояние кнопки изменилось
if (reading != buttonState) {
buttonState = reading;
// Обрабатываем только нажатие (LOW для INPUT_PULLUP)
if (buttonState == LOW && !buttonPressed) {
buttonPressed = true;
handleButtonPress();
}
}
}
// Сбрасываем флаг нажатия, когда кнопка отпущена
if (buttonState == HIGH) {
buttonPressed = false;
}
lastButtonState = reading;
// Логика секундомера
if (isRunning) {
// Обновление секунд
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
totalSeconds++;
// Останавливаемся при достижении 60, но не сбрасываем
if (totalSeconds >= 60) {
isRunning = false; // Автоматическая остановка при достижении 60
}
}
// Мигание точки каждые 500 мс (только когда время > 0)
if (totalSeconds > 0 && currentMillis - colonMillis >= colonInterval) {
colonMillis = currentMillis;
colonState = !colonState;
digitalWrite(colonPin, colonState ? LOW : HIGH);
}
}
// Постоянное обновление дисплея
if (currentMillis - displayMillis >= displayInterval) {
displayMillis = currentMillis;
displayTime(totalSeconds);
}
}
void handleButtonPress() {
// Обработка нажатия кнопки
if (!isRunning && isReset) {
// Запуск секундомера
isRunning = true;
isReset = false;
previousMillis = millis();
colonMillis = millis();
colonState = true; // Начинаем с включенной точки
digitalWrite(colonPin, HIGH);
} else if (isRunning) {
// Остановка секундомера
isRunning = false;
// Точки остаются в текущем состоянии при остановке
} else {
// Сброс секундомера
totalSeconds = 0;
isReset = true;
colonState = false; // Выключаем точку при сбросе
digitalWrite(colonPin, LOW);
}
}
void displayTime(int seconds) {
int minutes = seconds / 60; // Получаем минуты
int secs = seconds % 60; // Получаем секунды
int digits[4] = {0};
// Разбиваем время на цифры для 4 разрядов: MM:SS
// Если достигли 60 секунд, показываем "60"
if (seconds >= 60) {
digits[0] = 0; // Десятки минут
digits[1] = 0; // Единицы минут (показываем 6)
digits[2] = 6; // Десятки секунд
digits[3] = 0; // Единицы секунд
} else {
digits[0] = 0; // Десятки минут
digits[1] = 0; // Единицы минут
digits[2] = (secs / 10) % 10; // Десятки секунд
digits[3] = secs % 10; // Единицы секунд
}
// Отображаем время с динамической индикацией
for (int digitPos = 0; digitPos < 4; digitPos++) {
// Включаем только текущий разряд
for (int i = 0; i < 4; i++) {
digitalWrite(digit[i], HIGH);
}
digitalWrite(digit[digitPos], LOW);
// Включаем сегменты для текущей цифры
displayDigit(digits[digitPos]);
// Короткая задержка для динамической индикации
delay(1);
// Выключаем все сегменты перед переключением разряда
for (int i = 0; i < 7; i++) {
digitalWrite(segment[i], LOW);
}
}
}
void displayDigit(int num) {
if (num < 0 || num > 9) return;
byte pattern = digitPattern[num];
// Включаем соответствующие сегменты
for (int i = 0; i < 7; i++) {
digitalWrite(segment[i], bitRead(pattern, i));
}
}