Меню с энкодером на Arduino LCD 1602

Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1611
Зарегистрирован: 5 апреля 2013
С нами: 11 лет

#1 Дим » 14 ноября 2020, 19:28

Рассмотрим, как сделать меню с энкодером Ардуино на дисплее LCD 1602 I2C. Мы представим два примера: меню для включения светодиодов и меню на дисплее с управлением от энкодера яркостью светодиодов. Рекомендуем вам ознакомиться с подключением к Arduino дисплея LCD 1602 Arduino и модуля энкодер Ардуино. Если вы уже подключали данные модули, то можно приступать к этому мини проекту.
Меню на Ардуино LCD 1602 с энкодером

Меню на Ардуино LCD 1602 с энкодером.gif
Меню на Ардуино LCD 1602 с энкодером
Меню на Ардуино LCD 1602 с энкодером.gif (6.3 МБ) 3372 просмотра

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

Как сделать меню с энкодером на дисплее

Для этого проекта нам потребуется:

плата Arduino Uno / Arduino Nano / Arduino Mega;
модуль энкодера;
беспаечная макетная плата;
светодиоды и резисторы;
дисплей LCD 1602 Arduino;
провода «папа-папа», «папа-мама».
схема подключения дисплея и энкодера к Ардуино.jpg
схема подключения дисплея и энкодера к Ардуино
схема подключения дисплея и энкодера к Ардуино.jpg (80.63 КБ) 3372 просмотра

Управление энкодером меню дисплея LCD

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

Код: Выделить всё

#include "Wire.h"                                 // библиотека для протокола I2C
#include "LiquidCrystal_I2C.h"           // библиотека для дисплея
LiquidCrystal_I2C LCD(0x27, 16, 2);   // присваиваем имя дисплею

#include "RotaryEncoder.h"                // библиотека для энкодера
RotaryEncoder encoder(A2, A3);       // пины подключение энкодера (DT, CLK)

// задаем шаг энкодера и макс./мин. значение
#define STEPS  6
#define POSMIN 0
#define POSMAX 12

int lastPos, newPos;
boolean buttonWasUp = true;

void setup() {
   LCD.init();            // инициализация LCD дисплея и подсветки
   LCD.backlight();

   pinMode(9, OUTPUT);              // пины для светодиодов
   pinMode(10, OUTPUT);
   pinMode(11, OUTPUT);
   pinMode(2, INPUT_PULLUP);  // пин для кнопки энкодера

   Serial.begin(9600);
   encoder.setPosition(10 / STEPS);
}

void loop() {
   LCD.setCursor(0, 0);
   LCD.print("LED1  LED2  LED3");

   // проверяем положение ручки энкодера
   encoder.tick();
   newPos = encoder.getPosition() * STEPS;
   if (newPos < POSMIN) { encoder.setPosition(POSMIN / STEPS); newPos = POSMIN; }
   else if (newPos > POSMAX) { encoder.setPosition(POSMAX / STEPS); newPos = POSMAX; }

   // если положение изменилось - выводим на монитор и дисплей
   if (lastPos != newPos) {
      Serial.println(newPos);
      LCD.setCursor(lastPos, 1);
      LCD.print("    ");
      LCD.setCursor(newPos, 1);
      LCD.print("====");
      lastPos = newPos;
   }

   // узнаем состояние кнопки модуля энкодера
   boolean buttonIsUp = digitalRead(2);
   if (buttonWasUp && !buttonIsUp) {
      // исключаем дребезг контактов тактовой кнопки
      delay(10);
      // снова считываем сигнал с кнопки энкодера
      buttonIsUp = digitalRead(2);

      // если кнопка нажата, то включаем соответствующий светодиод
      if (!buttonIsUp  && newPos == 0) {
          digitalWrite(9, HIGH); digitalWrite(10, LOW); digitalWrite(11, LOW);
      }
      if (!buttonIsUp  && newPos == 6) {
          digitalWrite(9, LOW); digitalWrite(10, HIGH); digitalWrite(11, LOW);
      }
      if (!buttonIsUp  && newPos == 12) {
          digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, HIGH);
      }
   }

}

Пояснения к коду:
положение курсора на LCD может принимать три значения — 0, 6 или 12;
кнопка энкодера подключена к цифровому порту при помощи конфигурации пина параметром INPUT PULLUP, что позволяет считывать нажатие кнопки.
Двухуровневое меню с энкодером Ардуино

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

Код: Выделить всё

#include "Wire.h"                                 // библиотека для протокола I2C
#include "LiquidCrystal_I2C.h"           // библиотека для дисплея
LiquidCrystal_I2C LCD(0x27, 16, 2);   // присваиваем имя дисплею

#include "RotaryEncoder.h"                // библиотека для энкодера
RotaryEncoder encoder(A2, A3);       // пины подключение энкодера (DT, CLK)

// задаем шаг энкодера и макс./мин. значение в главном меню
#define STEPS  6
#define POSMIN 0
#define POSMAX 12

// задаем шаг энкодера и макс./мин. значение в подменю
#define STEPS_2  10
#define POSMIN_2 0
#define POSMAX_2 250

int lastPos, newPos;
boolean buttonWasUp = true;
byte w = 2;

void setup() {
  LCD.init();            // инициализация LCD дисплея и подсветки
  LCD.backlight();

  pinMode(9, OUTPUT);              // пины для светодиодов
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(2, INPUT_PULLUP);  // пин для кнопки энкодера

  Serial.begin(9600);
  encoder.setPosition(10 / STEPS);
}

void loop() {

   // ЦИКЛ С ГЛАВНЫМ МЕНЮ НА ДИСПЛЕЕ
  while (== 0) {
    LCD.setCursor(0, 0);
    LCD.print("LED1  LED2  LED3");
    // проверяем положение ручки энкодера
    encoder.tick();
    newPos = encoder.getPosition() * STEPS;
    if (newPos < POSMIN) {
      encoder.setPosition(POSMIN / STEPS);
      newPos = POSMIN;
    }
    else if (newPos > POSMAX) {
      encoder.setPosition(POSMAX / STEPS);
      newPos = POSMAX;
    }
    // если положение изменилось - выводим на монитор и дисплей
    if (lastPos != newPos) {
      Serial.println(newPos);
      LCD.setCursor(lastPos, 1);
      LCD.print("    ");
      LCD.setCursor(newPos, 1);
      LCD.print("====");
      lastPos = newPos;
    }
      // если кнопка нажата, то переходим в цикл с вложенным меню
      // перед входом в подменю очищаем дисплей и делаем задержку
    boolean buttonIsUp = digitalRead(2);
    if (buttonWasUp && !buttonIsUp) {
      delay(10);
      buttonIsUp = digitalRead(2);
      if (!buttonIsUp  && newPos == 0)  { LCD.clear(); delay(500); w = 1; }
      if (!buttonIsUp  && newPos == 6)  { LCD.clear(); delay(500); w = 2; }
      if (!buttonIsUp  && newPos == 12) { LCD.clear(); delay(500); w = 3; }
    }
  }

   // ВЛОЖЕННОЕ МЕНЮ-1 С ПЕРВЫМ СВЕТОДИОДОМ
  while (== 1) {
    LCD.setCursor(0, 0);
    LCD.print("LED1  - ");
    // проверяем положение ручки энкодера
    encoder.tick();
    newPos = encoder.getPosition() * STEPS_2;
    if (newPos < POSMIN_2) {
      encoder.setPosition(POSMIN_2 / STEPS_2);
      newPos = POSMIN_2;
    }
    else if (newPos > POSMAX_2) {
      encoder.setPosition(POSMAX_2 / STEPS_2);
      newPos = POSMAX_2;
    }
    // если положение изменилось - меняем яркость светодиода
    if (lastPos != newPos) {
      LCD.setCursor(7, 0);
      LCD.print(newPos);
      analogWrite(9, newPos);
    }
    // если кнопка энкодера была нажата, то выходим в главное меню
    // перед входом очищаем дисплей и выключаем светодиод
    boolean buttonIsUp = digitalRead(2);
    if (buttonWasUp && !buttonIsUp) {
      delay(10);
      buttonIsUp = digitalRead(2);
      if (!buttonIsUp)  { LCD.clear(); digitalWrite(9, LOW); delay(500); w = 0; }
  } 
}

   // ВЛОЖЕННОЕ МЕНЮ-2 СО ВТОРЫМ СВЕТОДИОДОМ
  while (== 2) {
    LCD.setCursor(0, 0);
    LCD.print("LED2 - ");
    // проверяем положение ручки энкодера
    encoder.tick();
    newPos = encoder.getPosition() * STEPS_2;
    if (newPos < POSMIN_2) {
      encoder.setPosition(POSMIN_2 / STEPS_2);
      newPos = POSMIN_2;
    }
    else if (newPos > POSMAX_2) {
      encoder.setPosition(POSMAX_2 / STEPS_2);
      newPos = POSMAX_2;
    }
    // если положение изменилось - меняем яркость светодиода
    if (lastPos != newPos) {
      LCD.setCursor(7, 0);
      LCD.print(newPos);
      analogWrite(10, newPos);
    }
    // если кнопка энкодера была нажата, то выходим в главное меню
    // перед входом очищаем дисплей и выключаем светодиод
    boolean buttonIsUp = digitalRead(2);
    if (buttonWasUp && !buttonIsUp) {
      delay(10);
      buttonIsUp = digitalRead(2);
      if (!buttonIsUp)  { LCD.clear(); digitalWrite(10, LOW); delay(500); w = 0; }
  }
}

   // ВЛОЖЕННОЕ МЕНЮ-3 С ТРЕТЬИМ СВЕТОДИОДОМ
  while (== 3) {
    LCD.setCursor(0, 0);
    LCD.print("LED3 - ");
    // проверяем положение ручки энкодера
    encoder.tick();
    newPos = encoder.getPosition() * STEPS_2;
    if (newPos < POSMIN_2) {
      encoder.setPosition(POSMIN_2 / STEPS_2);
      newPos = POSMIN_2;
    }
    else if (newPos > POSMAX_2) {
      encoder.setPosition(POSMAX_2 / STEPS_2);
      newPos = POSMAX_2;
    }
    // если положение изменилось - меняем яркость светодиода
    if (lastPos != newPos) {
      LCD.setCursor(7, 0);
      LCD.print(newPos);
      analogWrite(11, newPos);
    }
    // если кнопка энкодера была нажата, то выходим в главное меню
    // перед входом очищаем дисплей и выключаем светодиод
    boolean buttonIsUp = digitalRead(2);
    if (buttonWasUp && !buttonIsUp) {
      delay(10);
      buttonIsUp = digitalRead(2);
      if (!buttonIsUp)  { LCD.clear(); digitalWrite(11, LOW); delay(500); w = 0; }
  } 
}

}

Пояснения к коду:
для каждого раздела меню используется цикл while, так как изначально глобальная переменная w=0;, то выполняется цикл while (w == 0);
если вы не хотите, чтобы светодиоды выключались при выходе в главное меню — удалите команду digitalWrite() во всех циклах вложенных меню.
Лично мне не понравилась работа энкодера по данной статье
[center]i love you [s]mxIni[/s] Mysql[/center]


  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Программирование»

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 3 гостя