SX-150 を Arduino で制御する(お手軽版) [電子工作]
組み立ても完了し無事完了し、いろいろ遊んでいましたが、やはり演奏が難しいので、Arduinoで制御する方法をいろいろ調べました。
参考にしたのは、Make: Japan: HOW TO - 学研SX-150をArduinoでコントロールしようで紹介されていたやりかた。
オリジナルの接続はまどろっこしいので、思い切ってシンプルに改造。
シリアルによるPCとの接続を省略して、直接Arduinoのソースからコントロールさせます。
音階の制御データ(オリジナルではシリアルで渡される)は、int型で一オクターブが+12となるので、自分なりの制御をするのは非常に簡単です。
DAコンバータ(MCP4921)は入手が困難なので、秋月でMCP4922を購入(約200円)。
4921が2個入りでお得ですが、今回は例にならって片チャンネルのみ使用します。
(1) 回路を組む。
SX-150のテスター棒とEXT.SOURCEを、みの虫クリップで接続します。
ブレッドボード上にMCP4922等を配置します。LEDはタイミング表示用の飾りなので省略しても良いです。
回路図はこのようになります。
(2) Arduino
ArduinoとMCP4922はSPIという方式での接続になるようです。こちらはまだArduinoではライブラリ化されていないので、サンプルのソースをそのままで行くことにします。
Serial処理部分を「がっつり」除去して、簡単なベースラインを演奏するようにしています。
void loop() { NOTE(24); NOTE(24+12);
この例は関数NOTE()の引数で音の高さを指定しています。1オクターブ上はプラス12になります。音の長さは固定です。これだけでもかなり70年代シークエンサー風の演奏が楽しめます。
(3)完成!
動作中の動画をYouTubeにアップしました。Arduinoって本当に便利。
[2009/2/3追記]
SPIインターフェースについてまじめに勉強するのであれば下記リンク先が参考になりそう。
Interfacing a Serial EEPROM Using SPI (Arduino.cc)
[2009/2/4追記]
MrBookさんのオリジナルBLOG(英文)のリンク先を
<参考>ソースコード
・ベースとなったソースのオリジナル照会元(英文)
// SX-150 Controler // Original Source created by Mrbook // http://mrbook.org/blog/2008/11/22/controlling-a-gakken-sx-150-synth-with-arduino/ #define DATAOUT 11//MOSI #define DATAIN 12//MISO - not used, but part of builtin SPI #define SPICLOCK 13//sck #define SLAVESELECT 10//ss #define LEDPin 8 void setup() { byte clr; pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); digitalWrite(SLAVESELECT,HIGH); //disable device SPCR = (1&<&<SPE)|(1&<&<MSTR); clr=SPSR; clr=SPDR; delay(10); pinMode(LEDPin, OUTPUT); // sets the digital pin as output digitalWrite(LEDPin,LOW); Serial.begin(9600); } void write_value(uint16_t sample) { uint8_t dacSPI0 = 0; uint8_t dacSPI1 = 0; dacSPI0 = (sample &>&> 8) & 0x00FF; dacSPI0 |= 0x10; dacSPI1 = sample & 0x00FF; digitalWrite(SLAVESELECT,LOW); SPDR = dacSPI0; // Start the transmission while (!(SPSR & (1&<&<SPIF))) // Wait the end of the transmission { }; SPDR = dacSPI1; while (!(SPSR & (1&<&<SPIF))) // Wait the end of the transmission { }; digitalWrite(SLAVESELECT,HIGH); delay(5); } void playNote(int incomingByte) { int diff = 48 - incomingByte; diff *= 12; write_value (1125 - diff); // 1270 C4 60 // 1125 C3 48 // 980 C2 36 // 835 C1 24 // 690 C0 12 } void noteOff() { write_value(0); } int incomingByte = 0; void NOTE(int r) { static int flg=HIGH; if (flg == HIGH) { flg=LOW; } else { flg=HIGH; } digitalWrite(LEDPin,flg); playNote(r); delay(180); noteOff(); } void loop() { NOTE(24); NOTE(24+12); NOTE(19); NOTE(19+12); NOTE(21); NOTE(21+12); NOTE(22); NOTE(22+12); }
コメント 0