#include <LiquidCrystal_I2C.h> // Подключаем библиотеку для работы с LCD1602
#include <AlashKeypadMatrix.h> // Подключаем библиотеку для работы с матричной клавиатурой
// Настройки для LCD1602
LiquidCrystal_I2C lcd(0x27, 16, 2); // Инициализируем LCD с адресом 0x27 и размером 16x2
// Настройки для клавиатуры
const byte ROWS = 4; // Количество строк клавиатуры
const byte COLS = 4; // Количество столбцов клавиатуры
char keys[ROWS][COLS] = { // Массив символов клавиатуры
{'1', '2', '3', '+'},
{'4', '5', '6', '-'},
{'7', '8', '9', '*'},
{'C', '0', '=', '/'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; // Пины для строк клавиатуры
byte colPins[COLS] = {5, 4, 3, 2}; // Пины для столбцов клавиатуры
// Инициализация матричной клавиатуры
AlashKeypadMatrix keypad = AlashKeypadMatrix(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Переменные для хранения данных
String inputString = ""; // Строка для ввода чисел
double num1 = 0, num2 = 0; // Переменные для хранения чисел
char op = '\0'; // Переменная для хранения оператора
bool resultDisplayed = false; // Флаг для отслеживания отображения результата
int cursorPosition = 0; // Позиция курсора на дисплее
void setup() {
lcd.init(); // Инициализация LCD
lcd.backlight(); // Включение подсветки LCD
displayReadyMessage(); // Отображение сообщения о готовности калькулятора
}
void loop() {
char key = keypad.getKey(); // Получение нажатой клавиши
if (key) { // Проверка, была ли нажата клавиша
handleKeyPress(key); // Обработка нажатой клавиши
}
}
void displayReadyMessage() {
lcd.clear(); // Очистка дисплея
lcd.setCursor(0, 0); // Установка курсора в начало первой строки
lcd.print("Calc Ready:"); // Отображение сообщения о готовности калькулятора
lcd.setCursor(0, 1); // Установка курсора в начало второй строки
}
void handleKeyPress(char key) {
if (key == 'C') { // Проверка, была ли нажата клавиша 'C' (сброс)
clearData(); // Сброс данных
} else if (isDigit(key)) { // Проверка, является ли нажатая клавиша цифрой
handleDigit(key); // Обработка нажатой цифры
} else if (isOperator(key)) { // Проверка, является ли нажатая клавиша оператором
handleOperator(key); // Обработка нажатого оператора
} else if (key == '=') { // Проверка, была ли нажата клавиша '='
handleEquals(); // Обработка нажатия клавиши '='
}
}
void handleDigit(char key) {
if (resultDisplayed) { // Проверка, отображается ли результат
clearData(); // Сброс данных
resultDisplayed = false; // Сброс флага отображения результата
}
if (cursorPosition < 16) { // Проверка, не превышена ли длина строки на дисплее
inputString += key; // Добавление нажатой цифры к строке ввода
lcd.setCursor(cursorPosition, 1); // Установка курсора на позицию
lcd.print(key); // Отображение нажатой цифры на дисплее
cursorPosition++; // Перемещение курсора вправо
}
}
void handleOperator(char key) {
if (inputString. length() > 0 && !resultDisplayed) { // Проверка, была ли введена цифра и не отображается ли результат
num1 = inputString.toDouble(); // Преобразование строки в число
inputString = ""; // Очистка строки ввода
op = key; // Сохранение оператора
if (cursorPosition < 16) { // Проверка, не превышена ли длина строки на дисплее
lcd.setCursor(cursorPosition, 1); // Установка курсора на позицию
lcd.print(op); // Отображение оператора на дисплее
cursorPosition++; // Перемещение курсора вправо
}
} else if (resultDisplayed) { // Проверка, отображается ли результат
num1 = inputString.toDouble(); // Преобразование строки в число
inputString = ""; // Очистка строки ввода
op = key; // Сохранение оператора
lcd.clear(); // Очистка дисплея
displayReadyMessage(); // Отображение сообщения о готовности калькулятора
lcd.setCursor(0, 1); // Установка курсора в начало второй строки
lcd.print(num1); // Отображение числа на дисплее
cursorPosition = String(num1).length(); // Обновление позиции курсора
if (cursorPosition < 16) { // Проверка, не превышена ли длина строки на дисплее
lcd.setCursor(cursorPosition, 1); // Установка курсора на позицию
lcd.print(op); // Отображение оператора на дисплее
cursorPosition++; // Перемещение курсора вправо
}
resultDisplayed = false; // Сброс флага отображения результата
} else {
lcd.setCursor(cursorPosition - 1, 1); // Установка курсора на позицию оператора
lcd.print(key); // Заменяем операцию
op = key; // Сохранение нового оператора
}
}
void handleEquals() {
if (inputString.length() > 0 && op != '\0') { // Проверка, была ли введена цифра и выбран оператор
num2 = inputString.toDouble(); // Преобразование строки в число
lcd.setCursor(cursorPosition, 1); // Установка курсора на позицию
lcd.print("="); // Отображение знака '=' на дисплее
cursorPosition++; // Перемещение курсора вправо
calculateResult(); // Вычисление результата
}
}
void clearData() {
inputString = ""; // Очистка строки ввода
num1 = 0; // Сброс первого числа
num2 = 0; // Сброс второго числа
op = '\0'; // Сброс оператора
cursorPosition = 0; // Сброс позиции курсора
resultDisplayed = false; // Сброс флага отображения результата
displayReadyMessage(); // Отображение сообщения о готовности калькулятора
}
void calculateResult() {
double result; // Переменная для хранения результата
switch (op) { // Выбор действия в зависимости от оператора
case '+': result = num1 + num2; break;
case '-': result = num1 - num2; break;
case '*': result = num1 * num2; break;
case '/':
if (num2 != 0) { // Проверка на деление на ноль
result = num1 / num2; // Выполнение деления
} else {
lcd.clear(); // Очистка дисплея
lcd.setCursor(0, 1); // Установка курсора на позицию
lcd.print("Err: Div by 0"); // Отображение ошибки
delay(2000); // Задержка на 2 секунды
clearData(); // Сброс данных
return; // Возврат из функции
}
break;
}
String resultString = formatResult(result); // Форматирование результата
lcd.clear(); // Очистка дисплея
lcd.setCursor(0, 0); // Установка курсора в начало первой строки
lcd.print("Result:"); // Отображение сообщения "Result"
lcd.setCursor(0, 1); // Установка курсора в начало второй строки
lcd.print(resultString); // Отображение результата
resultDisplayed = true; // Установка флага отображения результата
cursorPosition = resultString.length(); // Обновление позиции курсора
inputString = resultString; // Установка результата как нового числа для следующей операции
}
String formatResult(double result) {
String resultString = String(result, 5); // Преобразование результата в строку с 5 знаками после запятой
if (resultString.length() > 16) { // Проверка длины строки
resultString = String(result, 1); // Уменьшение знаков после запятой до 1
if (resultString.length() > 16) {
resultString = String(result, 0); // Уменьшение знаков после запятой до 0
if (resultString.length() > 16) {
resultString = String(result, 1); // Использование экспоненциального формата
}
}
}
return resultString; // Возврат отформатированной строки
}
bool isDigit(char key) {
return key >= '0' && key <= '9'; // Проверка, является ли символ цифрой
}
bool isOperator(char key) {
return key == '+' || key == '-' || key == '*' || key == '/'; // Проверка, является ли символ оператором
}
|