====== LCD 1602 Keypad Shield ======
===== Описание =====
LCD Keypad Shield - простое и удобное решение для простых проектов, где требуется отобразить текстовую информацию на дисплее. Дисплей позволяет отображать латиницу в 2 строки по 16 символов в каждой из них. Поддерживается режим бегущей строки.

Для регулировки яркости на плате расположен потенциометр. Подсветка дисплея синего цвета.

Дополнительно на плате расположено 5 функциональных кнопок с помощью которых можно перемещаться по дисплею, а также запрограммировать их на определенные действия. Шестая кнопка выполняет функцию перезагрузки контроллера.

==== Технические характеристики ====
  * Рабочее напряжение: 5 В
  * Тип дисплея: LCD
  * Количество символов в строке: 16
  * Количество строк: 2
  * Язык (по умолчанию): латиница

==== Физические размеры ====
  * Шилд Д х Ш х В: 80 х 58 х 19 мм

===== Пример подключения и использования =====
==== Определение нажатой кнопки ====
**Описание:** В данном примере будет показано как определить какая кнопка была нажата.

**Приготовьте детали:**
^ Что нужно:                                                                                                                                       ^ Кол-во, шт  ^
| [[https://smartelements.ru/collection/kontrollery/product/kontroller-smart-uno|Контроллер Smart UNO]]                                                     | 1           |
| [[https://smartelements.ru/collection/shildy/product/lcd-1602-keypad-shield|LCD 1602 Keypad Shield]]                                                     | 1           |

**Схема подключения:** Установите шилд поверх контроллера Smart Uno.

**Загрузите на контроллер скетч:**
<file Arduino>
#include  <LiquidCrystal.h> //подключение библиотеки

#define BUTTON_NONE 0   //значение для BUTTON_NONE
#define BUTTON_RIGHT 1  //значение для BUTTON_RIGHT
#define BUTTON_UP 2     //значение для BUTTON_UP
#define BUTTON_DOWN 3   //значение для BUTTON_DOWN
#define BUTTON_LEFT 4   //значение для BUTTON_LEFT
#define BUTTON_SELECT 5 //значение для BUTTON_SELECT

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); //создание объекта дисплея

int getPressedButton() //инициализация переменной
{
  int buttonValue = analogRead(0); // чтение значения с аналогового входа
  
  if (buttonValue < 100) { //если при нажатии кнопки значение меньше 100
    return BUTTON_RIGHT;   // значит нажата кнопка BUTTON_RIGHT
  }
  else if (buttonValue < 200) { //если при нажатии кнопки значение меньше 200
    return BUTTON_UP; // значит нажата кнопка BUTTON_UP
  }
  else if (buttonValue < 400) { //если при нажатии кнопки значение меньше 400
    return BUTTON_DOWN; // значит нажата кнопка BUTTON_DOWN
  }
  else if (buttonValue < 600) { //если при нажатии кнопки значение меньше 600
    return BUTTON_LEFT; // значит нажата кнопка BUTTON_LEFT
  }
  else if (buttonValue < 800) { //если при нажатии кнопки значение меньше 800
    return BUTTON_SELECT; // значит нажата кнопка BUTTON_SELECT
  }
  return BUTTON_NONE; //иначе, нажата кнопка BUTTON_NONE
}

void setup()
{
  lcd.begin(16, 2); //Инициализация дисплея: 2 строки по 16 символов
  lcd.print("smartelements.ru");  //Выводи надпись www.smartelements.ru
  delay(1000); //задержка 1 сек
}

void loop()
{
  int button = getPressedButton(); //получение нажатой кнопки

  lcd.clear(); // очистка дисплея
  switch (button) //в зависимости от нажатой кнопки
  {
    case BUTTON_RIGHT: // при нажатии кнопки со значением BUTTON_RIGHT
      lcd.print("BUTTON: RIGHT");//вывести надпись BUTTON: RIGHT на экран
      break; //прервать выполнение
    case BUTTON_LEFT: // при нажатии кнопки со значением BUTTON_LEFT
      lcd.print("BUTTON: LEFT"); //вывести надпись BUTTON: LEFT на экран
      break; //прервать выполнение
    case BUTTON_UP: // при нажатии кнопки со значением BUTTON_UP
      lcd.print("BUTTON: UP"); //вывести надпись BUTTON: UP на экран
      break; //прервать выполнение
    case BUTTON_DOWN: // при нажатии кнопки со значением BUTTON_DOWN
      lcd.print("BUTTON: DOWN"); //вывести надпись BUTTON: DOWN на экран
      break; //прервать выполнение
    case BUTTON_SELECT: // при нажатии кнопки со значением BUTTON_SELECT
      lcd.print("BUTTON: SELECT"); //вывести надпись BUTTON: SELECT на экран
      break; //прервать выполнение
  }
}
</file>

==== Установка и запуск таймера ====
**Описание:** Создадим таймер, с возможностью управления им пользователем. 
Функциональные кнопки:
  * кнопка ВПРАВО: сброс таймера (если он в данный момент запущен)
  * кнопка ВЛЕВО: запуск таймера
  * кнопка ВВЕРХ: увеличение количества минут
  * кнопка ВНИЗ: уменьшение количества минут

**Приготовьте детали:**
^ Что нужно:                                                                                                                                       ^ Кол-во, шт  ^
| [[https://smartelements.ru/collection/kontrollery/product/kontroller-smart-uno|Контроллер Smart UNO]]                                                     | 1           |
| [[https://smartelements.ru/collection/shildy/product/lcd-1602-keypad-shield|LCD 1602 Keypad Shield]]                                                     | 1           |

**Схема подключения:** Установите шилд поверх контроллера Smart Uno.

**Загрузите на контроллер скетч:**
<file Arduino>
#include  <LiquidCrystal.h> //подключение библиотеки

#define BUTTON_NONE 0   //значение для BUTTON_NONE
#define BUTTON_RIGHT 1  //значение для BUTTON_RIGHT
#define BUTTON_UP 2     //значение для BUTTON_UP
#define BUTTON_DOWN 3   //значение для BUTTON_DOWN
#define BUTTON_LEFT 4   //значение для BUTTON_LEFT
#define BUTTON_SELECT 5 //значение для BUTTON_SELECT

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); //создание объекта дисплея

unsigned long currentTime;    //текущее время
unsigned long loopTime;       //время окончания
unsigned long LimitTime = 0;  //добавочное время таймера
boolean running = false;      //Флаг Запуска отсчета

int getPressedButton() //инициализация переменной
{
  int buttonValue = analogRead(0); // чтение значения с аналогового входа
  delay(200); //защита от дребезга

  if (buttonValue < 100) { //если при нажатии кнопки значение меньше 100
    return BUTTON_RIGHT;   // значит нажата кнопка BUTTON_RIGHT
  }
  else if (buttonValue < 200) { //если при нажатии кнопки значение меньше 200
    return BUTTON_UP; // значит нажата кнопка BUTTON_UP
  }
  else if (buttonValue < 400) { //если при нажатии кнопки значение меньше 400
    return BUTTON_DOWN; // значит нажата кнопка BUTTON_DOWN
  }
  else if (buttonValue < 600) { //если при нажатии кнопки значение меньше 600
    return BUTTON_LEFT; // значит нажата кнопка BUTTON_LEFT
  }
  else if (buttonValue < 800) { //если при нажатии кнопки значение меньше 800
    return BUTTON_SELECT; // значит нажата кнопка BUTTON_SELECT
  }
  return BUTTON_NONE; //иначе, нажата кнопка BUTTON_NONE
}

//сброс значений связанных с таймером
void reset_values()
{
  running = false;  // останавливаем таймер
  LimitTime = 0;    // сброс значения таймера
  delay(3000);      // пауза 3 секунды
  lcd.clear();      // очистить экран
}

//запуск таймера и отсчёт времени
void run_timer()
{
  currentTime = millis(); //текущее время
  loopTime = currentTime + LimitTime; //время окончания (текущее время + добавочное время таймера)

  while (currentTime < loopTime) { // сравнение текущего времени с временем окончания

    int button = getPressedButton(); //проверка на кнопку "Прервать"

    if (button == BUTTON_RIGHT) { // если нажата кнопка "RIGHT" - прервать
      lcd.clear(); // очистить экран
      lcd.print("Interrupted"); // вывод "прервано"
      reset_values(); //сброс значений
      return; //выход из процедуры
    }

    lcd.clear(); // очистить экран
    lcd.print("Time to off: "); // вывод надписи
    lcd.setCursor(13, 0); // установка курсора на 13 позицию
    lcd.print(LimitTime / 1000); // указать добавочное время, переводя миллисекунды в секунды

    delay(800); // задержка 0.8 секунды
    LimitTime = LimitTime - (millis() - currentTime);
    currentTime = millis(); //получить новое время
  }

  //окончание работы таймера
  lcd.clear(); // очистить экран
  lcd.print("Timer: OFF"); // вывести надпись "Timer: OFF"
  reset_values(); //сброс значений
}

//показать сообщение об ошибке на второй строке дисплея
void showError(String message)
{
  lcd.setCursor(0, 1); // установка курсора во вторую строку
  lcd.print (message); // вывести надпись ошибки
  delay (1000); //пауза 1 секунду
  lcd.setCursor(0, 1); // установка курсора во вторую строку
  lcd.print ("               "); //очистить строку
}

void setup()
{
  lcd.begin(16, 2); //Инициализация дисплея: 2 строки по 16 символов
  lcd.print("smartelements.ru");  //Выводи надпись www.smartelements.ru
  delay(1000); //задержка 1 сек
}

void loop()
{
  if (running == true) {  // таймер запущен
    run_timer(); // обработка таймера
  }

  //ожидание ввода команд пользователем
  keypad();
}

//ожидание ввода команд пользователем
void keypad()
{

  lcd.clear(); // очистить экран
  lcd.print ("Time:");  //вывести слово "Time:"

  int button = getPressedButton(); //проверка на кнопку "Прервать"
  switch (button) //в зависимости от нажатой кнопки
  {
    case BUTTON_UP: // при нажатии кнопки со значением BUTTON_UP
      if ((LimitTime + 60000) <= 300005) //если время меньше или равно 5 минутам
      {
        LimitTime += 60000; // прибавляем 1 минуту
        lcd.setCursor(7, 0); // установить курсор
        lcd.print(LimitTime / 60000); //вывести значение таймера в секундах
      }
      else { //иначе, при попытке прибавить больше 5 минут
        showError("maximum 5 min"); // показать сообщение об ошибке
      }
      break; //прервать выполнение
    case BUTTON_DOWN: // при нажатии кнопки со значением BUTTON_DOWN
      if (LimitTime  > 60000) // если время больше 1 минуты
      {
        LimitTime -= 60000; // отнять 1 минуту
        lcd.setCursor(7, 0); // установить курсор
        lcd.print(LimitTime / 60000); //вывести значение таймера в секундах
      }
      else { // иначе, при выборе значения меньше 1 минуты
        showError("minimum 1 min"); // показать сообщение об ошибке
      }
      break; //прервать выполнение
    case BUTTON_LEFT: // при нажатии кнопки со значением BUTTON_LEFT
      if (LimitTime != 0 ) //если добавочное время равно 0
      {
        running = true;                //Устанавливаем запуск отсчета
        lcd.clear(); // очистить экран
        lcd.print ("Start"); //выводим надпись "Start"
        delay(1000);
      } //ждем 1 секунду
      else { //иначе, если не выбрали время
        showError("no time selected"); // показать сообщение об ошибке
      }
      break; //прервать выполнение
  }
}
</file>