作者:乐多体育 | 发表于:2023-02-02 | 阅读:45次

在本应用中,我们将使用的点矩阵是8×8矩阵,这意味着它具有8列8行,因此总共包含64个LED。

arduino 点阵「Arduino乒乓球游戏之8×8点阵应用」

MAX7219芯片仅需使用Arduino电路板的3个数字引脚,即可更轻松地控制点矩阵。我认为最好的选择是购买以MAX7219芯片为模块的点矩阵,这将简化布线。

arduino 点阵「Arduino乒乓球游戏之8×8点阵应用」

您一次可以控制多个矩阵。为此,您只需要将它们彼此连接即可,因为它们的两侧都有引脚以扩展点矩阵。

所需部件

对于本应用,您需要:

1x 8×8点矩阵,带有MAX7219跳线Arduino UNO

引脚接线

您只需要将5个引脚从点矩阵连接到Arduino开发板即可。接线非常简单:

点矩阵针 接线到Arduino Uno

地线 地线

VCC 5伏

DIN标准 数码针

CS 数码针

时钟 数码针

如何使用Arduino控制点矩阵

为了使控制点矩阵更加容易,您需要下载并在Arduino IDE中安装LedControl库。要安装该库,请按照下列步骤操作:

1. 单击此处下载LedControl库。您的下载中应该有一个.zip文件夹

2. 解压缩.zip文件夹,您应该得到LedControl-master文件夹

3. 重命名文件夹 到LedControl

4. 将LedControl 文件夹移至Arduino IDE安装 库 文件夹

5. 最后,重新打开您的Arduino IDE

使用LedControl库函数

在点矩阵上显示内容的最简单方法是使用setLed(),setRow()或setColumn()函数。这些功能使您可以一次控制一个LED,一行或一列。

这是每个函数的参数:

setLed(addr,row,col,state)

· addr是矩阵的地址,例如,如果只有1个矩阵,则int addr将为零。

· row是led所在的行

· col是led所在的列

· state

· 如果您要打开LED,则为true或1

· 如果为假,则为false或0

setRow(addr,row,value)

setCol(addr,column,value)

指数

如前所述,此矩阵有8列和8行。每个索引的索引范围都是0到7。下面是一个更好理解的模型:

arduino 点阵「Arduino乒乓球游戏之8×8点阵应用」

如果要在矩阵中显示某些内容,则只需要知道确定的行或列中的LED是打开还是关闭。

例如,如果您想露出笑脸,这是您需要做的:

arduino 点阵「Arduino乒乓球游戏之8×8点阵应用」

源代码

这是一个简单的草图,其中显示三种类型的面孔:悲伤的面孔,中性的面孔和幸福的面孔。将以下代码上传到您的开发板上:

#include "LedControl.h"

#include "binary.h"

/*

DIN connects to pin 12

CLK connects to pin 11

CS connects to pin 10

*/

LedControl lc=LedControl(12,11,10,1);

// delay time between faces

unsigned long delaytime=1000;

// happy face

byte hf[8]= {B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100};

// neutral face

byte nf[8]={B00111100, B01000010,B10100101,B10000001,B10111101,B10000001,B01000010,B00111100};

// sad face

byte sf[8]= {B00111100,B01000010,B10100101,B10000001,B10011001,B10100101,B01000010,B00111100};

void setup() {

lc.shutdown(0,false);

// Set brightness to a medium value

lc.setIntensity(0,8);

// Clear the display

lc.clearDisplay(0);

}

void drawFaces(){

// Display sad face

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);

// Display neutral face

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);

// Display happy face

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();

}

乒乓球比赛

对于乒乓游戏,您只需要在前面的原理图中添加一个1k欧姆的电位器即可。组装新电路,如下所示:

arduino 点阵「Arduino乒乓球游戏之8×8点阵应用」

源代码

然后,将以下代码上传到您的Arduino开发板:

#include "LedControl.h"

#include "Timer.h"

#define POTPIN A5 // Potentiometer

#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; // Wind rose, 0 is north

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);

// initial position

xball = random(1, 7);

yball = 1;

direction = random(3, 6); // Go south

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: ");

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 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("->");

}

// Check hit: modify direction is left or right

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;

}

// Check orthogonal directions and borders ...

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;

}

// "Corner" case

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() {

// The MAX72XX is in power-saving mode on startup,

// we have to do a wakeup call

pinMode(POTPIN, INPUT);

lc.shutdown(0,false);

// Set the brightness to a medium values

lc.setIntensity(0, 8);

// and clear the display

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();

// Move pad

setPad();

#ifdef DEBUG

Serial.println(xpad);

#endif

// Update screen

drawGame();

if(checkLoose()) {

debug("LOOSE");

gameOver();

newGame();

}

delay(GAME_DELAY);

}

最后

您是否曾经在Arduino项目中使用过点矩阵?如果您喜欢这篇文章,可能您还会喜欢我的下一篇文章,敬请期待。谢谢阅读,

特别声明:所有资讯或言论仅代表发布者个人意见,乐多体育仅提供发布平台,信息内容请自行判断。

标签: 点阵 乒乓球 游戏

相关资讯