로그인회원등록 내글장바구니주문조회현재접속자
 상품 검색








 게시판 검색





 
 
회원등록 비번분실


온라인 입금계좌
ㆍ기업은행
ㆍ219-043192-01-028
ㆍ이건영

      거래은행 바로가기
 
 Sensor Applications
아듀이노 공개소스
작성자 leeky        
작성일 2008/08/24
Link#1 MIDIOutput (Down:310)
ㆍ추천: 0  ㆍ조회: 4991   
  아듀이노 MIDI 드럼
참조 : http://itp.nyu.edu/physcomp/Labs/MIDIOutput
재목 :
MIDI Output

센서의 연결
아날로그 센서는 아날로그 핀 0번으로 연결한다.
누르는 힘을 저항으로 변환하는 PSR 센서를 입력으로 사용한다.
작동 스위치는 디지털 핀 10번에, 누름 스위치를 연결한다.
 
MIDI 회로
아듀이노의 미디 출력 회로이다. 이 회로는 MIDI 규격과 완전히 일치하지 않는다,
그러나 모든 미디 장치에서의 작동을 확인 하였다.
이 회로는 물리적인 표현을 위한 아날로그와 디지털 센서를 포함하고 있다.
그러나 미디 데이터 전송에는 필요하지 않다.

 

MIDI 음악 연주 


------------------------------------------------------------------------------------------------------------------
모든 데이터는 2진이 기본이다.
한번 접속에서, 미디 전송은 몇개의 바이트를 송신한다. 바이트는 이진코드로 송신된다.
그러나 소스의 표현에서는 2진, 10진이나 16진의 포맷을 사용할 수도 있다.

모든 정수 혹은 바이트형의 상수 혹은 변수를 10진이나 16진을 사용하더라도.
즉 상수나 변수가 어떤 형식으로 표현되어 있더라도, 부동소숫점 외에는 저장상태는 모두 2진이다,
 
즉 프로그램이나 전송에서 사용하는 표현이나 정의하는 숫자의 진법이 틀리더라도,
프로그램과 데이터에서는, 모든 값들을 원래 2진으로 저장하고 있다.
 
마지막 단계인 표시절차에서, 예를 들면 직렬통신포트나 LCD에서 표시하려 할때만,
프로그램이 원하는 대로 1~4 바이트의 변수에 저장된 값을, 2진,  10진, 16진으로 변환되어 표시하는 것이다,
(실지로는 1 ~4 바이트 2진값을, 1개 혹은 n개의 ASCII 값으로 변환하여, 우리가 쉽게 읽을 수 있게 출력한다) 

미디신호의 절약방법
미디에서는 항상 2진 1 바이트씩, 직렬로 Serial.print()에서 송신된다.

원래의 신호
0x90 0x3C 0X7F 0x90 0x40 0x70 0x90 0x43 0x7A 0x91 ,,,,
NOTE_ON C Velo NOTE_ON E Velo NOTE_ON G Velo NOTE_ON ,,,,

절약한 신호
0x90 0x3C 0X7F 0x40 0x70 0x43 0x7A 0x91 ,,,
NOTE_ON C Velo E Velo G Velo NOTE_ON ,,,

같은 채널의 신호에서는 채널번호를 생략하는, 미디신호의 절약방법은,
미디 처리장치의 저장 메모리 크기를 키운 효과와 처리속도를 높혀준다.
미디 음원에서도, 들어오는 신호의 양이 적으므로, 무리가 없으므로 작동이 더 잘된다. 

------------------------------------------------------------------------------------------------------------------
아듀이노 MIDI 소스 예(연습)
// Variables:
char note = 0;            // MIDI의 발음 값
void setup()
{
  Serial.begin(31250);   // 미디의 표준속도를 설정
}

void loop()                 // 주 함수 

  for (note = 30; note < 90; note ++)   // 음원의 연주 F#-0 (30) ~ F#-5 (90): 
  {
     noteOn(0x90, note, 0x45);          // 음원 채널 (0x90), 음높이 값(note), 중간 음길이(velocity =0x45)
    delay(100);
    noteOn(0x90, note, 0x00);           // 음원 채널 (0x90), 음높이 값(note), 음길이 끝 (velocity =0x00) 
    delay(100);
  }
}

void noteOn(char cmd, char data1, char data2) // 명령은 127 이상이다, 127보다 작으면 데이터이다.
{
  Serial.print(cmd, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2, BYTE);
}

------------------------------------------------------------------------------------------------------------------

개인적인 음원의 연주를 허용
위에서 보여준 예는 단순히 음원을 발성한다. 교감(감정을 전달 =interactive)이 없다.
아래의 예제는 아날로그 입력을 음정(pitch)의 설정으로 사용한다.
그리고 디지털 입력(누름 스위치)은 음원(note)의 시작과 끝이다.  

#define switchPin 10      // 누름 스위치는 D10 이다.
#define middleC 60        // 기준 C는 MIDI 음원값 60 이다. 이곳에서 가장 낮은 값이다. 
#define LEDpin 13          // 작동 표시 LED:

char note = 0;               // 발성될 MIDI 음원(note) 값
int AnalogValue = 0;      // 아날로그 입력의 값
int lastNotePlayed = 0;  // 스위치를 누르면 음원을 켠다
int lastSwitchState = 0;  // 먼저 눌러진 스위치 상태
int currentSwitchState = 0;     // 현재 눌러진 스위치 상태

void setup()                         // 주함수 시작

  pinMode(switchPin, INPUT);   // 스위치 입력 핀의 설정
  pinMode(LEDpin, OUTPUT); 
  Serial.begin(31250);               // MIDI의 전송속도를 설정
  blink(3);                               // LED를 3번 켠다 (시작을 알림)
}

void loop()                                  // 주 함수의 시작    
{
  AnalogValue = analogRead(0);     // 가변저항은 0 부터 1023 까지 주어진다. 
  note = AnalogValue/8;                 // 범위를 0 부터 127 까지로 변환한다. 
  currentSwitchState = digitalRead(switchPin);     // 스위치가 눌렸는지 확인
  
  if (currentSwitchState == 1)            // 스위치가 켜지면 미디 신호를 송신, 아니면 else 이하를 실행
  { 
    if (lastSwitchState == 0)              // 스위치가 직전에 눌리지 않았다면, 음원을 켠다 
   {
     // 음원의 발성값은 아날로그 입력값을 기준 음계에 가산한다.
     noteOn(0x90, note, 0x40);         // note = note + 60;   음원의 발성을 시작 
     lastNotePlayed = note;             // 발성된 음원을 저장한다. 이 정보로 음원을 끈다. 
     digitalWrite(LEDpin, HIGH);       // 발성 표시기를 켠다
   }
 }

 else                                           // 만일 스위치 입력이 없으면, 이곳을 실행 
 {     
   if (lastSwitchState == 1)               // 그러나, 마지막에 스위치가 눌렸다면, 남은 시간을 처리
   {
     noteOn(0x90, lastNotePlayed, 0x00);   // 마지막 음원을 정지 시킴
     digitalWrite(LEDpin, LOW);
   }
 }
 lastSwitchState = currentSwitchState;     // 현재 스위치 상태를 저장한다
}                                                         // 주함수의 끝 (주함수의 시작 부분에서 다시 반복된다) 

void noteOn(char cmd, char data1, char data2)   // 통신으로 미디 음원을 제어한다
{
  Serial.print(cmd, BYTE);                     // 첫 바이트는 음원 번호 (0x90 = 채널 1) 
  Serial.print(data1, BYTE);                    // 두번째 바이트는 음정 (note = 60 + x)
  Serial.print(data2, BYTE);                    // 3번째 바이트는 음길이 (velocity =0 ~ 255)
}

void blink(int howManyTimes)                   // LED를 필요한 만큼 깜빡인다  
{
   int i;
   for (i=0; i< howManyTimes; i++)             // 함수 입력으로 3 이 들어오면 3번 깜빡인다.
  {
    digitalWrite(LEDpin, HIGH);                    // LED를 1 번 켜고
    delay(100);
    digitalWrite(LEDpin, LOW);                    // LED를 1 번 끈다
    delay(100);
  }
}

------------------------------------------------------------------------------------------------------------------
참조 : http://todbot.com/arduino/sketches/midi_drum_kit/
제목 : MIDI Drum Kit
저자 : Tod E. Kurt http://todbot.com/
 
미디 드럼은 2개의 압전센서와 3개의 누름 스위치를 사용하여,
아듀이노 기판에서 아날로그 입력으로 압전센서의 출력을 검출하여,
압전센서를 두드린 힘의 세기 만큼, 비례하는 소리의 크기를 정하고,
아듀이노 직렬통신포트에서 출력하는, 제어신호로 음원에서 출력하는 소리의 크기를 제어한다.
 
압전센서의 출력
  

드럼판의 제작
압전센서를 양면 테이프로 드럼판에 접착한다.
 
  

아듀이노 미디 드럼의 회로
 
미디 잭 2번 --- GND (접지)
미디 잭 4번 --- 220옴 저항 --- +5V (전원)
미디 잭 5번 --- 아듀이노 D1번 (TXD =송신신호) 
 

미디 잭(DIN 5핀)의 연결 방법
 
오른쪽부터 1, 4, 2, 5, 3 번 핀이다. (번호는 플럭이 꼽히는 측에서 좌측이 1번이다)

 
소스
#define drumchan 1  // 미디 채널
#define note_bassdrum 35  // 미디 드럼 노트
#define note_snaredrum    38
#define note_hihatclosed  42
#define note_hihatopen    44
#define note_crash        49
 
#define switchAPin 7  // 아듀이노 포트의 연결 스위치 3개
#define switchBPin 6
#define switchCPin 5

#define piezoAPin  0   // 드럼입력으로 사용하는 압전센서 #1
#define piezoBPin  1   // 드럼입력으로 사용하는 압전센서 #2
#define ledPin     13    // 작동 표시 LED (이미 기판에 있다)
#define PIEZOTHRESHOLD 100  // 압전검출기의 검출한계 (작은 진동은 받지 않는다)
 
int switchAState = LOW;  // 각 입력상태를 저장하는 변수들
int switchBState = LOW;
int switchCState = LOW;

int currentSwitchState = LOW;
int val,t;
 
void setup()                               // 기판의 초기화
{
  pinMode(switchAPin, INPUT);
  pinMode(switchBPin, INPUT);
  pinMode(switchCPin, INPUT);

  digitalWrite(switchAPin, HIGH);  // 입력핀에 1을 출력하면 풀업이 된다
  digitalWrite(switchBPin, HIGH);  // Pullup은 접지로 연결되는 스위치를 연결할 때 저항을 대신한다. 
  digitalWrite(switchCPin, HIGH);  // Pullup을 사용하면, LOW 상태가 입력이 들어온 것이다. 
 
  pinMode(ledPin, OUTPUT);
  Serial.begin(31250);                   // MIDI의 속도를 맞춘다 (31250 bps)
}
 
void loop()                                  // 주 함수 
{
  currentSwitchState = digitalRead(switchAPin);    // sw A를 읽어서 현재상태에 저장
  if( currentSwitchState == LOW && switchAState == HIGH ) // 눌렷나?
    noteOn(drumchan,  note_bassdrum, 100);
  if( currentSwitchState == HIGH && switchAState == LOW ) // 아닌가?
    noteOff(drumchan, note_bassdrum, 0);

  switchAState = currentSwitchState;                   // 상태 A에 스위치값를 저장
  currentSwitchState = digitalRead(switchBPin);    // sw B를 읽어서 변수에 저장
  if( currentSwitchState == LOW && switchBState == HIGH ) // 눌렷나?
    noteOn(drumchan,  note_snaredrum, 100);
  if( currentSwitchState == HIGH && switchBState == LOW ) // 아닌가?
    noteOff(drumchan, note_snaredrum, 0);

  switchBState = currentSwitchState;                  // 상태 B에 스위치값를 저장
  currentSwitchState = digitalRead(switchCPin);   // sw C를 읽어서 현재상태에 저장
  if( currentSwitchState == LOW && switchCState == HIGH ) // 눌렷나?
    noteOn(drumchan,  note_hihatclosed, 100);
  if( currentSwitchState == HIGH && switchCState == LOW ) // 아닌가?
    noteOff(drumchan, note_hihatclosed, 0);

  switchCState = currentSwitchState;                  // 상태 C에 스위치값를 저장
  val = analogRead(piezoAPin);                         // 압전센서 #1을 아날로그로 읽어서 val에 저장
  if( val >= PIEZOTHRESHOLD )                        // 압전센서에서 입력이 있는지?
  {
    t=0;
    while(analogRead(piezoAPin) >= PIEZOTHRESHOLD/2)   // 압전#1이 검출레벨의 1/2 이상이면 t를 +1
    {
       t++;                                                         // 압전센서에 들어온 진동시간을 측정
     }
     noteOn(1,note_hihatopen, t*2);                     // 드럼 음원의 음높이를 결정, 소리의 크기는 x2t
     delay(t);                                                    // t 만큼 기다린다
     noteOff(1,note_hihatopen,0);                        // 드럼 음원을 끈다  
    }
 
  val = analogRead(piezoBPin);                          // 압전센서 #2를 아날로그로 읽어서 val에 저장
  if( val >= PIEZOTHRESHOLD )                          // 압전#2가 검출레벨의 1/2 이상이면 t를 +1
  {
     t=0;
     while(analogRead(piezoBPin) >= PIEZOTHRESHOLD/2)
    {
       t++;
     }
     noteOn(1,note_crash, t*2);                    // 드럼 음원의 음높이를 결정, 소리의 크기는 x2t
     delay(t);                                             // t 만큼 기다린다
     noteOff(1,note_crash,0);                       // 드럼 음원을 끈다  
  }
}
 
// MIDI 음원에 발음정보를 송신하는 보조 함수, 피아노의 건반과 같다
void noteOn(byte channel, byte note, byte velocity)   // 함수를 부를 때느 음원, 음높이, 소리크기를 입력해야 한다
{
  midiMsg( (0x80 | (channel<<4)), note, velocity);    // 미디장치에 명령을 송신하는 함수를 실행
}
 
//  미디 음원의 소리를 끈다, 피아노의 간반과 같다
void noteOff(byte channel, byte note, byte velocity)
{
  midiMsg( (0x80 | (channel<<4)), note, velocity);    // 미디장치에 명령을 송신하는 함수를 실행
}
 
// 미디 음원의 명령을 전송하는 실제의 함수
void midiMsg(byte cmd, byte data1, byte data2)
{
  digitalWrite(ledPin,HIGH);                                       // LED를 켠다
  Serial.print(cmd, BYTE);                                       // 미디 cmd 송신 (음원의 번호)
  Serial.print(data1, BYTE);                                      // 미디 cmd 송신 (음높이)
  Serial.print(data2, BYTE);                                      // 미디 cmd 송신 (소리크기)
  digitalWrite(ledPin,LOW);                                       // LED를 끈다
}

이 소스는 압전센서 2개와 스위치 3개로 음원과 음높이를 변경하면,
아듀이노 직렬통신 출력에 연결된, 미디 케이블을 통해서 별도의 미디음원에 연결하고,
미디음원에서 음원번호로 설정된 종류의 드럼소리를 낸다.

이 프로그램은 무료 소프트웨어로, 신체와 재산 상의 어떤 위험과 손해를 보상하지 않습니다.
이 프로그램은 GNU 무료 소프트웨어 배포규정을 따릅니다.
Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA

 AVRTOOLS™
   
윗글 아듀이노 POV #1
아래글 아듀이노 SD/MMC 카드
    N         제목    글쓴이 작성일 조회 추천
61 비접점식 QTouch 방식 근접검출 스위치 leeky 2016/01/21 (목) 1074 0
60 Arduino 고속 오실로스코프 #3 avrtools™ 2012/03/29 (목) 18175 0
59 아날로그 8ch 데이터 로거 avrtools™ 2012/03/29 (목) 3057 0
58 Arduino DMX512 송신기 제작 avrtools™ 2012/03/15 (목) 3208 0
57 nRF24L01 무선모듈의 사용방법 avrtools™ 2012/03/07 (수) 6498 0
56 초음파 거리 측정기의 제작 avrtools™ 2011/09/18 (일) 5277 0
55 3축 가속도 센서 ADXL335 avrtools™ 2011/09/09 (금) 3802 0
54 Arduino Uno USBserial 펌웨어의 변경 avrtools™ 2011/08/27 (토) 3327 0
53 Arduino MIDI의 소개 avrtools™ 2011/08/19 (금) 3704 0
52 Arduino 고속 Oscillo Scope #2 avrtools™ 2011/08/12 (금) 3345 0
51 Arduino Uno 및 USB2serial Uno의 소개 [2] avrtools™ 2011/07/30 (토) 3625 0
50 Arduino IDE에서 AVRISP-mkII 사용방법 avrtools™ 2010/10/22 (금) 8294 0
49 아듀이노 초음파 거리측정 및 응용 avrtools™ 2010/03/14 (일) 4367 0
48 M328-USB의 비밀 온도센서 avrtools™ 2010/01/02 (토) 3774 0
47 M168-mini로 만드는 USBasp avrtools™ 2009/10/10 (토) 5717 0
46 OBDuino ISO9141 소스의 설명 avrtools™ 2009/10/08 (목) 4444 0
45 아듀이노 0017 업그레이드 avrtools™ 2009/08/18 (화) 3953 0
44 Arduino 0015 업그레이드 avrtools™ 2009/06/01 (월) 3654 0
43 CC2500 Zigbee RF Modem #1 [4] avrtools™ 2008/11/20 (목) 6985 0
42 아듀이노 소프트웨어 Ver 0012 avrtools™ 2008/09/23 (화) 4145 0
41 Arduino 소프트웨어 설치방법 avrtools™ 2008/08/31 (일) 5837 0
40 아듀이노 PC 카메라 제작 avrtools™ 2008/10/28 (화) 7483 0
39 아듀이노 AVR-ISP V2의 제작 [6] avrtools™ 2008/10/22 (수) 8639 0
38 아듀이노 J1850-PWM 스캐너 avrtools™ 2008/10/15 (수) 4684 0
37 아듀이노 MPGduino의 제작 avrtools™ 2008/10/11 (토) 5179 0
36 아듀이노 OBD-II PID 처리함수 avrtools™ 2008/10/12 (일) 5833 0
35 아듀이노 OBD-II PID 송수신 함수 avrtools™ 2008/10/09 (목) 10058 0
34 아듀이노 ODB-II 스캐너 제작 [9] avrtools™ 2008/10/04 (토) 17993 0
33 아듀이노 AC전원 THD 측정 [2] avrtools™ 2008/09/30 (화) 7033 0
32 아듀이노 소프트방식 16Bit ADC avrtools™ 2008/09/23 (화) 5748 0
31 아듀이노 초음파 모듈의 제작. avrtools™ 2008/09/22 (월) 5118 0
30 아듀이노 Wii 프로세싱 avrtools™ 2008/09/20 (토) 4320 0
29 아듀이노 초음파 거리측정 avrtools™ 2008/09/20 (토) 6311 0
28 아듀이노 8x5 초소형 전광판 avrtools™ 2008/09/11 (목) 4881 0
27 아듀이노 4선식 터치패널 avrtools™ 2008/09/10 (수) 4817 0
26 아듀이노 2색 8x8 LED avrtools™ 2008/09/10 (수) 5142 0
25 아듀이노 24x6 LED 전광판 avrtools™ 2008/09/10 (수) 5688 0
24 아듀이노 8x8 LED 프로세싱 avrtools™ 2008/09/10 (수) 4266 0
23 아듀이노 32x16 RGB 전광판 avrtools™ 2008/09/06 (토) 13895 0
22 아듀이노 맥박검출기 avrtools™ 2008/09/03 (수) 9851 0
21 아듀이노 적외선 거리센서 avrtools™ 2008/09/01 (월) 6147 0
20 아듀이노 DMX 수신장치 [7] avrtools™ 2008/08/31 (일) 7098 0
19 아듀이노 AVR-ISP 만들기 avrtools™ 2008/08/30 (토) 4345 0
18 아듀이노 POV #3 avrtools™ 2008/08/30 (토) 3636 0
17 아듀이노 POV #2 avrtools™ 2008/08/30 (토) 3409 0
16 AVR 병렬포트 굽기장치 avrtools™ 2008/08/30 (토) 5489 0
15 아듀이노 DMX 송신기 avrtools™ 2008/08/28 (목) 5331 0
14 아듀이노 부트로더의 개조 [1] avrtools™ 2008/08/28 (목) 5991 0
13 아듀이노 병렬포트 굽기장치 avrtools™ 2008/08/26 (화) 4396 0
12 아듀이노 POV #1 avrtools™ 2008/08/26 (화) 3658 0
11 아듀이노 MIDI 드럼 leeky 2008/08/24 (일) 4991 0
10 아듀이노 SD/MMC 카드 avrtools™ 2008/08/24 (일) 9969 0
9 아듀이노 MIDI 플륫 avrtools™ 2008/08/24 (일) 3843 0
8 아듀이노 RGB LED avrtools™ 2008/08/23 (토) 5258 0
7 아듀이노 USB 오실로스코프 [2] leeky 2008/08/21 (목) 6823 0
6 가속도계 ADXL202 응용소스 avrtools™ 2008/08/20 (수) 5136 0
5 아듀이노 가속도센서 avrtools™ 2008/08/18 (월) 5171 0
4 아듀이노 RC서보 제어 avrtools™ 2008/08/17 (일) 5468 0
3 아듀이노 910-ISP 만들기 avrtools™ 2008/08/16 (토) 5035 0
2 아듀이노 온도센서, XBee 송수신 avrtools™ 2008/08/15 (금) 7920 0
1 아듀이노 기본명령 avrtools™ 2008/08/07 (목) 7059 0
1

바구니 : 0
 보관함 : 0
오늘뷰 : 0
HOME   |   회사소개   |   제휴안내   |   회사위치   |   서비스이용 약관   |   개인정보 보호정책   |   사이트맵
17015 경기도 용인시 기흥구 동백중앙로16번길 16-25, 508호. 전화 : 031-282-3310
사업자 등록번호 : 697-47-00075 / 대표 : 이건영 / 업태 : 제조업 / 종목 : LED조명, LED전원, 제어장치.
개인정보 관리책임자 : 홈페이지 관리자 . Copyright ⓒ2016 아크레즈 (ACLEDS INC.)
HOME TOP PREVNEXT 0 0 0