新楽器「GHI2014」に向けて (技術資料/備忘録)
長嶋 洋一
- 概要
このページは、2013年から2014年にかけて新しく制作した(している)新楽器「GHI2014」に関する技術情報を、講義の中の教材として開発中から公開するとともに、自分で改良していくための備忘録として残すためのものです。内容は適宜、修正・追加されていく予定です。
2007年に提唱した「GHI」については、先行して制作した新楽器"Cyber Kendang"に関する以下の情報を参照して下さい。海外で説明するのに難儀するのですが(^_^;)、これは今後も続ける予定です。- GHIとは (楽器が光ってもいいじゃないか)
Cyber Kendang
ニューヨーク大学での演奏風景 ★
- 新楽器「GHI2014」に向けた構想(ニーズ)
- 「GHIシリーズ」の続編を作りたい
- 海外公演に持参するために、分解してコンパクト化し、現地で簡単に組み立てたい
- LEDの増量("Cyber Kendang"の304個よりも多くしたい)
- 教材としてメイキングを学生に紹介したい
- セミ・スタンドアロン動作とともに、光り方をMaxから制御したい
- 味気ない3Dプリンタの時代、20世紀の日本のものづくりを支えた「手作り」「試行錯誤」「現物合わせ」を再確認したい
- システム設計(シーズ)
- 2つの正八面体スケルトンが左右に並ぶ造形のイメージ
- 2つの正八面体スケルトンの造形はバルサ材で制作し、ジョイント部はネオジム磁石によって連結する
- 2つの正八面体、計24個の稜(断面は正方形)の4面にLEDテープが並んで光る
- マイコンとしてPropellerを使用する
- 多数のLED点灯制御(MIDI入力)用に1個、多数のセンサ(MIDI出力)用に1個、それぞれPropellerを使用する
- LEDとして、碧風祭で「光るワンピース」を制作した、樺山さんのシステムに使用した「テープLED」(12V高輝度LEDが5cmに3個並ぶテープ)を使用する
→ メイキング ★ ★ ★ ★ / 展示 ★- 正八面体の1辺を15cmとする。1辺あたりLEDテープが3本(9LED)が4面で36LED、これが計24稜あるのでLEDの総数は864個(^_^;)
- LEDは12V20mA高輝度タイプ、全数を最大輝度で点灯させると864*0.02=17.28Aなので、電源として「12V20A」(240W)のスイッチング電源を使用する
- 光りモノの中にいつものSHARPの赤外線距離センサ ★ は使えないので、距離センサとして新たにイギリスDevantech社の超音波レーダセンサ「SRF02」を採用、左右それぞれ3方向の計6個(最大拡張10個)を使用する
- PropellerのMIDI送受信は過去に実績のあるオリジナルライブラリを活用
- Propellerの24ブロックのLED点灯制御(PWM)は樺山さんシステムで開発したオリジナルライブラリを活用
- PropellerのSRF02送受制御はオリジナルライブラリを開発
- 超音波センサからのMIDI出力ラインをLED点灯制御のPropellerにも与えて(両方をモニタ)、スタンドアロンでも超音波センサにより発光制御できるようにする(点灯制御MIDI入力によりソフト的に停止)
回路図- 主要部品(シーズ)とメイキング
- Propellerソースコード
- ソフトウェアアーカイブ「prop.zip」
- Propeller[A](LED点灯制御)メインspinプログラム : MIDI_24LED_004.spin
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ pwmOut : "PwmPortOut03" midiIn : "MidiIn03" sensorIn : "MidiIn03" PUB start | i, dummy, phase, mode, value pwmOut.start pwmOut.speed_set(0) midiIn.start(24) sensorIn.start(25) LED_all_off phase := 0 repeat dummy := sensorIn.event if dummy <> -1 if phase == 0 if (dummy & $F00000) == $D00000 mode := (dummy & $0F0000) >> 16 + 100 value := dummy & $7F if value < 26 value := 0 elseif value < 35 value := 1 elseif value < 44 value := 2 elseif value < 53 value := 4 elseif value < 62 value := 8 elseif value < 71 value := 16 elseif value < 80 value := 32 elseif value < 89 value := 64 else value := 127 LED_control(mode, value) dummy := midiIn.event if dummy <> -1 if (dummy & $FF0000) == $AF0000 phase := 1 mode := (dummy & $7F00) >> 8 value := dummy & $7F if mode == 26 ' AF 26 dd ---> stand-alone mode phase := 0 else LED_control(mode, value) PUB LED_control(mode,value) | i if mode < 24 ' AF nn dd ---> each LED (nn=0-23) value(0-127) LED_data_set(mode, value) return elseif mode > 99 if mode < 106 mode := (mode-100) << 2 repeat i from 0 to 3 LED_data_set(mode+i, value) return case mode 106: 107: 108: 109: return case mode 24: ' AF 24 dd ---> all LED value(0-127) repeat i from 0 to 23 LED_data_set(i, value) return 25: pwmOut.speed_set(value) ' AF 25 dd ---> PWM speed (0-6) return PUB LED_all_off | i repeat i from 0 to 23 LED_data_set(i, 0) PUB LED_data_set(address, data) pwmOut.buffer_set(address<<8 + data) PUB pause1ms(period) waitcnt(80_000 * period + cnt)- Propeller[A](LED点灯制御)サブspinプログラム : PwmPortOut03.spin (LED点灯PWMオリジナルライブラリ)
VAR long speed_Data, pwm_Data[24], stack[10] PUB start : i buffer_address := @pwm_Data speed_address := @speed_Data speed_Data := %100000 cognew(@asm_entry, @stack[0]) PUB speed_set(data) if data > 6 data := 6 speed_Data := 1 << (data+9) PUB buffer_set(data) pwm_Data[data>>8] := data & $7F DAT org asm_entry mov dira,all_high andn outa,all_high rdlong counter1,speed_address mov counter2,#0 :start_entry sub counter1,#1 wz if_nz jmp #:start_entry rdlong counter1,speed_address add counter2,#1 and counter2,#%01111111 mov work_bit,#0 :bit_loop mov bit_mask,#1 shl bit_mask,work_bit mov t1,work_bit shl t1,#2 add t1,buffer_address rdlong pwm_value,t1 wz if_z jmp #:led_off cmp pwm_value,counter2 wz if_z jmp #:led_on cmp pwm_value,counter2 wc if_c jmp #:led_off :led_on or outa,bit_mask jmp #:next_bit :led_off andn outa,bit_mask :next_bit add work_bit,#1 cmp work_bit,#24 wz if_nz jmp #:bit_loop jmp #:start_entry all_high long %00000000111111111111111111111111 buffer_address long 0 counter1 long 0 counter2 long 0 speed_address long 0 work_bit long 0 bit_mask long 0 pwm_value long 0 t1 long 0 fit- Propeller[A](LED点灯制御)サブspinプログラム : MidiIn03.spin (MIDI入力汎用オリジナルライブラリ)
VAR long rx_Head, rx_Tail, rx_Buff[64] PUB start(_midiPin) : status midiPin := _midiPin rx_top := @rx_Head rx_end := @rx_Tail rx_fifo := @rx_Buff bitticks := clkfreq / 31_250 halfticks := bitticks / 2 longfill(@rx_Head,0,66) status := cognew(@asm_entry, 0) PUB event : status status := -1 if rx_Tail <> rx_Head status := rx_Buff[rx_Tail] rx_Tail := (rx_Tail + 1) & $3F DAT org asm_entry mov midiMask,#1 shl midiMask,midiPin getMidiByte waitpeq midiMask,midiMask mov bitClk,cnt add bitClk,halfticks add bitClk,bitticks mov testBits,#9 :check_loop waitcnt bitClk,bitticks test midiMask,ina wc rcr rx_data,#1 djnz testBits,#:check_loop shr rx_data,#32-9 xor rx_data,#$FF and rx_data,#$FF test rx_data,#%10000000 wz if_z jmp #:running mov t1,rx_data and t1,#%11110000 cmp t1,#%11110000 wz if_z jmp #getMidiByte mov rsb,rx_data mov dcb,#0 jmp #getMidiByte :running mov t1,rsb and t1,#%11100000 cmp t1,#%11000000 wz if_z jmp #:byte_2 tjnz dcb,#:byte_3 add dcb,#1 mov keyno,rx_data jmp #getMidiByte :byte_2 mov event_data,rsb shl event_data,#16 or event_data,rx_data jmp #:write_event :byte_3 mov dcb,#0 mov event_data,rsb shl event_data,#16 mov t1,keyno shl t1,#8 or event_data,t1 or event_data,rx_data :write_event rdlong t1,rx_top mov rx_pointer,t1 shl rx_pointer,#2 add rx_pointer,rx_fifo wrlong event_data,rx_pointer add t1,#1 and t1,#$3F wrlong t1,rx_top jmp #getMidiByte t1 long 0 midiMask long 0 testBits long 0 bitClk long 0 bitticks long 0 halfticks long 0 midiPin long 0 rx_top long 0 rx_end long 0 rx_fifo long 0 rx_data long 0 rx_pointer long 0 event_data long 0 rsb long 0 dcb long 0 keyno long 0 fit- Propeller[B](超音波距離センサ)メインspinプログラム : SRF02_MIDI_001.spin
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ midiOut : "MidiOut01" serialOut : "SRF02_Out01" serialIn : "SRF02_In01" PUB start | i, num_max, rx_data, old_data[10] midiOut.start(26) serialIn.start(14) serialOut.start(15) num_max := 6 repeat repeat i from 1 to num_max pause1ms(1) rx_data := rx_SF02(i) if rx_data < 3700 rx_data := 127 - ((rx_data>>5) & %01111111) if rx_data > 105 rx_data := 0 if rx_data <> old_data[i-1] old_data[i-1] := rx_data midiOut.fifoset(($D0+i-1)<<16 + rx_data) PUB rx_SF02(channel) | mode, dummy, rx_data serialOut.fifoset(channel) serialOut.fifoset($55) mode := 0 repeat if mode == 1 dummy := serialIn.event if dummy <> -1 rx_data := rx_data + dummy return(rx_data) elseif mode == 0 dummy := serialIn.event if dummy <> -1 rx_data := dummy << 8 mode := 1 PUB pause1ms(period) waitcnt(80_000 * period + cnt)- Propeller[B](超音波距離センサ)サブspinプログラム : MidiOut01.spin (MIDI出力汎用オリジナルライブラリ)
VAR long tx_Head, tx_Tail, tx_Buff[64] PUB start(_midiPin) : status midiPin := _midiPin tx_top := @tx_Head tx_end := @tx_Tail tx_fifo := @tx_Buff bitticks := clkfreq / 31_250 longfill(@tx_Head,0,66) status := cognew(@asm_entry, 0) PUB fifoset(_tx_data) tx_Buff[tx_Head] := _tx_data tx_Head := (tx_Head + 1) & $3F DAT org asm_entry mov midiMask,#1 shl midiMask,midiPin or dira,midiMask :fifo_check rdlong t1,tx_end rdlong t2,tx_top cmp t1,t2 wz if_z jmp #:fifo_check mov t2,t1 shl t1,#2 add t1,tx_fifo rdlong event_data,t1 mov t1,t2 add t1,#1 and t1,#$3F wrlong t1,tx_end mov tx_data,event_data shr tx_data,#16 call #send_event and tx_data,#%11100000 cmp tx_data,#%11000000 wz if_z jmp #:byte_2 mov tx_data,event_data shr tx_data,#8 call #send_event :byte_2 mov tx_data,event_data call #send_event jmp #:fifo_check send_event xor tx_data,#$FF and tx_data,#$FF shl tx_data,#1 or tx_data,#1 mov testBits,#10 mov bitClk,cnt add bitClk,bitticks :bit_send shr tx_data,#1 wc muxc outa,midiMask waitcnt bitClk,bitticks djnz testBits,#:bit_send send_event_ret ret t1 long 0 t2 long 0 midiMask long 0 testBits long 0 bitClk long 0 bitticks long 0 midiPin long 0 tx_top long 0 tx_end long 0 tx_fifo long 0 tx_data long 0 event_data long 0 fit- Propeller[B](超音波距離センサ)サブspinプログラム : SRF02_Out01.spin (センサ通信[送信]オリジナルライブラリ)
VAR long tx_Head, tx_Tail, tx_Buff[64] PUB start(_midiPin) : status midiPin := _midiPin tx_top := @tx_Head tx_end := @tx_Tail tx_fifo := @tx_Buff bitticks := clkfreq / 9600 longfill(@tx_Head,0,66) status := cognew(@asm_entry, 0) PUB fifoset(_tx_data) tx_Buff[tx_Head] := _tx_data tx_Head := (tx_Head + 1) & $3F DAT org asm_entry mov midiMask,#1 shl midiMask,midiPin or dira,midiMask :fifo_check rdlong t1,tx_end rdlong t2,tx_top cmp t1,t2 wz if_z jmp #:fifo_check mov t2,t1 shl t1,#2 add t1,tx_fifo rdlong event_data,t1 mov t1,t2 add t1,#1 and t1,#$3F wrlong t1,tx_end mov tx_data,event_data call #send_event jmp #:fifo_check send_event xor tx_data,#$FF and tx_data,#$FF shl tx_data,#1 or tx_data,#1 mov testBits,#11 mov bitClk,cnt add bitClk,bitticks :bit_send shr tx_data,#1 wc muxc outa,midiMask waitcnt bitClk,bitticks djnz testBits,#:bit_send send_event_ret ret t1 long 0 t2 long 0 midiMask long 0 testBits long 0 bitClk long 0 bitticks long 0 midiPin long 0 tx_top long 0 tx_end long 0 tx_fifo long 0 tx_data long 0 status_d long 0 event_data long 0 fit- Propeller[B](超音波距離センサ)サブspinプログラム : SRF02_In01.spin (センサ通信[受信]オリジナルライブラリ)
VAR long rx_Head, rx_Tail, rx_Buff[64] PUB start(_midiPin) : status midiPin := _midiPin rx_top := @rx_Head rx_end := @rx_Tail rx_fifo := @rx_Buff bitticks := clkfreq / 9600 halfticks := bitticks / 2 longfill(@rx_Head,0,66) status := cognew(@asm_entry, 0) PUB event : status status := -1 if rx_Tail <> rx_Head status := rx_Buff[rx_Tail] rx_Tail := (rx_Tail + 1) & $3F DAT org asm_entry mov midiMask,#1 shl midiMask,midiPin getMidiByte waitpeq midiMask,midiMask mov bitClk,cnt add bitClk,halfticks add bitClk,bitticks mov testBits,#11 :check_loop waitcnt bitClk,bitticks test midiMask,ina wc rcr rx_data,#1 djnz testBits,#:check_loop shr rx_data,#32-11 mov t1,#$100 test rx_data,t1 if_z jmp #getMidiByte shl t1,#1 test rx_data,t1 if_z jmp #getMidiByte xor rx_data,#$FF and rx_data,#$FF mov event_data,rx_data rdlong t1,rx_top mov rx_pointer,t1 shl rx_pointer,#2 add rx_pointer,rx_fifo wrlong event_data,rx_pointer add t1,#1 and t1,#$3F wrlong t1,rx_top jmp #getMidiByte t1 long 0 midiMask long 0 testBits long 0 bitClk long 0 bitticks long 0 halfticks long 0 midiPin long 0 rx_top long 0 rx_end long 0 rx_fifo long 0 rx_data long 0 rx_pointer long 0 event_data long 0 rsb long 0 dcb long 0 keyno long 0 fit- 「解説とサンプルMaxパッチのライブ制作」パフォーマンスの模様
- YouTube