2 октября 2011 в 18:01

«Бегущая строка» — динамическая индикация на примере светодиодной матрицы RL-M2388 и Arduino Mega

Данная статья не претендует на толкование как единственно возможного метода отображения и прокрутки информации на светодиодной матрице. Я с удовольствием выслушаю ваши замечания и предложения по улучшению метода/функций. Данная статья – изложение личного опыта и описание результата, которого я добился.

Немного теории

В данной светодиодной матрице находится 64 красных светодиода. Если выводить контакты каждого светодиода отдельно, то понадобится 64 контакта на корпусе матрицы и микроконтроллер с 65 цифровыми портами ввода/вывода. Это нецелесообразно и невыгодно. Поэтому на заводе-изготовителе светодиоды объединяют в матрицы различных размеров (в нашем случае 8х8), то есть в 8 групп по строкам и столбцам следующим образом:
image

В таком случае нам понадобится лишь 16 цифровых вводов/выводов. Например, чтобы зажечь светодиод в левом верхнем углу, нам нужно на pin13 (см. картинку) подать лог 1, а на pin9 лог 0. Такой способ отображения называется статическая индикация.

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

Динамическая индикация

Быстро мелькающий объект кажется человеческому глазу постоянно светящимся. Это свойство человеческого глаза – инертность. Как вы догадались, именно на этом свойстве и основан метод вывода информации в светодиодной матрице. Например, чтобы вывести на «экран» некий символ, нужно последовательно, проходя все «пиксели» матрицы с высокой скоростью, включать светодиод в нужном месте.

Условия, которые необходимо соблюдать при программировании матриц динамической индикации:
1. Длительность отображения каждого столбца/строки («пикселя» в моем случае) постоянна, одинакова для всех столбцов/строк («пикселей» в моем случае).
2. Частота смены столбцов/строк («пикселей» в моем случае) не меняется.

Принцип действия прошивки микроконтроллера

Признаюсь, когда у меня появилась отладочная плата на МК Atmega1280 и светодиодная матрица, я и понятия не имел что такое динамическая индикация и для чего она нужна. До понимания необходимости ее использования я дошел методом проб и методом «тыка».

Принцип действия прошивки:

1. Вывод символа на экран

Давайте представим, что наша светодиодная матрица – это двухмерный массив размерностью I на J, совпадающей с размерностью нашей матрицы. В нашем случае это 8 на 8 пикселей. Итак, есть двухмерный массив типа boolean. К примеру:

boolean A[8][8] =
{0,0,1,1,1,1,0,0,
 0,1,0,0,0,0,1,0,  
 0,1,0,0,0,0,1,0,  
 0,1,0,0,0,0,1,0,  
 0,1,1,1,1,1,1,0,  
 0,1,0,0,0,0,1,0,  
 0,1,0,0,0,0,1,0,  
 0,1,0,0,0,0,1,0}  


В цикле мы проверяем, если элемент массива A[i][j]=1, тогда включаем светодиод на матрице, находящийся в позиции (I;J), делаем паузу на отображения светодиода и выключаем светодиод в позиции (I;J). В результате работы программы по такому алгоритму на экране матрицы выведется символ «А» (в двумерном массиве именно этот символ отображен). Назовем этот алгоритм «Вывод на экран». Итак, с выводом информации на экран с помощью динамической индикации разобрались.

2. Прокрутка информации на экране

Конечно, классно выводить на экран неподвижную информацию, но было бы интереснее «оживить» ее – заставить передвигаться. Рассмотрим алгоритм перемещения информации:

В бесконечном цикле выполняем:
1. Вызываем алгоритм «Вывод на экран».
2. Берем 1й столбец матрицы А и записываем его в буфер (двухмерный массив BUFFER[8][1]).
3. Записываем содержимое матрицы с позиции A[i][j+1] в позицию A[i][j]. То есть мы по сути «сдвинули» матрицу влево на один столбец.
4. Записываем в последний столбец матрицы А (в свободный, так как мы сдвинули матрицу влево на один столбец) содержание буфера BUFFER. Назовем этот алгоритм «Прокрутка информации».

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

Подключение матрицы к отладочной плате

Каждый из 16ти выводов матрицы пронумерован. В соответствии этим номерам были подпаяны и выведены 8 контактов, отвечающих за строки, и 8 контактов, отвечающих за столбцы. У меня, например, матрица подключена так:

Выводы, отвечающие за строки 23,25,27,29,31,33,35,37 – это номера выводов ножек микроконтроллера;
Выводы, отвечающие за столбцы 39,41,43,45,47,49,51,53 — это номера выводов ножек микроконтроллера.

Программирование

Программирование и прошивка микроконтроллера производится в среде разработки Arduino IDE.

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

Функция pinMode()
Устанавливает режим работы заданного вход/выхода(pin) как входа или как выхода.
pinMode(pin, mode), где pin: номер вход/выхода(pin), который Вы хотите установить; mode: режим одно из двух значение — INPUT или OUTPUT, устанавливает на вход или выход соответственно.

Функция digitalWrite()
Подает HIGH или LOW значение на цифровой вход/выход (pin).
digitalWrite(pin, value), где pin: номер вход/выхода(pin); value: значение HIGH или LOW

Функция delayMicroseconds()
Останавливает выполнение программы на заданное в параметре количество микросекунд (1 000 000 микросекунд в 1 секунде).
delayMicroseconds(us), где us: количество микросекунд, на которое приостанавливается выполнение программы. (unsigned int)

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

void setup()
{
…
}

void loop()
{
  …
}


В функции setup() производятся настройки портов ввода/вывода МК, настройка подключенных устройств к МК, периферии МК, а так же выполняется все то, что нужно выполнить ОДИН раз.
В функции loop() пишется тело программы, которое будет выполняться циклически, пока микроконтроллер включен.

Выполним настройку выводов микроконтроллера. Состояний портов ввода/вывода существует два вида: настроен на вход либо на выход. В нашем случае нужно настроить на выход.


const int row[8]={23,25,27,29,31,33,35,37}; // Помните 8 выводов, отвечающих за строки и
const int col[8]={39,41,43,45,47,49,51,53}; // столбцы? А вот и они. 

void setup()
{
     for (int i=0; i<8; i++)
{
     pinMode(row[i],OUTPUT); // В цикле все выводы переводим в режим «на вывод»
     pinMode(col[i],OUTPUT); // Выключаем все светодиоды
}
     for (int i=0; i<8; i++)
         {
             digitalWrite(row[i],HIGH);
         }
}


Давайте теперь реализуем алгоритмы, которые я описал выше. Итак, мы имеем двухмерный массив:


boolean A[8][8] = 
{0,0,1,1,1,1,0,0,
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0,  
0,1,1,1,1,1,1,0,  
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0} 


Напишем функцию, которая реализует алгоритм «Вывод на экран».

int v=3; //Скорость прокручивания информации. То есть по сути это количество итераций цикла отрисовки информации в матрице
int dms=400; //Скорость обновления «пикселей». То есть время, когда светодиод находится во включенном состоянии. Чем оно больше, тем более заметнее глазу будет мерцание изображения
void paint(boolean screen[8][8], int v) //В качестве параметров передаем матрицу и параметр v  
{  
int i, j;
for (int c=0; c <v; c ++) // Тот самый цикл задержки отрисовки информации 
  {
    for (i=0; i<8; i++)
      for (j=0; j<8; j++)
        {
          if (screen[i][j]= =1) // Если элемент массива = 1
            {
              digitalWrite(row[i], LOW); 
              digitalWrite(col[j], HIGH); 
              delayMicroseconds(dms); 
 	      digitalWrite(row[i], HIGH); 
              digitalWrite(col[j], LOW); //  То включить светодиод                 в проверяемой позиции, задержать включенным, выключить светодиод.
            }
            else 
               {
                  digitalWrite(row[i], HIGH); 
                  digitalWrite(col[j], LOW); 
                  delayMicroseconds(dms);
                  digitalWrite(row[i], HIGH); 
                  digitalWrite(col[j], LOW);
              } // Иначе выключить светодиод в проверяемой позиции, задержать включенным, обновить экран. (даже если светодиод и был выключенным в этой позиции, то все равно его нужно «выключить» для того, чтобы проверка в цикле и действия проходили с одинаковой задержкой. Если в позиции 1 – то выполняются действия, если в позиции 0 – все равно должно что-то выполнится либо выполнится задержка, сопоставимая с задержкой выполнения включения светодиода)
        } 
    }
}


Напишем функцию, которая реализует алгоритм «Прокрутка информации».

void scroll(boolean screen[8][8]) // В качестве параметра передаем наш двухмерный массив   
{
boolean buf[8][1]; 
  for (int i=0; i<8; i++)
  {
    buf[i][0]=screen[i][0]; // Считали 1ю колонку в буфер
  }
  for (int i=0; i<8; i++)
    for (int j=0; j<8; j++)
      {
        screen[i][j]=screen[i][j+1]; // Сдвинули матрицу на один столбец влево
      }
  for (int i=0; i<8; i++)
  {
    screen[i][8-1]=buf[i][0]; // Записали содержимое буфера (первую колонку) в конец матрицы
  }
}


Теперь приведу полный код программы:


const int row[8]={23,25,27,29,31,33,35,37};
const int col[8]={39,41,43,45,47,49,51,53};
int v=3; 
int dms=400; 

boolean A[8][8] = 
{0,0,1,1,1,1,0,0,
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0,  
0,1,1,1,1,1,1,0,  
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0,  
0,1,0,0,0,0,1,0};  

void setup()
{
  for (int i=0; i<8; i++)
    {
      pinMode(row[i],OUTPUT);
      pinMode(col[i],OUTPUT);
    }
  for (int i=0; i<8; i++)
    {
      digitalWrite(row[i],HIGH); 
    }
}

void loop()
{
	paint(A, v);
	scroll(A);
}

void paint(boolean screen[8][8], int v) 
{  
int i, j;
for (int c=0; c <v; c ++) 
  {
    for (i=0; i<8; i++)
      for (j=0; j<8; j++)
        {
          if (screen[i][j]==1)            
           {
              digitalWrite(row[i], LOW); 
              digitalWrite(col[j], HIGH); 
              delayMicroseconds(dms); 
 	      digitalWrite(row[i], HIGH); 
              digitalWrite(col[j], LOW); 
           }
            else 
             {
                 digitalWrite(row[i], HIGH); 
                 digitalWrite(col[j], LOW); 
                 delayMicroseconds(dms); 
                 digitalWrite(row[i], HIGH); 
                 digitalWrite(col[j], LOW);
            } 
        } 
    }
}

void scroll(boolean screen[8][8]) 
{
boolean buf[8][1]; 
  for (int i=0; i<8; i++)
  {
    buf[i][0]=screen[i][0]; 
  }
  for (int i=0; i<8; i++)
    for (int j=0; j<8; j++)
      {
        screen[i][j]=screen[i][j+1]; 
      }
  for (int i=0; i<8; i++)
  {
    screen[i][8-1]=buf[i][0]; 
  }
}


Вот и все. Заливайте эту программу в свой микроконтроллер и наблюдайте, как буква «А» будет «бежать» влево. Добавлю, что массивом размерностью 8 на 8 элементов ограничиваться не стоит. Например, я использовал массив размером 8 на 86. Написал в нем целую фразу, как видно на этом видео.

Удачи!
Павел @FluffyMan
карма
79,0
рейтинг 0,0
Самое читаемое

Комментарии (80)

  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      почему 65? 8*8=64.

      второй вопрос уже к производителям. наверное все же выгоднее и логичнее производить матрицы без контроллера. обеспечивает встраиваемость и гибкость применения. я так думаю.
      • +8
        Потому что 64 катода, скажем, и один общий контакт для анодов. Или наоборот.
        • 0
          Вы правы. исправляю.
          • –1
            64 цифровых выходов + земля, 65-тый выход не нужен
      • 0
        + земля
  • 0
    Вы напрямую матрицу к микроконтроллеру подключаете или там более сложная схема?
    • 0
      я в радиоэлектронике не силен, мягко говоря. нет, выводы, отвечающие за строки подключаются (в моем случае) через резисторы. чтобы не вышли из строя ножки контроллера в лучшем случае и чтобы он не сгорел в худшем.
  • –2
    [irony]Красота оформления кода, и его структурированность просто поражают.[/irony]
    • +1
      знаете, код форматирован нормально. а как этот код отображается после публикации — другое дело. не пойму почему так.
    • +1
      буду благодарен, если вместо иронии подскажете как исправить)
      • 0
        может это поможет

        Подсвечивает код программы (поддерживается bash, cpp, cs, xml, html, java, javascript, lisp, lua, php, perl, python, ruby, sql, scala, tex)
        • 0
          чёрт, скушало теги source lang=«язык» и закрывающий тег /source
          • 0
            спасибо
      • +1
        Если чуть выше окна с комментарием нажать на ссылку «html-теги», то появится не плохая подсказка.
  • 0
    Вы наверное своим примером можете улучшить учебные примеры по arduino.
  • +1
    Напрямую аноды матрицы к выводам контроллера обычно не подключают. На то есть минимум две причины:

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

    2) Хорошо, если столбцов всего 8, а если их, скажем, 128 (как на большом табло «бегущая строка»)? Для коммутации столбцов удобно использовать счетчики, дешифраторы или сдвиговые регистры. В последнем случае достаточно использовать всего 2 вывода контроллера (сброс и сдвиг) независимо от количества столбцов.
  • +3
    Дичайше неэкономное использование ножек. Поставьте сдвиговые регистры, на любое количество светодиодов уйдёт всего 4 ножки или меньше.
    • 0
      Сдвиговые регистры не всегда подходят для таких вещей — например при инициализации регистров их выходы пляшут как хотят (такой Новый Год пускай идет доли секунды, но бывает очень портит весь проект).
      • 0
        Ничто не мешает буферезировать их.
      • +1
        Если это так критично — подключите линии строк через дополнительный буфер с tri-state выходами. Алгоритм работы следующий:
        1) Подали питание;
        2) Проинициализировали регистры;
        3) Переключили буфер из Z-состояния в рабочее.
      • 0
        Для этого придумали ещё одну ножку — сброс
        • 0
          Ардуина даже не успевает даже загрузиться пока пляшут регистры. Единственный придуманный колхоз — повесит питание регистров через «реле», и дальше включать его при готовности управлять (2 секунды после подачи питания).
          • +3
            А, понял о чём вы. Тогда можно подтягивающий резистор на reset повесить.
            • 0
              хмм, где вы были раньше…

              в итоге после пляски 3х регистров — поставил Arduino Mega на эти задачи. Сердито получилось))
          • 0
            Извините, немного не в теме, но что в Ардуино зашито такого, что грузится целых 2 секунды?
            • 0
              ничего сверх естественного, но Ардуинка подключена по USB к компьютеру, который ресетит его при загрузке.

              Посторюсь, даже доли секунды достаточно чтобы испортить картину — у меня на выходе регистров через ключи стояло 24 двигателя. Эта карусель сбивала датчики положения валов.
              • 0
                Понятно. В таком случае разрешение работы периферии по отдельному сигналу готовности должно спасти от дискотеки.
            • +2
              Бутлоадер, который ждёт 2 секунды?
      • 0
        Транзистор поставьте, который зажигает светодиоды, делов-то. Пока он закрыт, никакие пляски в регистрах ничего не испортят.
      • +1
        Регистры разные есть. Есть и с защелкой. Пока строб не дашь ничего не шелохнется. 595й вроде бы такой, но могу ошибаться с номером.
        • +2
          Да, у 74HC595 защёлка есть, и стоит он копейки. Хорошая штука, я через него не то что светодиодную матрицу, а LCD на HD44780 и сервы подключал.
    • +1
      я в общих чертах имею представление, что такое сдвиговые регистры, но с ними не работал. к тому же, в данном случае задача была не «как экономить порты ввода\вывода», а разобраться с принципом динамической индикации. ну и как вдобавок написать «бегущий» текст.
      • 0
        думаю, поняв алгоритм людям несложно будет это все реализовать со сдвиговыми регистрами. хотя, те кто работает со сдвиговыми регистрами, думаю, давно знают как программировать дин. индикацию :)
        • 0
          Какой-то парадокс курицы и яйца получился, не находите? В статье подробности не описаны, потому что «тем, кто подробности знает, эта статья не нужна».
          Принципы динамической индикации изложены отлично, не спорю, но хотя бы пару предложений о том, «как это делают в настоящих проектах» стоит добавить.
          • +1
            согласен. только я не делал «настоящих проектов» с матрицами и сдвиговыми регистрами. поэтому, эта статья — не более чем моя личная маленькая победа) о как загнул.
            • 0
              Если это победа лично ваша, и опыта или полезной информации другим она не принесет то зачем делать статью?

              ИМХО если вы включите все 8 светодиодов в одном столбце то нагрузка превысит допустимые значения по Даташиту, да это не критично но при продолжительной перегрузке МК будет греться и через «N-ое время» выйдет из стоя.
              • 0
                не выйдет из строя. к ножкам МК выводы строк подключены через резисторы.
                • 0
                  А ты ток посчитал? какой в общем будет? явно более 80 мА
                  • 0
                    я скажу так. ( в который раз:) в электронике я не силен. считал не я и паял тоже. вот. но я УВЕРЕН, что все там в порядке на 100%.
                    • 0
                      В этом случае яркость одного диода будет в 8 раз выше чем зажженых 8ми диодов. Цветастая получится картинка :)
                      • 0
                        так ведь в моей реализации в один момент времени включен только один светодиод всегда. 8 одновременно не включатся никак в моем коде)
                        • 0
                          А! У вас поточечная. Ну тогда да, согласен. Но это тускло. Хотя у данной матрицы весьма неплохой запас по яркости. Видать диоды светятся чуть ли не от святого духа (Помню были у меня зверские светодиоды которые начинали светиться если их просто в руки за разные ножки взять)
                          • 0
                            яркость программно можно «регулировать». задерживать больше времени светодиод в состоянии «включен». но можно дорегулироваться, что будет ярко, но картинка заметно мигает. или наоборот, мигание совсем нет, все плавно, но очень тускло.
                • +1
                  Перечитал внимательно код. У вас же развертка идет и по строкам, и по столбцам! То есть в данный момент времени горит не больше одного светодиода. Да, проблему нагрузочной способности это решает, но в целом такое решение хорошим не назовешь.
                  — частота обновления картинки в восемь раз ниже, чем могла бы быть;
                  — вместо побайтного вывода используется побитовый — слишком громоздкий и неэффективный код получается;
                  — нужны искуственные задержки для выключенных пикселей.
                  • 0
                    Ocelot, спасибо, я ошибся — думал что реализация как раз по байтовая, да в таком случае с нагрузкой все в порядке.
                  • 0
                    По поводу обновления картинки: на видео легко увидеть, что обновляется не весь массив, а его часть (будто выключили v-sync). Чем это обусловлено и как это исправить?
                    • +1
                      Увеличить скорость прорисовки, сделать как раз байтовую динамическую индикацию, когда обновляется 1 строка/столбец за шаг но в таком варианте обязательно использование внешних ключей (транзисторов)
                  • 0
                    я ведь написал, что это не эталон, как программировать дин. индикацию.

                    а как проверить одновременно строку, например? я пробегаю по массиву двумерному и где в массиве TRUE, то есть 1, в том месте включаю светодиод.

                    мне интересно посмотреть и услышать комментарии как другие реализовуют.
                    • 0
                      Пусть матрица 8x8 и управляется 16 выводами (8 столбцов — PORTB, 8 строк — PORTC) через ключи, чтобы решить проблему мощности, но без всяких сдвиг. регистров.
                      Состояние экрана хранить в виде массива из восьми байт, причем каждый байт соответствует столбцу.
                      Вывод:
                      
                      unsigned char screen_buffer [8];
                      // ...
                      for (char i=0; i<8; i++)
                      {
                         PORTB = (1 << i); // включили столбец i
                         PORTC = screen_buffer [i]; // зажгли нужные пиксели столбца
                         delay ();
                      }
                      
                      • 0
                        если можно привести код, например, зажечь какой-нибудь символ. для болей ясности.
                        • 0
                          Вместо //… вставить следующее:
                          
                          screen_buffer [0] = 0x1F; // 00011111
                          screen_buffer [0] = 0x3F; // 00111111
                          screen_buffer [0] = 0x6C; // 01101100
                          screen_buffer [0] = 0xCC; // 11001100
                          screen_buffer [0] = 0xCC; // 11001100
                          screen_buffer [0] = 0x6C; // 01101100
                          screen_buffer [0] = 0x3F; // 00111111
                          screen_buffer [0] = 0x1F; // 00011111
                          

                          Это для буквы A. Возможно значения придется инвертировать (смотря какие применяются ключи) или изменить порядок (смотря как скоммутированы выводы).
                          По-хорошему нужно один раз объявить набор констант с матрицами для всех символов, а потом просто копировать в screen_buffer / менять указатель. Бегущая строка организуется путем сдвига элементов в массиве screen_buffer:
                          
                          void shift (unsigned char &screen_buffer)
                          {
                             for (char i=0; i<7; i++)
                             {
                                 screen_buffer [i] = screen_buffer [i+1];
                             }
                             screen_buffer [7] = 0x00;
                          }
                          
                          • 0
                            в первом куске кода, конечно, индексы не все 0, а от 0 до 7.
                          • 0
                            жесть. это круто. мои мозги мыслили только в направлении точечной прорисовке картинки. оказывается можно целиком построчно\поколонно рисовать. спасибо.
                            • 0
                              Только вам под это дело придется схему переделывать. Т.к. один вывод не протащит через себя сразу 8 точек. либо они будут в восемь раз тусклей одного.
                              • 0
                                Ну я же написал:
                                >через ключи, чтобы решить проблему мощности
                                • 0
                                  я понял. просто взял на заметку, что есть такой способ.
                          • 0
                            я тоже так думал сделать. для каждой буквы объявить массив 8х8 типа boolean правда.

                            а бегущая строка и у меня организуется путем сдвига массива влево на одну колонку.

                            а вобще, мой подход корректен? или я изобрел велосипед с квадратными колесами?
                            • 0
                              Вполне корректен, не считая некоторой громоздкости кода, но для учебных целей это даже хорошо.
                              Сейчас еще такая идея в голову пришла: если выводим бегущую строку, и отображаемая область значительно меньше полной картинки, то эффективнее не сдвигать весь буфер экрана, а менять координаты «окна» вывода. Примерно так:
                              
                              unsigned char screen_buffer [256];
                              unsigned int position, endpos, column;
                              
                              // здесь забиваем в screen_buffer всю строку
                              
                              for (position = 0; position < 256; position++) // сдвиг окна
                              {
                                 endpos = position + 8; // определяем правую границу окна
                              // вывод столбцов,
                              // попавших в окно
                                 for (column=position; column<endpos; column++) 
                                 {
                                    delay (1);
                                    if (column > 255) continue; // проверка границ
                                    PORTB = (1 << column); // включили столбец 
                                    PORTC = screen_buffer [column]; // зажгли нужные пиксели столбца
                                 }
                                delay (1000);
                              }
                              

                              На будущее: вместо циклов с задержками правильнее использовать таймеры и прерывания.
                              • 0
                                Еще поправочка. Вместо:
                                for (column=position; column<endpos; column++)
                                ...
                                PORTB = (1 << column);

                                нужно написать:
                                for (char i=0, column=position; column<endpos; i++, column++)
                                ...
                                PORTB = (1 << i);

                                Всё, спать пора!
                              • 0
                                логично
      • +1
        Проблема динамической индикации только в одном — большая загрузка проца (когда число точек идет на сотни) и низкая яркость их. А срегистрами получается все очень дубово, можно воообще даже статично сделать, но это много регистров уйдет :)
        • 0
          если придется мне программировать матрицу на сдвиговых регистрах — обязательно напишу о получившемся) хотя до меня все уже давно написано и сделано и разжевано.
        • 0
          При дин. яркости можно ставить большие токи(максимально допустимые) или даже вылазить то тут уже надо смотреть при каком токе идет перегрев а при каком деградация.

          на счет мк, чаще всего под большие матрицы ставят отдельные мк к которыми управляют с Основного мк, получается что то на подобии самодельного графического дисплея

          регистры используют не на квадратных матрицах а на бегущих строках чаще всего…
          • +1
            Ну тут регистр незачем ставить, всего 16 выводов. Но если матрица большая… то регистры то что доктор прописал. Даже в динамике, правда вешать их надо будет на SPI и гонять данные на 100Мбит, а может и выше.
            • 0
              AVR такую скорость не потянет только ARM или что то работающие на таких скоростях
              • 0
                Ой не мегабит, 100-400 килобит. :))) SPI там аппаратная, так что это ее даже не напряжет. А скорости аврки вполне хватает, чтобы обслуживать LED CUBE 16x16x16
  • +1
    Здесь так много говорят о сдвиговых регистрах, что стало ужасно интересно как это все реализовать вместе с Arduino. Стал искать по статьям на хабре и… ничего не нашел. Тут столько людей об этом знают и никто ничего про это не написал? Или никто не реализовал ничего?

    Большое спасибо автору — все доступно, просто и понятно. На подходе Arduino, скоро буду экспериментировать и начну с вашей статьи =)
    • +2
      Интернет хабром не ограничивается, тем более есть «электронный хабр» — easyelectronics.ru, и там статей про сдвиговый регистр достаточно.
      • +1
        Ну это понятно, не первый день в сети. Все равно жаль, что приходится куда-то ходить и что-то искать вместо того, что бы прочесть это все на родном хабре =)
        • +1
          Если все-все-все пихать на хабр, то он быстро превратится в нетематическую помойку.
    • +8
      Тот кто пользуется сдвиговыми регистрами, чаще всего использует просто AVR или PIC без Arduino
    • 0
      robocraft.ru/blog/arduino/519.html лови про регистры. очень просто описано
      • 0
        О, спасибо большое!
        • +1
          Вообще это основы, поэтому когда вы вдруг начнете читать хоть какой угодно мануал для новичков, вы всеравно на них наткнетесь.
    • 0
      буду рад, если поможет статья.
    • +2
      А что там писать? Три строчки? Я вам и тут напишу: два входа, 8 выходов. Выставляете бит на входе, дрыгаете вверх-вниз ножку сдвига, при этом бит, который был на входе появляется на 0-м выходе, что было на 0-м появляется на 1-м, и так далее (данные на выходе сдвигаются). Подключив каскадом следующий регистр входом на 7-й выход предыдущего — получим регистр с 16-ю выходами, и так каскадировать можно до бесконечности.

      Есть еще вход сброса, есть регистры с защелками — на выходе данные не ползут, а буферизируются, появляются только по вашей команде. Но это частности.
  • 0
    Мой первый проект с микроконтроллером — это как раз бегущая строка. Делал на регистрах, что интересно, вообще мало понимал до того, как со всем этим хозяйством делать, но ничего — разобрался. Сделал успешно работающую строчку 7х5, потом решил сделать ее длиннее и перенести на печатную плату, но что-то там в регистрах загуляло не то, и в итоге в буфер писалось не то, что нужно. Так теперь изделие валяется не доделанное.
  • 0
    а можно код того, что на видео?
  • 0
    или опишите, пожалуйста, что менять надо под больший массив

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