4 мая 2012 г.

Arduino: бегающая точка на светодиодной матрице

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

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

Светодиодная матрица мне попалась двухцветная, у нее 24 ноги:




8 ног - аноды, 8 - зеленые катоды, 8 - красные катоды. Выводы располагаются следующим образом:



Здесь 1-8 - аноды, ra-rh - красные катоды, ga-gh - зеленые катоды. Пока мы будем работать только с красными, поэтому для подключения матрицы нам понадобится только 2 сдвиговых регистра 74HC595 - один для анодов, другой для катодов.

Схема подключения

Про SPI я уже писал столько (1, 2, 3, 4, 5), что у внимательного читателя может возникнуть SPI головного мозга. Я разжевывал схемы подключения и программы для управления внешними устройствами по SPI, поэтому сейчас мы просто берем и применяем его. Возьмем схему из старого поста про последовательное подключение регистров:


только теперь вместо 7-сегментников подключим матрицу. Первый в очереди регистр (на схеме слева) подключим к катодам матрицы, а второй (справа) - к анодам. Для удобства обзовем байты, которые мы будем передавать на эти два регистра, также "анодным" и "катодным".

Не забывайте ставить перед каждый светодиодом ограничивающий резистор!

У меня получилась вот такая вот установка (тут мало что понятно, но видно, к чему стремиться):



Первая попытка завести это чудо

Для начала попробуем просто поморгать светодиодиками, чтобы проверить работоспособность и правильность сборки схемы:


#include <SPI.h>  //подключаем библиотеку SPI
enum { reg = 9 }; //выбираем линию SS регистра на 9-м пине Arduino

void setup(){
  SPI.begin();    //инициализируем SPI
  pinMode(reg, OUTPUT); //инициализируем пин SS
}


int time = 150; //время задержки между фрэймами



void loop(){
  digitalWrite(reg, LOW);  //начинаем передачу 
  SPI.transfer(0x92);      //передаем 1-й байт
  SPI.transfer(0x00);      //передаем 2-й байт
  digitalWrite(reg, HIGH); //заканчиваем передачу

  delay(time);             //пауза
  digitalWrite(reg, LOW);
  SPI.transfer(0x49);
  SPI.transfer(0x00);
  digitalWrite(reg, HIGH);
  delay(time);

  digitalWrite(reg, LOW);

  SPI.transfer(0x24);
  SPI.transfer(0x00);
  digitalWrite(reg, HIGH);
  delay(time);
}

Числа для передачи я рассчитал так. Все катодные байты, понятно, 0x00, потому что мы хотим, чтобы загорался весь столбец. Анодные байты получаются из последовательности 01001001, 10010010, 00100100, которая имитирует движение линий справа налево. Мы помним, что байты передаются старшим разрядом вперед, поэтому при переводе бинарных чисел в шестнадцатеричные смотрим справа налево. Подробно на этом я останавливался в самом первом посте. Вы можете, конечно, писать в программе и бинарные числа с префиксом 0b, но, на мой взгляд, это занимает много места.

Наслаждаемся работой:



Прикручиваем джойстик

Джойстик очень просто подключается к Sensor Shield вот так:



Я подключил ось x к A1, ось y - к A2, а ось z - к A3. Вы можете выбрать любые другие аналоговые входы по вкусу. Третья ось нам в этом примере не понадобится, но в дальнейшем я придумаю ей какое-нибудь применение.

Читаем значения с джойстика и сразу ремапим их:

  xValue=map(analogRead(A1), 0, 1024, 0, 8);
  yValue=map(analogRead(A2), 0, 1024, 0, 8);
Теперь джойстик как будто бы выдает значения от 0 до 8, что нам очень удобно - числа прямо задают номер столбца и номер строки в матрице. Упакуем эти номера в байты и передадим по SPI:

  SPI.transfer(1 << xValue);
  SPI.transfer(0xFF ^ 1 << yValue);
"<<", если кто подзабыл, это битовый сдвиг влево, а "^" - это битовое исключающее ИЛИ (XOR). Два этих выражения означают, что мы подаем Vcc на анод с номером, считанным с оси x джойстика, и 0 на катод с номером, считанным с оси y.

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

#include <SPI.h>  //подключаем библиотеку SPI
enum { reg = 9 }; //выбираем линию SS регистра на 9-м пине Arduino

void setup(){
  SPI.begin();    //инициализируем SPI
  pinMode(reg, OUTPUT); //инициализируем пин SS
}



int xValue, yValue; //
int time = 30;



void loop(){
//читаем джойстик и ремапим значения от 0 до 8
  xValue = map(analogRead(A1), 0, 1024, 0, 8);
  yValue = map(analogRead(A2), 0, 1024, 0, 8);
  
  digitalWrite(reg, LOW);           //начинаем передачу
  SPI.transfer(1 << xValue);        //передаем номер столбца
  SPI.transfer(0xFF ^ 1 << yValue); //передаем номер строки
  digitalWrite(reg, HIGH);          //заканчиваем передачу
  delay(time);                      //ждем

}
Программа сразу делает то, что нам нужно:




Радуемся!

Далее по теме Arduino и SPI