Тетрис на базе arduino и двухцветных светодиодных матриц

Змейка и Тетрис на микроконтроллере

Увидел как-то интересный видеоролик в сети, в нем демонстрировалась игра змейка реализованная на микроконтроллере и светодиодной матрице 8х8, потом нашел еще несколько подобных роликов, которые заинтересовали меня.

Среди них также был ролик, где на “мощном” микроконтроллере была собрана игра тетрис.

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

Схема устройства показана ниже. Вывод информации на матрицы H1, H2 в динамическом режиме осуществляется посредством сдвиговых регистров DD2, DD3, DD4. Выходы микросхем DD2, DD3 подключены к анодам матриц . Катоды обеих матриц подключены к коллекторам транзисторов VT1-VT8, управляющие сигналы для которых формируются микросхемой DD4.

Микроконтроллер загружает данные в регистр DD4, при переполнении которого, информация с 9 вывода передается на вход регистра DD3, далее таким же образом данные передаются на регистр DD2. Резисторы R1-R16 ограничивают ток через светодиоды матриц. Резисторы R17-R23 устанавливают ток базы транзисторов VT1-VT8.

Микроконтроллер работает на частоте 8 МГц от внутреннего генератора. Частота обновления изображения составляет 100Гц.

После подачи питания, на игровом поле отображается заставка игры “Змейка”. В верхней части поля высвечивается цифра 1, в нижней части представлено изображение фрагмента игры.

При нажатии на кнопку SB5 “Старт/Пауза”, выполняется переход в меню игры, в верхней части которого отображается уровень игры в виде цифр от 1 до 9. Уровень игры устанавливается кнопкой SB1 “Вверх”, при каждом нажатии происходит последовательное увеличения номера уровня на единицу. После цифры 9, снова высвечивается цифра 1.

От установленного уровня игры зависит начальная длина змейки, так для 1-го уровня длина составляет 3 точки, для 9-го 11 точек. В нижней части меню отображается информация о скорости движения змейки. Цифре 1 соответствует минимальная скорость, а цифре 9 максимальная. Значение скорости устанавливается кнопкой SB4 “Вниз” подобно установке уровня игры.

Свечение светодиодов по периметру поля в меню означает, что выбран режим игры с наличием границ по периметру поля. В этом режиме, при выходе змейки за пределы игрового поля наступает проигрыш. Если в меню, светодиоды по периметру поля погашены, то выбран режим без наличия границ.

В этом случае при выходе за пределы игрового поля, голова змейки появляется с противоположной стороны поля. Кнопками SB2 “Вправо” и SB3 “Влево” устанавливается требуемый режим игры. При первоначальном входе в меню игры, значение длины и скорости устанавливаются на единицу, выбирается режим с наличием границ.

После нажатия кнопки “Старт/Пауза” из меню игры, на игровом поле высвечивается змейка в базовом положении и случайная свободная точка. Нажатие любой из кнопок “Вверх”, “Влево”, “Вправо” приводит змейку в движение по соответствующему напрвлению.

После начала движения, для управления змейкой также становится доступна кнопка “Вниз”. При наезде на светящуюся точку, длина змейки увеличивается. После набора 14 точек происходит переход на следующий уровень игры. После 9-го уровня происходит переход на первый уровень.

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

После начала движения змейки, нажатиями кнопками “Старт/Пауза” можно приостановить и возобновить игру.

Для выхода из меню игры необходимо удерживать нажатой кнопку “Старт/Пауза” в течении 1 секунды, после чего на игровом поле высветится заставка игры. Переключение между играми осуществляется нажатием любой из кнопок “Вверх”, “Вниз”, “Влево”, “Вправо”. При этом высвечивается заставка соответсвующей игры.

В верхнй части заставки игры “Тетрис” высвечивается цифра 2, в нижней части представлено изображение фрагмента игры. Переход в меню игры осуществляется нажатием кнопки “Старт/Пауза”. В верхней части меню отображается количество баллов набранных игроком. Баллы начисляются за каждую удаленную строку.

Счетчик баллов ведет счет до 99, затем обнуляется, и счет начинается заново. При старте каждой новой игры, счетчик также обнуляется. В нижней части меню отображается информация о скорости движения фигур, которая устанавливается кнопками “Вверх”, “Вниз” соответственно.

После нажатия кнопки “Старт/Пауза” из меню, начинается игра, в верхней части поля появляются случайные фигуры, которые можно перемещать кнопками “Влево” и “Вправо” в соответсвующую сторону. Кнопка “Вверх” поворачивает фигуру на 90 градусов по часовой стрелке, при каждом нажатии.

Удерживая нажатой кнопку “Вниз”, можно ускорить движение фигуры. Кнопкой “Старт/Пауза” можно приостановить и возобновить игру. Игра заканчивается когда новая фигура не может поместиться на игровом поле, после чего происходит переход в меню, где можно просмотреть количество баллов набранных игроком.

Выход из меню выполняется также как в игре “Змейка”.

Если в течении 4 минут не была нажата ни одна из кнопок, то устройство переходит в режим пониженного энергопотребления, микроконтроллер отключает светодиодные матрицы, и переходит в спящий режим. Устройство “просыпается” после нажатия кнопки “Старт”, и возвращается в прежнее состояние.

В устройстве применены резисторы – типоразмера 1206 для поверхностного монтажа. Конденсаторы С2, С3 – керамические типоразмера 1206. Светодиодные матрицы H1, H2 – TOM-1088BG-B зеленого цвета свечения с диаметром светодиодов 3мм, и разрешением 8х8 точек. Кнопки стандартные тактовые.

Источник питания – стабилизированный блок питания напряжением 3,7-5В, также можно использовать гальванические элементы или аккумуляторы, например 3 последовательно соединненные батарейки по 1,5В типоразмера AA или AAA, я например использую 3 батарейки AA. Устройство сохраняет работоспособность при снижении напряжения питания до 3,3В, при этом уменьшается яркость свечения светодиодных матриц.

Источник: http://radiolaba.ru/microcotrollers/zmeyka-i-tetris-na-mikrokontrollere.html

Персональный сайт Пьяных А.В

Источник: http://zlitos.com/publ/ehlektronika/arduino_i_t_p/arduino_i_svetodiodnye_matricy_8kh8_max7219/12-1-0-35

Подключение LED матрицы MAX7219 к Arduino

Сегодня мы научимся использовать светодиодную матрицу MAX7219 с платой Arduino UNO. И несмотря на то, что на первый взгляд применение платы может показаться достаточно непростым, на самом деле подключить ее и использовать очень легко.

Что нам понадобится:

Подключение

Процесс подключения совсем несложен. Необходимо подключить 5 контактов матрицы к плате:

  • Vcc – 5v
  • Gnd – Gnd
  • DIN (DataIN) – 11
  • CS (LOAD) – 10
  • CLK – 13

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

Код

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

/* This code is a public example. dil = 11 cs = 10 clk = 13 */ #include #include PROGMEM prog_uchar CH[] = { 3, 8, B00000000, B00000000, B00000000, B00000000, B00000000, // space 1, 8, B01011111, B00000000, B00000000, B00000000, B00000000, // ! 3, 8, B00000011, B00000000, B00000011, B00000000, B00000000, // ” 5, 8, B00010100, B00111110, B00010100, B00111110, B00010100, // # 4, 8, B00100100, B01101010, B00101011, B00010010, B00000000, // $ 5, 8, B01100011, B00010011, B00001000, B01100100, B01100011, // % 5, 8, B00110110, B01001001, B01010110, B00100000, B01010000, // & 1, 8, B00000011, B00000000, B00000000, B00000000, B00000000, // ' 3, 8, B00011100, B00100010, B01000001, B00000000, B00000000, // ( 3, 8, B01000001, B00100010, B00011100, B00000000, B00000000, // ) 5, 8, B00101000, B00011000, B00001110, B00011000, B00101000, // * 5, 8, B00001000, B00001000, B00111110, B00001000, B00001000, // + 2, 8, B10110000, B01110000, B00000000, B00000000, B00000000, // , 4, 8, B00001000, B00001000, B00001000, B00001000, B00000000, // – 2, 8, B01100000, B01100000, B00000000, B00000000, B00000000, // . 4, 8, B01100000, B00011000, B00000110, B00000001, B00000000, // / 4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // 0 3, 8, B01000010, B01111111, B01000000, B00000000, B00000000, // 1 4, 8, B01100010, B01010001, B01001001, B01000110, B00000000, // 2 4, 8, B00100010, B01000001, B01001001, B00110110, B00000000, // 3 4, 8, B00011000, B00010100, B00010010, B01111111, B00000000, // 4 4, 8, B00100111, B01000101, B01000101, B00111001, B00000000, // 5 4, 8, B00111110, B01001001, B01001001, B00110000, B00000000, // 6 4, 8, B01100001, B00010001, B00001001, B00000111, B00000000, // 7 4, 8, B00110110, B01001001, B01001001, B00110110, B00000000, // 8 4, 8, B00000110, B01001001, B01001001, B00111110, B00000000, // 9 2, 8, B01010000, B00000000, B00000000, B00000000, B00000000, // : 2, 8, B10000000, B01010000, B00000000, B00000000, B00000000, // ; 3, 8, B00010000, B00101000, B01000100, B00000000, B00000000, // < 3, 8, B00010100, B00010100, B00010100, B00000000, B00000000, // = 3, 8, B01000100, B00101000, B00010000, B00000000, B00000000, // > 4, 8, B00000010, B01011001, B00001001, B00000110, B00000000, // ? 5, 8, B00111110, B01001001, B01010101, B01011101, B00001110, // @ 4, 8, B01111110, B00010001, B00010001, B01111110, B00000000, // A 4, 8, B01111111, B01001001, B01001001, B00110110, B00000000, // B 4, 8, B00111110, B01000001, B01000001, B00100010, B00000000, // C 4, 8, B01111111, B01000001, B01000001, B00111110, B00000000, // D 4, 8, B01111111, B01001001, B01001001, B01000001, B00000000, // E 4, 8, B01111111, B00001001, B00001001, B00000001, B00000000, // F 4, 8, B00111110, B01000001, B01001001, B01111010, B00000000, // G 4, 8, B01111111, B00001000, B00001000, B01111111, B00000000, // H 3, 8, B01000001, B01111111, B01000001, B00000000, B00000000, // I 4, 8, B00110000, B01000000, B01000001, B00111111, B00000000, // J 4, 8, B01111111, B00001000, B00010100, B01100011, B00000000, // K 4, 8, B01111111, B01000000, B01000000, B01000000, B00000000, // L 5, 8, B01111111, B00000010, B00001100, B00000010, B01111111, // M 5, 8, B01111111, B00000100, B00001000, B00010000, B01111111, // N 4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // O 4, 8, B01111111, B00001001, B00001001, B00000110, B00000000, // P 4, 8, B00111110, B01000001, B01000001, B10111110, B00000000, // Q 4, 8, B01111111, B00001001, B00001001, B01110110, B00000000, // R 4, 8, B01000110, B01001001, B01001001, B00110010, B00000000, // S 5, 8, B00000001, B00000001, B01111111, B00000001, B00000001, // T 4, 8, B00111111, B01000000, B01000000, B00111111, B00000000, // U 5, 8, B00001111, B00110000, B01000000, B00110000, B00001111, // V 5, 8, B00111111, B01000000, B00111000, B01000000, B00111111, // W 5, 8, B01100011, B00010100, B00001000, B00010100, B01100011, // X 5, 8, B00000111, B00001000, B01110000, B00001000, B00000111, // Y 4, 8, B01100001, B01010001, B01001001, B01000111, B00000000, // Z 2, 8, B01111111, B01000001, B00000000, B00000000, B00000000, // [ 4, 8, B00000001, B00000110, B00011000, B01100000, B00000000, // backslash 2, 8, B01000001, B01111111, B00000000, B00000000, B00000000, // ] 3, 8, B00000010, B00000001, B00000010, B00000000, B00000000, // hat 4, 8, B01000000, B01000000, B01000000, B01000000, B00000000, // _ 2, 8, B00000001, B00000010, B00000000, B00000000, B00000000, // ` 4, 8, B00100000, B01010100, B01010100, B01111000, B00000000, // a 4, 8, B01111111, B01000100, B01000100, B00111000, B00000000, // b 4, 8, B00111000, B01000100, B01000100, B00101000, B00000000, // c 4, 8, B00111000, B01000100, B01000100, B01111111, B00000000, // d 4, 8, B00111000, B01010100, B01010100, B00011000, B00000000, // e 3, 8, B00000100, B01111110, B00000101, B00000000, B00000000, // f 4, 8, B10011000, B10100100, B10100100, B01111000, B00000000, // g 4, 8, B01111111, B00000100, B00000100, B01111000, B00000000, // h 3, 8, B01000100, B01111101, B01000000, B00000000, B00000000, // i 4, 8, B01000000, B10000000, B10000100, B01111101, B00000000, // j 4, 8, B01111111, B00010000, B00101000, B01000100, B00000000, // k 3, 8, B01000001, B01111111, B01000000, B00000000, B00000000, // l 5, 8, B01111100, B00000100, B01111100, B00000100, B01111000, // m 4, 8, B01111100, B00000100, B00000100, B01111000, B00000000, // n 4, 8, B00111000, B01000100, B01000100, B00111000, B00000000, // o 4, 8, B11111100, B00100100, B00100100, B00011000, B00000000, // p 4, 8, B00011000, B00100100, B00100100, B11111100, B00000000, // q 4, 8, B01111100, B00001000, B00000100, B00000100, B00000000, // r 4, 8, B01001000, B01010100, B01010100, B00100100, B00000000, // s 3, 8, B00000100, B00111111, B01000100, B00000000, B00000000, // t 4, 8, B00111100, B01000000, B01000000, B01111100, B00000000, // u 5, 8, B00011100, B00100000, B01000000, B00100000, B00011100, // v 5, 8, B00111100, B01000000, B00111100, B01000000, B00111100, // w 5, 8, B01000100, B00101000, B00010000, B00101000, B01000100, // x 4, 8, B10011100, B10100000, B10100000, B01111100, B00000000, // y 3, 8, B01100100, B01010100, B01001100, B00000000, B00000000, // z 3, 8, B00001000, B00110110, B01000001, B00000000, B00000000, // { 1, 8, B01111111, B00000000, B00000000, B00000000, B00000000, // | 3, 8, B01000001, B00110110, B00001000, B00000000, B00000000, // } 4, 8, B00001000, B00000100, B00001000, B00000100, B00000000, // ~ }; int data = 11; // 8, DIN pin of MAX7219 module int load = 10; // 9, CS pin of MAX7219 module int clock = 13; // 10, CLK pin of MAX7219 module int maxInUse = 1; //change this variable to set how many MAX7219's you'll use MaxMatrix m(data, load, clock, maxInUse); // define module byte buffer[10]; // active sentenses char string1[] = ” ABCDEFGHIJKLMNOPQRSTUVWXYZ “; void setup(){ m.init(); // module initialize m.setIntensity(0); // dot matix intensity 0-15 Serial.begin(9600); // serial communication initialize } void loop(){ byte c; // this is the code if you want to entering a message via serial console while (Serial.available() > 0){ byte c = Serial.read(); Serial.println(c, DEC); printCharWithShift(c, 100); } delay(100); m.shiftLeft(false, true); // 1st block – print the active sentences // comment this block when using the 2nd messages block printStringWithShift(string1, 100); //printStringWithShift(string2, 100); //printStringWithShift(string3, 100); //printStringWithShift(string4, 100); //printStringWithShift(string5, 100); //printStringWithShift(string6, 100); // 2nd block – print sentences just for tests // uncomment this block to use it /* printStringWithShift(string7, 100); printStringWithShift(string8, 100); printStringWithShift(string9, 100); printStringWithShift(string10, 100); printStringWithShift(string11, 100); */ } void printCharWithShift(char c, int shift_speed){ if (c < 32) return; c -= 32; memcpy_P(buffer, CH + 7*c, 7); m.writeSprite(maxInUse*8, 0, buffer); m.setColumn(maxInUse*8 + buffer[0], 0); for (int i=0; i

Источник: https://amperkot.ru/blog/led-matrix-arduino-max7219/

Как сделать очень заметный информер из светодиодного модуля для наружной рекламы и Arduino

Цель: Быстро подключить большую светодиодную матрицу P10 (16х32см) к ПК или другому устройству, превратив все это в очень заметный и яркий информер с динамической сменой выводимой информации.

Применений такой вещи можно найти массу и как показывает практика она очень привлекает внимание.

Вы только представьте, теперь точно все будут знать что у вас работает кондиционер и дверь предполагается закрывать!

Засветка не от окна, а от панели 😉

Однажды посмотрев на унылые матрицы 8х8 светодиодов для Arduino и на их стоимость мне стало грустно.

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

Капнув глубже обнаружилось что во всей подобной продукции используются типовые светодиодные модули (светодиодные матрицы).

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

Эти светодиодных модулей довольно дешевы. Порядка 6$, цена зависит от типоразмера и цветности. С контроллерами сложнее. Самые простые по цене сравнимы с одной светодиодной панелью.

Однако большинство из них “заточено” на работу в режиме демонстрации заранее заготовленных “презентаций” и не имеют возможности динамически менять выводимую информацию.

Признаюсь что только бегло ознакомился с функционалом самых простых контроллеров, но этого оказалось достаточно чтобы понять — дешевле и быстрее сделать необходимое на универсальном контроллере Arduino. Это позволит подключить совершенно спокойно несколько модулей. Но мы начнем с одного.

Светодиодный модуль (Р10) выглядит примерно так:

http://digital-wizard.net/avr_projects/p10_led_display_panel_interface

По сути это просто матрица светодиодов которые припаяны к выходам сдвиговых регистров, не будем вдаваться в дебри схемотехники, модули все стандартные и отличаются лишь размерами.

Р10 означает что между двумя соседними диодами 10мм. Бываю панели одноцветные, двухцветные и даже RGB.

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

Аппаратная часть

А для тех кто хочет быстрее получить результат, который можно “пощупать”, потребуется:

  1. Одна светодиодная матрица.
  2. Arduino. (Я использовал mini, но удобнее будет nano чтобы не использовать доп. переходники для связи с ПК).
  3. Блок питания на 5В/3А. Матрица прожорлива, если зажечь все диоды то питания надо много.
  4. Шлейф подключения. (Обычно он идет в комплекте с матрицей.)
  5. Желание довести дело до конца.

Будем делать монолитную конструкцию которую достаточно лишь воткнуть в розетку и ПК чтобы отображать нашу драгоценную информацию (например курс биткоина).

Необходимо взять шлейф от матрицы, разрезав его на пополам припаять по простой схеме к Arduino.

Если использовать Arduino Mini или UNO то паять надо к соответствующим пинам по аналогии.

Если по какой-то причине у вас не оказалось шлейфа то его можно заменить на MIDI кабель которым в старых звуковых картах подключается к самой плате MIDI разъем (вариант для старожил) или заменить на два штекера Dupont (мама) по 8 контактов. В принципе разъем стандартный, ищется довольно легко.

У меня же за 10 минут получилась следующая конструкция, болтается еще дополнительный USBtoUART переходник которого у вас не будет если использовать не Arduino Mini.

Аппаратная часть готова, необходимо только подключить дополнительный БП на 5В/3А для питания матрицы. Для этого на ней есть отдельный разъем, плюс к плюсу, минус к минусу. Наоборот можно, но работать не будет.

Хотя странно, так как всем известно что электроны, по обыкновению, текут от плюса к минусу.

А если учесть что электроны отрицательно заряженные то вообще не понятно почему они текут к отрицательному полюсу… 😉 Ерунды навыдумывали короче.

Я надеюсь что вы подключите питание более надежно, а мой способ отлично годится только если у вас много запасных БП. Ардуину можно прикрутить болтом (не саморезом!) к самой панели, в панели есть монтажные резьбовые отверстия.

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

Программная часть

Если вы подумали что нужно будет разбираться как программировать эту штуку из трех букв (SPI интерфейс) то могу вас разочаровать — все значительно проще. Как всегда все велосипеды придуманы до нас и не единожды. Собственно как и эта статья. Есть готовые библиотеки DMD и DMD2 и рисование сводится к тому что в скетче нужно просто указать что, как и куда выводить, все — Профит!

Немного поигравшись с формой квадрата этими библиотеками я пришел к выводу что скролинг текста во DMD2 выглядит “печально”, хотя там есть больше возможностей и управление яркостью. В итоге остановился на первой и вспомнив что “ты ж программист” добавил в нее примитивное управление яркостью. Тут стоит упомянуть что светят эти матрицы очень ярко. К концу отладки выжжет роговицу.

В общем все что вам надо сделать это загрузить скетч в плату, но именно из той директории куда распакуете мой архив, так как я немного доработал напильником некоторые библиотеки, которые лежат там же. Добавилось управление яркостью и чуть чуть разогнан SPI, может еще что, уже и не помню. Рабатет? Не трогай!

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

Чтобы изменить текст который прокручивается снизу нужно его просто “вгрузить” в COM порт Arduino используя специальный формат, некое подобие ESC последовательности.

Прилагается скрипт на Python который просто посылает на панель текущее время.

Формат управляющих команд:

  1. 0x1B (ESC) + 0x40 (“@”) // Опознание, возвращает строку ID устройства «P10_DISPLAY_V01rn»
  2. 0xOC (CLR) // Очистка экрана.
  3. 0x1F (US) + 0x58 («X») + 0x80 // Задать якрость экрана, 0x80 максимальная яркость.
  4. 0x1F (US) + 0x52 («B») + Строка // Задать нижнюю строку которая скролится.
  5. 0x1F (US) + 0x0A («LF») + 0x31, 0x32, 0x33, 0x34, 0x35 // Передать пятизначно число отображаемое вверху «12345»

Я не нашел готового и пришлось нарисовать русский шрифт 5*7. Наверно велосипед, но разве мы делаем всегда все рационально?

Скетч:

Код//====================== OneWire ====================================
#include
OneWire ds2 (2);
String res = “”;
byte type_s;
byte data[12];
byte addr_ds2[8];
bool temp_sensor_2_found = false;
float temp1 = 999;
//=================================================================== #include #include “DMD.h” #include “TimerOne.h” #include “SystemFont5x7rus.h” #define CLR 0x0C
#define US 0x1F
#define ESC 0x1B
#define LF 0x0A static const char ID[] = “P10_DISPLAY_V01rn”; // Device ID #define DISPLAYS_ACROSS 1
#define DISPLAYS_DOWN 1
DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN); // Конфигурация экрана, панелей может быть не одна.
#define max_char1 6
#define max_char2 176
char message1[max_char1] = {0x20,0x30,0x30,0x30,0x30,0x00}; // stores you message
char message2[max_char2]; // stores you message char r_char; byte index1 = 4; byte index2 = 176; int i;
long scrollSpeed = 25; char test[] = { 0x84,0x80,0x20,0x87,0x84,0x90,0x80,0x82,0x91,0x92,0x82,0x93,0x85,0x92,0x20,0x92, 0x8E,0x20,0x81,0x8B,0x80,0x83,0x8E,0x84,0x80,0x90,0x9F,0x20,0x97,0x85,0x8C,0x93, 0x20,0x8C,0x9B,0x20,0x8D,0x85,0x91,0x8C,0x8E,0x92,0x90,0x9F,0x20,0x8D,0x88,0x20, 0x8D,0x80,0x20,0x97,0x92,0x8E,0x20,0x88,0x20,0x82,0x8E,0x8F,0x90,0x85,0x8A,0x88, 0x20,0x82,0x91,0x85,0x8C,0x93,0x21,0x00}; //=============================================================================
bool get_sensor(byte addr[8], OneWire ds) { // Ищем адрес датчика if (! ds.search (addr)) { ds.reset_search (); delay (250); return false; } // Проверяем не было ли помех при передаче if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println(“get_sensor:CRC is not valid!”); return false; } // Определяем серию датчика switch (addr[0]) { case 0x10: //Chip = DS18S20 type_s = 1; break; case 0x28: //Chip = DS18B20 type_s = 0; break; case 0x22: //Chip = DS1822 type_s = 0; break; default: Serial.println(“get_sensor:Device is not a DS18x20 family device.”); return false; } return true;
} //============================================================================= double get_temp(byte addr[8], OneWire ds) { double celsius; ds.reset (); ds.select (addr); // Выбираем адрес ds.write (0x44, 1); // Производим замер, в режиме паразитного питания delay (750); ds.reset (); ds.select (addr); ds.write (0xBE); // Считываем оперативную память датчика for (int i = 0; i < 9; i++) { // Заполняем массив считанными данными data[i] = ds.read (); } // Данные о температуре содержатся в первых двух байтах, переведем их в одно значение и преобразуем в шестнадцатиразрядное число int raw = (data[1] 0x29) and (r_char < 0x3A)) { message1[index1] = r_char; index1++; } } } massage1Normalization(); } dmd.drawFilledBox( 0,8,31,15, GRAPHICS_INVERSE); break; default: break; } } while (Serial.available()) Serial.read(); dmd.writePixel(0,0,GRAPHICS_NORMAL,1); }Скрипт на Python:import serial
import os
import time
from datetime import datetime
import sys False = 0
True = 1 ser = serial.Serial(31) ser.flushInput()
ser.flushOutput()
while True: buf = 'x1FB'+ datetime.now().strftime(“%H:%M:%S %d %B %Y”) ser.write(buf) print ('Fire![' + buf + ']') time.sleep(5) ser.close() print('Game over!')

Работа на полной яркости:

Работа с человеческой яркостью:

Работа с динамической подгрузкой времени с ПК при помощи скрипта на Python:

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

Стоит отметить что совершенно свободно можно соеденить несколько модулей последовательно и всего лишь указав это в скетче получить экран большего размера.

Ограничения начинаются лишь после определенного количества панелей и связанны они с ограниченной производительностью Arduino и ее SPI интерфейса.

Спасибо ElectricFromUfa за подробнейшее и развернутый обзор панелей и не только!

Возможно в будущем все тоже самое я проделают на STM32F103C8T6 и на ESP-12F, там все должно шевелится побыстрее.

Ссылки:

1. Ссылка на архив со скетчем и сопутствующим.
2. Еще ссылка на BitBucket

Источник: http://www.pvsm.ru/arduino/258964

Светодиодная матрица на базе MAX7219

В этом примере мы используем светодиодную матрицу, на которой будем включать-выключать светодиоды и отображать ASCII символы.

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

Необходимые материалы

Для данного небольшого проекта вам понадобятся следующие компоненты:

  • плата Arduino Uno;
  • модуль матричного дисплея с красными светодиодами MAX7219;
  • 5 коннекторов папа-мама;

В данном примере используется плата Arduino Uno, но вы можете использовать любую аналогичный или совместимый микроконтроллер.

Найти модуль матричного дисплея не составит труда. Китайцы уже давно и больших количествах продают из на eBay и Aliexpress. Кроме того, на многих радиорынках Украины и России они тоже есть в наличии.

В состав этих модулей входят: 8х8 светодиодная матрица (красного цвета), чип MAX7219 для управления светодиодами, коннекторы, один резистор на 10 кОм, конденсатор на 100 нФ, электролитический конденсатор 10 uF, монтажная плата, на которой все это устанавливается.

Можно заказать собранный модуль, можно самому распаять все компоненты. Зависит от вас.

ВАЖНО: матричный светодиодный дисплей является общим катодом. Модуль не работает матрицами, которые имеют общий анод!

Библиотека Arduino для работы с матричным светодиодным дисплеем

Светодиодная матрица (LED matrix) управляется с помощью чипа MAX7219 и библиотеки Arduino.

Самая потрясающая вещь в этой библиотеке – это возможность подключения до 8 матриц и реализовать большой дисплей (более детально будет рассмотрено в отдельном туториале)

Библиотека LedControl library была дополнена некоторыми новыми методами для упрощения отображения символов и строк. Новая версия библиотеки доступна для скачивания по ссылкам:

LedControlMS.rar

LedControlMS.zip

Для интегрирования библиотеки в вашу Arduino IDE:

– распакуйте файл библиотеки, который вы только что скачали;

– убедитесь, что вы закрыли все открытые окна Arduino IDE;

– найди папку libraries внутри папки, где у вас установлена Arduino IDE (смотрите на рисунке ниже);

– скопируйте разархивированную папку LedControlMS (папку со всем ее содержимым) в папку libraries.

Если все прошло хорошо, вы можете вновь открыть Arduino IDE. В меню File -> Examples должна появится вкладка под названием LedControlMS с четырьмя файлами внутри.

Если у вас возникли дополнительные вопросы по установке библиотек в Arduino IDE, ознакомьтесь со статьей Библиотеки Arduinoгде рассмотрены все возможные сложности и порядок установки библиотек Arduino. Да и вообще, что это такое – библиотеки.

Подключение матричного дисплея к Arduino

После установки библиотеки можно подключать LED матрицу к плате Arduino.

На модуле светодиодной матрицы есть два набора контактов. В этом проекте мы будем использовать только контакты на вход, которые расположены ближе к чипу MAX 7219.

Есть пять контактов, которые надо подключить к соответствующим пинам Arduino.. Подключаем с помощью коннекторов папа-мама:

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

Пример скетча для 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. Не бойтесь ошибок! Именно ошибки часто ускоряют процесс обучения!

Matriz de LEDs.pdf

Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!

Источник: http://arduino-diy.com/arduino-svetodiodnaya-matritsa-na-baze-MAX7219

– Радиолюбитель

Автор: Юрий Всеволодович Ревич

Платформа Arduino предлагает широкие возможности для конструирования всяческих измерителей, но вопрос всегда упирается в вывод показаний так, чтобы это было эстетично и удобно.

ЖК-дисплеи очень хорошо подходят для автономных малопотребляющих приборов, но для настенных или настольных конструкций, по моему мнению, не годятся решительно из-за своей малой яркости и контраста. Куда лучше подходят для этой цели светодиодные или другие самосветящиеся устройства.

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

Вообще, ассортимент достаточно эстетично выглядящих светодиодных конструкций на рынке куда уже всех остальных разновидностей. Не размахиваться же на графический OLED-экран, когда нужно отобразить всего несколько символов, правда?

Рис.1 Разряд матричного индикатора 5×7

Поразрядные матричные индикаторы Здесь я предлагаю обратить свой взор в сторону матричных индикаторов 5×7 точек (Рис.1). Они выпускаются самых разных размеров и нескольких цветов, могут отображать любые символы, хоть китайские иероглифы.

Сложность состоит в надлежащей организации управления большим количеством светодиодов: только один разряд содержит их 35 штук, значит приемлемые для практических нужд линейки из четырех таких разрядов буду содержать 5х7х4 = 140 точек.

Разумеется, индивидуальное управление каждой точкой здесь невозможно и не предполагается: выводы таких индикаторов объединены по столбцам и строкам (Рис.1).

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

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

А самое главное, что в «методе Чарли» экономия числа управляющих выводов достигается за счет еще большего снижения коэффициента заполнения (то есть относительного времени в процентах, когда каждый светодиод оказывается включен), чем для обычного мультиплексирования. Для одного разряда по «методу Чарли» коэффициент заполнения будет около 15%.

При этом при обычном мультиплексировании (то есть, например, по столбцам, которых меньше, чем строк) коэффициент заполнения вырастет до 20%, но зато увеличится число управляющих выводов — на один разряд их придется 12. А на линейку из четырех таких индикаторов прямое мультиплексирование потребует уже 27 выводов, при этом коэффициент заполнения снизится еще в четыре раза, до 5% от максимальной светимости.

Учитывая, что у матриц и без того не слишком большая яркость (например, 18-миллиметровая зеленая ТА07-11GWA имеет силу света 8 мКд при токе 10 мА — вдвое хуже, чем самые тусклые дискретные светодиоды), такое падение яркости нельзя назвать хоть сколько-нибудь приемлемым.

Приходится искать альтернативные решения, позволяющие увеличить максимальный ток через каждую точку матрицы хотя бы до 15-20 мА и одновременно получить максимально возможный коэффициент заполнения.

Решение в виде схемы управления одновременно парой разрядов на коммутаторах-мультиплексорах малой степени интеграции с буферными элементами в каждой строке и столбце позволяет выжать максимум возможного из подобных схем подключения линейки 5х7х4: 24 управляющих вывода, ток через каждый светодиод до максимально допустимого (25 мА для матрицы ТА07-11).

Однако коэффициент заполнения все равно оказывается равен 10%, что слишком мало для нормального свечения, а схема получается настолько навороченной, что возникают сомнения в целесообразности использования таких матриц вообще. К тому же решение без дополнительных усилий не тиражируется на число разрядов, отличное от четырех.

По всем этим причинам я не буду останавливаться на нем подробно.

Видимо, эти обстоятельства и обусловили малую применимость точечных матриц в качестве простых индикаторов и в любительских, и в профессиональных применениях.

Однако, есть готовое решение, причем очень удобное как раз для простых приборов: это драйверы матричного дисплея конфигурации 5х7 точек х4 разряда под названием MAX6952 и MAX6953 (русское описание ), где эти проблемы решены.

MAX6952/6953 может обеспечить ток (устанавливаемый и программно и схемотехнически) через точку матрицы вплоть до 48 мА, обладает встроенной таблицей шрифтов из 104 символов, дополняемых 24 пользовательскими, и управляется через скоростной SPI-интерфейс (MAX6952) или I2C (MAX6953). Их недостаток — достаточно высокая стоимость (около 20 долларов) и редкость в отечественной розничной продаже, отчего приходится заказывать в компаниях, имеющих склады за рубежом, что медленно и дорого. Зато никаких проблем с управлением матричными табло вы больше иметь не будете.

Сразу отмечу, что решение с этими драйверами можно масштабировать практически неограниченно, получая линейки из четырех, восьми, двенадцати и т.д. разрядов. Причем без каких-то усложений, кроме увеличения числа микросхем и роста общего потребления. Для SPI-варианта при этом увеличится лишь число управляющих выводов «выбор кристалла» соответственно числу микросхем, а для I2C-версии в схеме управления не изменится вообще ничего — MAX6953 позволяет устанавливать коммутацией соответствующих выводов до 16 вариантов внутреннего I2C-адреса.

Схема подключения MAX6953 с I2C-интерфейсом
Особенности MAX6953, как имеющего минимальное число внешних соединений, мы и рассмотрим далее.

Напомним, что I2C-устройства управляются всего по двум проводам, причем вместе с драйвером индикатора на ту же шину можно навесить еще сколько угодно полезных приблуд: часы реального времени, различные датчики (вроде термометра и барометра), компас-магнетометр, энергонезависимую память и т.д. Платформа Arduino позволяет это делать просто и быстро.

Рис.2 Схема подключения 4-х матричных индикаторов 5х7 точек с драйвером MAX6953

Схема подключения линейки матричных индикаторов типа ТА07-11, рассчитанных на работу в качестве дисплея электронных часов, к драйверу MAX6953 показана на рис. 2.

Всего она имеет пять внешних соединений: питание +5 В и «земля», два вывода управляющего I2C-интерфейса (SDA и SCL), а также объединенные катоды светодиодов разделительной точки, обозначенные на схеме, как Blink_Dots. Этот вывод подключается к любому из свободных портов Arduino, и управляется отдельно.

Разбор схемы начнем с вопроса о подборе величин резистора R3 и конденсатора С1, от которых зависит как максимально возможный ток через светодиоды матрицы, так и внутренняя тактовая частота драйвера. От тактовой частоты зависит частота мигания дисплея при включении режима BLINK через драйвер.

Мы такой режим не используем, потому частота (fOSC) нас волнует во вторую очередь ( рекомендует выбирать ее от 1 до 8 МГц), а вот ток через сегменты (ISEG) очень важен. Согласно документации на MAX6953, эти величины определяются формулами (обозначения далее — в соответствии со схемой рис.

2): ISEG = 2144/R3 mA fOSC = 6003/(R3 ✕ (C1 + C0)) MHz Здесь R3 подставляется в килоомах, C1 — в пикофарадах, С0 – паразитная емкость монтажа (типовое значение около 2 пФ). По умолчанию документация рекомендует для R1 и C3 нестандартные значения 53,6 кОм и 26 пФ, что дает частоту fOSC в 4 МГц, и максимальный ток ISEG равный 40 мА.

Разобраться в том, что в документации понимается под «сегментом», непросто, потому я поясню, к чему относится эта величина тока: в каждый момент времени включены два из четырех разрядов, и для расчета общего среднего тока потребления величину ISEG надо умножать не на 20 (5х4 — общее число столбцов), а на 10. Это равносильно коэффициенту заполнения 50%, т.е.

реальный средний ток через столбец матрицы будет вдвое меньше ISEG, следовательно, под сегментом тут понимаются два столбца в разрядах, горящих одновременно. То есть при таком токе вся конструкция будет потреблять около 415 мА, считая собственное потребление драйвера.

Однако, при напряжении питания 5 В выделяющаяся мощность может превысить возможности микросхемы, потому документация рекомендует ставить дополнительный резистор по питанию. Мы в эти тонкости вникать не хотим, потому просто увеличим номинал R3 до 100 кОм, тем самым снизив пиковый ток через светодиоды матрицы до 20 мА.

Но имейте в виду, что у вас есть некоторый запас по яркости, и если вы, например, поставите матрицу побольше размерами, то можете увеличить яркость, просто уменьшив номинал R3 (только внимательно изучите документацию перед этим). Второе соображение относится к источнику питания.

При питании Arduino от USB-порта, его номинальных возможностей (500 мА максимум) может не хватить, особенно, если к Arduino подключены еще какие-то устройства.

При питании от адаптера 7-9 В встроенный в Arduino Uno или Micro стабилизатор NCP1117 имеет достаточно высокую нагрузочную способность (до 1 А), однако надо учитывать, что он не установлен на радиатор, и при большом токе и высоком напряжении адаптера может перегреваться. По всем этим причинам питать нашу схему от платы Arduino необходимо с оглядкой. А на период отладки настоятельно рекомендую включать ее от отдельного источника 5 В — если вы что-то не так соедините, какие-то выводы MAX6953 окажутся висящими в воздухе или перемкнуты между собой (что случается при любительском монтаже микросхем в корпусах с мелким шагом), то ток потребления может резко возрасти и лучше пожертвовать одной микросхемой MAX6953, чем еще и платой Arduino. По той же причине для любительских целей я рекомендую приобретать MAX6953 в DIP-корпусе с шагом 2,54, хотя они встречаются в продаже еще реже, чем в корпусе SSOP с шагом 0,8 мм, и занимают гораздо больше места.

В остальном схема столь тонких расчетов не требует. Токоограничивающие резисторы для светодиодов разделительного двоеточия выбраны опытным путем, чтобы подогнать яркость под точки матрицы. Тип трехмиллиметровых светодиодов L132 выбран по длине волны (т.е.

их цвету свечения) соответствующему индикатору ТА07-11 и минимальной яркости среди других типов.

Контакты MAX6953 21 (SDA) и 22 (SCL) подключаются к штатным выводам интерфейса I2C Arduino A4 и A5, соответственно, а катоды светодиодов (вывод Blink_Dots) — к выводу A0 (цифровой вывод 14).

Программа
Рассмотрим построение программы управления драйвером MAX6953 от Arduino. Схема рис. 2 предполагает I2C-адрес устройства по умолчанию (0x50).

О том, какие выводы надо переключить для изменения адреса, если это необходимо, читайте документацию. Запуск драйвера предполагает довольно громоздкую процедуру инициализации всех нужных регистров, которую следует размещать в секции setup.

Предварительно в программе следует подключить библиотеку wire.h и установить необходимые переменные:

#include

void setup() { //====инициализация матрицы===== Wire.begin(); // подключаем i2c bus Wire.beginTransmission(deviceaddress); // запись в устройство Wire.write(0x04); // регистр конфигурации //MAX6953 Table 6 – номер таблицы в описании Wire.write(0x01); // выключаем режим shutdown; Wire.endTransmission(); //MAX6953 Table 23 – следующий шаг: Wire.beginTransmission(deviceaddress); Wire.

write(0x01); // Интенсивность разрядов 0 и 2 Wire.write(0xFF); //все сегменты на максимум = 20 мА Wire.endTransmission(); //MAX6953 Table 24 – следующий шаг: Wire.beginTransmission(deviceaddress); Wire.write(0x02); // Интенсивность разрядов 1 и 3 Wire.write(0xFF); // все сегменты на максимум = 20 мА Wire.

endTransmission(); //Включаем test mode для проверки: все светодиоды горят //MAX6953 Table 22 Wire.beginTransmission(deviceaddress); Wire.write(0x07); Wire.write(0x01); Wire.endTransmission(); delay(1000); //секундная задержка //выключаем test mode //MAX6953 Table 22 Wire.beginTransmission(deviceaddress); Wire.write(0x07); Wire.write(0x00); Wire.

endTransmission(); //=====конец инициализации ======= pinMode(ledPin, OUTPUT); //управление разделительным двоеточием

}

Далее отдельно вставляем текст функции для вывода символа в определенный разряд. Автор этих строк ненавидит перечеркнутый ноль на дисплеях — анахронизм времен АЦПУ и алфавитно-цифровых терминалов, потому функция заодно заменяет цифру «0» на букву «O». Если вас это не волнует, удалите всю функцию IF..ELSE, оставив от нее только строку Wire.write(value)):

//запись символа value в разряд disp void writeChar(byte value,byte disp) { Wire.beginTransmission(0x50); Wire.write(disp); if (value == ‘0’) Wire.write(‘O’); //ноль заменяем на букву O!! else Wire.write(value); Wire.endTransmission();

}

И, наконец, собственно проба вывода символов в функции Loop:

void loop() { //матрица: writeChar(‘0′,dig3); writeChar(‘2′,dig2); writeChar(‘0′,dig1); writeChar(‘3′,dig0); delay(500); digitalWrite(ledPin, LOW); writeChar(‘6′,dig3); writeChar(‘0′,dig2); writeChar(‘8′,dig1); writeChar(‘0′,dig0); delay(500); digitalWrite(ledPin, HIGH);

}

Эта программа выводит на дисплей попеременно строку цифр «30:20» и «08:06» с одновременным подмигиванием двоеточием. Вы можете поэкспериментировать, подставляя в функции writeChar разные другие символы.

Придется, однако, ограничиться только английским алфавитом и рядом специальных знаков (см. таблицу 15 в документации).

Среди этих знаков есть символы доллара, евро и иены, что позволяет на основе MAX6953 делать, например, табло валютных обменников.

Часы полностью
Остановимся поподробнее на реализации электронных часов, для чего мы и вводили мигающее двоеточие. Для этого надо лишь подключить любой модуль часов, например, на основе микросхемы DS1307.

Я рекомендую распространенный модуль RTC, продающийся, например, в Он самый малогабаритный из всех, однако рассчитан на редко встречающуюся в рознице батарейку типоразмера 1225. Несколько более громоздкий модуль, рассчитанный на стандартную CR2032 (к тому же большей емкости), продается в Он основан на версии тех же часов под названием M41T56 от STMicroelectronics. Библиотека DS1307.

h (ее можно скачать на ), которую мы будем использовать далее, полностью совместима с M41T56 и опыт показал, что модуль работает даже стабильнее оригинального.

Внешний вид платы часов c матричными индикаторами.

Обратите внимание, что, в отличие от семисегментных, в индикаторах отсутствует разделительное поле справа и слева, они рассчитаны на возможность составлять непрерывные матрицы большего размера. Это, однако, приводит к тому, что символы шрифта 5х7 сливаются, потому индикаторы установлены с некоторым промежутком.

Видимый на фото концевик, прикрученный к плате справа, не имеет отношения к нашей теме — он пробовался в усложненном варианте программы для вывода других параметров на тот же дисплей. Контакты I2C-интерфейса модуля RTC подключаются к тем же выводам Arduino A4 и A5, параллельно драйверу дисплея.

Полную программу для такого варианта часов можно скачать с сайта автора по этой ссылке.

Обратите внимание, что там пришлось дополнительно вводить функцию decToBcd для распаковки значений часов и минут, чтобы иметь возможность вывести цифры поразрядно — это очень важный нюанс, который придется учитывать во всех случаях вывода многоразрядных чисел на такой дисплей.

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

Это можно сделать из той же программы, если сначала раскомментировать соответствующие строки в секции setup, ввести в них значения времени, загрузить программу, потом закомментировать их снова и заново загрузить уже окончательный вариант. О том, как можно оформить процедуру установки часов через последовательный порт, читайте в 3-м издании моей книги .

Если будут вопросы, пишите автору по адресу revich@lib.ru.

Источник: http://radio-stv.ru/arduino-i-matrichnyie-indikatoryi

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}
");let k=document.querySelector(".flat_pm_modal[data-id-modal=\""+a.ID+"\"]");if(-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(k,d):jQuery(k).html(b+d),"px"==a.how.popup.px_s)e.bind(h,()=>{e.scrollTop()>a.how.popup.after&&(e.unbind(h),f.unbind(i),j())}),void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{e.unbind(h),f.unbind(i),j()});else{let b=setTimeout(()=>{f.unbind(i),j()},1e3*a.how.popup.after);void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{clearTimeout(b),f.unbind(i),j()})}f.on("click",".flat_pm_modal .flat_pm_crs",()=>{jQuery.arcticmodal("close")})}if(void 0!==a.how.outgoing){let b,c="0"==a.how.outgoing.indent?"":" style=\"bottom:"+a.how.outgoing.indent+"px\"",e="true"==a.how.outgoing.cross?"":"",f=jQuery(window),g="scroll.out"+a.ID,h=void 0===flatPM_getCookie("flat_out_"+a.ID+"_mb")||"false"!=flatPM_getCookie("flat_out_"+a.ID+"_mb"),i=document.createElement("div"),j=jQuery("body"),k=()=>{void 0!==a.how.outgoing.cookie&&"false"==a.how.outgoing.cookie&&h&&(jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show"),j.on("click",".flat_pm_out[data-id-out=\""+a.ID+"\"] .flat_pm_crs",function(){flatPM_setCookie("flat_out_"+a.ID+"_mb",!1)})),(void 0===a.how.outgoing.cookie||"false"!=a.how.outgoing.cookie)&&jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show")};switch(a.how.outgoing.whence){case"1":b="top";break;case"2":b="bottom";break;case"3":b="left";break;case"4":b="right";}jQuery("body > *").eq(0).before("
"+e+"
");let m=document.querySelector(".flat_pm_out[data-id-out=\""+a.ID+"\"]");-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(m,d):jQuery(m).html(e+d),"px"==a.how.outgoing.px_s?f.bind(g,()=>{f.scrollTop()>a.how.outgoing.after&&(f.unbind(g),k())}):setTimeout(()=>{k()},1e3*a.how.outgoing.after),j.on("click",".flat_pm_out .flat_pm_crs",function(){jQuery(this).parent().removeClass("show").addClass("closed")})}countMode&&(flat_count["block_"+a.ID]={},flat_count["block_"+a.ID].count=1,flat_count["block_"+a.ID].click=0,flat_count["block_"+a.ID].id=a.ID)}catch(a){console.warn(a)}}function flatPM_start(){let a=flat_pm_arr.length;if(0==a)return flat_pm_arr=[],void jQuery(".flat_pm_start, .flat_pm_end").remove();flat_body=flat_body||jQuery("body"),!flat_counter&&countMode&&(flat_counter=!0,flat_body.on("click","[data-flat-id]",function(){let a=jQuery(this),b=a.attr("data-flat-id");flat_count["block_"+b].click++}),flat_body.on("mouseenter","[data-flat-id] iframe",function(){let a=jQuery(this),b=a.closest("[data-flat-id]").attr("data-flat-id");flat_iframe=b}).on("mouseleave","[data-flat-id] iframe",function(){flat_iframe=-1}),jQuery(window).on("beforeunload",()=>{jQuery.isEmptyObject(flat_count)||jQuery.ajax({async:!1,type:"POST",url:ajaxUrlFlatPM,dataType:"json",data:{action:"flat_pm_ajax",data_me:{method:"flat_pm_block_counter",arr:flat_count}}})}).on("blur",()=>{-1!=flat_iframe&&flat_count["block_"+flat_iframe].click++})),flat_userVars.init();for(let b=0;bflat_userVars.textlen||void 0!==a.chapter_sub&&a.chapter_subflat_userVars.titlelen||void 0!==a.title_sub&&a.title_subc&&cc&&c>d&&(b=flatPM_addDays(b,-1)),b>e||cd||c-1!=flat_userVars.referer.indexOf(a))||void 0!==a.referer.referer_disabled&&-1!=a.referer.referer_disabled.findIndex(a=>-1!=flat_userVars.referer.indexOf(a)))&&(c=!0),c||void 0===a.browser||(void 0===a.browser.browser_enabled||-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser))&&(void 0===a.browser.browser_disabled||-1==a.browser.browser_disabled.indexOf(flat_userVars.browser)))){if(c&&void 0!==a.browser&&void 0!==a.browser.browser_enabled&&-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser)&&(c=!1),!c&&(void 0!==a.geo||void 0!==a.role)&&(""==flat_userVars.ccode||""==flat_userVars.country||""==flat_userVars.city||""==flat_userVars.role)){flat_pm_then.push(a),flatPM_setWrap(a),flat_body.hasClass("flat_pm_block_geo_role")||(flat_body.addClass("flat_pm_block_geo_role"),flatPM_ajax("flat_pm_block_geo_role")),c=!0}c||(flatPM_setWrap(a),flatPM_next(a))}}}let b=jQuery(".flatPM_sticky");b.each(function(){let a=jQuery(this),b=a.data("height")||350,c=a.data("top");a.wrap("
");let d=a.parent()[0];flatPM_sticky(this,d,c)}),debugMode||countMode||jQuery("[data-flat-id]:not([data-id-out]):not([data-id-modal])").contents().unwrap(),flat_pm_arr=[],jQuery(".flat_pm_start, .flat_pm_end").remove()}
   Сегодня на повестке дня вывод информации на кластер матричных светодиодных панелей разрешением 8х8 точек на микросхемах MAX7219. Опишу подключение к Arduino и использование двух наиболее популярных библиотек MAX72xx Panel от Марка Райса и Parola от MajicDesigns. Рассмотрю вывод кириллических и создание пользовательских символов.

    Наконец доехали из поднебесной матричные модули. Каждый модуль состоит из микросхемы MAX7219 (здесь я уже описывал эту микросхему), светодиодной матрицы, в обвязке стоят один конденсатор и один резистор.

    Управляется MAX7219 по интерфейсу SPI.

   Микросхемы в кластере соединены последовательно. Читал в интернете, что максимально возможное последовательное подключение допускает всего 8 штук MAX7219. Не верьте. 16 модулей соединил, и все прекрасно работает.

   Модули, представленные на Али, бывают в нескольких вариантах исполнения. Наибольшей популярностью пользуются 2 вида: с микросхемой в DIP и в SOIC корпусах. Модуль с DIP-микросхемой большего размера и не так удобен при соединении в кластер. Соединять придется кучей проводов.

   Модули с микросхемой в SOIC-корпусе имеют размер светодиодной матрицы и соединяются пайкой или джамперами. Получается красиво и аккуратно.

   Наиболее известными библиотеками для работы с матрицами и кластерами  являются MAX72xx Panel от Марка Райса и Parola от MajicDesigns: первая библиотека проще в использовании, вторая посложнее с бОльшими возможностями. Распишу подробнее.

MAX72xx Panel

   При использовании MAX72xx Panel обязательна установка библиотеки Adafruit GFX.

   Для русификации текста необходимо будет скачать ЭТОТ ФАЙЛ и заменить стандартный  файл glcdfont.c в каталоге Arduino/Libraries/Adafruit-GFX-Library-master. Также в этом файле описаны, кроме нужных букв и цифр, куча всяких символов. Далеко не все они могут пригодиться. Картинка ниже поясняет как формируются символы.

   При необходимости Вы можете создать свои символы и заменить ими любые неиспользуемые в файле. Практически все точечные  шрифты, используемые в различных библиотеках, сформированы подобным образом.

   Итак, библиотеки MAX72xx Panel и Adafruit GFX установлены, файл glcdfont.c заменен. Запускаем Arduino IDE, открываем ФАЙЛ. В скетче есть функция utf8rus. Она обеспечивает перекодировку таблицы символов для русского языка.

Она нужна только для нормального вывода из программы, то есть в программе нужный текст пишется на русском. Если текст вводится через СОМ-порт, то коррекция кодов символа происходит в функции Serial_Read.

В IDE и в консоли разработчики использовали разные кодировки.

   В начале файла присутствуют строки необходимые для работы библиотеки.

int numberOfHorizontalDisplays = 1;

int numberOfVerticalDisplays = 16;

   У меня модули с микросхемой в SOIC-корпусе. У них есть небольшая особенность. Матрица у модулей установлена повернутой на 90 градусов. Это плата за удобство соединения.

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

Для лечения этого недуга библиотеке надо “сказать”, что вертикальных дисплеев 16 (физически они расположены горизонтально). И потом в void Setup указать библиотеке строку

matrix.setRotation(matrix.getRotation() + 1);

   Она программно перевернет каждую матрицу. И отображаться все будет нормально.

   У модулей с DIP-корпусом микросхем такого нет. Там все красиво, кроме кучи проводов.

   Библиотека MAX72xx Panel довольно скромная. Визуальных эффектов вывода нет. Кластер воспринимается как одно целое. Намного лучше дела обстоят с MD Parola.

Parola от MajicDesigns.

   Обладатели модулей с микросхемой в SOIC-корпусе также столкнутся с проблемой ориентации модулей в кластере. Только выглядит это немного по-другому нежели в MAX72xx. Здесь модули окажутся как бы не в своей очереди.

   Скетч HelloWorld из образцов в комплекте с библиотекой.

   Программно в скетче мне не удалось вылечить этот недуг. Я вылечил его по-другому. В файле Adruino/libraries/MD_MAX72xx_lib.h в конце нужно найти строки как на картинке.

   И исправить в выделенной строке выделенную 1 на 0. Сохранить файл. Arduino IDE можно не перезагружать. Заливаем, смотрим.

   Теперь можно использовать 24 эффекта анимации. Анимация запускается командой P.displayText(«Текст для вывода», «выравнивание текста», скорость, задержка показа, эффект появления, эффект исчезновения). Как видите, настроек достаточно много.

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

   Как вы уже догадываетесь проблема с кириллическими буквами. Она тоже решаема. Рядом с предыдущим файлом в той же директории лежит файлик MD_MAX72xx_font.cpp. Это файл шрифта. Символы в нем сформированы аналогично файлу шрифта GFX библиотеки. Есть небольшое отличие. Здесь размер символа может быть меньше 5 точек.

В библиотеке Adafruit GFX восклицательный знак, например, занимает также 5 точек шириной, как и любой другой символ, только используется один ряд точек. Остальные не светятся, но используются под символ. В Parola тот же восклицательный знак занимает также один ряд точек, только рядом не пустые точки, а могут стоять соседние символы.

Понятнее будет разобраться по картинке.

   Дополнить файл кириллическими символами аналогично файлу из первой рассмотренной библиотеки пока времени нет. Если кто-нибудь это сделает и пришлет мне файл, я добавлю его к этой статье, и Вам будут благодарны и я, и гости моего сайта.

   Итог. Библиотека MAX72xx Panel от Марка Райса проста в использовании и понимании, но с бедным функционалом.

   Библиотека Parola от MajicDesigns посложнее и ее возможностей хватит практически для любого применения.