이번에 만든 것은 별거 없다.

 

설명을 하자면 매우 간단한데... 엉뚱한 부분에서 고생을 좀 했다. 바로 소리 재생 부분에서...

 

간략히 설명을 하자면...

 

3개의 자기스위치와 2개의 피에조센서를 이용하여 5개지 음을 재상 하도록 한 것이다.

 

각각의 센서 또는 스위치가 작동하면 pc로 시그널을 보내고 피시에서 해당 시그널에 해당하는 mp3파일을 로딩&플레이 시키도록 한 것이다.

 

피시에서 작동하는 프로그램을 만들기 위해 좀 고생을 하긴 했다.

 

어디서 부터 시작을 해야할지 몰라서... -_-;;

 

찾은 해답은 prosessing이라는 언어에 있었다. (물론 다른 방법도 있을 것이다...)

 

프로세싱에 대한 정보는 http://www.processing.org/ <- 여기서 찾아보자. 물론 영문이다. ㅠㅠ

 

사용한 센서에 대해 설명을 간단히 하자면...

 

일단 자기 스위치. 이것은 자석을 근처에 가져가면 스위치가 on이 되고 멀어지면 off되는 간단한 스위치이다.

 

이를 이용해서 디지털 시그널을 만드는 것은 어렵지 않으므로 설명 생략

 (자기 스위치)

 

피에조 센서에 대해 알아보자.

 

이것은 일종의 축전기(capactor)이다. 정확한 내용은 잘 모르겠지만.

 

진동이나 압력을 가하면 축전 용량이 변하면서 축전된 전하를 방출하거나, 부족한 전하를 충전 시킨다.

 

이때 발생하는 전위차이를 이용하는 것이다. (설명이 틀렸을지도 모른다. 믿지말자. )

(피에조 센서)

 

 

위 그림은 피에조 센서를 사용한 회로도이다.

 

물론 이렇게 꾸미는 것이 정답은 아닐 것이다. (그래도 동작은 하더라... ㅋㅋ)

 

일단 회로가 준비되면 프로그래밍을 해야할터...

 

처음에는 3개의 스위치를 각각 인터럽트로 등록해서 사용할 생각이었는데...

 

내가 사용하는 밀라두에노브 버전의 아두이노는 인터럽트가 2개 밖에 지원이 안되더라... ;;

 

그래서 어쩔수 없이 수정...

 

아두이노 보드에 업로딩 할 것은 아두이노 스케치북에 코딩을 하면 될것이고

 

pc에서 사운드를 출력할 부분은 프로세싱 스케치북에다 코딩을 하면 된다. (앞서 소개한 사이트에서 다운 받을수 있다)

 

프로세싱은 처음 접하다 보니.. 많은 시행 착오를 격었다.

 

기본으로 제공되는 예제를 최대한 활용하여 내 목적에 맞게 수정하였다.

 

주석 다는건 귀찮아서 패스....

(물론 프러세싱 코드에 대한 주석은... 몰라서 못다는 경우도 많다.. ㅋㅋ)

 

아래는 아두이노에 업로드 되는 소스코드이다.

 


unsigned int lastTimeFor1st = 0;
unsigned int lastTimeFor2nd = 0;
unsigned int lastTimeFor3th = 0;
unsigned int lastValFor4th = 1024;
unsigned int lastValFor5th = 1024;
const int swFor1stPin = 2;
const int swFor2ndPin = 3;
const int swFor3thPin = 4;
int lastState = LOW;

void play1st(){
  unsigned int thisTime = millis();
  if (thisTime - lastTimeFor1st >= 100) {
    lastTimeFor1st = thisTime;
    Serial.println(1);
  }
}

void play2nd(){
  unsigned int thisTime = millis();
  if (thisTime - lastTimeFor2nd >= 100) {
    lastTimeFor2nd = thisTime;
    Serial.println(2);
  }
}

void setup() {
  // initialize the serial communication:
  Serial.begin(9600);
  attachInterrupt(0,play1st,RISING);
  attachInterrupt(1,play2nd,RISING);
  pinMode(swFor3thPin, INPUT);
}

void loop()
{
  check3th();
  check4th();
  check5th();
}

void check3th(){
  unsigned int thisTime = millis();
  int thisState = digitalRead(swFor3thPin);
  if ((lastState == LOW) && (thisState == HIGH) && (thisTime - lastTimeFor3th > 70)) {
    Serial.println(3);
    lastState = HIGH;
    lastTimeFor3th = thisTime;
  }
  if ((lastState == HIGH) && (thisState == LOW)) lastState = LOW;
  delay(5);
}

void check4th(){
  unsigned int thisVal = analogRead(0);
  if ((lastValFor4th < (thisVal* 0.7)) || ((lastValFor4th + 100) < thisVal))
     Serial.println(4);
  lastValFor4th = thisVal;
  delay(5);
}

void check5th(){
  unsigned int thisVal = analogRead(1);
  if ((lastValFor5th < (thisVal*0.7)) || ((lastValFor5th + 100) < thisVal))
     Serial.println(5);
  lastValFor5th = thisVal;
  delay(5);
}

 

 

 

 

다음은 프로세싱으로 피시에서 실행되는 프로그램의 소스코드이다.

 

import processing.serial.*;
import ddf.minim.*;

Minim minim;
AudioPlayer groove;
WaveformRenderer waveform = null;
Serial myPort;        // The serial port

void setup() {
  size(512, 200, P2D);
  println(Serial.list());
 myPort = new Serial(this, Serial.list()[0], 9600);
 myPort.bufferUntil('\n');
}

void serialEvent (Serial myPort) {
  if (waveform != null) {
  groove.close();
  minim.stop();
  }
  minim = new Minim(this);
  String inString = myPort.readStringUntil('\n');
  if (inString != null) {
    inString = trim(inString);
    float inByte = float(inString);
    char temp = '0';
    println('0');
    if (inByte == 1.00) temp = '1';
    if (inByte == 2.00) temp = '2';
    if (inByte == 3.00) temp = '3';
    if (inByte == 4.00) temp = '4';
    if (inByte == 5.00) temp = '5';
    switch (temp){
      case '1' :
      println('1');
      groove = minim.loadFile("1.mp3", 512);
      break;
      case '2' :
      println('2');
      groove = minim.loadFile("2.mp3", 512);
      break;
      case '3' :
      println('3');
      groove = minim.loadFile("3.mp3", 512);
      break;
      case '4' :
      println('4');
      groove = minim.loadFile("4.mp3", 512);
      break;
      case '5' :
      println('5');
      groove = minim.loadFile("5.mp3", 512);
      break;
    }
    groove.play();
    waveform = new WaveformRenderer();
    groove.addListener(waveform);
  }
}

void draw()
{
  background(0);
}

void stop()
{
  groove.close();
  minim.stop();
  super.stop();
}

 

 

다음은 웨이브 출력을 위해 만들어진 클레스 ( 이 역시 프로세싱 스케치북에다 넣자.)

이것은 프로세싱 홈페이지에 공개된 클레스이다.

 

class WaveformRenderer implements AudioListener
{
  private float[] left;
  private float[] right;
 
  WaveformRenderer()
  {
    left = null;
    right = null;
  }
 
  synchronized void samples(float[] samp)
  {
    left = samp;
  }
 
  synchronized void samples(float[] sampL, float[] sampR)
  {
    left = sampL;
    right = sampR;
  }
 
  synchronized void draw()
  {
    // we've got a stereo signal if right or left are not null
    if ( left != null && right != null )
    {
      noFill();
      stroke(255);
      beginShape();
      for ( int i = 0; i < left.length; i++ )
      {
        vertex(i, height/4 + left[i]*50);
      }
      endShape();
      beginShape();
      for ( int i = 0; i < right.length; i++ )
      {
        vertex(i, 3*(height/4) + right[i]*50);
      }
      endShape();
    }
    else if ( left != null )
    {
      noFill();
      stroke(255);
      beginShape();
      for ( int i = 0; i < left.length; i++ )
      {
        vertex(i, height/2 + left[i]*50);
      }
      endShape();
    }
  }
}

 

 

실행해보면 알겠지만... 자꾸만 뭔가 오류가 생긴다..

 

아마도 먼저 플레이된 사운드가 끝나기도 전에 다음 사운드 발생 명령이 내려져서인듯 싶은데...

 

어찌 수정 해야 할지 모르겠다.

 

하지만... 되기는 된다.. ㅋㅋ

 

이번에 만든 전자드럼은... 좀... 많이 부족한 감이 있긴 하지만...

 

프로세싱을 알게됐다는 것에 의의를 두기로 했다.

 

아 참... 이걸로 연주는 불가능하다...

 

동시에 두가지 소리가 같이 나도록 하는 법을 몰라... 대충 했더니... 연주는 불가능.. ㅠㅠ

 

소스코드와 회로도는 참고용으로 사용되길 바란다.

 

 

 

 

이 글은 상업적으로 이용될수 없으며. 퍼가시는 것은 자유로우나, 출처를 꼭 밝혀야 합니다.

 

수정 또는 변경으로 인해 만들어진 새로운 콘텐츠에 대한 사용권이 본 저작자에게도 있음을 허용할 경우, 이 게시물의 수정 또는 변경을 허락합니다.