Arduino:Примеры/Гайд по использованию светодиодной матрицы MAX7219 с Arduino (плюс игра Pong)
Содержание | Знакомство с Arduino | Продукты | Основы | Справочник языка Arduino | Примеры | Библиотеки | Хакинг | Изменения | Сравнение языков Arduino и Processing |
Гайд по использованию светодиодной матрицы MAX7219 с Arduino (плюс игра Pong)[1]
Светодиодная матрица, которую мы будем использовать в это статье, состоит из 8 рядов и 8 столбцов. То есть в общей сложности она оснащена 64 светодиодами.
Управление светодиодной матрицей можно упростить при помощи чипа MAX7219 – благодаря ему вам понадобится всего 3 цифровых контакта платы Arduino. Думаю, будет лучше купить модуль, в который уже встроены и светодиодная матрица, и чип MAX7219. Это упростит возню с проводами. Такой модуль можно купить на eBay менее чем за 2 доллара.
Одновременно можно управлять несколькими такими матрицами. Вы даже можете собрать из них большую матрицу, т.к. у них есть специальные контакты для подключения друг к другу.
Необходимые компоненты
- Одна светодиодная матрица (8 на 8) с чипом MAX7219 (см. на eBay)
- Одна плата Arduino (см. на eBay)
- Один потенциометр на 1 кОм
- Провода-перемычки
Подключение контактов
В подключении светодиодной матрицы к плате Arduino нет ничего сложного. Вам понадобится подключить всего 5 контактов:
- Контакт GND на матрице – к контакту GND на Arduino
- Контакт VCC – к контакту 5V
- Контакт DIN – к цифровому контакту
- Контакт CS – к цифровому контакту
- Контакт CLK – к цифровому контакту
Как управлять светодиодной матрицей с помощью Arduino
Чтобы упростить управление матрицей, вам понадобится загрузить и установить в IDE Arduino библиотеку «LedControl». Для этого проделайте следующее:
- Кликните здесь, чтобы скачать ZIP-архив с библиотекой.
- Распакуйте скачанный архив. В итоге у вас должна получиться папка под названием «LedControl-master».
- Переименуйте ее на «LedControl».
- Переместите папку «LedControl» в папку «libraries» IDE Arduino.
- Перезапустите IDE Arduino.
Функции библиотеки LedControl
Самый простой способ показать что-нибудь на матрице – это воспользоваться функциями setLed(), setRow() и setColumn(). Они позволяют вам управлять, соответственно, одним светодиодом, одним рядом светодиодов или одним столбцом светодиодов.
Параметры для каждой функции:
- setled(addr, row, col, state)
- addr – адрес матрицы; к примеру, если вы используете всего одну матрицу, то в этом параметре должен стоять «0»
- row – ряд, в котором находится светодиод
- col – столбец, в котором находится светодиод
- state – состояние светодиода; true или 1 – чтобы включить светодиод, false или 0 – чтобы выключить
- setRow(addr, row, value)
- setCol(addr, row, value)
- value – значение, которое обозначает, какие светодиоды надо включить
Индекс
Итак, матрица состоит из 8 столбцов и 8 рядов. Каждый из них имеет индекс от «0» до «7». Ниже – рисунок для наглядности:
Таким образом, если вы хотите что-то показать на матрице, вам нужно задать ряд или столбец, а также то, какие светодиоды включить, а какие нет.
К примеру, если я хочу показать смайлик, то мне нужно сделать следующее:
Код
Ниже – простой скетч, который показывает на матрице три разные рожицы: веселую, «покерфейс» и грустную. Загрузите его на свою Arduino:
/*
Автор – Руи Сантос (Rui Santos)
Более подробно о проекте на: http://randomnerdtutorials.com/
*/
#include "LedControl.h"
#include "binary.h"
/*
Контакт DIN на матрице – к цифровому контакту 12 на Arduino
Контакт CLK – к цифровому контакту 11
Контакт CS – к цифровому контакту 10
*/
LedControl lc=LedControl(12,11,10,1);
// задержка между разными рожицами:
unsigned long delaytime=1000;
// веселая рожица:
byte hf[8]= {B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100};
// «покерфейс»:
byte nf[8]={B00111100, B01000010,B10100101,B10000001,B10111101,B10000001,B01000010,B00111100};
// грустная рожица:
byte sf[8]= {B00111100,B01000010,B10100101,B10000001,B10011001,B10100101,B01000010,B00111100};
void setup() {
lc.shutdown(0,false);
// выставляем яркость на среднее значение:
lc.setIntensity(0,8);
// очищаем дисплей:
lc.clearDisplay(0);
}
void drawFaces(){
// показываем грустную рожицу:
lc.setRow(0,0,sf[0]);
lc.setRow(0,1,sf[1]);
lc.setRow(0,2,sf[2]);
lc.setRow(0,3,sf[3]);
lc.setRow(0,4,sf[4]);
lc.setRow(0,5,sf[5]);
lc.setRow(0,6,sf[6]);
lc.setRow(0,7,sf[7]);
delay(delaytime);
// показываем «покерфейс»:
lc.setRow(0,0,nf[0]);
lc.setRow(0,1,nf[1]);
lc.setRow(0,2,nf[2]);
lc.setRow(0,3,nf[3]);
lc.setRow(0,4,nf[4]);
lc.setRow(0,5,nf[5]);
lc.setRow(0,6,nf[6]);
lc.setRow(0,7,nf[7]);
delay(delaytime);
// показываем веселую рожицу:
lc.setRow(0,0,hf[0]);
lc.setRow(0,1,hf[1]);
lc.setRow(0,2,hf[2]);
lc.setRow(0,3,hf[3]);
lc.setRow(0,4,hf[4]);
lc.setRow(0,5,hf[5]);
lc.setRow(0,6,hf[6]);
lc.setRow(0,7,hf[7]);
delay(delaytime);
}
void loop(){
drawFaces();
}
В результате у вас должно получится примерно следующее:
Игра «Pong»
Игра «Pong» для этого примера была написана Алессандро Пасотти (Alessandro Pasotti). Кроме того, для этого проекта вам нужно будет добавить к схеме выше потенциометр на 1 кОм. Подключите друг к другу компоненты как показано на рисунке ниже:
Код
Теперь загрузите на Arduino вот этот код:
/*
* Игра «Pong» на светодиодной матрице 8x8 (проект с itopen.it)
*/
#include "LedControl.h"
#include "Timer.h"
#define POTPIN A5 // потенциометр
#define PADSIZE 3
#define BALL_DELAY 200
#define GAME_DELAY 10
#define BOUNCE_VERTICAL 1
#define BOUNCE_HORIZONTAL -1
#define NEW_GAME_ANIMATION_SPEED 50
#define HIT_NONE 0
#define HIT_CENTER 1
#define HIT_LEFT 2
#define HIT_RIGHT 3
//#define DEBUG 1
byte sad[] = {
B00000000,
B01000100,
B00010000,
B00010000,
B00000000,
B00111000,
B01000100,
B00000000
};
byte smile[] = {
B00000000,
B01000100,
B00010000,
B00010000,
B00010000,
B01000100,
B00111000,
B00000000
};
Timer timer;
LedControl lc = LedControl(12,11,10,1);
byte direction; // роза ветров, «0» - это север
int xball;
int yball;
int yball_prev;
byte xpad;
int ball_timer;
void setSprite(byte *sprite){
for(int r = 0; r < 8; r++){
lc.setRow(0, r, sprite[r]);
}
}
void newGame() {
lc.clearDisplay(0);
// начальная позиция:
xball = random(1, 7);
yball = 1;
direction = random(3, 6); // идем на юг
for(int r = 0; r < 8; r++){
for(int c = 0; c < 8; c++){
lc.setLed(0, r, c, HIGH);
delay(NEW_GAME_ANIMATION_SPEED);
}
}
setSprite(smile);
delay(1500);
lc.clearDisplay(0);
}
void setPad() {
xpad = map(analogRead(POTPIN), 0, 1020, 8 - PADSIZE, 0);
}
void debug(const char* desc){
#ifdef DEBUG
Serial.print(desc);
Serial.print(" XY: "); // "Координаты X и Y: "
Serial.print(xball);
Serial.print(", ");
Serial.print(yball);
Serial.print(" XPAD: "); // "Расположение платформы: "
Serial.print(xpad);
Serial.print(" DIR: "); // " Направление: "
Serial.println(direction);
#endif
}
int checkBounce() {
if(!xball || !yball || xball == 7 || yball == 6){
int bounce = (yball == 0 || yball == 6) ? BOUNCE_HORIZONTAL : BOUNCE_VERTICAL;
#ifdef DEBUG
debug(bounce == BOUNCE_HORIZONTAL ? "HORIZONTAL" : "VERTICAL");
#endif
return bounce;
}
return 0;
}
int getHit() {
if(yball != 6 || xball < xpad || xball > xpad + PADSIZE){
return HIT_NONE;
}
if(xball == xpad + PADSIZE / 2){
return HIT_CENTER;
}
return xball < xpad + PADSIZE / 2 ? HIT_LEFT : HIT_RIGHT;
}
bool checkLoose() {
return yball == 6 && getHit() == HIT_NONE;
}
void moveBall() {
debug("MOVE");
int bounce = checkBounce();
if(bounce) {
switch(direction){
case 0:
direction = 4;
break;
case 1:
direction = (bounce == BOUNCE_VERTICAL) ? 7 : 3;
break;
case 2:
direction = 6;
break;
case 6:
direction = 2;
break;
case 7:
direction = (bounce == BOUNCE_VERTICAL) ? 1 : 5;
break;
case 5:
direction = (bounce == BOUNCE_VERTICAL) ? 3 : 7;
break;
case 3:
direction = (bounce == BOUNCE_VERTICAL) ? 5 : 1;
break;
case 4:
direction = 0;
break;
}
debug("->");
}
// проверяем удар: модифицируем направление (влево или вправо):
switch(getHit()){
case HIT_LEFT:
if(direction == 0){
direction = 7;
} else if (direction == 1){
direction = 0;
}
break;
case HIT_RIGHT:
if(direction == 0){
direction = 1;
} else if(direction == 7){
direction = 0;
}
break;
}
// проверяем ортогональные направления и границы:
if((direction == 0 && xball == 0) || (direction == 4 && xball == 7)){
direction++;
}
if(direction == 0 && xball == 7){
direction = 7;
}
if(direction == 4 && xball == 0){
direction = 3;
}
if(direction == 2 && yball == 0){
direction = 3;
}
if(direction == 2 && yball == 6){
direction = 1;
}
if(direction == 6 && yball == 0){
direction = 5;
}
if(direction == 6 && yball == 6){
direction = 7;
}
// при попадании в угол:
if(xball == 0 && yball == 0){
direction = 3;
}
if(xball == 0 && yball == 6){
direction = 1;
}
if(xball == 7 && yball == 6){
direction = 7;
}
if(xball == 7 && yball == 0){
direction = 5;
}
yball_prev = yball;
if(2 < direction && direction < 6) {
yball++;
} else if(direction != 6 && direction != 2) {
yball--;
}
if(0 < direction && direction < 4) {
xball++;
} else if(direction != 0 && direction != 4) {
xball--;
}
xball = max(0, min(7, xball));
yball = max(0, min(6, yball));
debug("AFTER MOVE");
}
void gameOver() {
setSprite(sad);
delay(1500);
lc.clearDisplay(0);
}
void drawGame() {
if(yball_prev != yball){
lc.setRow(0, yball_prev, 0);
}
lc.setRow(0, yball, byte(1 << (xball)));
byte padmap = byte(0xFF >> (8 - PADSIZE) << xpad) ;
#ifdef DEBUG
//Serial.println(padmap, BIN);
#endif
lc.setRow(0, 7, padmap);
}
void setup() {
// в начале MAX72xx находится в режиме сбережения энергии;
// нужно его «разбудить»:
pinMode(POTPIN, INPUT);
lc.shutdown(0,false);
// выставляем яркость на среднюю величину:
lc.setIntensity(0, 8);
// очищаем дисплей:
lc.clearDisplay(0);
randomSeed(analogRead(0));
#ifdef DEBUG
Serial.begin(9600);
Serial.println("Pong");
#endif
newGame();
ball_timer = timer.every(BALL_DELAY, moveBall);
}
void loop() {
timer.update();
// двигаем платформу:
setPad();
#ifdef DEBUG
Serial.println(xpad);
#endif
// обновляем данные на экране:
drawGame();
if(checkLoose()) {
debug("LOOSE");
gameOver();
newGame();
}
delay(GAME_DELAY);
}
Демонстрация
Вот так игра в «Pong» выглядит вживую:
См.также
Внешние ссылки
Arduino продукты | |
---|---|
Начальный уровень | Arduino Uno • Arduino Leonardo • Arduino 101 • Arduino Robot • Arduino Esplora • Arduino Micro • Arduino Nano • Arduino Mini • Arduino Starter Kit • Arduino Basic Kit • MKR2UNO • TFT-дисплей Arduino |
Продвинутые функции | Arduino Mega 2560 • Arduino Zero • Arduino Due • Arduino Mega ADK • Arduino Pro • Arduino Motor Shield • Arduino USB Host Shield • Arduino Proto Shield • MKR Proto Shield • MKR Proto Large Shield • Arduino ISP • Arduino USB 2 Serial Micro • Arduino Mini USB Serial Adapter |
Интернет вещей | Arduino Yun • Arduino Ethernet • Arduino MKR1000 • Arduino WiFi 101 Shield • Arduino GSM Shield V2 • Arduino WiFi Shield • Arduino Wireless SD Shield • Arduino Wireless Proto Shield • Arduino Ethernet Shield V2 • Arduino Yun Shield • Arduino MKR1000 Bundle |
Носимые устройства | Arduino Gemma • Lilypad Arduino Simple • Lilypad Arduino Main Board • Lilypad Arduino USB • LilyPad Arduino SimpleSnap |
3D-печать | Arduino Materia 101 |
Устаревшие устройства | - |
Примеры Arduino | |
---|---|
Стандартные функции | |
Основы |
|
Цифровой сигнал |
|
Аналоговый сигнал |
|
Связь |
|
Управляющие структуры |
|
Датчики |
|
Дисплей |
Примеры, объясняющие основы управления дисплеем:
|
Строки |
|
USB (для Leonardo, Micro и Due плат) |
В этой секции имеют место примеры, которые демонстрируют использование библиотек, уникальных для плат Leonardo, Micro и Due.
|
Клавиатура |
|
Мышь |
|
Разное |
- Страницы, использующие повторяющиеся аргументы в вызовах шаблонов
- Справочник языка Arduino
- Arduino
- Перевод от Сubewriter
- Проверка:myagkij
- Оформление:myagkij
- Редактирование:myagkij
- Страницы, где используется шаблон "Навигационная таблица/Телепорт"
- Страницы с телепортом
- Пример
- Примеры
- Пример программирования Arduino
- Примеры программирования Arduino