대화하는 캐릭터 만들기

by 강종구 | 2017-07-07 15:37
대화 무드등 아두이노 적외선 캐릭보드 통신

서로 대화하는 캐릭터를 만들어 보려고 합니다.

이를 위해서는 Master 역할을 할 캐릭보드 1개와 Slave 역할을 할 캐릭보드 1개, 총 2개의 캐릭보드가 필요합니다. (캐릭보드 더블 박스 1개)


1. 캐릭터 모듈 만들기

1) Master에 적외선 발신부 연결하기

위와 같이 Master를 담당할 캐릭보드에 적외선 발신부를 연결해줍니다.



2) Slave에 적외선 수신부 연결하기

그리고 위와 같이 Slave를 담당하는 캐릭보드에는 적외선 수신부를 연결해줍니다.


3) Master와 Slave에 네오픽셀과 스피커 연결하기

이제 둘다 공통으로 네오픽셀과 스피커를 연결해줍니다.


자 이렇게 모든 모듈을 캐릭보드에 연결했다면 아두이노IDE를 켜고 코드작성에 들어갑니다.


2. 코드 작성

우선 적외선 통신을 하기 위해서는 Arduino-IRremote-master 라이브러리가 필요합니다.

IRremote 라이브러리 링크를 통해서 이 라이브러리를 다운 받아 저장합니다.


또한 네오픽셀과 mp3를 사용하기에 DFplayer_Mini_mp3 라이브러리와 Adafruit_NeoPixel-master 라이브러리 또한 미리 저장합니다. 이는 앞의 프로젝트에서 설명하였기에 따로 링크를 걸진 않겠습니다.


제가 구현할 Master와 Slave는 '따라쟁이'입니다. Master가 변하는 색을 Slave가 따라서 변하고, Master가 부르는 노래를 Slave가 따라 부르는 형식입니다. 이제 코드를 보시죠!


1) Master 만들기

먼저 Master를 포트에 꽂고 다음 코드를 업로드 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#define BLYNK_PRINT Serial
#define PIN 6
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
#include <IRremote.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
 
SoftwareSerial mp3Serial(1213);
 
Adafruit_NeoPixel strip = Adafruit_NeoPixel(5, PIN, NEO_GRB + NEO_KHZ800);
 
//IR Send
IRsend irsend;
 
//IR
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
boolean checkIR = false;
 
int red;
int green;
int blue;
 
void setup()
{
  Serial.begin(9600);
  strip.begin();
  mp3Serial.begin(9600);
  mp3_set_serial (mp3Serial);
  delay(1);
  mp3_set_volume (20);
  Serial.println("Setting...");
}
 
void loop()
{
   for (int i = 0; i < 5; i++) {
    strip.setPixelColor(i, strip.Color(0,255,0));
    strip.show();
  }
  
  if (Serial.available() > 0) {
    char str = Serial.read();
    if (str == '1') { //1을 입력 받으면
      for (int i = 0; i < 5; i++) {
        strip.setPixelColor(i, strip.Color(0,0,255));
        strip.show();
      }
      mp3Serial.listen();
      if (mp3Serial.isListening()) {
        Serial.println("Play1_Master");
        mp3_play(1);
        delay (15000);
        mp3_stop();
      }
      sendIR(0xa); //적외선 신호를 발사
      for (int i = 0; i < 5; i++) {
        strip.setPixelColor(i, strip.Color(0,255,0));
        strip.show();
      }
    } else if (str == '2') {
      for (int i = 0; i < 5; i++) {
        strip.setPixelColor(i, strip.Color(255,0,0));
        strip.show();
      }
      mp3Serial.listen();
      if (mp3Serial.isListening()) {
        Serial.println("Play2_Master");
        mp3_play(2);
        delay (15000);
        mp3_stop();
      }
      sendIR(0xb); //적외선 신호를 발사
      for (int i = 0; i < 5; i++) {
        strip.setPixelColor(i, strip.Color(0,255,0));
        strip.show();
      }
    }    
  } 
}
 
void sendIR(int hex) {
  for (int i = 0 ; i < 3; i++) {
    irsend.sendSony(hex, 20);
    delay(100);
  }
  delay(500);
  Serial.println("IR has been sent");
  Serial.println(hex, HEX);
  irrecv.enableIRIn();
}
 
 
cs


위의 코드의 경우, Master의 기본 색을 초록으로 지정하였고, 적외선 신호를 발신하기 전, 입력 명령어에 해당하는 색으로 캐릭터를 바꾸고 mp3를 15초간 출력한 뒤 적외선 신호를 발신하였습니다. 그리고 발신한 이후 원래의 초록색으로 색이 돌아오게 하였습니다.


2) Slave 만들기

새로운 토프에 Slave를 꽂은 뒤, Slave 코드를 업로드 해줍니다. 이때 'tool'에서 Master의 포트가 아닌 Slave의 새로운 포트로 변경해주시는 것 잊지마시길!



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#define PIN 6
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
#include <IRremote.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
 
SoftwareSerial mp3Serial(1213);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(5, PIN, NEO_GRB + NEO_KHZ800);
 
int red;
int green;
int blue;
 
//IR
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
boolean checkIR = false;
 
void setup() {
  Serial.begin(9600);
  mp3Serial.begin(9600);
  mp3_set_serial (mp3Serial);
  delay(1);
  mp3_set_volume (20);
  irrecv.enableIRIn();
  strip.begin();
  for (int i = 0; i < 5; i++) { // 흰색 불을 켠다
    strip.setPixelColor(i, strip.Color(255255255));
    strip.show();
  }
  Serial.println("Setting...");
}
 
void loop() {
  if (receiveIR(0xa== true) { //0xa 신호를 받으면
    for (int i = 0; i < 5; i++) { // 파란 불을 켠다
      strip.setPixelColor(i, strip.Color(00255));
      strip.show();
    }
      mp3Serial.listen();
      if (mp3Serial.isListening()) {
        Serial.println("Play1_Slave");
        mp3_play(1);
        delay (10000);
        mp3_stop();
      }
     for (int i = 0; i < 5; i++) { // 흰색 불을 켠다
      strip.setPixelColor(i, strip.Color(255255255));
      strip.show();
    }
  } else if (receiveIR(0xb== true) { //0xb 신호를 받으면
    for (int i = 0; i < 5; i++) {
        strip.setPixelColor(i, strip.Color(255,0,0));
        strip.show();
      }
      mp3Serial.listen();
      if (mp3Serial.isListening()) {
        Serial.println("Play2_Slave");
        mp3_play(2);
        delay (10000);
        mp3_stop();
      }
      for (int i = 0; i < 5; i++) { // 흰색 불을 켠다
        strip.setPixelColor(i, strip.Color(255255255));
        strip.show();
      }
  }
}
 
boolean receiveIR(int hex) {
  checkIR = false;
  if (irrecv.decode(&results)) {
    Serial.print("Result.value = ");
    Serial.println(results.value);
    Serial.print("HEX = ");
    Serial.println(HEX);
    if (results.value == hex) {
      Serial.println("Hello");
      checkIR = true;
    }
    irrecv.resume();
  }
  delay(30);
  return checkIR;
}
 
cs


 Slave는 흰색을 기본색으로 가지고 있다가, Master의 적외선 통신이 수신되면 Master와 똑같은 색으로 바뀝니다. 그리고 노래를 따라 부르기 시작하죠. 그 다음에 다시 원래의 흰색으로 돌아옵니다.


마스터의 시리얼 모니터를 킨 후, 이제 명령어를 입력해보죠.

저는 1, 2라는 명령어를 지정해주어 적외선을 발신되게 해놓았습니다.



이제 1, 2를 막 입력해보면


짜잔 이런 식으로 송신이 제대로 되었는지 모니터에 띄워줍니다.

만약 Slave의 모니터를 통해 수신이 제대로 되는지를 알아보려면, 컴퓨터 2대가 필요하겠군요!



위와 같이 이제 실행할 수 있습니다.

근데 막 생각처럼 잘 되지는 않는군요...

적외선이 약한건지.. Slave가 말을 잘 안듣네요.. 노래를 다시 부르지 않나, 끝까지 다 안부르지 않나...

Master의 파워가 약한... 슬픈 현실입니다.


사실 코드에서 캐릭터의 통신은 적외선 송수인이 끝입니다. 미리 명령어를 똑같이 집어넣고, 적외선 통신이 수신되면, 정해져있는 코드를 실행할 뿐이죠. 마치 우리가 사용하는 TV리모콘 등과 같이 적외선 통신을 사용하는 기기처럼 말이죠.

정확한 의미의 대화하는 캐릭터는 아니지만 적외선 통신에 대해 이해할 수 있는 과정이었습니다.


댓글 0