Ранее на нашем сайте мы уже рассматривали подключение к плате Raspberry Pi таких базовых устройств как светодиод, кнопка, ЖК дисплей, двигатель постоянного тока, серводвигатель, шаговый двигатель, АЦП модуль, регистр сдвига и т.д.. В этой же статье мы рассмотрим подключение к плате Raspberry Pi модуля светодиодной матрицы 8x8 и будем управлять отображением символов на этой матрице с помощью программы на Python. Ранее на нашем сайте мы уже рассматривали подключение подобной матрицы к плате Arduino и микроконтроллеру AVR.
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- Светодиодная матрица 8х8 (купить на AliExpress).
- Резистор 1 кОм – 8 шт. (купить на AliExpress).
- Конденсатор 1000 мкФ, соединенный по питанию (купить на AliExpress).
- Светодиод.
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Модуль светодиодной матрицы 8x8
Модуль светодиодной матрицы 8x8 содержит 64 светодиода, упорядоченных в форме матрицы, поэтому эта структура и называется светодиодной матрицей. Подобные модули доступны в различных размерах и цветовых решениях. Распиновка этого модуля показана на рисунке ниже. Помните о том, что контакты модуля светодиодной матрицы должны быть пронумерованы в точности так, как показано на представленном рисунке, чтобы не возникало ошибок в работе модуля.
У модуля светодиодной матрицы 8+8=16 выводов (контактов). Таким образом, мы имеем 8 общих положительных выводов и 8 общих отрицательных выводов, которые образуют 8 строк и 8 столбцов матрицы. Схему соединений модуля светодиодной матрицы 8x8 можно представить следующим рисунком:
То есть для 8 строк мы имеем 8 общих положительных выводов (9, 14, 8, 12, 17, 2, 5). Если рассматривать первый столбец, то светодиоды с D1 по D8 имеют общий положительный вывод - PIN9. Если мы хотим зажечь один или светодиоды в этой строке, то на PIN9 необходимо будет подать +3.3v.
Аналогично, для 8 столбцов мы имеем 8 общих отрицательных выводов (13, 3, 4, 10, 6, 11, 15, 16). Чтобы зажечь один или несколько светодиодов в конкретном столбце, необходимо на общий отрицательный вывод этого столбца подать напряжение низкого уровня.
Схема проекта
Схема подключения светодиодной матрицы 8x8 к плате Raspberry Pi представлена на следующем рисунке.
В схеме необходимо сделать соединения между платой Raspberry Pi и светодиодной матрицей, показанные в следующей таблице.
Контакт светодиодной матрицы | Функция | Контакт платы Raspberry Pi |
13 | POSITIVE0 | GPIO12 |
3 | POSITIVE1 | GPIO22 |
4 | POSITIVE2 | GPIO27 |
10 | POSITIVE3 | GPIO25 |
6 | POSITIVE4 | GPIO17 |
11 | POSITIVE5 | GPIO24 |
15 | POSITIVE6 | GPIO23 |
16 | POSITIVE7 | GPIO18 |
9 | NEGATIVE0 | GPIO21 |
14 | NEGATIVE1 | GPIO20 |
8 | NEGATIVE2 | GPIO26 |
12 | NEGATIVE3 | GPIO16 |
1 | NEGATIVE4 | GPIO19 |
7 | NEGATIVE5 | GPIO13 |
2 | NEGATIVE6 | GPIO6 |
5 | NEGATIVE7 | GPIO5 |
Далее рассмотрим принципы работы проекта.
Объяснение работы проекта
В нашем проекте мы будем использовать технологию мультиплексирования чтобы показывать различные символы на светодиодной матрице 8x8. Допустим, к примеру, нам необходимо зажечь светодиод D10 в матрице. Для этого необходимо подать напряжение высокого уровня на PIN14 матрицы и напряжение низкого уровня на PIN3 как показано на следующем рисунке.
А если мы хотим зажечь светодиод D1, то нам необходимо будет подать напряжение высокого уровня на PIN9 матрицы и напряжение низкого уровня на PIN13 как показано на следующем рисунке.
Теперь, допустим, что нам необходимо одновременно зажечь светодиоды D1 и D10. Для этого нам необходимо подать напряжение высокого уровня на PIN9 и PIN14 матрицы и напряжение низкого уровня на PIN13 и PIN3. Светодиоды D1 и D10 при этом зажгутся, однако при этом начнут светиться и светодиоды D2 и D9 поскольку они имеют общие выводы со светодиодами D1 и D10. Эта ситуация показана на следующем рисунке.
Чтобы предотвратить эту проблему, мы будем использовать так называемую технологию мультиплексирования. Подробно суть этой технологии рассмотрена в статье про подключение светодиодной матрицы 8x8 к микроконтроллеру AVR. Также эта же технология использована в статье про скроллинг текста на светодиодной матрице 8x8 с помощью микроконтроллера AVR.
Суть технологии мультиплексирования заключается в следующем. Человеческий глаз не может различить частоту более 30 Гц. То есть если светодиод будет включаться и выключаться с частотой 30 Гц или больше, то человеческий глаз будет воспринимать его непрерывно горящим.
К примеру, мы хотим включить только светодиоды D1 и D10 в матрице, чтобы при этом не зажглись светодиоды D2 и D9. Для этого мы можем сначала подать соответствующие уровни напряжения на контакты PIN 9 и 13 чтобы зажечь светодиод D1. Затем подождать 1 мсек и выключить светодиод D1. После этого мы подадим соответствующие уровни напряжения на контакты PIN 14 и 3 чтобы зажечь светодиод D10. Затем подождать 1 мсек и выключить светодиод D10. Этот цикл будет продолжаться непрерывно, в котором светодиоды D1 и D10 будут с высокой частотой включаться и выключаться, поэтому человеческий глаз будет воспринимать их непрерывно горящими. Аналогичным образом можно поступать если мы хотим зажечь любые другие светодиоды в матрице.
К примеру, мы хотим отобразить на светодиодной матрице букву “A” как показано на следующем рисунке. Для этого нам необходимо выполнить следующую последовательность действий.
В момент времени t=0 мс (миллисекунд) на PIN09 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN3, PIN4, PIN10, PIN6, PIN11, PIN15 подается земля (низкий уровень) (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=1 мс на PIN14 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN4, PIN10, PIN6, PIN11, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=2 мс на PIN08 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=3 мс на PIN12 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=4 мс на PIN01 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN4, PIN10, PIN6, PIN11, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=5 мс на PIN07 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN4, PIN10, PIN6, PIN11, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=6 мс на PIN02 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В момент времени t=7 мс на PIN05 устанавливается HIGH (на остальные выводы данного ряда в это время подается LOW), на контакты PIN13, PIN3, PIN15, PIN16 подается земля (на остальные контакты столбцов в это время подается уровень HIGH).
В результате этих операций человеческий глаз будет видеть на светодиодной матрице непрерывно горящий символ “A” как показано на рисунке выше.
Исходный код программы на Python
В тексте программы имеются комментарии, поясняющие смысл отдельных команд. Значения портов для показа каждого символа приведены в программе. Вы можете выводить любые символы на светодиодной матрице просто поменяв значения переменных ‘pinp’ в соответствующих циклах в приведенной программе. Более подробно работу проекта можно посмотреть на видео, приведенном в конце статьи.
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 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
import RPi.GPIO as IO # подключение библиотеки для работы с контактами ввода/вывода import time # подключение библиотеки для работы с задержками IO.setwarnings(False) # отключаем показ любых предупреждений x=1 y=1 IO.setmode (IO.BCM) # мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть к контакту PIN29 будем обращаться 'GPIO5' IO.setup(12,IO.OUT) # инициализируем GPIO12 в качестве цифрового выхода IO.setup(22,IO.OUT) # инициализируем GPIO22 в качестве цифрового выхода IO.setup(27,IO.OUT) IO.setup(25,IO.OUT) IO.setup(17,IO.OUT) IO.setup(24,IO.OUT) IO.setup(23,IO.OUT) IO.setup(18,IO.OUT) IO.setup(21,IO.OUT) IO.setup(20,IO.OUT) IO.setup(26,IO.OUT) IO.setup(16,IO.OUT) IO.setup(19,IO.OUT) IO.setup(13,IO.OUT) IO.setup(6,IO.OUT) IO.setup(5,IO.OUT) PORTVALUE = [128,64,32,16,8,4,2,1] # значения контактов на каждом порту A=[0,0b01111111,0b11111111,0b11001100,0b11001100,0b11001100,0b11111111,0b01111111] B =[0,0b00111100,0b01111110,0b11011011,0b11011011,0b11011011,0b11111111,0b11111111] C= [0,0b11000011,0b11000011,0b11000011,0b11000011,0b11100111,0b01111110,0b00111100] D=[0,0b01111110,0b10111101,0b11000011,0b11000011,0b11000011,0b11111111,0b11111111] E=[0,0b11011011,0b11011011,0b11011011,0b11011011,0b11011011,0b11111111,0b11111111] F=[0,0b11011000,0b11011000,0b11011000,0b11011000,0b11011000,0b11111111,0b11111111] G=[0b00011111,0b11011111,0b11011000,0b11011011,0b11011011,0b11011011,0b11111111,0b11111111] H=[0,0b11111111,0b11111111,0b00011000,0b00011000,0b00011000,0b11111111,0b11111111] I=[0b11000011,0b11000011,0b11000011,0b11111111,0b11111111,0b11000011,0b11000011,0b11000011] J=[0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b11000011,0b11001111,0b11001111] K=[0,0b11000011,0b11100111,0b01111110,0b00111100,0b00011000,0b11111111,0b11111111] L=[0b00000011,0b00000011,0b00000011,0b00000011,0b00000011,0b00000011,0b11111111,0b11111111] M=[0b11111111,0b11111111,0b01100000,0b01110000,0b01110000,0b01100000,0b11111111,0b11111111] N=[0b11111111,0b11111111,0b00011100,0b00111000,0b01110000,0b11100000,0b11111111,0b11111111] O=[0b01111110,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b01111110] P=[0,0b01110000,0b11111000,0b11001100,0b11001100,0b11001100,0b11111111,0b11111111] Q=[0b01111110,0b11111111,0b11001111,0b11011111,0b11011011,0b11000011,0b11111111,0b01111110] R=[0b01111001,0b11111011,0b11011111,0b11011110,0b11011100,0b11011000,0b11111111,0b11111111] S=[0b11001110,0b11011111,0b11011011,0b11011011,0b11011011,0b11011011,0b11111011,0b01110011] T=[0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b11000000,0b11000000,0b11000000] U=[0b11111110,0b11111111,0b00000011,0b00000011,0b00000011,0b00000011,0b11111111,0b11111110] V=[0b11100000,0b11111100,0b00011110,0b00000011,0b00000011,0b00011110,0b11111100,0b11100000] W=[0b11111110,0b11111111,0b00000011,0b11111111,0b11111111,0b00000011,0b11111111,0b11111110] X=[0b01000010,0b11100111,0b01111110,0b00111100,0b00111100,0b01111110,0b11100111,0b01000010] Y=[0b01000000,0b11100000,0b01110000,0b00111111,0b00111111,0b01110000,0b11100000,0b01000000] Z=[0b11000011,0b11100011,0b11110011,0b11111011,0b11011111,0b11001111,0b11000111,0b11000011] def PORT(pin): # устанавливаем контакты GPIO порта в состояние, определяемое значением 'pin' if(pin&0x01 == 0x01): IO.output(21,0) # если bit0 8-битного значения 'pin' равен true, то устанавливаем на PIN21 уровень low else: IO.output(21,1) # если bit0 8-битного значения 'pin' равен false, то устанавливаем на PIN21 уровень high if(pin&0x02 == 0x02): IO.output(20,0) # если bit1 8-битного значения 'pin' равен true, то устанавливаем на PIN20 уровень low else: IO.output(20,1) # если bit1 8-битного значения 'pin' равен false, то устанавливаем на PIN20 уровень high if(pin&0x04 == 0x04): IO.output(26,0) # если bit2 8-битного значения 'pin' равен true, то устанавливаем на PIN26 уровень low else: IO.output(26,1) # если bit2 8-битного значения 'pin' равен false, то устанавливаем на PIN26 уровень high if(pin&0x08 == 0x08): IO.output(16,0) else: IO.output(16,1) if(pin&0x10 == 0x10): IO.output(19,0) else: IO.output(19,1) if(pin&0x20 == 0x20): IO.output(13,0) else: IO.output(13,1) if(pin&0x40 == 0x40): IO.output(6,0) else: IO.output(6,1) if(pin&0x80 == 0x80): IO.output(5,0) else: IO.output(5,1) def PORTP(pinp): # устанавливаем контакты GPIO порта для положительных контактов светодиодной матрицы в состояние, определяемое значением 'pinp' if(pinp&0x01 == 0x01): IO.output(12,1) # если bit0 8-битного значения 'pinp' равен true, то устанавливаем на PIN12 уровень high else: IO.output(12,0) # если bit0 8-битного значения 'pinp' равен false, то устанавливаем на PIN12 уровень low if(pinp&0x02 == 0x02): IO.output(22,1) # если bit1 8-битного значения 'pinp' равен true, то устанавливаем на PIN22 уровень high else: IO.output(22,0) # если bit1 8-битного значения 'pinp' равен false, то устанавливаем на PIN22 уровень low if(pinp&0x04 == 0x04): IO.output(27,1) # если bit2 8-битного значения 'pinp' равен true, то устанавливаем на PIN27 уровень high else: IO.output(27,0) # если bit2 8-битного значения 'pinp' равен false, то устанавливаем на PIN27 уровень low if(pinp&0x08 == 0x08): IO.output(25,1) else: IO.output(25,0) if(pinp&0x10 == 0x10): IO.output(17,1) else: IO.output(17,0) if(pinp&0x20 == 0x20): IO.output(24,1) else: IO.output(24,0) if(pinp&0x40 == 0x40): IO.output(23,1) else: IO.output(23,0) if(pinp&0x80 == 0x80): IO.output(18,1) #if bit7 of 8bit 'pinp' is true pull PIN18 high else: IO.output(18,0) #if bit7 of 8bit 'pinp' is false pull PIN18 low while 1: for y in range (100): # выполняем цикл 100 раз for x in range (8): # выполняем цикл 8 раз инкрементируя значение x от 0 до 7 pin = PORTVALUE[x] # присваиваем значение 'pin' для каждого знака (символа) PORT(pin); # устанавливаем необходимые значения на контактах GPIO pinp= C[x] # присваиваем значение символа 'C' переменной 'pinp' PORTP(pinp); # устанавливаем соответствующие значения на контактах GPIO чтобы показать символ 'C' time.sleep(0.0005) # задержка 0.5msec for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= I[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= R[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= C[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= U[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= I[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= T[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= D[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= I[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= G[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= E[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= S[x] PORTP(pinp); time.sleep(0.0005) for y in range (100): for x in range (8): pin = PORTVALUE[x] PORT(pin); pinp= T[x] PORTP(pinp); time.sleep(0.0005) pinp= 0 PORTP(pinp); time.sleep(1) |