// --- Піни підключення сегментів ---
const int pinA = 6;
const int pinB = 7;
const int pinC = 8;
const int pinD = 9;
const int pinE = 10;
const int pinF = 12;
const int pinG = 11;
const int pinDP = 13;
// --- Піни підключення розрядів (Common Cathode) ---
const int dig1 = 2;
const int dig2 = 3;
const int dig3 = 4;
const int dig4 = 5;
// --- Периферія ---
const int btnPin = 0;
const int buzzerPin = A0;
// --- Глобальні змінні для секундоміра ---
unsigned long previousTime = 0;
const unsigned long interval = 1000; // 1 секунда
int secondsCount = 0;
// --- Глобальні змінні для режимів та кнопки ---
int modeState = 0; // 0 — Номер варіанту, 1 — Секундомір
const int variantNumber = 3;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;
bool buttonPressed = false;
// ================= КРОК 1 =================
void setup() {
// Налаштування пінів сегментів
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
pinMode(pinD, OUTPUT);
pinMode(pinE, OUTPUT);
pinMode(pinF, OUTPUT);
pinMode(pinG, OUTPUT);
pinMode(pinDP, OUTPUT);
// Налаштування пінів розрядів
pinMode(dig1, OUTPUT);
pinMode(dig2, OUTPUT);
pinMode(dig3, OUTPUT);
pinMode(dig4, OUTPUT);
// Вимикаємо всі розряди (для загального катода - HIGH це вимкнено)
digitalWrite(dig1, HIGH);
digitalWrite(dig2, HIGH);
digitalWrite(dig3, HIGH);
digitalWrite(dig4, HIGH);
// Налаштування кнопки та динаміка
pinMode(btnPin, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
// Serial.begin(9600); // Закоментовано, бо кнопка на піні 0 (RX)
}
// ================= КРОК 2 =================
// Функція для встановлення станів сегментів для відображення цифр (0-9)
void setDigitSegments(int digit) {
// Спочатку вимикаємо всі сегменти (LOW)
digitalWrite(pinA, LOW); digitalWrite(pinB, LOW); digitalWrite(pinC, LOW);
digitalWrite(pinD, LOW); digitalWrite(pinE, LOW); digitalWrite(pinF, LOW); digitalWrite(pinG, LOW);
// Вмикаємо потрібні сегменти залежно від цифри
switch (digit) {
case 0:
digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH); digitalWrite(pinC, HIGH);
digitalWrite(pinD, HIGH); digitalWrite(pinE, HIGH); digitalWrite(pinF, HIGH);
break;
case 1:
digitalWrite(pinB, HIGH); digitalWrite(pinC, HIGH);
break;
case 2:
digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH); digitalWrite(pinG, HIGH);
digitalWrite(pinE, HIGH); digitalWrite(pinD, HIGH);
break;
case 3:
digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH); digitalWrite(pinG, HIGH);
digitalWrite(pinC, HIGH); digitalWrite(pinD, HIGH);
break;
case 4:
digitalWrite(pinF, HIGH); digitalWrite(pinG, HIGH); digitalWrite(pinB, HIGH);
digitalWrite(pinC, HIGH);
break;
case 5:
digitalWrite(pinA, HIGH); digitalWrite(pinF, HIGH); digitalWrite(pinG, HIGH);
digitalWrite(pinC, HIGH); digitalWrite(pinD, HIGH);
break;
case 6:
digitalWrite(pinA, HIGH); digitalWrite(pinF, HIGH); digitalWrite(pinE, HIGH);
digitalWrite(pinD, HIGH); digitalWrite(pinC, HIGH); digitalWrite(pinG, HIGH);
break;
case 7:
digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH); digitalWrite(pinC, HIGH);
break;
case 8:
digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH); digitalWrite(pinC, HIGH);
digitalWrite(pinD, HIGH); digitalWrite(pinE, HIGH); digitalWrite(pinF, HIGH);
digitalWrite(pinG, HIGH);
break;
case 9:
digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH); digitalWrite(pinC, HIGH);
digitalWrite(pinD, HIGH); digitalWrite(pinF, HIGH); digitalWrite(pinG, HIGH);
break;
}
}
// Головна функція керування дисплеєм
void updateDisplay(int number) {
// Розділяємо число на цифри
int d4 = number % 10; // Одиниці
int d3 = (number / 10) % 10; // Десятки
int d2 = (number / 100) % 10; // Сотні
int d1 = (number / 1000) % 10; // Тисячі
// Масив розрядів і цифр для зручності циклу
int digits[4] = {d1, d2, d3, d4};
int digPins[4] = {dig1, dig2, dig3, dig4};
// Динамічна індикація (мультиплексування)
for (int i = 0; i < 4; i++) {
// 1. Формуємо відповідну цифру
setDigitSegments(digits[i]);
// 2. Активуємо один розряд (LOW для загального катода)
digitalWrite(digPins[i], LOW);
// 3. Мікрозатримка (щоб око побачило світіння)
delay(5);
// 4. Деактивуємо розряд (HIGH) перед переходом до наступного
digitalWrite(digPins[i], HIGH);
}
}
// ================= КРОК 3 =================
void runStopwatch() {
unsigned long currentTime = millis();
// Неблокуюча затримка
if (currentTime - previousTime >= interval) {
previousTime = currentTime;
secondsCount++;
if (secondsCount > 9999) { // Захист від переповнення дисплея
secondsCount = 0;
}
}
}
// ================= КРОК 4 =================
void processButton() {
int reading = digitalRead(btnPin);
// Логіка антивідскоку (Debounce)
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// Якщо стан кнопки стабільний і вона натиснута (LOW)
if (reading == LOW && !buttonPressed) {
buttonPressed = true;
// Перемикаємо режим
modeState = (modeState == 0) ? 1 : 0;
// Короткий звуковий сигнал динаміком для підтвердження
tone(buzzerPin, 1500, 50);
}
// Скидаємо прапорець, коли кнопка відпущена
else if (reading == HIGH) {
buttonPressed = false;
}
}
lastButtonState = reading;
}
int main() {
// ЕК - викликаємо ініт метод для того щоб ініціалізувати таймери
init();
// ЕК - прямий виклик setup оскільки ми використовуємо мейн функцію:
setup();
while(1)
{
// 1. Миттєва реакція на кнопку
processButton();
// 2. Відлік часу в фоні
// runStopwatch();
// 3. Відображення на дисплеї
if (modeState == 0) {
updateDisplay(variantNumber);
//ЕК - для відліку заново:
secondsCount = 0;
} else {
updateDisplay(secondsCount); // Відображає секунди
//ЕК - для відліку заново.
//В принципі можна було залишити на попередньому місці,
//але оптимізація полягає в тому, що тепер метод не викликається коли не потрібно
runStopwatch();
}
}
}