В данной статье мы рассмотрим подключение семисегментного индикатора (семисегментного дисплея) к плате Raspberry Pi. В настоящее время семисегментные идикаторы (7 segment display) являются одним из самых дешевых устройств для отображения буквенно-цифровой информации. Два таких индикатора, соединенных вместе, можно использовать для отображения температуры, скорости потока воды и многих других целей. Мы будем подключать семисегментный дисплей к контактам ввода/вывода платы Raspberry Pi и с помощью программы на Python отображать на нем последовательно цифры от 0 до 9.
Также на нашем сайте мы уже рассматривали подключение семисегментного индикатора к плате Arduino и микроконтроллеру AVR.
Принцип работы семисегментного дисплея (индикатора)
Но прежде чем идти дальше, кратко остановимся на том, что такое семисегментный дисплей. Этот дисплей получил свое название исходя из того факта, что он имеет семь светящихся сегментов. Каждый из этих сегментов содержит светодиод. Диаграмма контактов семисегментного дисплея показана на рисунке ниже.
Светодиоды в таком дисплее установлены таким образом, что каждый из них содержит свой собственный сегмент. Важная вещь, которую здесь необходимо отметить, светодиоды в семи сегментном дисплее могут быть упорядочены в общем анодном режиме (положительном) или в общем катодном режиме (отрицательном). Соединение цепей семисегментного дисплея для этих режимов показано на следующем рисунке.
Как мы можем видеть, в катодном режиме (Common Cathode) отрицательные выводы светодиодов соединены вместе и названы "землей (GND)". В анодном режиме (Common Anode) положительные выводы светодиодов соединены вместе и названы "напряжением постоянного тока (VCC)". Эти режимы имеют значение (то есть их надо учитывать) когда мы объединяем несколько семи сегментных дисплеев в одно целое.
Чтобы человеческий глаз не замечал мерцания светодиодов семисегментного индикатора их необходимо переключать с частотой не менее 50 Гц.
Более подробно принципы работы с семисегментным индикатором вы можете изучить в следующих статьях на нашем сайте:
- семисегментный светодиодный индикатор: описание, подключение к микроконтроллеру;
- перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор;
- многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации.
Схема расположения контактов ввода/вывода (GPIO) на плате Raspberry Pi показана на следующем рисунке. Более подробно об этих контактах вы можете прочитать в статье про мигание светодиода с помощью Raspberry Pi.
Напряжения +3.3V, подаваемого с контактов ввода/вывода платы Raspberry Pi (GPIO’s pin 1 или 17), будет вполне достаточно для подачи питания на семисегментный индикатор. Чтобы ограничить ток, протекающий по сегментам индикатора, мы использовали резисторы сопротивлением 1 кОм как показано на схеме ниже.
Необходимые компоненты
- Плата Raspberry Pi 2 Model B или другая аналогичная (купить на AliExpress).
- Семисегментный индикатор с общим катодом, например, LT543 (купить на AliExpress).
- Резистор 1 кОм – 8 шт. (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Схема проекта
Схема подключения семисегментного индикатора к Raspberry Pi представлена на следующем рисунке.
В схеме необходимо сделать следующие соединения между семисегментным индикатором и платой Raspberry Pi.
PIN1 или e ------------------ GPIO21
PIN2 или d ------------------ GPIO20
PIN4 или c ------------------ GPIO16
PIN5 или h или DP ---------- GPIO 12 //не обязательно поскольку мы не используем десятичную точку
PIN6 или b ------------------GPIO6
PIN7 или a ------------------GPIO13
PIN9 или f ------------------ GPIO19
PIN10 или g ---------------- GPIO26
PIN3 или PIN8 ------------- к общему проводу (земле)
Таким образом, мы будем использовать 8 контактов ввода/вывода (GPIO pins) как 8-битный порт (PORT). В этом порту GPIO13 будет младшим значащим битом (Least Significant Bit, LSB), а GPIO12 – старшим значащим битом (Most Significant Bit, MSB).
Теперь, к примеру, если нам необходимо будет отобразить на индикаторе цифру “1”, нам необходимо будет подать питание на его контакты B и C, а для этого нам нужно будет подать напряжение высокого уровня на GPIO6 и GPIO16. В этом случае байт данных, передаваемый на порт (в программе с помощью функции ‘PORT’) должен иметь значение 0b00000110, а в шестнадцатеричном виде это будет значение 0x06. Когда на обоих этих контактах будет уровень high мы увидим цифру “1” на семисегментном индикаторе.
Мы записали шестнадцатеричные коды, необходимые для отображения всех символов, в строку символов под именем ‘DISPLAY’ (см. далее программу). Затем мы последовательно будем извлекать значения из этой строки и использовать их для отображения соответствующих символов на семисегментном индикаторе с помощью функции ‘PORT’.
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
После того, как все необходимые соединения в схеме сделаны, мы можем подать питание на Raspberry Pi и после загрузки ее операционной системы можно начать писать программу в ней на Python.
В программе нам первым делом необходимо подключить (импортировать) библиотеку для работы с контактами ввода/вывода. Также мы импортируем эту библиотеку RPi.GPIO под именем “IO” (то есть переименовываем ее для использования в программе), то есть далее в программе всегда, когда мы захотим обратиться к контактам ввода/вывода, мы будем использовать слово ‘IO’.
1 |
import RPi.GPIO as IO |
Иногда контакты ввода/вывода (GPIO pins), которые мы собираемся использовать в программе, могут выполнять другие функции. В этом случае во время исполнения программы мы будем получать предупреждения (warnings). Следующей командой мы укажем плате Raspberry Pi на то, чтобы она игнорировала эти предупреждения и продолжала исполнение программы.
1 |
IO.setwarnings(False) |
Мы можем обращаться к контактам ввода/вывода (GPIO pins) платы Raspberry Pi используя либо номер контакта на плате, либо его функциональный номер. Например, если смотреть распиновку контактов ввода/вывода платы Raspberry Pi, то можно увидеть, что в ней обозначение GPIO5 соответствует контакту PIN 29. То есть в зависимости от того, какой способ обращения к контактам мы выбрали, мы можем обращаться к рассмотренному контакту либо по номеру ‘29’, либо по номеру ‘5’. В данном проекте мы выберем способ обращения к контактам по их функциональным номерам, поэтому используем следующую команду:
1 |
IO.setmode (IO.BCM) |
Мы инициализируем 8 контактов ввода/вывода (GPIO pins) платы Raspberry Pi в качестве цифровых выходов – с них мы будем производить управление семисегментным индикатором.
1 2 3 4 5 6 7 8 |
IO.setup(13,IO.OUT) IO.setup(6,IO.OUT) IO.setup(16,IO.OUT) IO.setup(20,IO.OUT) IO.setup(21,IO.OUT) IO.setup(19,IO.OUT) IO.setup(26,IO.OUT) IO.setup(12,IO.OUT) |
Далее в программе мы запишем условие, необходимое для установки на GPIO13 значения high или low. Для этого мы запишем условие, показанное в фрагменте кода ниже. Согласно этому условию если bit0 из нашего 8-битного значения 'pin' будет равен true, то на контакте PIN13 мы установим уровень HIGH, иначе на контакте PIN13 мы установим уровень LOW. Таких условий у нас в программе будет 8 штук, для проверки значений с bit0 по bit7 в 8-битной переменной 'pin'. С помощью этих условий мы установим необходимые нам значения уровней на всех контактах нашего порта, к которым подключены выводы семисегментного индикатора. Таким образом, мы сможем высветить на индикаторе нужную нам цифру.
1 2 3 4 |
if(pin&0x01 == 0x01): IO.output(13,1) else: IO.output(13,0) |
Следующая команда будет формировать у нас цикл, который будет исполняться 10 раз, в нем переменная x будет инкрементироваться от 0 до 9.
1 |
for x in range(10): |
А следующая команда используется для формирования бесконечного цикла, в которой все команды будут исполняться непрерывно.
1 |
While 1: |
Далее приведен полный текст программы.
Исходный код программы на Python
В результате исполнения данной программы на семисегментном индикаторе будут последовательно высвечиваться цифры от 0 до 9.
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 |
import RPi.GPIO as IO # подключение библиотеки для работы с контактами ввода/вывода import time # подключение библиотеки для работы с задержками DISPLAY = [0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67] # строка с шестнадцатеричными кодами, которые используются для отображения цифр на семисегментном индикаторе IO.setwarnings(False) # отключаем показ любых предупреждений IO.setmode (IO.BCM) # мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть мы будем обращаться к PIN29 как ‘GPIO5’ IO.setup(13,IO.OUT) # инициализируем контакты GPIO в качестве цифровых выходов IO.setup(6,IO.OUT) IO.setup(16,IO.OUT) IO.setup(20,IO.OUT) IO.setup(21,IO.OUT) IO.setup(19,IO.OUT) IO.setup(26,IO.OUT) IO.setup(12,IO.OUT) def PORT(pin): # функция для передачи значения 'pin' на выходные контакты if(pin&0x01 == 0x01): IO.output(13,1) # если bit0 из 8bit 'pin' is true, на PIN13 устанавливаем high else: IO.output(13,0) # если bit0 из 8bit 'pin' is false, на PIN13 устанавливаем low if(pin&0x02 == 0x02): IO.output(6,1) # если bit1 из 8bit 'pin' is true, на PIN6 устанавливаем high else: IO.output(6,0) # если bit1 из 8bit 'pin' is false, на PIN6 устанавливаем low if(pin&0x04 == 0x04): IO.output(16,1) else: IO.output(16,0) if(pin&0x08 == 0x08): IO.output(20,1) else: IO.output(20,0) if(pin&0x10 == 0x10): IO.output(21,1) else: IO.output(21,0) if(pin&0x20 == 0x20): IO.output(19,1) else: IO.output(19,0) if(pin&0x40 == 0x40): IO.output(26,1) else: IO.output(26,0) if(pin&0x80 == 0x80): IO.output(12,1) # если bit7 из 8bit 'pin' is true, на PIN12 устанавливаем high else: IO.output(12,0) # если bit7 из 8bit 'pin' is false, на PIN12 устанавливаем low while 1: for x in range(10): # цикл, который исполняется 10 раз, в нем переменная x инкрементируется от 0 до 9 pin = DISPLAY[x] # присваиваем значение переменной 'pin' для каждой цифры PORT(pin); # показываем каждую цифру на семисегментном индикаторе time.sleep(1) |