ЖК (жидкокристаллические) дисплеи в настоящее время являются одними из самых популярных типов дисплеев, используемых в современной электронике. В большинстве своем они используют для работы драйвер Hitachi HD44780. В данной статье мы рассмотрим подключение алфавитно-цифрового ЖК дисплея 20x4, работающего на основе драйвера Hitachi HD44780 к плате Raspberry Pi 4, и попробуем выводить на экран данного дисплея строки символов, производить скроллинг текста, создавать новые пользовательские символы и многое другое.
В проекте мы будем использовать библиотеку RPLCD from PyPI. С ее помощью можно создавать собственные пользовательские функции для работы с ЖК дисплеем: скроллинг текста, создание новых символов и т.п.
Необходимые компоненты
- Плата Raspberry Pi 4 (или другая подходящая модель платы) (купить на AliExpress) (Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158).
- ЖК дисплей 20x4.
- Соединительные провода.
ЖК дисплей 20x4
"Сердцем" данного ЖК дисплея является схема драйвера HD44780. Даташит на нее можно посмотреть по следующей ссылке. Данный дисплей можно подключить к плате Raspberry Pi двумя способами: по интерфейсу I2C или с помощью непосредственного подключения контактов. Однако второй способ потребует использования 14 контактов платы Raspberry Pi, также он займет и контакты SPI порта платы если мы будем использовать 8-битный способ передачи. Поэтому в данной статье мы будем использовать интерфейс I2C для подключения дисплея к плате Raspberry Pi.
Если у вас нет модуля I2C, то тогда можно использовать следующую схему подключения дисплея к плате:
Контакт ЖК дисплея | Контакт Raspberry Pi |
RS | 15 |
RW | 18 |
E | 16 |
Data 4 | 21 |
Data 5 | 22 |
Data 6 | 23 |
Data 7 | 24 |
Другие альтернативные способы подключения ЖК дисплея 20x4 к плате Raspberry Pi вы можете посмотреть в документации RPLCD.
Модуль расширения I2C PCF8574
Данный модуль позволяет преобразовать параллельные контакты общего назначения в стандартную двунаправленную двухпроводную шину интерфейса I2C (линии SCL и SDA). Модуль имеет очень низкое потребление тока (2.5uA) что делает его пригодным для применения в мобильных приложениях. Диапазон питающих напряжения для модуля: от 2.5 V до 6V. Может обеспечивать Latched-выходы для непосредственного управления светодиодами.
Схема проекта
Схема подключения ЖК дисплея 20x4 к плате Raspberry Pi по интерфейсу I2C представлена на следующем рисунке.
Как видите, использование интерфейса I2C, значительно упрощает подключения ЖК дисплея к плате Raspberry Pi.
Внешний вид собранной конструкции проекта показан на следующем рисунке.
На следующем рисунке показана способ формирования блоков для отображения символов на экране ЖК дисплея 20x4. Из рисунка видно, что для отображения одного символа на экране дисплея используется блок (матрица) 8x5 пикселов.
Установка необходимых библиотек для работы с ЖК дисплеем 20x4
В данном проекте для работы с дисплеем мы будем использовать библиотеку RPLCD from PyPI. Ее можно установить в плату Raspberry Pi с помощью команды:
1 |
Sudo pip install RPLCD |
Если вы используете I2C модуль для подключения дисплея, то в этом случае вам необходимо будет установить и библиотеку Python-SMBUS. Ее можно установить с помощью следующей команды:
1 |
sudo apt install python-smbus |
или с помощью команды:
1 |
sudo pip install smbus2 |
Библиотека RPLCD будет автоматически использовать необходимые функции из библиотеки smbus. После установки библиотек вы увидите запрос на установку адреса I2C. В случае использования I2C модуля PCF8574 (вместо него можно также использовать модули MCP2308 или MCP23017) у него будет I2C адрес равный 0x27. Подробнее о том, как определить I2C адрес устройства, подключенного к плате Raspberry Pi, можно прочитать в этой статье.
В нашем проекте мы используем ЖК дисплей в 4-битном режиме – интерфейс I2C будет работать только в этом режиме, в 8-битном режиме он уже работать не будет.
Код программы для вывода строки на ЖК дисплей 20x4
Попробуем вывести строку символов ‘Hello world’ на экран ЖК дисплея. Для этого создадим новый python файл, его имя вы можете выбрать по своему желанию. Вначале этой программы подключим (импортируем) необходимые библиотеки и создадим объект для работы с ЖК дисплеем.
1 2 3 4 |
from RPLCD import * from time import sleep from RPLCD.i2c import CharLCD lcd = CharLCD('PCF8574', 0x27) |
Библиотека RPLCD содержит файл i2c.py и импортируя его мы получаем доступ к всем методам (функциям), содержащимся в "i2c.py". При создании объекта для работы с ЖК дисплеем с помощью функции CharLCD(), нам необходимо указать I2C имя устройства (у нас это PCF8574) и I2C адрес устройства (в нашем случае 0x27).
Далее вывести строку символов на экран дисплея можно с помощью функции lcd.write_string(). Позицию курсора для вывода начала этой строки можно изменить с помощью функции cursor_pos(m,n). Для ЖК дисплея 20x4 номер строки m может принимать значения от 0 до 3, а номер столбца n – значения от 0 до 19.
Но помните о том, что с помощью функции lcd.write_string() на экран дисплея можно вывести только строку, но нельзя вывести значение целого типа (integer). Чтобы вывести значение целого типа на экран дисплея его предварительно необходимо конвертировать в строку. С помощью функции lcd.write_string() можно вывести строку на двух строках дисплея если отключена опция auto_linebreak().
1 2 |
lcd.cursor_pos = (0, 0) lcd.write_string('Hello World') |
Код программы для скроллинга текста на экране дисплея
Поскольку у нас нет в распоряжении никакой готовой функции для вывода длинного текста в одной строке или для скроллинга текста, то попробуем запрограммировать ее самостоятельно.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
framebuffer = [ '', '', ] def write_to_lcd(lcd, framebuffer, num_cols): """Write the framebuffer out to the specified LCD.""" lcd.home() for row in framebuffer: lcd.write_string(row.ljust(num_cols)[:num_cols]) lcd.write_string('\r\n') def long_text(text): if len(text)<20: lcd.write_string(text) for i in range(len(text) - 20 + 1): framebuffer[1] = text[i:i+20] write_to_lcd(lcd, framebuffer, 20) sleep(0.2) |
В представленном фрагменте кода мы используем способ буферизации кадров для отображения длинных строк. Также мы используем двухмерный массив, содержащий строки и столбцы, для вывода информации на экран ЖК дисплея 20x4.
После этого для вывода длинного текста с помощью скроллинга мы используем функцию:
1 2 |
lcd.cursor_pos = (1, 0) long_text('This is a long Scrolling text') |
Эта команда выведет скроллинг текста во второй строке ЖК дисплея как показано на следующем рисунке:
Код программы для создания нового символа
Мы можем создавать свои собственные символы для вывода на экран ЖК дисплея с помощью функции create_char(location,bitmap_tuple).
Переменная location в этой функции – это местоположение символа в памяти, а bitmap_tuple – двухмерный массив данных размером 5х8 элементов (пикселов). Массива 5х8 пикселов достаточно для представления всех символов английского алфавита.
Используемый нами ЖК дисплей содержит память для хранения 8 новых пользовательских символов. Каждый из них может храниться по любому адресу в диапазоне от x00 до x07. Обращаясь по нужному адресу, мы можем “вызвать” нужный нам символ.
Создадим массивы растровых данных для хранения символов “locked” и “unlock”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Locked = ( 0b00000, 0b01110, 0b10001, 0b10001, 0b11111, 0b11111, 0b11011, 0b11111 ) Un_Locked = ( 0b00000, 0b01110, 0b00001, 0b00001, 0b11111, 0b11111, 0b11011, 0b11111 ) |
Разместим символ “Locked” по адресу 0.
1 |
lcd.create_char(0, Locked) |
Выведем на экран наш символ “Locked” на позиции (2,4).
1 2 |
lcd.cursor_pos = (2, 4) lcd.write_string(‘\x00’) |
Аналогичным образом вы можете создавать свои любые символы для их последующего вывода на экран ЖК дисплея 20x4.
Код программы для индикации заряда батареи
Сначала создадим битовые массивы для необходимых нам символов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
battery_EMP = ( 0b00000, 0b01110, 0b11111, 0b10001, 0b10001, 0b10001, 0b10001, 0b11111 ) battery_HLF = ( 0b00000, 0b01110, 0b11111, 0b10001, 0b10001, 0b11111, 0b11111, 0b11111 ) battery_FULL = ( 0b00000, 0b01110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 ) |
После этого мы будем по очереди выводить их на экран дисплея на одной и той же позиции курсора.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
lcd.create_char(2, battery_EMP) lcd.create_char(3, battery_HLF) lcd.create_char(4, battery_FULL) while 1: lcd.cursor_pos = (0, 0) lcd.write_string('Battery Charging') lcd.cursor_pos = (0, 19) lcd.write_string(‘\x02’) sleep(.4) lcd.cursor_pos = (0, 19) lcd.write_string(‘\x03’) sleep(.4) lcd.cursor_pos = (0, 19) lcd.write_string(‘\x04’) sleep(.6) |
Код программы для создания нескольких символов
Мы создадим 4 символа таким образом, чтобы размещенные вместе они формировали улыбающееся лицо человека. Массивы для создания этих символов назовем face_LB, face_LT, face_RT и face_RB. Для создания этих символов можно использовать любой растровый редактор, даже размещенный на каком-нибудь сайте в сети.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
face_LB=( 0b10000, 0b10100, 0b10011, 0b10000, 0b11100, 0b11111, 0b01111, 0b00111 ) face_LT=( 0b10111, 0b10111, 0b01000, 0b01000, 0b10000, 0b10001, 0b10001, 0b10000 ) face_RT=( 0b10101, 0b11101, 0b00010, 0b00010, 0b00001, 0b10001, 0b10001, 0b00001 ) face_RB=( 0b00001, 0b00101, 0b11001, 0b00001, 0b01111, 0b11111, 0b11110, 0b11100 ) lcd.create_char(4, face_LT) lcd.create_char(5, face_RT) lcd.create_char(6, face_LB) lcd.create_char(7, face_RB) lcd.cursor_pos = (0, 0) lcd.write_string('Our Custom Character') lcd.cursor_pos = (2, 4) lcd.write_string('\x04') lcd.cursor_pos = (2, 5) lcd.write_string('\x05') lcd.cursor_pos = (3, 4) lcd.write_string('\x06') lcd.cursor_pos = (3, 5) lcd.write_string('\x07') |
Внешний вид получившегося у нас символа, составленного из 4-х созданных нами символов, показан на следующем рисунке.
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
#Try RPLCD Liberary # from RPLCD-master import * # from RPLCD import RPLCD from RPLCD import * from time import sleep from RPLCD.i2c import CharLCD lcd = CharLCD('PCF8574', 0x27) lcd.cursor_pos = (0, 5) lcd.write_string('Wlcomme to') lcd.cursor_pos = (1, 3) lcd.write_string('Circuit Digest') sleep(2) framebuffer = [ '', '', ] def write_to_lcd(lcd, framebuffer, num_cols): """Write the framebuffer out to the specified LCD.""" lcd.home() for row in framebuffer: lcd.write_string(row.ljust(num_cols)[:num_cols]) lcd.write_string('\r\n') def long_text(text): if len(text)<20: lcd.write_string(text) for i in range(len(text) - 20 + 1): framebuffer[1] = text[i:i+20] write_to_lcd(lcd, framebuffer, 20) sleep(0.2) face_LB=( 0b10000, 0b10100, 0b10011, 0b10000, 0b11100, 0b11111, 0b01111, 0b00111 ) face_LT=( 0b10111, 0b10111, 0b01000, 0b01000, 0b10000, 0b10001, 0b10001, 0b10000 ) face_RT=( 0b10101, 0b11101, 0b00010, 0b00010, 0b00001, 0b10001, 0b10001, 0b00001 ) face_RB=( 0b00001, 0b00101, 0b11001, 0b00001, 0b01111, 0b11111, 0b11110, 0b11100 ) battery_EMP = ( 0b00000, 0b01110, 0b11111, 0b10001, 0b10001, 0b10001, 0b10001, 0b11111 ) battery_HLF = ( 0b00000, 0b01110, 0b11111, 0b10001, 0b10001, 0b11111, 0b11111, 0b11111 ) battery_FULL = ( 0b00000, 0b01110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 ) Locked = ( 0b00000, 0b01110, 0b10001, 0b10001, 0b11111, 0b11111, 0b11011, 0b11111 ) Un_Locked = ( 0b00000, 0b01110, 0b00001, 0b00001, 0b11111, 0b11111, 0b11011, 0b11111 ) lcd.create_char(0, battery_EMP) lcd.create_char(1, battery_HLF) lcd.create_char(2, battery_FULL) lcd.create_char(3, Locked) # lcd.create_char(4, Un_Locked) lcd.create_char(4, face_LT) lcd.create_char(5, face_RT) lcd.create_char(6, face_LB) lcd.create_char(7, face_RB) # U_L_Ch='\x04' L_Ch='\x03' B_F_Ch='\x02' B_H_Ch='\x01' B_E_Ch='\x00' while 1: lcd.clear() lcd.cursor_pos = (0, 0) lcd.write_string('Chargerging') lcd.cursor_pos = (0, 19) lcd.write_string(B_E_Ch) sleep(.4) lcd.cursor_pos = (0, 19) lcd.write_string(B_H_Ch) sleep(.4) lcd.cursor_pos = (0, 19) lcd.write_string(B_F_Ch) sleep(1) lcd.cursor_pos = (1, 0) long_text('This is a Scrolling text') # lcd.cursor_pos = (3, 19) # lcd.write_string(U_L_Ch) # sleep(.6) lcd.cursor_pos = (2, 4) lcd.write_string('\x04') lcd.cursor_pos = (2, 5) lcd.write_string('\x05') lcd.cursor_pos = (3, 4) lcd.write_string('\x06') lcd.cursor_pos = (3, 5) lcd.write_string('\x07') # sleep(2) lcd.cursor_pos = (3, 19) lcd.write_string(L_Ch) sleep(2) |