Подключаем LCD-дисплей на базе HD44780 к Arduino


При работе с Arduino иногда возникает необходимость вывести какие-либо данные на дисплей, но передавать для этого данные на ПК имеет смысл только если устройство будет использоваться в связке с ПК. А как же быть с автономными устройствами? Тут на помощь придут LCD-дисплеи.

Рассмотрим LCD-дисплеи на базе контроллера HD44780 на примере WH1602B-YYK-CTK.


Этот монохромный дисплей имеет опциональную подсветку и может отображать 2 строки по 16 символов. Разрешение символов — 5×8 точек. Есть поддержка кириллицы, но странная, об этом — в конце статьи.

Чем хороши такие дисплеи? Контроллер HD44780 — стандарт де-факто среди небольших монохромных LCD-дисплеев, поэтому библиотеку для работы с дисплеями на его базе не написал только ленивый. Ленивым на сей раз оказался я, а вот разработчики Arduino написали библиотеку для своей платформы, и называется она LiquidCrystal. Её мы и используем для работы с выбранным мной дисплеем.

Итак, прежде чем писать код, нужно подключить дисплей к Arduino. Вам понадобятся:

  • Arduino или CraftDuino
  • LCD-дисплей, например WH1602B-YYK-CTK
  • макетная плата
  • соединительные провода
  • потенциометр

Схема подключения в официальном руководстве на сайте Arduino выглядит так:

Однако, здесь по какой-то причине не используется подсветка, без которой изображение на дисплее выглядит хуже, чем на дешёвых китайских электронных часах. Так что мы, как подобает настоящим джедаям, её задействуем.

Кстати, дисплей имеет режим самотестирования, который можно включить, подсоединив выводы:

  • 1 — Vss, земля ⇨ GND
  • 2 — Vdd, питание ⇨ +5 В
  • 3 — Vo, управление контрастностью напряжением ⇨ выход потенциометра
  • 15 — A, питание для подсветки ⇨ +5 В
  • 16 — K, земля для подсветки ⇨ GND

Верхний ряд символов должен полностью заполниться тёмными прямоугольниками:

Повращайте ручку потенциометра, чтобы настроить контрастность дисплея. Если вы не видите верхний ряд прямоугольников, то либо вы неправильно подключили дисплей, либо его сожгли.
Хотя, кто знает — может, просто режим самотестирования не поддерживается (:

А для полноценной работы с дисплеем подключим 12 выводов:

  • 1 — Vss, земля ⇨ GND
  • 2 — Vdd, питание ⇨ +5 В
  • 3 — Vo, управление контрастностью напряжением ⇨ выход потенциометра
  • 4 — RS, выбор регистра ⇨ пин 12 Arduino
  • 5 — R/W, чтение/запись ⇨ земля (режим записи)
  • 6 — E, он же Enable, cтроб по спаду ⇨ пин 11 Arduino
  • 7-10 — DB0-DB3, младшие биты 8-битного интерфейса; не подключены
  • 11-14 — DB4-DB7, старшие биты интерфейса ⇨ пины 5-2 Arduino
  • 15 — A, питание для подсветки ⇨ +5 В
  • 16 — K, земля для подсветки ⇨ GND

Этот дисплей, как и прочие на контроллере HD44780, поддерживает два варианта параллельного интерфейса:

  • 8-битный, выводы DB0-DB7, за один такт передаётся 1 байт (8 бит)
  • 4-битный, выводы DB4-DB7, за один такт передаётся половина байта (4 бита)

Смысла использовать 8-битный вариант нет, потому что это требует больше ног, а выигрыша в скорости всё равно нет: частота обновления дисплея не больше 10 раз в секунду, так что мы всё равно не сможем увидеть часто обновляемые данные. Поэтому выводы DB0-DB3 оставляем неподключенными.

Ну что же, всё подключено — пора писать код. Начнём с классического «Hello, World», который доступен в Arduino IDE через пункт меню File ⇨ Examples ⇨ LiquidCrystal ⇨ HelloWorld:

/* Подключаем библиотеку для работы с LCD */
#include <LiquidCrystal.h>

/* Создаём объект LCD-дисплея, используя конструктор класса LiquidCrystal
* с 6ю аргументами. Библиотека по количеству аргументов сама определит,
* что нужно использовать 4-битный интерфейс.
* Указываем, к каким пинам Arduino подключены выводы дисплея:
*   RS, E, DB4, DB5, DB6, DB7
*/
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{
 /* Инициализируем дисплей: 2 строки по 16 символов */
 lcd.begin(16, 2);
 /* Выводим на дисплей традиционную фразу (: */
 lcd.print("hello, world!");
}

void loop()
{
 /* Устанавливаем курсор в 1 столбец 2й строки. Нумерация идёт с нуля,
  * первым аргументом идёт номер столбца.
  */
 lcd.setCursor(0, 1);
 /* Выводим на дисплей число секунд, прошедших с момента старта Arduino */
 lcd.print(millis() / 1000);
}

Ничего сложного, как видите: основного кода набралось всего 4 строки.
Обратите внимание на инициализацию дисплея:

lcd.begin(16, 2);

Здесь мы задали размер экрана: 2 строки по 16 символов. Прелесть в том, что можно, ничего не меняя в схеме, подцепить другой дисплей — например, размером 16х4 символа, или сэкономить и взять 8х2. Достаточно изменить строку инициализации соответственно размеру подключенного дисплея.

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

  • home() и clear()
    Первый метод возвращает курсор в начало экрана; clear() делает то же самое, заодно стирая всё, что было на дисплее до этого.
  • write(ch)
    Выводит одиночный символ ch на дисплей.
    Пример:

    lcd.write('z');
    lcd.write(0); // вывести символ с кодом 0; см. метод createChar()
  • cursor() и noCursor()
    Позволяют показать курсор на дисплее (символ подчёркивания) и скрыть его.
  • blink() и noBlink()
    Включить и выключить мигание курсора, если включено его отображение.
  • display() и noDisplay()
    Включить и выключить дисплей.
  • scrollDisplayLeft() и scrollDisplayRight()
    Прокрутить экран на один символ влево или вправо.
  • autoscroll() и noAutoscroll()
    Включить и выключить режим автопрокрутки. В этом режиме при выводе каждого следующего символа содержимое экрана будет смещено на один символ влево (или вправо, если включен режим вывода справа налево), а выводимый символ займёт место первого сдвинутого. Проще говоря, в этом режиме все последующие символы выводятся в одно и то же место, вытесняя текущее содержимое экрана.
  • leftToRight() и rightToLeft()
    Устанавливают направление вывода текста: слева направо и справа налево, соответственно.
  • createChar(ch, bitmap)
    Самая крутая функция: позволяет создать свой символ с кодом ch (от 0 до 7), пользуясь массивом битовых масок bitmap для задания тёмных и светлых точек.

Неплохо бы опробовать все эти функции, не правда ли? Сказано — сделано! Напишем большой и фаршированный функционалом скетч:

#include <LiquidCrystal.h>

/* Константа: высота символа в точках */
enum { SYMBOL_HEIGHT = 8 };

/* Описываем наши собственные символы в виде массивов битовых масок.
 * Каждый символ - это восемь масок по пять бит.
 */
byte arnie[SYMBOL_HEIGHT] =
{
  B10101,
  B11111,
  B10111,
  B11111,
  B11111,
  B00111,
  B11110,
  B00000,
};

byte skull_and_bones[SYMBOL_HEIGHT] =
{
  B01110,
  B10101,
  B11011,
  B01110,
  B00000,
  B10001,
  B01110,
  B10001,
};

byte lightning[SYMBOL_HEIGHT] =
{
  B00010,
  B00100,
  B01000,
  B11111,
  B00010,
  B00100,
  B01000,
  B00000,
};

/* Константы размеров экрана. Нужны для того, чтобы размер экрана
 * менять только в одном месте, а не по всему коду. Везде, где
 * результат вывода на дисплей должен зависеть от размера экрана,
 * следует использовать эти константы.
 */
enum { LCD_WIDTH = 16, LCD_HEIGHT = 2 };

/* Объявляем объект нашего дисплея */
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


void setup()
{
  /* Регистрируем собственные символы с кодами 0, 1 и 2 */
  lcd.createChar(0, arnie);
  lcd.createChar(1, skull_and_bones);
  lcd.createChar(2, lightning);
  /* Начинаем работу с дисплееем */
  lcd.begin(LCD_WIDTH, LCD_HEIGHT);
}


typedef void (*LCD_demo)();

/* Это список демо-функций. Добавляйте свои или меняйте их порядок,
 * если хотите разнообразить этот скетч (:
 */
LCD_demo const demos[] =
{
  showArnie,
  showWarning,
  showScrolling,
  showAutoscroll,
  showRTL
};

/* Этот макрос - обычный "синтаксический сахар". Мне просто влом писать
 * по 10 почти одинаковых циклов for. Конечно, в серьёзном коде такое лучше не писать.
 */
#define dotimes(n, code) for (int i = 0; i < (n); ++i) code;


void loop()
{
  dotimes(sizeof(demos) / sizeof(demos[0]),
  {
    demos[i](); // запускаем очередную демонстрацию

    /* Даём насладиться её последними "кадрами", после чего очищаем экран */
    delay(2000);
    lcd.clear();
    delay(1000);
  });
}


void showArnie()
{
  lcd.cursor(); // показываем курсор
  lcd.blink(); // заставляем его мигать
  delay(1000);

  lcd.write(0); // выводим наш собственный символ с кодом 0 (ноль)
  lcd.write(' ');
  delay(1000);

  lcd.print("I'll be back"); // угадай, кто на экране (:
  delay(1000);

  lcd.noBlink(); // больше мигать не нужно
  lcd.noCursor(); // прячем курсор
}


void showWarning()
{
  /* Так как коды наших собственных символов - от 0 до 7,
   * можно смело использовать запись символов в строке при помощи
   * восьмеричных кодов: \1, \2 и т.д.
   * НО: код 0 (ноль) в C и C++ используется в качестве маркера конца строки,
   * так что используйте lcd.write(0) для вывода нулевого символа.
   */
  lcd.print("Smoke kills \1"); // в конце строки будет черепок с костями
  delay(2000);

  lcd.setCursor(0, 1); // переходим на следующую строку
  /* Можно вывести молнию как в начале, так и в середине */
  lcd.print("\2 AC/DC \2  rocks");
}


void showScrolling()
{
  lcd.print("I'm scrolling");
  delay(1000);

  /* Прокручиваем текст вправо за экран */
  dotimes(16,
  {
    lcd.scrollDisplayRight();
    delay(150);
  });

  /* И возвращаем на место, прокручивая влево */
  dotimes(16,
  {
    lcd.scrollDisplayLeft();
    delay(150);
  });
}

void showAutoscroll()
{
  lcd.setCursor(LCD_WIDTH - 2, 0);
  lcd.autoscroll(); // включаем автопрокрутку

  const char *text = "autoscroll";

  /* Печатаем строку буква за буквой. Текст будет "выползать" справа. */
  dotimes(strlen(text),
  {
    lcd.write(text[i]);
    delay(200);
  });

  lcd.noAutoscroll(); // выключаем автопрокрутку
}


void showRTL()
{
  lcd.setCursor(LCD_WIDTH - 1, 0);
  lcd.rightToLeft(); // теперь пишем справа налево

  const char *text = "tfel-ot-thgir"; // похоже на заклинание

  /* Печатаем строку буква за буквой. Текст будет выводиться задом наперёд. */
  dotimes(strlen(text),
  {
    lcd.write(text[i]);
    delay(200);
  });

  lcd.leftToRight(); // пишем слева направо
}

Видеозапись процесса работы этого скетча:

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

Теперь о кириллице. Дело в том, что китайцы решили, что поддержка кириллицы — это значит произвольным образом раскидать по таблице знаков кириллические символы, без соответствия какой-либо кодировке. Один добрый человек, Илья Данилов, в далёком 2010 году написал библиотеку LiquidCrystalRus, которая умело справляется с китайской кириллицей, делая её поддержку прозрачной. Однако с тех пор она малость устарела, поэтому я, да не осудит меня автор, её освежил и выкладываю в репозитории.

Напишем с её помощью русский вариант «Hello, World»:

#include <LineDriver.h>
#include <LiquidCrystalExt.h>
#include <LiquidCrystalRus.h>

LiquidCrystalRus lcd(12, 11, 5, 4, 3, 2);

void setup()
{
  lcd.begin(16, 2);
  lcd.print("Здравствуй, мир!");
}

void loop()
{
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
}

Теперь вы знаете всё о работе с библиотекой LiquidCrystal, и в ваших силах создать более функциональное устройство с LCD-дисплеем — нужно только проявить фантазию (:

Для написания статьи были использованы:

Выражаю всяческие благодарности Zoltberg и noonv за железо и помощь в подготовке статьи, а также Илье Данилову за библиотеку с поддержкой кириллицы.


97 комментариев на «“Подключаем LCD-дисплей на базе HD44780 к Arduino”»

    • Судя по ответам, у всех работает, а у меня не желает…

  1. Поддерживаю. Хорошая статья. Четко, конкретно, по делу и с хорошими картинками!
    До меня картинки доходят намного лучше чем буквы )))

    • Отличная статя, спасибо!
      P.S skystorm, согласен)

    • Спасибо за спасибо! Обозначения на фотках специально тщательно вырисовывал, потому что для меня самого обычные схемы не очень-то наглядны — слишком серы и скучны (:

  2. Очень хорошая статья. Наполняя такими вещами сайт, можно привлечь большое количество новичков, ведь очень сложно начать самому с нуля. Спасибо!

    • А я уже пишу 😉
      Тут один товарищ ещё хотел сервами через сдвиговый регистр порулить — об этом тоже будет (:

    • Можно использовать любые пины Arduino — хоть в обратном порядке, хоть вперемешку. Я недавно LCD вообще через сдвиговый регистр подключал (:

  3. Может кто-нибудь подробнее объяснить куда скопировать папку LiquidCrystalRus? Сам скопировал сюда \arduino\libraries. Но при компиляции появляется куча ошибок:
    In file included from HelloWorldRus.cpp:1:
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h:16: error: expected class-name before ‘{‘ token
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h: In constructor ‘LiquidCrystalRus::LiquidCrystalRus(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)’:
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h:21: error: class ‘LiquidCrystalRus’ does not have any field named ‘LiquidCrystal’
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h: In constructor ‘LiquidCrystalRus::LiquidCrystalRus(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)’:
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h:28: error: class ‘LiquidCrystalRus’ does not have any field named ‘LiquidCrystal’
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h: In constructor ‘LiquidCrystalRus::LiquidCrystalRus(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)’:
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h:34: error: class ‘LiquidCrystalRus’ does not have any field named ‘LiquidCrystal’
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h: In constructor ‘LiquidCrystalRus::LiquidCrystalRus(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)’:
    C:\Users\Дмитрий\Desktop\arduino-1.0-rc2\libraries\LiquidCrystalRus/LiquidCrystalRus.h:40: error: class ‘LiquidCrystalRus’ does not have any field named ‘LiquidCrystal’
    HelloWorldRus.cpp: In function ‘void setup()’:
    HelloWorldRus.pde:-1: error: ‘class LiquidCrystalRus’ has no member named ‘print’

    • В Arduino 1.0 чуточку поломали обратную совместимость.
      Создал в репозиториях на GitHub отдельные ветки arduino-1.x для библиотек LineDriver, LiquidCrystalExt и LiquidCrystalRus, не забудьте обновить все три. Можете через git:

      git clone git://github.com/RoboCraft/LineDriver.git -b arduino-1.x
      git clone git://github.com/RoboCraft/LiquidCrystalExt.git -b arduino-1.x
      git clone git://github.com/RoboCraft/LiquidCrystalRus.git -b arduino-1.x

      или скачав их архивами:

    • Как и в прошлый раз — в arduino-1.0-rc2\libraries. Можно также создать папку «libraries» в папке, где у вас скетчи лежат (у вас это C:\Users\Дмитрий\Documents\Arduino), и распаковать в неё — так даже правильнее будет (:

    • все скопировал в папку libraries\LiquidCrystalRus. Теперь компилируется без ошибок, но все равно не на русском

    • Скиньте мне в личку скетч, который не работает.

    • Залил скетч AlphabetRus, так там через одну русская буква через одну кракозябра

    • Все дело в синтаксической ошибке в файле LiquidCrystalRus.cpp:

      size_t LiquidCrystalRus::write(uint8_t value)
      {
      uint8_t out_char = value;
      if (value >= 0x80) // UTF-8 handling
      {
      if (value >= 0xc0)
      utf_hi_char = value — 0xd0;
      else
      {
      value &= 0x3f;
      if (!utf_hi_char && value == 1)
      out_char = 0xa2; // РЃ
      else if (utf_hi_char == 1 && value == 0x11)
      out_char = 0xb5; // С‘
      else
      out_char = pgm_read_byte_near(utf_recode + value + (utf_hi_char << 6) — 0x10);

      return LiquidCrystal::write(out_char);
      }
      }
      return LiquidCrystal::write(out_char);
      }

      а на самом деле в последней строчке должно быть :else return LiquidCrystal::write(out_char);
      иначе при вводе русских букв они в начале обрабатываются и выводятся как русские, а потом выводятся как «кракозябры» пр обработке символов из основной кодировки. Исправьте пожалуйста исходник.

    • На самом деле, эта ошибка уже давно была исправлена, а исправленный код лежал в репозитории. Но, раз уж вы напомнили, я обновил библиотеку для совместимости с Arduino 1.x и залил в репозиторий, а заодно обновил ссылку на архив — теперь он будет браться напрямую с GitHub.

    • Версия LiquidCrystalRus для Arduino 1.0 есть в репозитории на GitHub в ветке arduino-1.x, брать тут.
      Т.к. LiquidCrystalRus требует также библиотеки LineDriver и LiquidCrystalExt, нужно скачать и их: раз и два.

      Позже я обновлю ссылки на наши библиотеки во всех статьях.

    • Использовал последние библиотеки, все равно не компилируется, все равно выдает ошибки
      In file included from LCD_example.cpp:6:
      G:\программы\Arduino\arduino-1.0.1\libraries\LiquidCrystal/LiquidCrystal.h:45: error: redefinition of ‘class LiquidCrystal’
      G:\программы\Arduino\arduino-1.0.1\libraries\LiquidCrystalExt/LiquidCrystalExt.h:112: error: previous definition of ‘class LiquidCrystal’

      Что еще там нужно править?

    • Вот незадача. Постараюсь завтра посмотреть; если не получится — в понедельник. Во втором случае черканите в личку в понедельник — на всякий случай: я тут неравный бой с ARM веду, могу и забыть ненароком.

  4. Не скажите почему таблица символов в даташите на НД44780 отличается от стандартной таблице, которая прописана и в CV AVR и везде в статьях выдается? Спасибо.

    • В описании написано:

      Обратите внимание — потенциометр регулировки контраста включается между +5В и 15 ногой, подсветка включается подачей GND (через резистор!) на 16 ногу!

      Это единственное отличие в подключении этого дисплея, всё остальное — так же, как в статье.

    • Да точно, единственное отличие. Но как это — между 5 вольтами и 15 ногой??? Можно сказать между Шестью и восемью вольтами или между Тринадцатой и пятнадцатой ногой, это же совсем разные системы счисления!..

      И вопрос не по теме — Когда планируется следующий урок по ARM???

    • Только заметил новый коммент. Раз по теме всё понятно, отвечаю не по теме — урок почти дописан, скоро будет. В праздники я честно балду гонял, поэтому так долго (:

    • Если попадётся когда-нибудь недорогой вариант и будет время — почему бы и нет. Дисплей, использованный в статье по ссылке, стоит около 20$, а показывает всего-то 20 символов. Дорогое удовольствие получается.

  5. Извините если не в тему, но тоже про дисплей. Попалась мне мини-АТС LG LKD-30DS с дисплеем 24х2 18 ножек имеет. Есть ли какие-нибудь аналоги этого дисплея, чтобы можно было сориентироваться с выходами? Хотел бы подключить к крафтдуино. На нем написано P24201B-C R4-H(R.1). Имеет на борту 3 микросхемы (капли). Если кто может помочь, буду очень рад 🙂

    • Вышеуказанные способы не сработали. В общем спишу на дисплей (3шт.). Может у них там что-то с прошивкой, не знаю

    • Разобрался! Подключение точно такое же как и любого другого дисплея.

  6. Скажите а можно подключить 2 таких дисплея к одной Arduino? Точнее я понимаю что можно. Интересует можно ли использовать какие-то выводы ардуины как общие для двух дисплеев? Для экономии. Ну, к примеру, могу я подключать к разным выводам ардуины только входы DB4-DB7 дисплеев?

    • Думаю что скетч работать будет только с одним из двух. А собственно выходов-то хватить?

    • Вы же в скетче будете прописывать куда (12,11,10,5-2) «вещать» данные? Вот и будете получать только на том дисплее куда и посылаете данные

    • Я имел ввиду можно ли какие-то из этих выводов использовать как общие для нескольких дисплеев. Понятно что можно прописывать
      LiquidCrystalRus lcd_1(12, 11, 5, 4, 3, 2);
      LiquidCrystalRus lcd_2(13, 10, 9, 8, 7, 6);

      Но это ведет к лишним подключениям проводов, да и выводы занимает. На Arduino Mega их 54 конечно, но мне есть чем их занять.

    • Судя по всему, так можно сделать, только нужно, чтобы как минимум линии ENABLE были свои для каждого дисплея. Я так не пробовал ещё, сужу по коду библиотеки.

    • Своими раскопками получил такую же информацию. Да вот проблема что попробовать не могу. Дисплеи в пути еще, а распланировать нужно. Если есть возможность попробовать повесить 2 дисплея с разделением только пина E был бы премного благодарен за информацию о результатах испытаний.

    • Интуиция нас не обманула: всё работает именно так — раздельные линии ENABLE, все остальные общие. Подключал два дисплея — 16×2 и 8×2, оба в 4-битном режиме. Завёл счётчик и выводил его значение попеременно то на один дисплей, то на другой. Всё работает без проблем.

      фотка с дисплеями и STM32VLDISCOVERY

      Жёлтые провода — это ENABLE.

    • Это отличные новости. Спасибо огромное за эксперимент и фото. Почему-то в инете не смог накопать информации по этому поводу.

  7. Здравствуйте. У меня Arduino UNO появилась месяц назад. Вот решил попробывать в ней разобраться. Подключил LCD дисплей выбрал в примерах пример «Hello world!». У меня ничего на дисплее не происходит (как горел изначально, так и продолжает гореть), а мне на экране компьютера пишет:
    Binary sketch size: 2.570 bytes (of a 32.256 byte maximum)
    avrdude: stk500_getsync(): not in sync: resp=0x00
    Как запустить «Hello world»?

    • Очевидно же, что проблема не с дисплеем, а с подключением Arduino: IDE не находит плату и не заливает скетч. К сожалению, этой версии Arduino у меня нет, так что Google вам в помощь. На будущее: задавая подобные вопросы, пишите, какая у вас ОС (хотя по формулировке вашего вопроса догадываюсь, что Windows — XP или 7) и какая версия Arduino IDE: старые версии IDE могут не поддерживать Uno. Кстати, проверьте, что в меню IDE у вас выбрана правильная плата (Tools⇨Board⇨Arduino Uno) и соответствующий Serial port.

  8. подскажите пожалуйста, в чем может быть проблема. заказал дисплей 1602А. все соединил, как в инструкции, но у дисплея работает только подсветка. потенциометр крутил, но на дисплее ничего не менялось. пробовал разные скетчи

    • Ну, я не знаю… Перепроверьте подключение, запостите фотку подключения, на которой отчётливо видно, куда какой провод идёт.

  9. Уважаемые! Кто может разьяснить: суть вопроса-скопировал «русскую библиотеку» для жки в папку«библиотека» Ардуино, операционная система на компе-Windows-7.При копировании русской библиотеке выдается сообщение-«библиотека не может быть использована».Естественно при компиляции скетча выдаются ошибки.?

  10. Если при подключении LCD к ардуино постоянно горит верхний ряд, регулировка контраста работает, но загружаемые скетчи никак не влияют на поведение дисплея, это значит что дисплей сломан?
    Может ли неверное подключение повредить дисплей? При подключении WH0802A было перепутано направление нумерации… 🙁

    • Ну, если вы перепутали Vcc и GND, то дисплей мог сломаться — и то, обычно электроника достаточно устойчива даже к таким издевательствам. Но у вас он, судя по всему, работает. Если заполнен верхний ряд, то, скорее всего, у вас до сих пор имеет место неверное подключение; перепроверьте его. Не мешало бы открыть даташит на ваш конкретный дисплей и свериться с распиновкой. И, если ничего не поможет, запостите фотку вашего подключения — поглядим зоркими глазами (:

    • Второй раз все собрал, прозвонил:

      Сделал такой переходник для LCD:

      Все в сборе:

      В общем, перед этим подключил дисплей так, что на DB7 попало +5, а на DB6 — GND…

  11. Не компилируется с ошибкой:
    /usr/share/arduino/libraries/LiquidCrystalRus/LiquidCrystalRus.cpp:38:15: error: ‘prog_uchar’ does not name a type
    /usr/share/arduino/libraries/LiquidCrystalRus/LiquidCrystalRus.cpp: In member function ‘virtual size_t LiquidCrystalRus::write(uint8_t)’:
    /usr/share/arduino/libraries/LiquidCrystalRus/LiquidCrystalRus.cpp:97:20: error: ‘utf_recode’ was not declared in this scope
    Что я делаю не так?

    • Сам не раз так прокалывался, теперь все соединения по три раза проверяю (:

    • Сбило с толку то, что оно нормально звонилось. Вернее звонился штейкер одетый сверху. А до ножек на самом дисплее я видимо достучался не до всех.

    • Японский городовой, это же японская слоговая азбука катакана! Проблема в том, что в вашем дисплее кодам символов из второй половина таблицы ASCII были назначены японские знаки, а русских там нет. Зато, если в памяти дисплея забита вся азбука, можете на нём показывать крутые смайлики — си シ и цу ツ, если подберёте коды этих символов. Ну или можно обменяться с электронщиком-анимешником и узреть скульптуру «писающий кипятком мальчик» (:

  12. Здравствуйте!
    Собрал вот такую схемку s017.radikal.ru/i414/1304/5c/e448cc1beec0.jpg
    Вот скеч:

    #include <LiquidCrystal.h> // бібліотека lcd

    LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // призначення виводів lcd

    float opn=5; // опорна напруга
    float volt1; // змінна напруги на вході В
    float volt2; // змінна напруги на виході В
    float amp; // змінна струму на виході мА
    float var0; // проміжне значення вольт на ан. вх. №0
    float var1; // проміжне значення вольт на ан. вх. №1
    int pinSensor =A0; // назначаєм ф-ю ан. вх. №0 зчитування з потенціометра
    int ledPin =9; // назначаєм ф-ю циф. вих. №9 — світлодіод
    int valorSensor =0;

    void setup()
    {
    pinMode(ledPin, OUTPUT); // назначаєм вих. світлодіода як вихід
    lcd.begin(16, 2); // ініціалізація LCD 1602
    }

    void loop ()
    {
    valorSensor = analogRead(pinSensor); // зчитуєм з ан. вх.
    analogWrite(ledPin, valorSensor / 4);// посилаєм шім на циф. вих. і ділим 1024 на 4 (255)
    var0 = analogRead(0); // призначаєм значення на ан. вх. №0 змінній var0
    var1 = analogRead(1); // призначаєм значення на ан. вх. №1 змінній var1
    volt1 =(opn*var0/1024.0); // вираховуєм кінцеве значення напруги
    volt2 =(opn*var1/1024.0); // вираховуєм кінцеве значення напруги
    amp =((opn*var1/1024.0)/125*1000); // вираховуєм кінцеве значення струму

    lcd.setCursor(0,0); // установка курсора по адр. 0,0
    lcd.print(volt1); // виводим значення напруги на ан. вив. №0
    lcd.print(«V»); // пишим букву V
    lcd.setCursor(0,1); // установка курсора по адр. 0,1
    lcd.print(volt2); // виводим значення напруги на ан. вив. №1
    lcd.print(«V»); // пишим букву V
    lcd.setCursor(6,1); // установка курсора по адр. 6,1
    lcd.print(amp); // виводим значення струму на ан. вив. №1
    lcd.print(«mA»); // пишим букви mA

    delay(333); // пауза 0,333 с
    lcd.clear(); // очищаєм дисплей

    }

    Коментарии на украинском, если что не понятно, постараюсь обяснить.

    Вопрос: как зделать чтоб текст на дисплее появлялся только после изменения положения ползунка переменного резистора и исчезал до очередного изменения?

    Спасибо!

  13. Извините конечно если мой вопрос покажется бональным, но как выводить на дисплей результаты измерения с какого нибудь датчика например DHT11? у меня конечно есть догадки, но поэксперементировать пока времени нет.

    • zelectro.com.ua/TemperatureHumiditySensor
      Там как раз такой датчик используется. Если будете пробовать, напишите, получилось ли. А я попробую ультразвуковой датчик расстояния по аналогии присоединить.

    • Подключил уже))все работает даже сделал шаблон чтоб все это как термостат или регулятор влажности юзать. а у тя как с датчиком расстояния?

    • Пока никак, я только сегодня с дисплеем разобрался более-менее.
      Но на днях планирую сделать. Выставлю, если настроение будет на форум, может кому полезно будет)

    • Получилось с ультразвуковым дальномером и выводом расстояния в сантиметрах на дисплей. Скетч простой как двери, если нужно, могу тиснуть статейку

  14. Со стороны Китая мне тут пришла пара дисплеев HD44780 с катаканой, зашитой вместо кириллицы в знакогенераторе. По понятным причинам RusLiquidCrystal не завёлся. Основательно нагуглившись, я пришёл к мысли, что на сегодняшний день никто эту бяку с катаканой выводить русский пока не научил.
    Размыслив немного над проблемой, я за день создал под это дело маленькую библиотеку (скромно, по нику названную) WolfCrystal.

    Добыть последнюю версию можно здесь: http://github.com/Wolf4D/WolfCrystal
    Архивом: http://github.com/Wolf4D/WolfCrystal/archive/master.zip


    Принцип действия прост — русские буквы частью (на лету) заменяются похожими из набора имеющихся символов, частью рисуются с использованием пользовательских символов (глифов). Реализация (с учётом корявости местного Си) местами страшновата, но вполне работоспособна.

    HD44780 Arduino русский кириллица
    P.S. По умолчанию все строчные русские буквы переводятся в прописные.
    О причинах и способе отключить данную опцию см. справку.

  15. Доброго времени суток. Господа, я абсолютный нуб в этом, но вот решил познакомиться с микроконтроллером Freeduino Through-Hole и дисплеем WH1602B-YYK-CTK. Соединяю все согласно схеме на сайте фридуино. После записи скетча дисплей начинает выдавать рандомные символы целыми строчками. Скетч не выполняется. Кто-нибудь сталкивался с подобным?

  16. На IDE 1.0.6 всё работает отлично. Когда я пытаюсь использовать библиотеку LiquidCrystalRus в версии IDE 1.6.1 — тестовые скетчи библиотеки работают и на экране всё видно.
    После использования библиотеки в моей программе и заливки с помощью 1.6.1 моего скетча уже получаю на экране сдвиг влево на четыре символа. Есть мысли, как этого избежать?

    Скетч использую этот https://yadi.sk/d/UpEOkOAhfSMwE

  17. Проблема! Долго мучался с подключением, перепаивал несколько раз. В итоге получил на дисплее результат работы скетча. Вылезла другая проблема. Верхняя строка отобразается только на половину высоты, т.е. верхняя часть букв видна, а нижняя — нет.

  18. Скажите, а как вывести русский шрифт на дисплей в знакогенераторе которого нет русских букв?
    Т.е. библиотека LiquidCrystalRus успешно рисует те русские буквы, аналоги которых есть в английском шрифте, а вместо остальных рисует иероглифы

    • Боюсь, никак — это врождённый недостаток подобных дисплеев. По-хорошему, если хочется настоящей универсальности, следует использовать графические дисплеи, т.к. там можно нарисовать что угодно, и можно просто создать свой шрифт.

    • У меня у самого 1602 с катаканой пример ни авторский ни wolfCrystal почему то не завелись(скорее всего рукожопость), помогла библиотека LiquidCrystal_1602_RUS ищется быстро в GitHub ну естественно с некоторыми ограничениями

  19. При компиляции с библиотекой автора выдается такая ошибка… Что можно поправить?
    Arduino: 1.6.7 (Windows 7), Плата:«Arduino Nano, ATmega328»
    In file included from C:\Users\YG\Documents\Arduino\libraries\RoboCraft-LiquidCrystalRus-ce8603e\examples\HelloWorldRus\HelloWorldRus.ino:1:0:
    C:\Users\YG\Documents\Arduino\libraries\RoboCraft-LiquidCrystalRus-ce8603e/LiquidCrystalRus.h:30:24: fatal error: LineDriver.h: No such file or directory
    #include «LineDriver.h»
    ^
    compilation terminated.
    exit status 1
    Ошибка компиляции.
    Это сообщение будет содержать больше информации чем
    «Отображать вывод во время компиляции»
    включено в Файл > Настройки

  20. Доброго времени, подскажите пожалуйста, а есть пример как считывать данные с дисплея?
    я так понимаю в библиотеке LiquidCrystal нет нужных команд или я ошибаюсь?

    • На момент написания статьи таких команд не было. Давно не занимался ардуйнёй, не в курсе, какова ситуация сейчас.

  21. у меня вот этот код

    #include <LiquidCrystal.h>
    #include <LiquidCrystalRus.h>
    
    LiquidCrystalRus lcd(12, 11, 5, 4, 3, 2);
    
    void setup()
    {
      lcd.begin(16, 2);
      lcd.print("Здравствуй, мир!");
    }
    
    void loop()
    {
      lcd.setCursor(0, 1);
      lcd.print(millis() / 1000);
    }

    скомпилировался только тогда, когда убрал строчку #include <LiquidCrystal.h>. Ну и кракозяблы соответственно

  22. Русский язык вот так подключил, перед тем как вставлять прогоняю просто через конвертер. LiquidCrystalRus у меня так и не заработал.

    Это обычный html, создайте например 1.html и вставьте туда этот код

    <META http-equiv=Content-Type content="text/html; charset=UTF-8">
     <script type="text/javascript">
    
    var abc1 = new Array();
    abc1['а'] = 'a';
    abc1['б'] = '\\262';
    abc1['в'] = '\\263';
    abc1['г'] = '\\264';
    abc1['д'] = '\\343';
    abc1['е'] = 'e';
    abc1['ё'] = '\\265';
    abc1['ж'] = '\\266';
    abc1['з'] = '\\267';
    abc1['и'] = '\\270';
    abc1['й'] = '\\271';
    abc1['к'] = '\\272';
    abc1['л'] = '\\273';
    abc1['м'] = '\\274';
    abc1['н'] = '\\275';
    abc1['о'] = 'o';
    abc1['п'] = '\\276';
    abc1['р'] = 'p';
    abc1['с'] = 'c';
    abc1['т'] = '\\277';
    abc1['у'] = 'y';
    abc1['ф'] = '\\344';
    abc1['х'] = '\\325';
    abc1['ц'] = '\\345';
    abc1['ч'] = '\\300';
    abc1['ш'] = '\\301';
    abc1['щ'] = 'w';
    abc1['ъ'] = '\\302';
    abc1['ы'] = '\\303';
    abc1['ь'] = '\\304';
    abc1['э'] = '\\305';
    abc1['ю'] = '\\306';
    abc1['я'] = '\\307';
    abc1['А'] = 'A';
    abc1['Б'] = '\\240';
    abc1['В'] = 'B';
    abc1['Г'] = '\\241';
    abc1['Д'] = '\\340';
    abc1['Е'] = 'E';
    abc1['Ё'] = '\\242';
    abc1['Ж'] = '\\243';
    abc1['З'] = '\\244';
    abc1['И'] = '\\245';
    abc1['Й'] = '\\246';
    abc1['К'] = 'K';
    abc1['Л'] = '\\247';
    abc1['М'] = 'M';
    abc1['Н'] = 'H';
    abc1['О'] = 'O';
    abc1['П'] = '\\250';
    abc1['Р'] = 'P';
    abc1['С'] = 'C';
    abc1['Т'] = 'T';
    abc1['У'] = '\\251';
    abc1['Ф'] = '\\252';
    abc1['Х'] = 'X';
    abc1['Ц'] = '\\341';
    abc1['Ч'] = '\\253';
    abc1['Ш'] = '\\254';
    abc1['Щ'] = '\\342';
    abc1['Ъ'] = '\\255';
    abc1['Ы'] = '\\256';
    abc1['Ь'] = '\'\'';
    abc1['Э'] = '\\257';
    abc1['Ю'] = '\\260';
    abc1['Я'] = '\\261';
    
    function translatesymboltocharset1(symb)
    {
    	return abc1[symb]?abc1[symb]:symb;
    }
    
       function form1(txt) {
    
    	var txtnew = '';
    
    
    	for (kk=0;kk<txt.length;kk++)
    	{
    		symb = translatesymboltocharset1(txt.substr(kk,1));
    		txtnew = txtnew.substr(0,txtnew.length) + symb;
    	}
    	document.getElementById("r").value = txtnew;
    
    
       }
      </script>
    
    
    <textarea id='s' onkeyup="form1(this.value)" style="width:300px;height:100px"></textarea>
    <textarea id='r' style="width:300px;height:100px"></textarea>
    • Я сейчас поробовал скопи-пастить текст программы и запустив проверку получаю сообщение call of overloaded write(int)’is ambiguous на строке lcd.write(0); // выводим наш собственный символ с кодом 0 (ноль) Попробовал исправить, вплоть до полного удаления комментария, всё равно — call of overloaded write(int)’is ambiguous
      Объясните пожалуйста, почему так и как с этим бороться?
      Благодарю заранее.

    • Ну, кто- нибудь, ответьте пожалуйста, почему не компилируется

      #include <LiquidCrystal.h>
      #include <LiquidCrystalRus.h>

      LiquidCrystalRus lcd(12, 11, 5, 4, 3, 2);

      void setup()
      {
      lcd.begin(16, 2);
      lcd.print(«Здравствуй, мир!»);
      }

      void loop()
      {
      lcd.setCursor(0, 1);
      lcd.print(millis() / 1000);
      }

      Ошибка ‘LiquidCrystalRus’ does not name a type

    • Он почему-то не хочет нуль обрабатывать. Изменил номер, под которым зарегистрировал символ «arnie» на 3 — и всё заработало.

      lcd.createChar(3, arnie); 

      lcd.write(3); 
  23. Кто глазастый или в теме подскажите, пожалуйста, что не так. Подключил все как нужно (прозвонил все 100 раз), дисплей 20х4 (новый, эксперименты над ним не ставились, поэтому подразумевается, что рабочий)

    При неверном подключении или неверном порядке или номерам ПИНов получаю стандартное тестирование.

    При верном подключении всегда получаю следующее, но только не текст.

    #include <LiquidCrystal.h>
    
    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
    
    void setup()
    {
     lcd.begin(20, 4);
     lcd.print("hello, world!");
    }
    
    void loop()
    {
     lcd.setCursor(0, 1);
     lcd.print(millis() / 1000);
    }
    • А модель дисплея указать? У вашего может быть другой порядок пинов.

    • Насколько могу судить порядок тот же самый. QY-2004A при неверном порядке получаю тестирование, то есть ту странную картину я получаю только в одном случае, во всех остальных тестирование. По крайней мере я подключал по маркировке на ножках и их порядок такой же как на картинке на сайте arduino

  24. Не смог собрать с русским, сделал по своему.
    В скетч добавляем

    // except 0401 --> 0xa2 = Ё, 0451 --> 0xb5 = ё
    const prog_uchar utf_recode[] PROGMEM =
    {
      0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,
      0xa8,0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1,
      0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,
      0xbe,0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0,0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7
    };
    
    char* RusStr(char *data)
    {
      int i=0;
      for(i = 0; i < strlen(data); i++) data[i] = RusChar(data[i]);
    return data;
    }
    
    uint8_t RusChar(uint8_t data)
    {
      uint8_t utf_hi_char; // UTF-8 high part
      uint8_t out_char = data;
    
      if (data >= 0x80) // UTF-8 handling
      {
        if (data >= 0xc0)
          utf_hi_char = data - 0xd0;
        else
        {
          data &= 0x3f;
    
          if (!utf_hi_char && data == 1)
            out_char = 0xa2; // Ё
          else if (utf_hi_char == 1 && data == 0x11)
            out_char = 0xb5; // ё
          else
            out_char = pgm_read_byte_near(utf_recode + data + (utf_hi_char << 6) - 0x10);
    
          return out_char;
        }
      }
      else
        return out_char;
    }
    

    Используем так

    lcd.print(RusStr("Привет, мир!"));
    

    Ничего кроме #include <LiquidCrystal.h> подключать не нужно

    • Решение корявенькое, конечно. Оно правда работает? Судя по коду, не должно. К тому же, что будет при попытке вывести один и тот же строковый литерал два раза подряд? Обычно компилятор назначает одинаковым строковым литералам одинаковые адреса памяти, чтобы минимизировать использование памяти. Это работает корректно, т.к. строковые литералы по стандарту C++ являются указателями на константные данные (const char *) и неизменяемыми. В вашем же коде переданный литерал («Привет, мир!») меняется

      data[i] = RusChar(data[i])

      и так делать — плохо.

      Как бы там ни было, если оно-таки работает, я бы рекомендовал сделать что-то вроде:

      char* RusStr(const char *in, char *out)
      {
        for ( ; *in != 0; ++in, ++out)
          *out = RusChar(*in);
      
        return data;
      }

      Ну, и объявление utf_hi_char должно, по смыслу кода, быть таким:

      static uint8_t utf_hi_char;
    • Таблицу перекодировки взял с LiquidCrystalRus.
      Решение не корявенькое, корявенько подключать мутные модули которые не собираются без костылей ради одной функции по перекодированию одного числа в другое.
      Работать должно, у меня дисплей без кириллицы оказался, пробовал выдать в него от 0 до 255, русских букв нет.

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение