LED матрица на микроконтроллере ATmega328p или самопальный модуль Arduino. Часть первая — Разработка

в 11:14, , рубрики: arduino, ATMEGA328P, c++, dev board, display, diy или сделай сам, electronics, IoT, LED, led display, LED matrix, matrix, ардуинщик, Программирование, программирование микроконтроллеров, Производство и разработка электроники, разработка, разработка электронных устройств, робототехника, самоделки, самодельный, сдвиговой регистр, Электроника для начинающих

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

image

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

Компоненты

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

  1. Резисторы 150 ом 0.25 Ватт — 7 шт.
  2. Конденсаторы 50 вольт 1 микрофарад — 5 шт.
  3. Кварцевый резонатор 16 мгц — 1 шт.
  4. Разъём типа гребёнка ( потребуется 18 контактов ) — 1 шт.
  5. Сдвиговый регистр 74ch595 корпус DIP — 1 шт.
  6. Панель под микросхему 74ch595 корпус DIP (16 ножек) — 1 шт.
  7. Светодиоды 5мм 3 вольта — 35 шт.
  8. Микроконтроллер ATmega328p корпус DIP — 1 шт.
  9. Панель под микросхему ATmega328p корпус DIP (28 ножек) — 1 шт.
  10. Монтажная плата 5x7 — 1 шт.

Рекомендую при необходимости купить флюс, припой и паяльник.

Я намеренно не указываю марку проводов которая вам подойдет, так как совсем не владею информацией о их параметрах могу посоветовать МГТФ вполне возможно что подойдут, если вы знаете какие провода точно оптимальны, оставьте информацию в комментариях или мне в личные сообщения jsusdev

Я не буду вам советовать какие-либо конкретные интернет магазины потому что это было давно и не правда.

Сдвиговый регистр 74ch595

Наверно для многих новичков, станет не по себе от понимания принципов работы микросхемы 74ch595 вне этой статьи. Сейчас я попробую максимально доступно объяснить как она работает и чем будет полезна в конкретном случае с моей LED-матрицей.

Проще говоря микросхема предназначена для увеличения количества цифровых пинов.

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

image
Самые загадочные контакты, управления которые вызывают интерес:

  • output pin * — контакты вывода
  • DS — (Serial Data Input) контакт который определяет состояние напряжения на контактах вывода
  • SH — (Shift Register Clock Input) контакт который записывает состояние которое определенно в DS
  • ST — (Storage Register Clock Input) контакт который открывает микросхему для записи и закрывает, устанавливая на контакты вывода нужные состояния определенные DS

Уверен визуальный пример поможет вам осознать происходящие лучше.

image

Если нет то я оставил и интерактивную версию: 74ch595.swf все кнопочки работают можно понажимать.

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

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

int ST = 7;
int SH = 6;
int DS = 5;

digitalWrite(ST, 1); // начало записи в байт

  for (int i = 0; i < 8; i++) {

    digitalWrite(SH, 1); // начало записи бита 

      digitalWrite(DS, 1); // < --- последний аргумент это бит который будет записан

    digitalWrite(SH, 0); // конец записи бита

  }

digitalWrite(ST, 0); // конец записи в байт

Код который будет работать

int ST = 7;
int SH = 6;
int DS = 5;

void setup() {
  
  pinMode(7, 1);
  pinMode(6, 1);
  pinMode(5, 1);

}

void loop() {

  digitalWrite(ST, 1); // начало записи в байт
  
    for (int i = 0; i < 8; i++) {

      digitalWrite(SH, 1); // начало записи бита

        digitalWrite(DS, 1); // < --- последний аргумент это бит который будет записан

      digitalWrite(SH, 0); // конец записи бита

    }
  
  digitalWrite(ST, 0); // конец записи в байт

}

Теперь когда вы овладели работой с микросхемой. Можно приступить к следующему пункту.

Подготовка к разработке матрицы

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

image

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

Не стоит беспокоиться о количестве проводов на фото, далее покажу как все устроено.

image

Совсем забыл и вы наверно упустили из внимания что на устройстве в визуально расположено всего 6 резисторов но на самом деле их 7 один из них находится прямо под 74ch595.

image

Стоит добавить что кварцевый генератор (16 мгц) можно заменить на 24 мгц, это существенно ускорит работу, но такие изменения применимы только к готовому устройству, так как ATmega328p просто не прошивается на кварцевом генераторе 24 мгц.

Разработка матрицы

Принципиальная схема устройства.
image

Внимание светодиоды расположены «минусом» к ATmega328p и в тоже время «плюсом» к 74ch595. Расположение компонентов на плате.
image
Обратная часть (вариант без конденсаторов)
image
3D-модель, которую можно повертеть в редакторе Google SketchUp. Саму модель можно скачать тут: 3D_Schema.skp

Когда мы запаяли все компоненты, можно припаивать провода.
image
Стартуем:
image
Соединяем контакты rx, tx, reset и светодиоды. (светодиоды соединены отрезанными от них ножками):
image
Соединяем компоненты питание и кварцевый генератор:
image
Соединяем светодиоды с 74ch595:
image
Соединяем светодиоды с ATmega328p и ATmega328p и 74ch595:
image
Соединяем конденсаторы:
image
Поздравляю физическая часть закончена:
image
Наверняка устройство сразу не оживет без прошивки но можно попробовать стандартный blink Arduino. (Да в некоторых случаях действительно может заработать).

У меня Blink заработал. если у вас хоть что-то на первом ряду будет мигать значит все ок если нет то читаем дальше.

image

Разработка программы

Чтобы микроконтроллер управлял своими контактами их надо «инициализировать»

Да. я мог сделать иначе например: использовать массив и цикл чтобы сократить количество кода в функции, вообще множество программных решений которые я принял в процессе реализации губительны с какой-то позиции, например для программируемой памяти (Flash) но позитивны для динамической. (RAM) Мне удалось снизить использование динамической памяти с 69% до 23%

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

Поэтому примите и смиритесь или сделайте лучше!


// функция инициализации 

void init() {

    pinMode(5, 1);
    pinMode(6, 1);
    pinMode(7, 1);
    pinMode(9, 1);
    pinMode(10, 1);
    pinMode(11, 1);
    pinMode(12, 1);
    pinMode(13, 1);
    
    digitalWrite(5,0);
    digitalWrite(6,0);
    digitalWrite(7,0);
    digitalWrite(9,0);
    digitalWrite(10,0);
    digitalWrite(11,0);
    digitalWrite(12,0);
    digitalWrite(13,0);
    
  };

Для управления матрицей я разработал такую функцию она является ключевой по сути.


void path(char bits[5]) {
    
    for (int l = 0;l < 5;l++) {
      
      digitalWrite(9, 1);
      digitalWrite(10, 1);  
      digitalWrite(11, 1);  // эта часть просто отключает пины
      digitalWrite(12, 1);    
      digitalWrite(13, 1);  

      if (l == 1) digitalWrite(13, 0);
      if (l == 2) digitalWrite(12, 0);
      if (l == 3) digitalWrite(11, 0); // эта часть включает пины в зависимости от условия
      if (l == 4) digitalWrite(10, 0);
      if (l == 0) digitalWrite(9, 0);

      
      // эта часть нужна для управления регистром, см. пункт выше
    
      digitalWrite(7, 1); 
        for (int i = 0; i < 8;i++) {
          digitalWrite(6, 1);
           digitalWrite(5, (bits[l] >> i) & 1);  

           /* (bits[l] >> i) 
            * такой вот способ преобразовывать 
            * из 10 в 2, спасибо 
            * чуваку который мне 
            * помог с этим условием  
            */

          digitalWrite(6, 0);
        }
      digitalWrite(7, 0);
      
      delay(2); // каким то образом эта строчка помогает избавиться мерцания
    }
  };
  

Каждый элемент массива это одна колонка светодиодов.


char Matrx_symbol[5] = { 127, // 1
                         0,   // 2
                         0,   // 3
                         0,   // 4
                         0    // 5
                       };

path(Matrx_symbol);

Нумерование колонок идет справа налево то есть зеркально массиву.
image
Что это за магические цифры в массиве?
image
Проще говоря колонка светодиодов это байт вмещающий число в десятичной системе счисления от 0 до 127, этим числом мы определяем каким светодиодам нужно зажечься.

Конечно мы не будем собирать свои символы путем грубого или осознанного перебора бит в байте. Я разработал страницу на которой можно сформировать любой символ Symbol creater.

image

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

image

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

Буквально только что я об этом узнал в 5:31 по МСК

image

Функция которая конвертирует строку в набор перебираемых символов. Принимает два параметра это саму строку «Hellow world!» и вторым параметром время между переключением символов в мс.

Много кода


void message(String text, int Delay) {

    int len = text.length();

    for (int i = 0; i < len; i++) {      
     
      for (int Delay_ = 0; Delay_ < Delay/15; Delay_++){

       if (text[i] == 32) { char Symbol[5] = {0,0,0,0,0}; path(Symbol); } // 
       if (text[i] == 43) { char Symbol[5] = {8,8,62,8,8}; path(Symbol); } // +
       if (text[i] == 45) { char Symbol[5] = {8,8,8,8,8}; path(Symbol); } // -
       if (text[i] == 61) { char Symbol[5] = {20,20,20,20,20}; path(Symbol); } // =
       if (text[i] == 95) { char Symbol[5] = {1,1,1,1,1}; path(Symbol); } // _
       if (text[i] == 41) { char Symbol[5] = {62,65,0,0,0}; path(Symbol); } // )
       if (text[i] == 40) { char Symbol[5] = {0,0,0,65,62}; path(Symbol); } // (
       if (text[i] == 123) { char Symbol[5] = {0,65,65,54,8}; path(Symbol); } // {
       if (text[i] == 125) { char Symbol[5] = {8,54,65,65,0}; path(Symbol); } // }
       if (text[i] == 62) { char Symbol[5] = {8,20,34,65,0}; path(Symbol); } // >
       if (text[i] == 60) { char Symbol[5] = {0,65,34,20,8}; path(Symbol); } // <
       if (text[i] == 46) { char Symbol[5] = {0,0,1,0,0}; path(Symbol); } // .
       if (text[i] == 44) { char Symbol[5] = {0,0,3,2,0}; path(Symbol); } // ,
       if (text[i] == 63) { char Symbol[5] = {48,72,69,64,48}; path(Symbol); } // ?
       if (text[i] == 33) { char Symbol[5] = {0,0,125,0,0}; path(Symbol); } // !
       if (text[i] == 64) { char Symbol[5] = {58,69,93,65,62}; path(Symbol); } // @
       if (text[i] == 35) { char Symbol[5] = {20,127,20,127,20}; path(Symbol); } // #
       if (text[i] == 36) { char Symbol[5] = {38,73,127,73,50}; path(Symbol); } // $
       if (text[i] == 37) { char Symbol[5] = {19,11,4,50,49}; path(Symbol); } // %
       if (text[i] == 94) { char Symbol[5] = {0,32,64,32,0}; path(Symbol); } // ^
       if (text[i] == 58) { char Symbol[5] = {0,0,0,34,0}; path(Symbol); } // :
       if (text[i] == 42) { char Symbol[5] = {8,20,42,20,8}; path(Symbol); } // * 
       if (text[i] == 38) { char Symbol[5] = {2,53,73,73,54}; path(Symbol); } // &
       if (text[i] == 34) { char Symbol[5] = {0,112,0,112,0}; path(Symbol); } // "
       if (text[i] == 59) { char Symbol[5] = {0,0,0,38,2}; path(Symbol); } // ;
       if (text[i] == 48) { char Symbol[5] = {62,65,65,65,62}; path(Symbol); } // 0
       if (text[i] == 49) { char Symbol[5] = {0,1,127,33,16}; path(Symbol); } // 1
       if (text[i] == 50) { char Symbol[5] = {49,73,69,67,49}; path(Symbol); } // 2
       if (text[i] == 51) { char Symbol[5] = {54,73,73,65,34}; path(Symbol); } // 3
       if (text[i] == 52) { char Symbol[5] = {5,127,37,20,12}; path(Symbol); } // 4
       if (text[i] == 53) { char Symbol[5] = {6,73,73,73,114}; path(Symbol); } // 5
       if (text[i] == 54) { char Symbol[5] = {38,73,73,73,62}; path(Symbol); } // 6
       if (text[i] == 55) { char Symbol[5] = {96,80,79,64,64}; path(Symbol); } // 7
       if (text[i] == 56) { char Symbol[5] = {54,73,73,73,54}; path(Symbol); } // 8
       if (text[i] == 57) { char Symbol[5] = {62,73,73,73,50}; path(Symbol); } // 9
       if (text[i] == 97) { char Symbol[5] = {1,62,37,37,18}; path(Symbol); } // a
       if (text[i] == 65) { char Symbol[5] = {3,28,36,28,3}; path(Symbol); } // A
       if (text[i] == 98) { char Symbol[5] = {6,9,9,9,126}; path(Symbol); } // b
       if (text[i] == 66) { char Symbol[5] = {6,57,73,73,127}; path(Symbol); } // B
       if (text[i] == 99) { char Symbol[5] = {18,33,33,33,30}; path(Symbol); } // c
       if (text[i] == 67) { char Symbol[5] = {34,65,65,65,62}; path(Symbol); } // C
       if (text[i] == 100) { char Symbol[5] = {126,9,9,9,6}; path(Symbol); } // d
       if (text[i] == 68) { char Symbol[5] = {62,65,65,65,127}; path(Symbol); } // D
       if (text[i] == 101) { char Symbol[5] = {26,37,37,37,30}; path(Symbol); } // e
       if (text[i] == 69) { char Symbol[5] = {65,65,73,73,127}; path(Symbol); } // E
       if (text[i] == 102) { char Symbol[5] = {0,32,36,31,4}; path(Symbol); } // f
       if (text[i] == 70) { char Symbol[5] = {64,64,72,72,127}; path(Symbol); } // F
       if (text[i] == 103) { char Symbol[5] = {62,73,73,74,48}; path(Symbol); } // g
       if (text[i] == 71) { char Symbol[5] = {38,73,73,65,62}; path(Symbol); } // G 
       if (text[i] == 104) { char Symbol[5] = {0,7,8,8,63}; path(Symbol); } // h 
       if (text[i] == 72) { char Symbol[5] = {127,8,8,8,127}; path(Symbol); } // H
       if (text[i] == 105) { char Symbol[5] = {0,0,47,0,0}; path(Symbol); } // i
       if (text[i] == 73) { char Symbol[5] = {0,65,127,65,0}; path(Symbol); } // I
       if (text[i] == 106) { char Symbol[5] = {0,94,1,1,2}; path(Symbol); } // j
       if (text[i] == 74) { char Symbol[5] = {126,1,1,1,6}; path(Symbol); } // J
       if (text[i] == 107) { char Symbol[5] = {0,16,9,6,63}; path(Symbol); } // k
       if (text[i] == 75) { char Symbol[5] = {64,33,18,12,127}; path(Symbol); } // K
       if (text[i] == 108) { char Symbol[5] = {0,1,63,0,0}; path(Symbol); } // l
       //if (text[i] == 76) { char Symbol[5] = {1,1,1,1,127}; path(Symbol); } // L
       if (text[i] == 109) { char Symbol[5] = {15,16,24,16,15}; path(Symbol); } // m
       if (text[i] == 77) { char Symbol[5] = {63,64,56,64,63}; path(Symbol); } // M
       if (text[i] == 110) { char Symbol[5] = {31,32,32,32,63}; path(Symbol); } // n
       if (text[i] == 78) { char Symbol[5] = {127,4,8,16,127}; path(Symbol); } // N
       if (text[i] == 111) { char Symbol[5] = {14,17,17,17,14}; path(Symbol); } // o
       if (text[i] == 79) { char Symbol[5] = {62,65,65,65,62}; path(Symbol); } // O
       if (text[i] == 112) { char Symbol[5] = {0,24,36,36,63}; path(Symbol); } // p
       if (text[i] == 80) { char Symbol[5] = {56,68,68,68,63}; path(Symbol); } // P
       if (text[i] == 113) { char Symbol[5] = {31,36,36,36,24}; path(Symbol); } // q
       if (text[i] == 81) { char Symbol[5] = {61,66,65,65,62}; path(Symbol); } // Q
       if (text[i] == 114) { char Symbol[5] = {0,48,16,32,63}; path(Symbol); } // r
       if (text[i] == 82) { char Symbol[5] = {56,69,70,68,63}; path(Symbol); } // R
       if (text[i] == 115) { char Symbol[5] = {0,18,37,41,18}; path(Symbol); } // s
       //if (text[i] == 83) { char Symbol[5] = {38,73,73,73,50}; path(Symbol); } // S
       if (text[i] == 116) { char Symbol[5] = {0,2,17,62,16}; path(Symbol); } // t
       if (text[i] == 84) { char Symbol[5] = {64,64,127,64,64}; path(Symbol); }// T
       if (text[i] == 117) { char Symbol[5] = {29,2,1,1,30}; path(Symbol); } // u
       if (text[i] == 85) { char Symbol[5] = {126,1,1,1,126}; path(Symbol); } // U
       if (text[i] == 118) { char Symbol[5] = {60,2,1,2,60}; path(Symbol); } // v
       if (text[i] == 86) { char Symbol[5] = {124,2,1,2,124}; path(Symbol); } // V
       if (text[i] == 119) { char Symbol[5] = {30,1,6,1,30}; path(Symbol); } // w
       if (text[i] == 87) { char Symbol[5] = {126,1,6,1,126}; path(Symbol); } // W
       if (text[i] == 120) { char Symbol[5] = {17,10,4,10,17}; path(Symbol); } // x
       if (text[i] == 88) { char Symbol[5] = {99,20,8,20,99}; path(Symbol); } // X
       if (text[i] == 121) { char Symbol[5] = {56,4,6,57,0}; path(Symbol); } // y
       if (text[i] == 89) { char Symbol[5] = {112,8,7,8,112}; path(Symbol); } // Y
       if (text[i] == 122) { char Symbol[5] = {17,25,21,19,17}; path(Symbol); } // z
       if (text[i] == 90) { char Symbol[5] = {97,81,73,69,67}; path(Symbol); } // Z
       if (text[i] == 76) { char Symbol[5] = {24,60,30,60,24}; path(Symbol); } // L
       if (text[i] == 83) { char Symbol[5] = {6,113,1,113,6}; path(Symbol); } // S   
      
      }
    }

Теперь когда мы «разобрали» принцип работы функций данной программы в контроллере, нужно его оформить.

Очень много кода


class Jsus {
  
  public:
  
  void init() {
    
    pinMode(5, 1);
    pinMode(6, 1);
    pinMode(7, 1);
    pinMode(9, 1);
    pinMode(10, 1);
    pinMode(11, 1);
    pinMode(12, 1);
    pinMode(13, 1);
    
    digitalWrite(5,0);
    digitalWrite(6,0);
    digitalWrite(7,0);
    digitalWrite(9,0);
    digitalWrite(10,0);
    digitalWrite(11,0);
    digitalWrite(12,0);
    digitalWrite(13,0);
    
  };
  
  void path(char bits[5]) {
    
    for (int l = 0;l < 5;l++) {
      
      digitalWrite(9, 1);
      digitalWrite(10, 1);  
      digitalWrite(11, 1);  
      digitalWrite(12, 1);    
      digitalWrite(13, 1);  

      if (l == 1) digitalWrite(13, 0);
      if (l == 2) digitalWrite(12, 0);
      if (l == 3) digitalWrite(11, 0);
      if (l == 4) digitalWrite(10, 0);
      if (l == 0) digitalWrite(9, 0);

      
      digitalWrite(7, 1);
        for (int i = 0; i < 8;i++) {
          digitalWrite(6, 1);
           digitalWrite(5, (bits[l] >> i) & 1);  
          digitalWrite(6, 0);
        }
      digitalWrite(7, 0);
      
      delay(2);
    }
  };
  
  void message(String text, int Delay) {

    int len = text.length();

    for (int i = 0; i < len; i++) {      
     
      for (int Delay_ = 0; Delay_ < Delay/15; Delay_++){

       if (text[i] == 32) { char Symbol[5] = {0,0,0,0,0}; path(Symbol); } // 
       if (text[i] == 43) { char Symbol[5] = {8,8,62,8,8}; path(Symbol); } // +
       if (text[i] == 45) { char Symbol[5] = {8,8,8,8,8}; path(Symbol); } // -
       if (text[i] == 61) { char Symbol[5] = {20,20,20,20,20}; path(Symbol); } // =
       if (text[i] == 95) { char Symbol[5] = {1,1,1,1,1}; path(Symbol); } // _
       if (text[i] == 41) { char Symbol[5] = {62,65,0,0,0}; path(Symbol); } // )
       if (text[i] == 40) { char Symbol[5] = {0,0,0,65,62}; path(Symbol); } // (
       if (text[i] == 123) { char Symbol[5] = {0,65,65,54,8}; path(Symbol); } // {
       if (text[i] == 125) { char Symbol[5] = {8,54,65,65,0}; path(Symbol); } // }
       if (text[i] == 62) { char Symbol[5] = {8,20,34,65,0}; path(Symbol); } // >
       if (text[i] == 60) { char Symbol[5] = {0,65,34,20,8}; path(Symbol); } // <
       if (text[i] == 46) { char Symbol[5] = {0,0,1,0,0}; path(Symbol); } // .
       if (text[i] == 44) { char Symbol[5] = {0,0,3,2,0}; path(Symbol); } // ,
       if (text[i] == 63) { char Symbol[5] = {48,72,69,64,48}; path(Symbol); } // ?
       if (text[i] == 33) { char Symbol[5] = {0,0,125,0,0}; path(Symbol); } // !
       if (text[i] == 64) { char Symbol[5] = {58,69,93,65,62}; path(Symbol); } // @
       if (text[i] == 35) { char Symbol[5] = {20,127,20,127,20}; path(Symbol); } // #
       if (text[i] == 36) { char Symbol[5] = {38,73,127,73,50}; path(Symbol); } // $
       if (text[i] == 37) { char Symbol[5] = {19,11,4,50,49}; path(Symbol); } // %
       if (text[i] == 94) { char Symbol[5] = {0,32,64,32,0}; path(Symbol); } // ^
       if (text[i] == 58) { char Symbol[5] = {0,0,0,34,0}; path(Symbol); } // :
       if (text[i] == 42) { char Symbol[5] = {8,20,42,20,8}; path(Symbol); } // * 
       if (text[i] == 38) { char Symbol[5] = {2,53,73,73,54}; path(Symbol); } // &
       if (text[i] == 34) { char Symbol[5] = {0,112,0,112,0}; path(Symbol); } // "
       if (text[i] == 59) { char Symbol[5] = {0,0,0,38,2}; path(Symbol); } // ;
       if (text[i] == 48) { char Symbol[5] = {62,65,65,65,62}; path(Symbol); } // 0
       if (text[i] == 49) { char Symbol[5] = {0,1,127,33,16}; path(Symbol); } // 1
       if (text[i] == 50) { char Symbol[5] = {49,73,69,67,49}; path(Symbol); } // 2
       if (text[i] == 51) { char Symbol[5] = {54,73,73,65,34}; path(Symbol); } // 3
       if (text[i] == 52) { char Symbol[5] = {5,127,37,20,12}; path(Symbol); } // 4
       if (text[i] == 53) { char Symbol[5] = {6,73,73,73,114}; path(Symbol); } // 5
       if (text[i] == 54) { char Symbol[5] = {38,73,73,73,62}; path(Symbol); } // 6
       if (text[i] == 55) { char Symbol[5] = {96,80,79,64,64}; path(Symbol); } // 7
       if (text[i] == 56) { char Symbol[5] = {54,73,73,73,54}; path(Symbol); } // 8
       if (text[i] == 57) { char Symbol[5] = {62,73,73,73,50}; path(Symbol); } // 9
       if (text[i] == 97) { char Symbol[5] = {1,62,37,37,18}; path(Symbol); } // a
       if (text[i] == 65) { char Symbol[5] = {3,28,36,28,3}; path(Symbol); } // A
       if (text[i] == 98) { char Symbol[5] = {6,9,9,9,126}; path(Symbol); } // b
       if (text[i] == 66) { char Symbol[5] = {6,57,73,73,127}; path(Symbol); } // B
       if (text[i] == 99) { char Symbol[5] = {18,33,33,33,30}; path(Symbol); } // c
       if (text[i] == 67) { char Symbol[5] = {34,65,65,65,62}; path(Symbol); } // C
       if (text[i] == 100) { char Symbol[5] = {126,9,9,9,6}; path(Symbol); } // d
       if (text[i] == 68) { char Symbol[5] = {62,65,65,65,127}; path(Symbol); } // D
       if (text[i] == 101) { char Symbol[5] = {26,37,37,37,30}; path(Symbol); } // e
       if (text[i] == 69) { char Symbol[5] = {65,65,73,73,127}; path(Symbol); } // E
       if (text[i] == 102) { char Symbol[5] = {0,32,36,31,4}; path(Symbol); } // f
       if (text[i] == 70) { char Symbol[5] = {64,64,72,72,127}; path(Symbol); } // F
       if (text[i] == 103) { char Symbol[5] = {62,73,73,74,48}; path(Symbol); } // g
       if (text[i] == 71) { char Symbol[5] = {38,73,73,65,62}; path(Symbol); } // G 
       if (text[i] == 104) { char Symbol[5] = {0,7,8,8,63}; path(Symbol); } // h 
       if (text[i] == 72) { char Symbol[5] = {127,8,8,8,127}; path(Symbol); } // H
       if (text[i] == 105) { char Symbol[5] = {0,0,47,0,0}; path(Symbol); } // i
       if (text[i] == 73) { char Symbol[5] = {0,65,127,65,0}; path(Symbol); } // I
       if (text[i] == 106) { char Symbol[5] = {0,94,1,1,2}; path(Symbol); } // j
       if (text[i] == 74) { char Symbol[5] = {126,1,1,1,6}; path(Symbol); } // J
       if (text[i] == 107) { char Symbol[5] = {0,16,9,6,63}; path(Symbol); } // k
       if (text[i] == 75) { char Symbol[5] = {64,33,18,12,127}; path(Symbol); } // K
       if (text[i] == 108) { char Symbol[5] = {0,1,63,0,0}; path(Symbol); } // l
       //if (text[i] == 76) { char Symbol[5] = {1,1,1,1,127}; path(Symbol); } // L
       if (text[i] == 109) { char Symbol[5] = {15,16,24,16,15}; path(Symbol); } // m
       if (text[i] == 77) { char Symbol[5] = {63,64,56,64,63}; path(Symbol); } // M
       if (text[i] == 110) { char Symbol[5] = {31,32,32,32,63}; path(Symbol); } // n
       if (text[i] == 78) { char Symbol[5] = {127,4,8,16,127}; path(Symbol); } // N
       if (text[i] == 111) { char Symbol[5] = {14,17,17,17,14}; path(Symbol); } // o
       if (text[i] == 79) { char Symbol[5] = {62,65,65,65,62}; path(Symbol); } // O
       if (text[i] == 112) { char Symbol[5] = {0,24,36,36,63}; path(Symbol); } // p
       if (text[i] == 80) { char Symbol[5] = {56,68,68,68,63}; path(Symbol); } // P
       if (text[i] == 113) { char Symbol[5] = {31,36,36,36,24}; path(Symbol); } // q
       if (text[i] == 81) { char Symbol[5] = {61,66,65,65,62}; path(Symbol); } // Q
       if (text[i] == 114) { char Symbol[5] = {0,48,16,32,63}; path(Symbol); } // r
       if (text[i] == 82) { char Symbol[5] = {56,69,70,68,63}; path(Symbol); } // R
       if (text[i] == 115) { char Symbol[5] = {0,18,37,41,18}; path(Symbol); } // s
       //if (text[i] == 83) { char Symbol[5] = {38,73,73,73,50}; path(Symbol); } // S
       if (text[i] == 116) { char Symbol[5] = {0,2,17,62,16}; path(Symbol); } // t
       if (text[i] == 84) { char Symbol[5] = {64,64,127,64,64}; path(Symbol); }// T
       if (text[i] == 117) { char Symbol[5] = {29,2,1,1,30}; path(Symbol); } // u
       if (text[i] == 85) { char Symbol[5] = {126,1,1,1,126}; path(Symbol); } // U
       if (text[i] == 118) { char Symbol[5] = {60,2,1,2,60}; path(Symbol); } // v
       if (text[i] == 86) { char Symbol[5] = {124,2,1,2,124}; path(Symbol); } // V
       if (text[i] == 119) { char Symbol[5] = {30,1,6,1,30}; path(Symbol); } // w
       if (text[i] == 87) { char Symbol[5] = {126,1,6,1,126}; path(Symbol); } // W
       if (text[i] == 120) { char Symbol[5] = {17,10,4,10,17}; path(Symbol); } // x
       if (text[i] == 88) { char Symbol[5] = {99,20,8,20,99}; path(Symbol); } // X
       if (text[i] == 121) { char Symbol[5] = {56,4,6,57,0}; path(Symbol); } // y
       if (text[i] == 89) { char Symbol[5] = {112,8,7,8,112}; path(Symbol); } // Y
       if (text[i] == 122) { char Symbol[5] = {17,25,21,19,17}; path(Symbol); } // z
       if (text[i] == 90) { char Symbol[5] = {97,81,73,69,67}; path(Symbol); } // Z
       if (text[i] == 76) { char Symbol[5] = {24,60,30,60,24}; path(Symbol); } // L
       if (text[i] == 83) { char Symbol[5] = {6,113,1,113,6}; path(Symbol); } // S   
      
      }
    }
  };  
  
};

Jsus matrix;

Код для старта.


void setup() {

  matrix.init();

}


void loop() {

   matrix.message("Fuck RKN!", 400);

}

Тут можно найти готовый к загрузке в Arduino cкетч.

Результаты разработки

2018. Текущая версия устройства:

2017. Текущая версия устройства (не оптимизированная):

2016. Первая тестовая версия устройства. Еще даже без микросхем на плате:

Все необходимые ссылки можно найти в репозитории на Github проекта: Arduino-matrix-module.

Если статья не ответила на какие то вопросы реализации, пишите их в комментариях.

Всё, вроде ничего не забыл. Поки чмоки лавки лавки.

Автор: Александр

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js