#include <LiquidCrystal_I2C.h> // Підключення бібліотеки для роботи з LCD дисплеєм
#include <Wire.h> // Підключення бібліотеки для роботи з протоколом I2C
#define MAXBITS 4 // Максимальна кількість ввідних біт
bool but0 = 0, but1 = 0, but0Flag = 0, but1Flag = 0, standbyFlag = 0; // Змінні та прапорці для роботи з кнопками
const int greenLED = 7, redLED = 8; // Оголошення пінів для світлодіодів
const int button0 = 9, button1 = 10; // Оголошення пінів для кнопок
int binaryInput[MAXBITS]; // Масив для зберігання введеного двійкового числа
int currentBit = 0; // Індекс поточного введеного біта
int randomNumber = 0, enteredNumber = 0; // Зміннi для зберігання згенерованого та введеного чисел
int maxRandomNumber = pow(2, MAXBITS); // Обчислення максимального числа для заданих бітів
unsigned long timer = 0,pressTimer = 0, standbyTimer; // Таймери для роботи з затримками часу (аналог delay)
LiquidCrystal_I2C disp(0x27, 16, 2); // Створення об'єкта I2C LCD дисплею, адреса 0x27, 16 символів, 2 рядки
void setup() {
disp.init(); // Ініціалізація LCD дисплею
disp.backlight(); // Увімкнення підсвітки LCD дисплею
pinMode(button0, INPUT_PULLUP); // Налаштування піну кнопки "0" як входу із внутрішнім підтягуванням до 5 вольт
pinMode(button1, INPUT_PULLUP); // Налаштування піну кнопки "1" як входу із внутрішнім підтягуванням до 5 вольт
pinMode(greenLED, OUTPUT); // Налаштування піну зеленого світлодіоду як вихід
pinMode(redLED, OUTPUT); // Налаштування піну червоного світлодіоду як вихід
resetInput(); // Початкове скидання даних для коректної роботи
}
void loop() {
timer = millis(); // Отримання часу, що пройшло від початку роботи мікроконтролера
but0 = !digitalRead(button0); // Читання стану кнопки введення нуля
but1 = !digitalRead(button1); // Читання стану кнопки введення одиниці
if (currentBit < MAXBITS) { // Перевірка, чи ввідний біт не перевищує максимального біту
if (but0 && !but0Flag) { // Якщо кнопка натиснута і прапорець "справжній"
but0Flag = !but0Flag; // Зміна прапорця для уникнення багатократного натискання
binaryInput[currentBit] = 0; // Присвоєння нуля поточному біту
currentBit++; // Перехід на наступний біт
}
else if (!but0 && but0Flag && timer - pressTimer > 100) { // Якщо ж прапорець "фальшивий" і минуло 100 мс
but0Flag = !but0Flag; // Зміна прапорця для уникнення багатократного відпускання
timer = pressTimer; // Оновлення таймера
}
if (but1 && !but1Flag ) { // Якщо кнопка натиснута і прапорець "справжній"
but1Flag = !but1Flag; // Зміна прапорця для уникнення багатократного натискання
binaryInput[currentBit] = 1; // Присвоєння одиниці поточному біту
currentBit++; // Перехід на наступний біт
}
else if (!but1 && but1Flag && timer - pressTimer > 100) { // Якщо ж прапорець "фальшивий" і минуло 100 мс
but1Flag = !but1Flag; // Зміна прапорця для уникнення багатократного відпускання
timer = pressTimer; // Оновлення таймера
}
}
disp.setCursor(0, 1); // Встановлення курсору на початок другого рядка
disp.print("Binary: "); // Виведення тексту
if (currentBit){
disp.setCursor(7 + currentBit, 1); // Переведення курсору для введення числа
disp.print(binaryInput[currentBit-1]); // Виведення ввідного числа
}
if (currentBit == MAXBITS && !standbyFlag) { // Якщо введенi всі біти
for (int i = 0; i < currentBit; i++) { // Цикл для конвертації введеного двійкового числа в десяткове
enteredNumber = (enteredNumber << 1) | binaryInput[i]; // Зсув на один біт і додавання біта з `binaryInput`
}
if (enteredNumber == randomNumber) { // Якщо введене число відповідає згенерованому
digitalWrite(greenLED, HIGH); // Вмикання зеленого світлодіоду
digitalWrite(redLED, LOW); // Вимикання червоного світлодіоду
}
else { // Якщо числа не співпадають
digitalWrite(greenLED, LOW); // Вимикання зеленого світлодіоду
digitalWrite(redLED, HIGH); // Вмикання червоного світлодіоду
}
standbyTimer = timer; // Оновлення таймера
standbyFlag = !standbyFlag; // Зміна стану прапорця
}
if (timer - standbyTimer > 750 && standbyFlag){ // Якщо минуло 750 мс і прапорець "справжній"
standbyFlag = !standbyFlag; // Зміна стану прапорця
resetInput(); // Виклик функції скидання для нового введення
standbyTimer = timer; // Оновлення таймера
}
}
void resetInput() {
currentBit = 0; // Обнулення індексу біта
enteredNumber = 0; // Обнулення обчисленго десяткового числа
for(int i = 0; i < MAXBITS; i++){ // Цикл для обнулення масиву
binaryInput[i] = 0; // Обнулення кожного біту
}
disp.clear(); // Очищування дисплею
disp.setCursor(0, 0); // Встановлення курсору на початок першого рядку
disp.print("Number: "); // Виведення тексту
randomNumber = random(0, maxRandomNumber); // Генерування нового випадкового числа
disp.print(randomNumber); // Виведення нового згенерованого числа
digitalWrite(greenLED, LOW); // Вимикання зеленого світлодіоду
digitalWrite(redLED, LOW); // Вимикання червоного світлодіоду
}
// Кінець ;)