Меню для Ардуино на LCD Nokia 5110

titul lcdВ основе сегодняшнего проекта лежит ЖК-дисплей Nokia 5110. Nokia 5110 LCD является одним из самых популярных ЖК-дисплеев среди производителей. Первоначально он был разработан для использования в качестве экрана для мобильных телефонов и использовался во многих мобильных телефонах в 90-х годах. Дисплей использует низкопотребляющий контроллер/драйвер PCD8544, который управляет графическим дисплеем 84×48px. В нормальном состоянии дисплей потребляет от 6 до 7 мА, что делает его идеальным для устройств с низким энергопотреблением.

Чтобы продемонстрировать, как создать меню на дисплее с Arduino, мы построим простое демо-меню с тремя страницами.  Для навигации по меню мы будем использовать 3 кнопки. Первую для прокрутки вверх, вторую для прокрутки вниз и третью для выбора выделенного пункта. Первый экран меню будет служить домашней страницей и будет содержать параметры, которые открывают следующие две страницы. Вторая страница откроется после выбора первой опции меню на главной странице. Пользователи смогут изменить контрастность дисплея с помощью кнопок вверх и вниз, чтобы увеличить или уменьшить контраст. Нажав кнопку Select, пользователи смогут вернуться на главную страницу. Второй вариант на главной странице отображает третью страницу, где пользователи смогут включить/выключить подсветку дисплея, нажав кнопку Select.

Screen Shot 2019 04 25 at 1 09 34 AM 768x455

Выбор последней опции на главной странице очищает все предыдущие настройки для контраста и подсветки. Это интересный проект может быть очень полезен любому, независимо от уровня вашего технического профессионализма.

Необходимые компоненты

Для построения этого проекта требуются следующие компоненты:

  • Arduino Uno или аналогичная плата
  • Nokia 5110 LCD
  • Макетная плата
  • Кнопки
  • Перемычки
  • Провода

 Схема подключения LCD Nokia 5110 к Ардуино

Схема подключения довольно проста, соедините все компоненты как показано на рисунке ниже:

LCD MENU 768x903

Для удобства ниже показана распинвка соединения между Arduino Uno и Nokia 5110.

LCD - Arduino
RST - D12
CE  - D11
DC  - D10
DIN - D9
CLK - D8
VCC - VCC
LIGHT - D7
GND - GND

Глядя на схему, вы увидите, что кнопки подключены к Arduino без подтягивающих резисторов. Это потому, что мы будем использовать внутренние подтягивающие резисторы Arduino. После  всех подключений мы можем перейти к программированию.

Код

Честно говоря, код для этого проекта немного сложный, и сильно зависит от двух основных библиотек: The Adafruit GFX library and the Adafruit Nokia 5110 LCD Library. Библиотека Adafruit GFX позволяет легко отображать графику и выполнять простые анимации на поддерживаемых дисплеях. С другой стороны, библиотека Nokia 5110 LCD уменьшает объем работы и код, необходимый для взаимодействия с ЖК-дисплеем.

Сначала мы подключаем библиотеки, необходимые для проекта,  в данном случае это Adafruit GFX и Nokia 5110 LCD.

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

Затем мы объявляем контакты, к которым подключены кнопки, а также объявляем все переменные, которые мы будем использовать для проекта. Имя переменной обеспечивает достаточное представление о том, что означает каждая переменная.

boolean backlight = true;
    int contrast=50;
    int menuitem = 1;
    int page = 1;
    volatile boolean up = false;
    volatile boolean down = false;
    volatile boolean middle = false;
    int downButtonState = 0;
    int upButtonState = 0;  
    int selectButtonState = 0;          
    int lastDownButtonState = 0;
    int lastSelectButtonState = 0;
    int lastUpButtonState = 0;

Далее пишем функцию void setup. Здесь мы объявляем все контакты, к которым кнопки подключены в качестве входов и установливаем контакт 7 в качестве выхода, так как контакт полсветки ЖК-дисплея подключен к нему. Этот контакт позже будет использоваться для включения/выключения подсветки.

void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(0, INPUT_PULLUP);
pinMode(7,OUTPUT);

 После установки режимов выводов мы инициализируем последовательную связь, инициализируем экран и устанавливаем контраст экрана 50, который служит значением по умолчанию (которое будет изменяться позже с помощью кнопок меню), и используем дисплей.функция display () для применения изменений.

Serial.begin(9600);
display.begin();
display.setContrast(contrast); //Set contrast to 50
display.clearDisplay();
display.display();

Затем мы пишем функцию void loop. Мы запускаем функцию void loop, вызывая функцию drawmenu (), которая содержит код для создания объектов меню на экране.

void loop()
{ drawMenu();

Затем мы читаем кнопки, чтобы проверить, нажата ли какая-либо из них.

downButtonState = digitalRead(2);
selectButtonState = digitalRead(1);
upButtonState = digitalRead(0);
checkIfDownButtonIsPressed();
checkIfUpButtonIsPressed();
checkIfSelectButtonIsPressed();

Затем состояние кнопок подается в серию операторов if-else, которые проверяют, какая кнопка была нажата и какой из экранов в настоящее время отображается, чтобы определить, какое действие будет сделано дальше. Например, первая инструкция if проверяет, находится ли меню на странице 1 и нажата ли кнопка вверх. Если это так, он проверяет положение курсора меню и соответствующим образом настраивает его.

if (up && page == 1 ) {
    up = false;
    menuitem--;
    if (menuitem==0)
    {
      menuitem=3;
    }      
  }else if (up && page == 2 ) {
    up = false;
    contrast--;
    setContrast();
  }
  if (down && page == 1) {
    down = false;
    menuitem++;
    if (menuitem==4)
    {
      menuitem=1;
    }      
  }else if (down && page == 2 ) {
    down = false;
    contrast++;
    setContrast();
  }
  if (middle) {
    middle = false;
    
    if (page == 1 && menuitem==2)
    {
      if (backlight)
      {
        backlight = false;
        turnBacklightOff();
        }
      else
      {
        backlight = true;
        turnBacklightOn();
       }
    }
    if(page == 1 && menuitem ==3)
    {
      resetDefaults();
    }
else if (page == 1 && menuitem==1) {
      page=2;
     }
else if (page == 2) {
      page=1;
     }
   }
   
  }

Оставшаяся часть эскиза-это функции, вызываемые внутри функции цикла.

void drawMenu()
      {
        
      if (page==1)
      {    
        display.setTextSize(1);
        display.clearDisplay();
        display.setTextColor(BLACK, WHITE);
        display.setCursor(15, 0);
        display.print("MAIN MENU");
        display.drawFastHLine(0,10,83,BLACK);
        display.setCursor(0, 15);
       
        if (menuitem==1)
        {
          display.setTextColor(WHITE, BLACK);
        }
        else
        {
          display.setTextColor(BLACK, WHITE);
        }
        display.print(">Contrast");
        display.setCursor(0, 25);
       
        if (menuitem==2)
        {
          display.setTextColor(WHITE, BLACK);
        }
        else
        {
          display.setTextColor(BLACK, WHITE);
        }    
        display.print(">Light: ");
        
        if (backlight)
        {
          display.print("ON");
        }
        else
        {
          display.print("OFF");
        }
        display.display();
        
        if (menuitem==3)
        {
          display.setTextColor(WHITE, BLACK);
        }
        else
        {
          display.setTextColor(BLACK, WHITE);
        }  
        display.setCursor(0, 35);
        display.print(">Reset");
        display.display();
      }
        
     
      else if (page==2)
      {
        
        display.setTextSize(1);
        display.clearDisplay();
        display.setTextColor(BLACK, WHITE);
        display.setCursor(15, 0);
        display.print("CONTRAST");
        display.drawFastHLine(0,10,83,BLACK);
        display.setCursor(5, 15);
        display.print("Value");
        display.setTextSize(2);
        display.setCursor(5, 25);
        display.print(contrast);
     
        display.setTextSize(2);
        display.display();
      }
      
      }
      void resetDefaults()
      {
        contrast = 50;
        setContrast();
        backlight = true;
        turnBacklightOn();
      }
      void setContrast()
      {
        display.setContrast(contrast);
        display.display();
      }
      void turnBacklightOn()
      {
        digitalWrite(7,LOW);
      }
        void turnBacklightOff()
      {
        digitalWrite(7,HIGH);
      }

Полный код для проекта показан ниже и прилагается для загрузки в конце статьи.

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
boolean backlight = true;
int contrast=50;
int menuitem = 1;
int page = 1;
volatile boolean up = false;
volatile boolean down = false;
volatile boolean middle = false;
int downButtonState = 0;
int upButtonState = 0;  
int selectButtonState = 0;          
int lastDownButtonState = 0;
int lastSelectButtonState = 0;
int lastUpButtonState = 0;
Adafruit_PCD8544 display = Adafruit_PCD8544( 5, 4, 3);
void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(0, INPUT_PULLUP);
  pinMode(7,OUTPUT);
  digitalWrite(7,LOW); //Turn Backlight ON
 
  Serial.begin(9600);
 
  display.begin();      
  display.setContrast(contrast); //Set contrast to 50
  display.clearDisplay();
  display.display();   
}
void loop() {
 
  drawMenu();
  downButtonState = digitalRead(2);
  selectButtonState = digitalRead(1);
  upButtonState =   digitalRead(0);
 
  checkIfDownButtonIsPressed();
  checkIfUpButtonIsPressed();
  checkIfSelectButtonIsPressed();
  if (up && page == 1 ) {
    up = false;
    menuitem--;
    if (menuitem==0)
    {
      menuitem=3;
    }      
  }else if (up && page == 2 ) {
    up = false;
    contrast--;
    setContrast();
  }

  if (down && page == 1) {
    down = false;
    menuitem++;
    if (menuitem==4)
    {
      menuitem=1;
    }      
  }else if (down && page == 2 ) {
    down = false;
    contrast++;
    setContrast();
  }

  if (middle) {
    middle = false;
    
    if (page == 1 && menuitem==2)
    {
      if (backlight)
      {
        backlight = false;
        turnBacklightOff();
        }
      else
      {
        backlight = true;
        turnBacklightOn();
       }
    }
    if(page == 1 && menuitem ==3)
    {
      resetDefaults();
    }

else if (page == 1 && menuitem==1) {
      page=2;
     }
else if (page == 2) {
      page=1;
     }
   }
   
  }
  void checkIfDownButtonIsPressed()
  {
    if (downButtonState != lastDownButtonState)
  {
    if (downButtonState == 0)
    {
      down=true;
    }
    delay(50);
  }
   lastDownButtonState = downButtonState;
  }
void checkIfUpButtonIsPressed()
{
  if (upButtonState != lastUpButtonState)
  {
    if (upButtonState == 0) {
      up=true;
    }
    delay(50);
  }
   lastUpButtonState = upButtonState;
}
void checkIfSelectButtonIsPressed()
{
   if (selectButtonState != lastSelectButtonState)
  {
    if (selectButtonState == 0) {
      middle=true;
    }
    delay(50);
  }
   lastSelectButtonState = selectButtonState;
}
 
  void drawMenu()
  {
    
  if (page==1)
  {    
    display.setTextSize(1);
    display.clearDisplay();
    display.setTextColor(BLACK, WHITE);
    display.setCursor(15, 0);
    display.print("MAIN MENU");
    display.drawFastHLine(0,10,83,BLACK);
    display.setCursor(0, 15);
   
    if (menuitem==1)
    {
      display.setTextColor(WHITE, BLACK);
    }
    else
    {
      display.setTextColor(BLACK, WHITE);
    }
    display.print(">Contrast");
    display.setCursor(0, 25);
   
    if (menuitem==2)
    {
      display.setTextColor(WHITE, BLACK);
    }
    else
    {
      display.setTextColor(BLACK, WHITE);
    }    
    display.print(">Light: ");
    
    if (backlight)
    {
      display.print("ON");
    }
    else
    {
      display.print("OFF");
    }
    display.display();
    
    if (menuitem==3)
    {
      display.setTextColor(WHITE, BLACK);
    }
    else
    {
      display.setTextColor(BLACK, WHITE);
    }  
    display.setCursor(0, 35);
    display.print(">Reset");
    display.display();
  }
    
 
  else if (page==2)
  {
    
    display.setTextSize(1);
    display.clearDisplay();
    display.setTextColor(BLACK, WHITE);
    display.setCursor(15, 0);
    display.print("CONTRAST");
    display.drawFastHLine(0,10,83,BLACK);
    display.setCursor(5, 15);
    display.print("Value");
    display.setTextSize(2);
    display.setCursor(5, 25);
    display.print(contrast);
 
    display.setTextSize(2);
    display.display();
  }
 
  }
  void resetDefaults()
  {
    contrast = 50;
    setContrast();
    backlight = true;
    turnBacklightOn();
  }
  void setContrast()
  {
    display.setContrast(contrast);
    display.display();
  }
  void turnBacklightOn()
  {
    digitalWrite(7,LOW);
  }
    void turnBacklightOff()
  {
    digitalWrite(7,HIGH);
  }

Скачать проект в архиве

Загрузка...