Midterm Presentation
★ 발표할 때 슬라이드 만들어놨는데 귀찮다는 이유로 안 썼기 때문인지 별 말 못했고 왠지 아무 고생도 안하고 만든 것 같은 느낌을 줘 버려서 뒤늦게 정성들여 쓰는 본격 신세한탄 포스팅 ★
그러나 이걸 구구절절 말하는 게 플러스가 될지 마이너스가 될지는 모르겠음
2013-10139_조민아_중간프로젝트_발표.pptx < 원래 발표에 쓰려던 피피팈ㅋㅋㅋㅋ
작품명
대화가 필요한 피아노
제작 의도
흔히 볼 수 있는 아두이노 피아노에 '커뮤니케이션'의 형식을 결합, 피아노와 사용자가 인터랙션을 할 수 있도록 하였다.
피아노를 눌러서 연주해보는 것만으로도 사용자는 즐거운 경험을 할 수 있지만, 그에 더하여
'피아노가 원하는 음을 들려주면 피아노의 기분이 좋아진다'는 전제 하에 피아노와 인터랙션을 할 수 있다면 더욱 흥미로울 것이다.
인터페이스를 최대한 직관적으로 만들기 위해 실제 피아노의 외관을 차용하였고, 컴퓨터와의 연결은 없앴다.
부품 명세 (Bill of Materials)
부품명 | 갯수 | 구매처 |
아두이노 우노 + 확장 보드 |
1 |
http://www.devicemart.co.kr/1329654 |
I2C LCD 캐릭터 모듈 |
1 |
http://www.devicemart.co.kr/1327456 |
MAX2179 LED Matrix |
1 |
http://www.devicemart.co.kr/1287132 |
830핀 브레드보드 |
1 |
http://www.devicemart.co.kr/1322408 |
점퍼 케이블 및 전선, 저항 |
다수 |
- |
푸쉬버튼 |
8 |
http://www.devicemart.co.kr/1324930 |
Piezo Buzzer |
1 |
http://www.devicemart.co.kr/25038 |
부품에 얽힌 비하인드 스토리
센서를 안 쓴 사람이 클래스에서 진지하게 나뿐이라는 사실에 경악을 금치 못했다.
딱히 "센서 안써!!!!!!!!!!! 나의 콘셉트는 기술력의 최소화이다!!!!!" 라는 것을 모토로 작업하지는 않았지만, 어째 기술력에 관한 한 거의 0인 느낌
솔직히 저의 기술력은 0이 맞습니다 저 푸쉬버튼 사는 데에도 '택트 스위치'라는 말을 몰라서 뭔 키트 하나를 통째로 다 삼ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
그리고 830 핀짜리 긴 브레드보드의 양쪽이 연결되어 있지 않다는 쇼킹한 사실 때문에 하루 정도는 꼬박 날렸다
대체 뭐가 문제인지 전선 하나하나 다 점검하다가 결국 저 브레드보드 양쪽이 분리된 2개의 브레드보드임을 깨닫고 정말 바보된 기분이 들었습니다..
피에조는... 우리한테 있던 그 피에조 아니고 좀더 커다란 걸 '운에 맡겨보자'는 기분으로 아무렇게나 사봤는데 다행히 소리가 잘 났다.
아니 사실 원래는 뮤직실드(http://www.devicemart.co.kr/1112620)를 사려고 했는데요
미디 코덱 다 내장되어 있어서 막 드럼이랑 전자기타, 피아노 소리로 자유롭게 소리 낼 수 있는 좋은 부품이었는데 4만원이었던데다가
저걸 사용할 수 있다는 걸 4/24 밤쯤 깨달아서.... 해외배송이라 거의 일주일 넘게 걸린다고 하더라고요 그래서 안 샀다.
지금 보면 클래스에 막 몇십만원씩 돈 드신 분들도 계셔서 나는 되게 싸게 만들었다(?)고 생각하지만, 그래도 뮤직실드 사놓고 늦게 와서 못 쓰면 아깝잖아요.
LCD 때문에 6키짜리 피아노조차 못 만들 뻔 했는데 (디지털포트를 너무 많이 먹으니까.. 가변저항도 하나 넣어야 돼서 회로도 더러워지고)
다행히 I2C 모듈이 달린 LCD라는 유레카한 것을 구할 수 있어서!!! 살았습니다 아날로그 포트로 LCD 돌릴 수 있다니 거의 할렐루야였음
Schematic (Firtzing)
fritzing를 제가 잘 다룰 줄 모르나봅니다 없는 부품이 너무 많아서..
이렇게 손으로 추가해서 그려버림ㅋㅋㅋㅋㅋㅋㅋㅋ
이게 그 모듈 달린거 표현해야 되는데... 대체 어쩌지.... 초난감
Arduino Code
// LCD 제어를 위한 라이브러리
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// LED Matrix 제어를 위한 라이브러리
#include <LedControl.h>
#define ACTIVATED LOW
const int gamePin = 8;
const int DIN = 10;
const int CS = 11;
const int CLK = 12;
const int Piezo = 13;
int buttonPins[] = {2, 3, 4, 5, 6, 7};
int Notes[] = {1136, 1275, 1432, 1519, 1700, 1915};
int buttonState[] = {1, 1, 1, 1, 1, 1};
int test[] = {2, 3, 4, 6, 5, 7};
LedControl lc = LedControl(DIN, CLK, CS, 0);
LiquidCrystal_I2C lcd(0x27, 16, 2);
unsigned long delaytime = 500;
void setup() {
lcd.init();
lcd.backlight();
lcd.clear();
lc.shutdown(0, false);
lc.setIntensity(0, 8);
lc.clearDisplay(0);
for (int i = 0; i < 6; i++) {
pinMode(buttonPins[i], INPUT);
digitalWrite(buttonPins[i], HIGH);
}
pinMode(gamePin, INPUT);
}
// (성공 시 적용될) LED Matrix가 특정 모양으로 빛나는 함수
void writeArduinoOnMatrix() {
byte heart[8] = {B00000000, B00011000, B00111100, B01111110, B11111111, B11111111, B11111111, B01100110};
byte smile[8] = {0x7E, 0x81, 0xBD, 0xC3, 0xA5, 0xA5, 0x81, 0x7E};
byte clean[8] = {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000};
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, heart[i]);
}
delay(delaytime);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, clean[i]);
}
delay(delaytime);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, smile[i]);
}
delay(delaytime);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, clean[i]);
}
delay(delaytime * 2);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, heart[i]);
}
delay(delaytime);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, clean[i]);
}
delay(delaytime * 2);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, smile[i]);
}
delay(delaytime);
for (int i = 0; i < 9; i++) {
lc.setRow(0, i, clean[i]);
}
delay(delaytime);
}
// 피아노가 소리를 낼 수 있는 함수
void toneMelody() {
while (digitalRead(buttonPins[0]) == ACTIVATED) {
tone(Piezo, Notes[0]);
}
while (digitalRead(buttonPins[1]) == ACTIVATED) {
tone(Piezo, Notes[1]);
}
while (digitalRead(buttonPins[2]) == ACTIVATED) {
tone(Piezo, Notes[2]);
}
while (digitalRead(buttonPins[3]) == ACTIVATED) {
tone(Piezo, Notes[3]);
}
while (digitalRead(buttonPins[4]) == ACTIVATED) {
tone(Piezo, Notes[4]);
}
while (digitalRead(buttonPins[5]) == ACTIVATED) {
tone(Piezo, Notes[5]);
}
noTone(Piezo);
}
void loop() {
int gameon = 0;
// 피아노를 누르면 소리는 나되, gamepin(start button)이 눌릴 때까지 LCD에는 'PUSH StartButton'이라는 문구만 떠 있음
toneMelody();
lcd.clear();
lcd.print("PUSH StartButton");
delay(100);
int i;
int j = 0;
// Start button이 눌리면 LCD에 피아노가 원하는 음이 표시되고, 사용자의 입력을 받도록 함
if (digitalRead(gamePin) == LOW) {
lcd.clear();
lcd.print("1 2 3 5 4 6");
gameon = 1;
}
while (gameon == 1) {
int buttonchange = 1;
while (buttonchange == 1) {
for (i = 0; i < 6; i++) {
buttonState[i] = digitalRead(i + 2); // 버튼 2, 3, 4, 5, 6, 7의 상태를 읽은 다음
if (buttonState[i] == 0) { // 눌린 상태이면
if (i + 2 == test[j]) { // test array(피아노가 원하는 음)의 j 번째 성분과 일치하는지 살펴보고
j++; // 일치하면 다음 것을 점검한다
i = 6; // for 반복문을 강제로 탈출한다
}
toneMelody();
}
}
if (j == 6) {
lcd.clear();
lcd.print("THANKS");
writeArduinoOnMatrix();
buttonchange = 0;
}
}
gameon = 0;
}
}
회로와 코드에 얽힌 비하인드 스토리
굉장히 단순한 코드들의 조합이지만 제가 이 코딩을 하는 데에 장장 nn시간이 걸렸다는 사실을 누군가 인지해주셨으면 좋겠습니다
진짜... 정말... 저 모든 코드들을 짜는 데 굉장히 오래 걸렸고 저는 완성도가 높지 않다는 사실을 알아서 슬퍼요
작동 영상 및 설명
피아노의 기분이나 원하는 음계를 여러 가지로 표현하는 기능은 구현하지 못했다.
현재 존재하는 코드 자체가 '6개의 입력을 받고 해당입력을 한꺼번에 점검하여 test array와 일치하는지 확인'하는 알고리즘이 아니라
'들어온 입력이 test array의 i번째 성분과 맞는지 하나하나 점검하여 test array와 순서, 내용이 일치하는 입력이 들어오게 되면 피아노가 반응'하는 것이라....
시간이 허락한다면 꼭!! 개인적으로 코드를 수정해보고 싶다.
저 코드가 중간오류를 허락한다는 점에서 장점과 단점을 동시에 갖고 있는데,
사실 피아노가 '기분좋아진다'는 전제가 인터랙션에 깔려있는 만큼 중간오류를 허용하는 것이 그다지 좋은 방법이라는 생각이 들지 않는다.
하지만 테스트해봤을 때 다들 불빛은 진짜 귀엽다며 좋아해 주셔서 행복했음
참고 자료 목록
- I2C LCD 사용 : http://zelkun.tistory.com/55
- 아두이노 피아노 만들기 : https://youtu.be/CvZ-SGJ8fGo
- LED Matrix 제어하기 : https://youtu.be/TOuKnOG8atk
'인터랙티브 미디어 (2017)' 카테고리의 다른 글
170515 10주차 실습 기록 (0) | 2017.05.15 |
---|---|
170508 9주차 실습 기록 (0) | 2017.05.10 |
170424 8주차 실습 기록 (0) | 2017.04.24 |
170417 7주차 실습 기록 (0) | 2017.04.17 |
170410 6주차 실습 기록 (0) | 2017.04.10 |