Pull to refresh

Knight rider. Программируем плавную анимацию на микроконтроллере

Reading time 3 min
Views 5.2K
Доброго времени суток.

Сегодня хочу вам рассказать как сделать плавную анимацию на микроконтроллере с помощью светодиодов. За основу взято микросхему attiny2313 фирмы Atmel, именно такая у меня валялась нашлась. Не буду углубляться в подробности прошивки, программатора, все это было на хабре. Вот и вот и под линукс

Большинство помнят фильм, а потом уже и сериал «Рыцарь дорог» (Knight Rider). Кто в детстве не мечтал о такой машине? Ну вот, для примера решил сделать анимацию, такую как впереди самой машины.

image



Спаял схему по следующему принципу.
схема

Планку со светодиодами взял от телевизора «Электрон», как раз там было 8 штук. Там были светодиоды на 3 вольта, поэтому в моем варианте, последовательно диодам я добавил резисторы по 200 Ом.

Теория



Тривиальная штука, если на порт вывода записать единицу, то диод будет светить, если ноль, он погаснет. Для того, чтобы он частично светил (светил, но не на полную мощность) нужно эмулировать ШИМ на каждом порту.

Точность формирования импульса решил разнести на 10 итераций. То есть возможно 10 разных вариантом силы свечения диода. Если у всех итераций на выходе будет 1, то это максимальное свечение, если 5 из 10 — получиться половинное. То есть, когда на выходе 1 он будет загораться, но дальше идет 0, и он угасает. Такой ШИМ-сигнал имеет несколько сотен килогерц, и сама инерция диода дает нам нужный эффект.

Реализация



Всю анимацию засунул в матрицу, это дает нам возможность легко и просто программировать саму анимацию.

const char mat[] =
{
  10,0,0,0,0,0,0,0,
  6,10,0,0,0,0,0,0,
  2,6,10,0,0,0,0,0,
  0,2,6,10,0,0,0,0,
  0,0,2,6,10,0,0,0,
  0,0,0,2,6,10,0,0,
  0,0,0,0,2,6,10,0,
  0,0,0,0,0,2,6,10,
  0,0,0,0,0,0,2,6,
  0,0,0,0,0,0,0,2,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,10,
  0,0,0,0,0,0,10,6,
  0,0,0,0,0,10,6,2,
  0,0,0,0,10,6,2,0,
  0,0,0,10,6,2,0,0,
  0,0,10,6,2,0,0,0,
  0,10,6,2,0,0,0,0,
  10,6,2,0,0,0,0,0,
  6,2,0,0,0,0,0,0,
  2,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0
};

short timeAnim = 3000;


* This source code was highlighted with Source Code Highlighter.


И так timeAnim это время всей анимации. Каждая строчка это 10 итераций одного фрейма, где каждая ячейка это «светловая сила» диода.

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

  //вычисляем время для одного фрейма
  sPeriodTime = timeAnim * 4 / sizeof(mat) * 8;   
  iCycle = 0;                 
  
  // вычисляем количество фреймов для анимации
  iMaxCycle = sizeof(mat) / 8;

  while (1)
  {
    PORTB = 0;
    TCNT1 = 0; 
    iCycle = 0;      
    while(iCycle < iMaxCycle)
    {
      while(TCNT1 < (iCycle + 1)*sPeriodTime)//проверяем, истекло ли время для анимации одного фрейма
      {
        for(i = 0; i < 10; i++) //анимация 10 подфреймов
        {   
          iTemp = 0;     
          for(j = 0; j < 8; j++)//формируем выходное значения
          {
            iTemp <<= 1;
            iTemp |= (mat[iCycle*8 + j] - i) > 0;
          }          
          PORTB = iTemp; //записываем значения в порт
        }
      };
      iCycle++;
    }
  };

* This source code was highlighted with Source Code Highlighter.


Результат







Ну и кому интересно, исходники

По традициям хабра, это моя первая статья, сильно не пинайте.

Успехов.
Tags:
Hubs:
+36
Comments 7
Comments Comments 7

Articles