Ардуино: светодиодная матрица с драйвером max7219. Светодиодная матрица и управление ей в Arduino
Светодиодная матрица – удобное средство для отображения информации: во-первых, она ярче обычных TFT-дисплеев, во-вторых, больше по размеру, что в ряде случаев имеет преимущества (если нам не надо отображать фотографии).
При желании без особых затруднений можно найти готовую сборку – матрица 1088 (или любая подобная, 8×8 светодиодов) и в комплекте с ней контроллер MAX7219. Эта небольшая микросхема способна самостоятельно управлять не только отображением светодиодов, но и менять их яркость (для всей матрицы, а не по светодиодам), а также она «знает», как вывести цифры на семисегментный индикатор. Это означает, что разработчику будет меньше работы. Управление достаточно простое, по интерфейсу SPI по трём проводам – выбор устройства, данные и синхронизация.
Также часто такие сборки объединяют в блоки по 4 последовательно, получается мини-дисплей размером 32×8 пикселей, что достаточно удобно – можно отобразить слово длиной до 5 букв. Стоит отметить, что эта сборка умеет передавать данные дальше по цепочке, и 4 штуки последовательно – не предел. Я объединял 4 блока по 4 такие сборки, получался дисплей 128×8 (также можно получить 64×16 при соответствующей программной настройке, это просто), работавший без торможения и обновляющийся 50 раз в секунду. Хотя, в отличие от схемы , здесь программное обновление не нужно – за вывод информации отвечает контроллер на плате, дело программиста – указать, что выводить, а не как.
Для работы с такими сборками есть специальная библиотека для Arduino – Max72xxPanel, доступная на GitHub. Для её корректной работы также требуется подключение библиотек SPI и Adafruit_GFX, но это не проблема. Первая библиотека присутствует по умолчанию в дистрибутиве Arduino IDE, вторая доступна на GitHub.
Инициализируем матрицу
Для начала попробуем инициализировать нашу матрицу. Выводы питания VCC и GND соединяем с аналогичными на плате Arduino, DIN подключаем к выводу 11, CS – 9, CLK – 13. Учтите, что эта нумерация верна для платы Arduino UNO, для других моделей интерфейс SPI может находиться на выводах с другими номерами.
С этой сборкой удобнее работать, «повернув» её программно на 90 градусов. Фактически, у нас есть 4 блока по вертикали и 1 по горизонтали, но отображать будем, как будто она ориентирована горизонтально. Причина простая – 1 столбец занимает ровно 1 байт, удобнее строить изображение.
Пишем начальный программный код для инициализации:
#include
Нажимаем Ctrl+U, загружаем скетч в плату и смотрим на результат, точнее, на полностью погасший дисплей.
Так и должно быть, мы просто очистили его. Попробуйте сами изменить строку 18 следующим образом:
Matrix.fillScreen(HIGH);
В результате получим полностью светящуюся матрицу. Если светится тускло, увеличивайте яркость в строке 11, только постепенно и осторожно – у меня уже при значении 3 при взгляде на светодиоды ощущается дискомфорт и болят глаза. Так что с яркостью стоит начинать с минимума и плавно увеличивать.
![](https://i2.wp.com/rizado.ru/wp-content/uploads/2018/10/P_20181013_125057.jpg)
Простейшую операцию мы выполнили, теперь давайте попробуем что-то написать.
Вывод статического изображения
Для примера возьмём слово из пяти букв, чтобы максимально заполнить матрицу. Можно, конечно, вывести по одному символу на матрицу, но для любой буквы хватает места 5*7 символов, поэтому с учётом интервала получится до 5 букв. Для примера возьмём слово «Старт».
Формируем изображение:
![](https://i2.wp.com/rizado.ru/wp-content/uploads/2018/10/start.png)
И модифицируем программный код, добавив туда массив с данными для включения определённых светодиодов (приводить не буду, скетч можно скачать для ознакомления по ссылке внизу). Рисовать будем по вертикали, старший бит – верхний ряд. Кроме этого, из кода можно исключить начальное заполнение матрицы, поскольку все светодиоды будут определены явно:
Void setup() {
byte x, y;
matrix.setIntensity(brightness);
matrix.setRotation(0);
for (y = 0; y < 32; y++) {
for (x = 0; x < 8; x++) {
matrix.drawPixel(x, y, leds[y] & (1< Компилируем скетч, загружаем в плату и смотрим на результат: В следующий раз сделаем на матрице бегущую строку и выведем надпись, которая не помещается по длине. Напрямую с выводов общего назначения. Проблема, которую нам тогда предстояло решить, заключалась в ограниченном количестве управляемых выводов у контроллера Ардуино. Апогеем же наших изысканий стало использование динамической индикации для . Теперь пришло время еще немного усложнить задачу: учимся работать со светодиодной матрицей. Как мы уже знаем, сегментные индикаторы, будь то шкалы или цифры, состоят из отдельных светодиодов, соединенных вместе. Например, у группы светодиодов могут быть соединены все катоды. Такой индикатор имеет приписку «с общим катодом», в противном случае — «с общим анодом». А что будет, если мы разместим светодиоды не в виде цифры или шкалы, а в виде сетки? Получится уже вполне себе графический индикатор. То есть такой, на котором можно отобразить не только число, но и какое-то изображение. Такая сетка называется матричным индикатором, а в случае использования светодиодов — светодиодной матрицей. Разрешение матричного индикатора — это количество точек по горизонтали и вертикали. Например, самые распространенные индикаторы имеют разрешение 8×8 точек. Если требуется светодиодная матрица с большим разрешением, то её просто-напросто составляют из нескольких 8×8 индикаторов. Как это делать, мы увидим позже. А пока разберемся как соединяются все 64 светодиода внутри матрицы. Конечно, можно бы было как и в случае семисегментного индикатора соединить все светодиоды общим катодом или анодом. В этом случае нам бы потребовалось либо 64 вывода контроллера, либо 8 сдвиговых регистров. Оба варианта весьма расточительны. Более правильный вариант — объединить светодиоды в группы по 8 штук с общим катодом. Пусть это будут столбцы матрицы. Затем, параллельные светодиоды в этих столбцах объединить снова в группы по 8 штук уже с общим анодом. Получится вот такая схема:
Предположим, стоит задача зажечь светодиод R6C3. Для этого нам потребуется подать высокий уровень сигнала на вывод R6, а вывод C3 соединить с землей. Не выключая эту точку, попробуем зажечь другую — R3C7. Положительный контакт питания соединим с R3 и землю с C7. Но в таком случае строки R6 и R3 будут пересекаться с колонками C3 и C7 не в двух, а в четырех местах! Следовательно и зажжется не две, а четыре точки. Проблема! Очевидно, что помочь сможет всё та же . Если мы будем включать точки R6C3 и R3C7 по-очереди очень быстро, то сможем использовать персистентность зрения — способность интерпретировать быстро сменяющиеся изображения как одно целое. В нашем уроке мы будем подключать к Ардуино Уно самую простую светодиодную матрицу 8×8 красного свечения. Нумерация выводов начинается с нижнего левого угла. При этом, нумерация ног 1-16 не связана никакой логикой с нумерацией колонок и строк C и R. Ориентируясь на урок про динамическую индикацию, попробуем использовать в схеме управления матричным индикатором 8-битные сдвиговые регистры. Один регистр подключим к выводам индикатора, отвечающим за колонки, а второй к выводам строк. Принципиальная схема
Важное замечание №1.
Необходимо, чтобы резисторы в этой схеме были на линиях, идущих от первого сдвигового регистра. Этот сдвиговый регистр отвечает за колонки. При таком подключении, каждый резистор будет задавать ток только для одного светодиода на каждом шаге динамического алгоритма. Следовательно, все светодиоды будут светиться равномерно. Важное замечание №2.
Указанная выше схема носит сугубо ознакомительный характер. Правильнее будет включить в разрыв между вторым регистром и матрицей дополнительную силовую микросхему, например транзисторную сборку ULN2003. Чтобы было веселей, попробуем высветить на индикаторе смайлик. Как уже было сказано, для вывода изображения на матрицу воспользуемся динамической индикацией. А именно, будем высвечивать нашу картинку построчно. Сначала зажжем нужные колонки в самой верхней строке, затем во второй, в третьей, и так все 8 строк. За колонки у нас будет отвечать первый сдвиговый регистр, а за строки второй. Следовательно, вывод строки будет состоять из двух последовательных записей в регистр: сначала передаем код строки, затем код точек в этой строке. В этой программе мы также воспользуемся ускоренной версией функции digitalWrite. Это необходимо для того, чтобы процесс динамической индикации проходил очень быстро. В противном случае, мы увидим заметное мерцание матрицы. Исходный код
Const byte data_pin = PD2;
const byte st_pin = PD3;
const byte sh_pin = PD4;
unsigned long tm, next_flick;
const unsigned int to_flick = 500;
byte line = 0;
const byte data = {
0b00111100,
0b01000010,
0b10100101,
0b10000001,
0b10100101,
0b10011001,
0b01000010,
0b00111100
};
void latchOn(){
digitalWriteFast(st_pin, HIGH);
digitalWriteFast(st_pin, LOW);
}
void fill(byte d){
for(char i=0; i<8; i++){
digitalWriteFast(sh_pin, LOW);
digitalWriteFast(data_pin, d & (1< next_flick){
next_flick = tm + to_flick;
line++;
if(line == 8)
line = 0;
// передаем код строки
fill(~(1<<(7-line)));
// зажигаем точки в строке № line
fill(data);
// открываем защелку
latchOn();
}
}
Основная часть этой программы, включая переменные data_pin, sh_pin, st_pin, next_flick, to_flick
и функцию fill
уже известны нам из уроков про и про . Массив data
хранит восемь строк нашей картинки. Для экономии памяти мы записали каждую комбинацию точек в бинарном виде. Функция latchOn
открывает защелку регистра. Это нужно делать только после заполнения обоих сдвиговых регистров. После загрузки программы на Ардуино, на индикаторе появится смайл. А теперь доработаем программу таким образом, чтобы изображение на индикаторе менялось каждые пол секунды. Для этого вспомним еще раз . Const byte data_pin = PD2;
const byte st_pin = PD3;
const byte sh_pin = PD4;
unsigned long tm, next_flick, next_switch;
const unsigned int to_flick = 500;
const unsigned long to_switch = 500000;
byte line = 0;
byte frame = 0;
const byte data = {
{ 0b00111100,
0b01000010,
0b10100101,
0b10000001,
0b10100101,
0b10011001,
0b01000010,
0b00111100
},
{ 0b00111100,
0b01000010,
0b10100101,
0b10000001,
0b10000001,
0b10111101,
0b01000010,
0b00111100
}};
void latchOn(){
digitalWriteFast(st_pin, HIGH);
digitalWriteFast(st_pin, LOW);
}
void fill(byte d){
for(char i=0; i<8; i++){
digitalWriteFast(sh_pin, LOW);
digitalWriteFast(data_pin, d & (1< next_flick){
next_flick = tm + to_flick;
line++;
if(line == 8)
line = 0;
fill(~(1<<(7-line)));
fill(data);
latchOn();
}
tm = micros();
if(tm > next_switch){
next_switch = tm + to_switch;
frame = !frame;
}
}
Загружаем программу на Ардуино и наблюдаем результат. Светодиодная матрица с разрешением 8×8 подойдет для отображения двух цифр или простого символа. Если требуется вывести на индикатор какое-то более или менее полезное изображение, необходимо объединить матрицы. Делается это с помощью добавления новых сдвиговых регистров как по вертикали, так и по горизонтали. Следует отметить, что быстродействия контроллера Ардуино Уно в связке со сдвиговыми регистрами хватит разве что на дисплей 16×16. Дальнейшее увеличение размеров светодиодного дисплея приведет к появлению заметного мерцания. Собрав схему управления матрицей, у многих может возникнуть вопрос: «Ну неужели за 30 лет никто не придумал более простого способа работы с матрицей?» На самом деле, придумали. Существуют специализированные микросхемы для работы с разными типами дисплеев, в том числе и для работы со светодиодной матрицей. В одном из следующих уроков мы научимся управлять индикатором с помощью микросхемы MAX7219. Такой способ позволит нам легко объединять несколько матриц с один большой дисплей, без необходимости сильно усложнять электрическую схему. Материалы:
Шаг 1: Как работает:
На каждом регистре числится 8 выходов, используется всего 3 вывода Arduino для контролирования огромного числа сдвиговых регистров. Как было сказано ранее, сканирование происходит с помощью этого счётчика 4017, через подключение одного ряда к земле за один раз и отправке данных через резисторы в колонки. Шаг 2: Схема
Для расчёта величин 24 резисторов можно воспользоваться калькулятором Для начала смотрят спецификацию светодиода, для того чтобы узнать их прямое напряжение и их прямой ток. Информацию можно узнать сразу при покупке. Схема работает от напряжения 5В. Соответственно необходим источник питания с таким же напряжением. Также добавлен макет платы управления, который изготовлен с помощью инструментального средства Willard 2.0. Шаг 3: пайка
Автор сгибает вниз положительный вывод светодиодов по направлению к остальным выводам, и делается ряд, после чего отрезается неприменимая часть вывода, и пытается сделать эти соединения максимально низкими. Эта процедура делается для каждого положительного вывода. На данном этапе отрицательные выводы соединены в колонку и их спаивание неудобно, так как у них на пути положительный ряд. Поэтому отрицательный вывод сгибается на 90 градусов, и делается мост над положительным рядом к следующему отрицательному выводу, и так для всех остальных светодиодов. Сдвиговые регистры и оставшиеся компоненты можно припаиваются на усмотрение каждого отдельно. Шаг 4: программирование
Автор до этого писал несколько похожих программ. Поэтому ему пришлось только добавить программу, которая будет получать слово или же целое предложение от монитора IDE arduino и затем отображает его на матрице. Код, конечно же, можно создать свой или изменить этот на своё усмотрение. Как это сделать:
В этом примере мы используем светодиодную матрицу, на которой будем включать-выключать светодиоды и отображать ASCII символы. В конце гайда приведено видел с результатом работы, так что не поленитесь - загляните. Уверен, вас впечатлит и вы тут же приметесь за дело. Для данного небольшого проекта вам понадобятся следующие компоненты: В данном примере используется плата Arduino Uno, но вы можете использовать любую аналогичный или совместимый микроконтроллер. Найти модуль матричного дисплея не составит труда. Китайцы уже давно и больших количествах продают из на eBay и Aliexpress. Кроме того, на многих радиорынках Украины и России они тоже есть в наличии. В состав этих модулей входят: 8х8 светодиодная матрица (красного цвета), чип MAX7219 для управления светодиодами, коннекторы, один резистор на 10 кОм, конденсатор на 100 нФ, электролитический конденсатор 10 uF, монтажная плата, на которой все это устанавливается. Можно заказать собранный модуль, можно самому распаять все компоненты. Зависит от вас. ВАЖНО: матричный светодиодный дисплей является общим катодом. Модуль не работает матрицами, которые имеют общий анод! Светодиодная матрица (LED matrix) управляется с помощью чипа MAX7219 и библиотеки Arduino . Самая потрясающая вещь в этой библиотеке - это возможность подключения до 8 матриц и реализовать большой дисплей (более детально будет рассмотрено в отдельном туториале) Библиотека LedControl library была дополнена некоторыми новыми методами для упрощения отображения символов и строк. Новая версия библиотеки доступна для скачивания по ссылкам: Для интегрирования библиотеки в вашу Arduino IDE: Распакуйте файл библиотеки, который вы только что скачали; Убедитесь, что вы закрыли все открытые окна Arduino IDE; Найди папку libraries внутри папки, где у вас установлена Arduino IDE (смотрите на рисунке ниже); Скопируйте разархивированную папку LedControlMS (папку со всем ее содержимым) в папку libraries. Если все прошло хорошо, вы можете вновь открыть Arduino IDE. В меню File -> Examples должна появится вкладка под названием LedControlMS с четырьмя файлами внутри. Если у вас возникли дополнительные вопросы по установке библиотек в Arduino IDE, ознакомьтесь со статьей Библиотеки Arduinoгде рассмотрены все возможные сложности и порядок установки библиотек Arduino. Да и вообще, что это такое - библиотеки. После установки библиотеки можно подключать LED матрицу к плате Arduino . На модуле светодиодной матрицы есть два набора контактов. В этом проекте мы будем использовать только контакты на вход, которые расположены ближе к чипу MAX 7219. Есть пять контактов, которые надо подключить к соответствующим пинам Arduino.. Подключаем с помощью коннекторов папа-мама: На рисунке ниже коннекторы имеют цвета, приведенные в пояснениях. Так что можете смело перепроверить подключение с помощью рисунка. Библиотека LedControl library может работать как с 7-ми сегментными светодиодными дисплеями, так и со светодиодными матрицами. В нашем случае будут использоваться методы для работы со светодиодными матрицами. Обновленная библиотека, которая была создана для Makespace Madrid позволяет определять алфавит/шрифт символов, которые отображаются на светодиодном матричном дисплее. Кроме того, включено два новых метода: writeString и displayChar. Практические примеры работы различных методов вы можете увидеть в примере MakeSpace_LEDMatrix, который включен в состав библиотеки. Открыть скетч можно выбрав в Arduino IDE File -> Examples -> LedControlMS -> MakeSpace_ LEDMatrix Можете загрузить пример на вашу плату Arduino и повосхищаться результатом. Примечание 1: если у вас на ПК стоит старая версия Arduino IDE (0.x), вам придется изменить расширение скетчей, которые входят в состав библиотеки. Измените расширение файлов с.ino на.pde (MakeSpace_ LEDMatrix.ino -> MakeSpace_ LEDMatrix.pde). В таком случае ваша Arduino IDE сможет прочитать и открырь эти файлы (возможно, вам опять таки надо будет закрыть окно Arduino IDE и только после этого изменить расширение файла). Примечание 2: перед загрузкой скетча убедитесь, что вы выбрали корректный COM-порт. Обещанный результат на видео ниже: Если все прошло успешно, ваша светодиодная матрица начнет отрабатывать последовательность операций, включая/выключая светодиоды и отображая различные символы. Уверен, вы с легкостью сможете сопоставить код в скетче с действиями, которые отрабатывает матричный дисплей на базе MAX 7219. Дальше предлагаю вам изменять скетч, экспериментировать с представлеными в библиотеке методами и отображать ваши собственные идеи с помощью матричного дисплея. В помощь прилагаю ниже в PDF файле некоторые данные о светодиодах, строках и колонках, которые пронумерованы и зашиты в библиотеку LEDControl library. Не бойтесь ошибок! Именно ошибки часто ускоряют процесс обучения! Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!
Два года назад, когда я только начал заниматься мультикоптерами, мне пришлось сделать небольшой . Поскольку квадрокоптер задумывался сугубо автономным, все что требовалось от этого пульта - это управлять беспилотником во время испытаний и настройки. В принципе, пульт со всеми возложенными на него задачами справлялся вполне успешно
. Но были и серьезные недостатки.
Чтобы устранить все эти недостатки, я решил кардинально переделать пульт. И железную часть, и софт. Вот что мне захотелось сделать: Идея чрезвычайно проста и эффективна. Вырезаем из оргстекла или другого тонкого материала две пластины и соединяем их стойками. Все содержимое корпуса крепится либо к верхней, либо к нижней пластине. Чтобы управлять кучей параметров, нужно либо разместить на пульте кучу потенциометров и добавить АЦП, либо делать все настройки через меню. Как я уже говорил, настройка потенциометрами не всегда хорошая идея, но и отказываться от нее не стоит. Так что, решено было оставить в пульте четыре потенциометра, и добавить полноценное меню.
Чтобы перемешаться по меню, и менять параметры обычно используют кнопки. Влево, вправо, вверх, вниз. Но мне захотелось использовать вместо кнопок энкодер. Эту идею я подсмотрел у контроллера 3D-принтера. Разумеется, за счет добавления меню, код пульта распух в несколько раз. Для начала я добавил всего три пункта меню: "Telemetry", "Parameters" и "Store params". В первом окне отображается до восьми разных показателей. Пока я использую только три: заряд батареи, компас и высота. Во втором окне доступны шесть параметров: коэффициенты PID регулятора для осей X/Y,Z и корректировочные углы акселерометра. Третий пункт позволяет сохранять параметры в EEPROM. Над выбором пилотных джойстиков я долго не размышлял. Так получилось, что первый джойстик Turnigy 9XR я добыл у коллеги по квадрокоптерному делу - Александра Васильева, хозяина небезызвестного сайта alex-exe.ru . Второй такой же заказал напрямую на Hobbyking. Первый джойстик был подпружинен в обоих координатах - для контроля рыскания и тангажа. Второй я взял такой же, чтобы затем переделать его в джойстик для управления тягой и вращением. В старом пульте я использовал простой регулятор напряжения LM7805, который кормил связкой из 8 батареек AA. Жутко неэффективный вариант, при котором 7 вольт уходили на нагрев регулятора. 8 батареек - потому что под рукой был только такой отсек, а LM7805 - потому что в то время этот вариант мне представлялся самым простым, и главное быстрым. Теперь же я решил поступить мудрее, и поставил достаточной эффективный регулятор на LM2596S. А вместо 8-ми AA батареек, установил отсек на два LiIon аккумулятора 18650. Собрав все воедино, получился вот такой аппарат. Вид изнутри. А вот с закрытой крышкой. Не хватает колпачка на одном потенциометре и колпачков на джойстиках. Наконец, видеоролик о том, как происходит настройка параметров через меню.
Физически пульт собран. Сейчас я занимаюсь тем, что дорабатываю код пульта и квадрокоптера, чтобы вернуть им былую крепкую дружбу. По ходу настройки пульта, были выявлены недостатки. Во-первых, нижние углы пульта упираются в руки:(Наверное я немного перепроектирую пластины, сглажу углы. Во-вторых, даже дисплея 16х4 не хватает для красивого вывода телеметрии - приходится названия параметров сокращать до двух букв. В следующей версии девайса установлю точечный дисплей, либо сразу TFT матрицу.1. Матричный индикатор
2. Светодиодная матрица и сдвиговые регистры
3. Программа
4. Анимация на светодиодной матрице
5. Масштабирование светодиодной матрицы
Задания
Заключение
- светодиоды 144 шт
- резисторы 24 шт (определяется по типу светодиодов, в этом случае 91 Ом)
- счетчик десятичный 4017
- резисторы 6 шт (номинал 1 кОм)
- транзисторы 6 шт 2N3904
- Длинная макетная плата
- Arduino
- регистры сдвига 3 шт (74HC595)
- штыревые разъёмы
Обычно информация в светодиодной матрице разбивается на мелкие части, которые после передаются друг за другом. Таким образом, экономится большое количество выводов на Arduino, и программа становится достаточно простой.
Единственные элементы не указанные на схеме - это резисторы ограничения тока, так как их номинал напрямую зависит от того какого типа светодиоды используются. Поэтому их величина должна быть вычислена самостоятельно.
Пайка такого большого количества светодиодов задача ни из лёгких если не знаешь наверняка как это делается правильно.
Пришло время к последнему этапу проекта.
В архиве приложен excel файл, для возможности создания своих знаков или символов.
Создаётся нужный знак пиксель за пикселем (ничего сложного в этом нет), и копируется выходная строка - #define {OUTPUT LINE}Необходимые материалы
Библиотека Arduino для работы с матричным светодиодным дисплеем
Пример скетча для Arduino
Резутьтат!
Новый корпус
Элементы управления и меню
Джойстики
Питание
Результат
Итог