아두이노

아두이노 - 도트 매트릭스

haniru 2026. 3. 29. 21:57

하트 그리기

#include "NDelayFunc.h"

// R1~R4가 빠져있어서 추가했습니다.
enum { R5=1, R7, C2, C3, R8, C5, R6, R3, R1, C4, C6, R4, C1, R2, C7, C8 };

const unsigned int pins[1+16] = {
  -1, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 8, 9
};

const unsigned int R[1+8] = { -1, R1, R2, R3, R4, R5, R6, R7, R8 };
const unsigned int C[1+8] = { -1, C1, C2, C3, C4, C5, C6, C7, C8 }; // C5 중복 및 오타 수정

const unsigned int heart[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 1, 1, 0, 0, 1, 1, 0},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 0, 1, 1, 1, 1, 1, 1, 0},
  {-1, 0, 0, 1, 1, 1, 1, 0, 0},
  {-1, 0, 0, 0, 1, 1, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0}
}; // 세미콜론 추가

void dot_matrix_init() {
  for (int n=1; n<=8; n++) {
    pinMode(pins[R[n]], OUTPUT);
    pinMode(pins[C[n]], OUTPUT);
  }
  for (int n=1; n<=8; n++) {
    digitalWrite(pins[R[n]], HIGH);
    digitalWrite(pins[C[n]], HIGH);
  }
}

void dot_matrix_draw(const unsigned int image[1+8][1+8]) {
  static int n = 1;
  
  // 이전 라인 끄기
  digitalWrite(pins[R[n]], HIGH); 

  n++;
  if (n > 8) n = 1;

  // 열 제어 (Common Cathode/Anode에 따라 HIGH/LOW가 달라질 수 있음)
  for (int m=1; m<=8; m++) {
    if (image[n][m] == 1) {
      digitalWrite(pins[C[m]], LOW); // 선택된 열을 LOW로 (일반적 matrix 기준)
    } else {
      digitalWrite(pins[C[m]], HIGH);
    }
  }

  // 현재 행 켜기
  digitalWrite(pins[R[n]], HIGH); 
  // ※ 실제 매트릭스 구동 방식에 따라 HIGH/LOW 논리는 하드웨어에 맞춰 조정해야 합니다.
}

void draw() {
  dot_matrix_draw(heart);
}

NDelayFunc nDelayDraw(1, draw); // 언더바(_)를 공백으로 수정

void setup() {
  dot_matrix_init();
}

void loop() {
  nDelayDraw.run();
}

 

 

함수 만들기

DotMatrix.h

#ifndef NDelayFunc_h_
#define NDelayFunc_h_

enum { R5=1, R7, C2, C3, R8, C5, R6, R3, R1, C4, C6, R4, C1, R2, C7, C8 };

class _DotMatrix {
    static const unsigned int pins[1+16];
    static const unsigned int R[1+8];
    static const unsigned int C[1+8];

    public:
        static void init();
        static void draw(const unsigned int image[1+8][1+8]);
};

extern _DotMatrix DotMatrix;

#endif

 

DotMatrix.cpp

#include "Arduino.h"
#include "DotMatrix.h"

const unsigned int _DotMatrix::pins[1+16] = {
    -1, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 8, 9
};

const unsigned int _DotMatrix::R[1+8] = { -1, R1, R2, R3, R4, R5, R6, R7, R8 };
const unsigned int _DotMatrix::C[1+8] = { -1, C1, C2, C3, C4, C5, C6, C7, C8 };

void _DotMatrix::init() {
    for (int n=1; n<=8; n++) {
        pinMode(pins[R[n]], OUTPUT);
        pinMode(pins[C[n]], OUTPUT);
    }

    for (int n=1; n<=8; n++) {
        digitalWrite(pins[R[n]], HIGH);
        digitalWrite(pins[C[n]], HIGH);
    }
}

void _DotMatrix::draw(const unsigned int image[1+8][1+8]) {
    static int n = 1;
    n++;
    if (n>8) n = 1;

    if (n>1) digitalWrite(pins[R[n-1]], HIGH);
    if (n==1) digitalWrite(pins[R[8]], HIGH);

    for (int m=1; m<=8; m++) {
        if (image[n][m] == 1) {
            digitalWrite(pins[C[m]], HIGH);
        } else {
            digitalWrite(pins[C[m]], LOW);
        }
    }

    for (int m=1; m<=8; m++) {
        if (image[n][m] == 1) {
            digitalWrite(pins[R[n]], LOW);
            break;
        }
    }
}

_DotMatrix DotMatrix;

 

 

함수 활용해 하트 그리기

#include "NDelayFunc.h"
#include "DotMatrix.h"

const unsigned int heart[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 1, 1, 0, 0, 1, 1, 0},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 0, 1, 1, 1, 1, 1, 1, 0},
  {-1, 0, 0, 1, 1, 1, 1, 0, 0},
  {-1, 0, 0, 0, 1, 1, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0}
}; // 세미콜론 추가

void draw() {
  DotMatrix.draw(heart);
}

NDelayFunc nDelayDraw(1, draw);

void setup() {
  DotMatrix.init();
}

void loop() {
  nDelayDraw.run();
}

 

큰 하트와 작은 하트 교대로 그리기

#include "NDelayFunc.h"
#include "DotMatrix.h"

const unsigned int heart[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 1, 1, 0, 0, 1, 1, 0},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 0, 1, 1, 1, 1, 1, 1, 0},
  {-1, 0, 0, 1, 1, 1, 1, 0, 0},
  {-1, 0, 0, 0, 1, 1, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0}
}; // 세미콜론 추가

const unsigned int small_heart[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 1, 0, 0, 1, 0, 0},
  {-1, 0, 1, 1, 1, 1, 1, 0, 0},
  {-1, 0, 0, 1, 1, 1, 1, 0, 0},
  {-1, 0, 0, 0, 1, 1, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0}
}; // 세미콜론 추가

int heart_state = 0;
void choose() {
  heart_state++;
  if (heart_state > 1) heart_state = 0;
}

NDelayFunc nDelayChoose(500, choose);
void draw() {
  if (heart_state == 0) DotMatrix.draw(heart);
  else if (heart_state == 1) DotMatrix.draw(heart_small);
}

NDelayFunc nDelayDraw(1, draw);

void setup() {
  DotMatrix.init();
}

void loop() {
  nDelayChoose.run();
  nDelayDraw.run();
}

 

벽돌깨기

#include "NDelayFunc.h"
#include "DotMatrix.h"

unsigned int game_display[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 1, 1, 1, 1, 1, 1, 1, 1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 1, 1, 1, 0, 0, 0},
};

unsigned int game_lose[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 1, 1, 0, 0, 1, 1, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 1, 1, 1, 1, 0, 0},
  {-1, 0, 1, 0, 0, 0, 0, 1, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
};


unsigned int game_win[1+8][1+8] = {
  {-1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 1, 0, 0, 1, 0, 0},
  {-1, 0, 0, 1, 0, 0, 1, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 1, 0, 0, 0, 0, 1, 0},
  {-1, 0, 0, 1, 1, 1, 1, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
  {-1, 0, 0, 0, 0, 0, 0, 0, 0},
};

enum {PLAY=0, LOSE, WIN};
int game_state = PLAY;

int ball_x = 4;
int ball_x_dir = 1;
int ball_y = 7;
int ball_y_dir = 1;

int how_many_bricks = 24;

void ball_move() {

  if (game_state != PLAY) return;

  game_display[ball_y][ball_x] = 0;
  ball_x += ball_x_dir;
  if (ball_x >= 8) {
    ball_x = 8;
    ball_x_dir = ball_x_dir;
  }

  if (ball_x <= 1) {
    ball_x = 1;
    ball_x_dir = -ball_x_dir;
  }

  ball_y += ball_y_dir;
  if(ball_y>=8) {
    if (game_display[ball_y][ball_x] == 1) {
      ball_y-=2*ball_y_dir;
      ball_y_dir=-ball_y_dir;
    } else {
      game_state = LOSE;
      return;
    }
  }

  if (ball_y <= 1) {
    ball_y = 1;
    ball_y_dir = -ball_y_dir;
  }

  if (game_display[ball_y+ball_y_dir][ball_x]==1) {
    if (ball_y != 7) {
      game_display[ball_y+ball_y_dir][ball_x] = 0;
      how_many_bricks--;
      if (how_many_bricks == 0) game_state = WIN;
    }
    ball_y_dir = -ball_y_dir;
  } else if (game_display[ball_y+ball_y_dir][ball_x+ball_x_dir] == 1) {
    if (ball_y != 7) {
      game_display[ball_y+ball_y_dir][ball_x+ball_x_dir] = 0;
      how_many_bricks--;
      if(how_many_bricks == 0) game_state = WIN;
    }
    ball_y_dir=-ball_y_dir;
    ball_x_dir=-ball_x_dir;
  }

  game_display[ball_y][ball_x] = 1;
}

NDelayFunc nDelayGame(500, ball_move);

void draw() {
  if(game_state == PLAY) DotMatrix.draw(game_display);
  if(game_state == LOSE) DotMatrix.draw(game_lose);
  if(game_state == WIN) DotMatrix.draw(game_win);
}

NDelayFunc nDelayDraw(1, draw);

int bar_x = 4;
const int bar_y = 8;

void bar_move() {
  if (game_state != PLAY) return;

  int analogValue = analogRead(A5);

  static int prevAnalogValue = 0;

  int new_bar_x = bar_x;

  if (analogValue > prevAnalogValue + 1024/8) {
    prevAnalogValue = analogValue;
    new_bar_x++;
    if (new_bar_x >= 7) new_bar_x = 7;
    Serial.println(new_bar_x);
  } else if (analogValue < prevAnalogValue-1024/8) {
    prevAnalogValue = analogValue;
    new_bar_x--;
    if(new_bar_x<=2) new_bar_x = 2;
    Serial.println(new_bar_x);
  }

  if (new_bar_x != bar_x) {
    game_display[bar_y][bar_x] = 0;
    game_display[bar_y][bar_x-1] = 0;
    game_display[bar_y][bar_x+1] = 0;

    bar_x = new_bar_x;

    game_display[bar_y][bar_x] = 1;
    game_display[bar_y][bar_x-1] = 1;
    game_display[bar_y][bar_x+1] = 1;
  }
}

void setup() {
  DotMatrix.init();
  Serial.begin(115200);
}

void loop() {
  bar_move();
  nDelayGame.run();
  nDelayDraw.run();
}

'아두이노' 카테고리의 다른 글

온습도 센서(D11) openCR 에러  (0) 2026.04.09
아두이노 millis  (0) 2026.03.29
아두이노 - 7세그먼트  (0) 2026.03.26
아두이노 - 서보모터, 초음파  (0) 2026.03.23
아두이노 - Timer (빛, 부저)  (0) 2026.03.23