Arduino UNOとATTiny13Aを使ったタッチセンサーMIDIコントロールデバイスの作り方
何?
昨日、六本木のGoogle Japanで開催されたWeb Music ハッカソン #3で、りんごやナスにセンサーを繋いでヒドい音を鳴らすというパフォーマンスをさせていただきました。
「Web Music ハッカソン #3」Hangoutsライブストリームの録画。私は7:00くらいから登場!
ビデオ何回見てもヒドい感じでw例によって技術的な説明無しだったので、前回同様、使ったデバイスの作り方を記事にしてお茶を濁そうという魂胆です。
洗濯バサミやワニ口クリップが写っていますが、これと洗濯カゴの中にある基板と繋がっていて通電しています。
(Macについてる洗濯バサミは、単なる飾りですw)
これに通電するモノを繋ぐと、それがセンサーになる。というものです。
作りたくないよ?
単に繋いだモノをなんでもセンサーにして、音出す系のモノは、結構登場しています。
やりたいことは下記のようなことですので、
こんな感じのものが使えそうですね。
安いのはMaKey MaKeyの方ですが、いきなりMIDIが使えるのはototoの方です。
ただ、MaKey MaKeyはオープンソースハードウエアでArduino Leonardoと同じIC(ATmega32u4)を使ってることもあり、Arduino環境の資産を生かせばMIDI化も可能と思います。
ここなどを見れば、USB MIDIにすることもできそうですね。
工作はしたくないなぁ、という方は、どちらか試してみると楽しいかも!
というか、正直どっちも欲しい!w
今回の話からは脱線だけど、音はドラムでいいよ。という人は「Wave Drum mini」by KORGという製品もある。これも楽しそうw
Arduino UNO持ってるしなぁ、という人向けに。
しかし、セコい私は別の道を選びました。
Arduino Leonardoに出来るなら、UNOにも出来るはずです。
Arduino UNOには、「超簡単!Arduino UNOをMIDIコントローラーにしよう!」で紹介させて頂いたように、Morecat_Labさんの「Midi Firmware for Arduino Uno (Moco)」という強い味方が居ます。MIDI側は万全!
というわけで、センサーを検討するだけです。
MaKey MaKeyの回路図を見れば? あれ?
実は、MaKey MaKeyの回路図を見れば、UNOでも同じことができることが判ります。
Makey Makeyの回路図を見ると、最初端子は通電してなくて、身体の2カ所で端子とグランドの2つを接続することで通電することでスイッチオン!と判定する方式のようです。
なんとも単純!すばらしい。
[出典:http://www.makeymakey.com/]
ただ、これは、2カ所触らなければならないみたいなんですね。グランド側を常にどっかにつけとく感じ。
1カ所タッチするだけで反応するモノは作れないものか。と、MaKey MaKeyとは別の方式で作ることにしました。
そのくらい違わないと作る意味ないしね!w
静電容量式で。
というわけで、タッチセンサーの常套手段、静電容量式センサーを作ることにしました。
Arduino UNOで静電容量式タッチセンサーの作り方を教えてくれるありがたいリンク
既にインターネットにはいろいろな情報が公開されていて、Arduinoが判ればすぐに試すことができます。
- Arduino タッチセンサ(建築発明工作ゼミ2008) by KOUSAKUさん
- [電子工作]Arduinoを使ったタッチセンサの作り方(Inter-Arteq) by AKIFUMI NAMBUさん
このあたりを見れば、作り方が判りやすく解説されています。
しかし。
プログラム見れば判りますが、
#define OUTPORT 13
#define INPORT 12
void loop(){
int cnt = 0;
digitalWrite(OUTPORT,HIGH); // 出力をON
while (digitalRead(INPORT)!=HIGH){
cnt++;
}
digitalWrite(OUTPORT, LOW); // 出力をOFF
// cntの値を判定することで、タッチを判断する。
}
といった流れになります。
これは、センサーが1つであれば良いのですが、
複数のセンサーを繋ごうとすると1つのArduinoで処理するのは
プログラムが面倒なことになりそうですね。
私はこのプログラムを見た時点で、並列的に1つのArduinoで処理するのは諦めました。
だってMIDIのシリアル出力もあるし、負荷をあまりかけたくないので。
贅沢に。でも、安く。複数のマイコンを使おう。
というわけで、センサー用のArduinoとMIDIを出力する用のArduinoを分けることに。
と、言っても、下記のような話ではありません!w
これでは、あまりにお金がかかります。
やっぱMaKey MaKeyにしよう!ということに確実になりますw
先ほどのようなセンサーのプログラムだけが動けば良いので、日本でおそらく一番安価に入手できるArduino互換マイコンのATTiny13Aを使うことにします。
これなら、安くできるはずです!
材料
とりあえず、全部買うかもしれないので、リストを置いときます。
秋月電子で全部揃いますね!
センサー1個あたりの材料です。
- ATTiny13A (8PinDIP)
- LED
- 抵抗(330-470Ωぐらい)※LED用
- 抵抗(10KΩ)※タクトスイッチプルダウン用
- 抵抗(1MΩ)※センサー電流抑制用
- コンデンサ(0.1uF)
- タクトスイッチ
こんなところでしょうか。1個あたり100円以下でできるといいですね。
(なんにも持ってないぞ〜!という状態からだと、100円はさすがにムリw)
無いものだけ買う感じで。抵抗も上記値は目安で厳密なものではありません。
1MΩのもの以外は、倍くらい違っても結構OKな気がしてますw(←いい加減)
実際につくる!
前置き長くてすいません。
ようやく作り方に入ります。
回路
前回の缶の時は手書きでしたが。。。w
私も進歩したので、EAGLEで回路図を書いてみました。
下の図は、Arduinoとセンサーを8個繋ぐ前提の絵になっています。
Qiitaに上げると見にくくなると思うので、ダウンロードして見てください。
注意点
回路的には、難しい部分は特にないのですが、2つ注意点があります。
- センサー沢山つなげようとすると、沢山回路を作る必要があるので、それなりに疲れるw
- 何を繋ぐかを想像してから、コネクタ部分を作ろう。
1つ目は、まぁ、頑張るしかありませんw
2つ目は、ブレッドボードで作る場合は検討の余地が無いので良いのですが、ユニバーサル基板などで作る場合は、ピンヘッダを使うか、ピンソケットの方にしとくかは悩みどころです。
その先に何を繋ぎたいか。例えば、ジャンパワイヤーを使いたい場合は、ピンソケットの方が良いでしょうし、ワニ口クリップを使いたい場合は、ピンヘッダを離して1つづつ設置した方が良いかもしれません。ワニ口クリップ専用にする場合は、銅板で接点を作った方が安定するかもですね。
センサー部分(ATTiny13A)のプログラム
回路が出来たら、ATTiny13Aへのプログラム(スケッチ)を焼き込みます。
Arduino ISPで。
詳細はArduinoで、小っちゃいIC(ATTiny)を使う方法を参照して欲しいのですが、kosakalabさんの
Arduino IDEでATtiny他の開発(Arduino-ISP編)を参照して、Arduino ISPによるATTiny13Aへのファームウエア書き込み環境を作っておく必要があります。
あとで書くサンプルも、kosakalabさんの環境を前提にしています。
今回は利用してないので、参考情報ですが、
ATTiny13AはROMサイズ1Kbyte/RAM 64byteと非常に小さいのでプログラム容量には気を使う必要があります。
ATtiny13をArduino IDEで使う(暫定版)(構想100年) by まりす さんが、ATTiny13AやATTiny10という小さなAVRに最適化されたArduinoライブラリを公開されていますので、もっとATTiny13Aを使い倒したい時などは試してみると良いと思います!
ソース(ATTiny13A用)
センサー部分(ATTiny13A)のスケッチは下記の通りです。
ロジックは、「Arduino タッチセンサ(建築発明工作ゼミ2008)」さんの記事の流用(マルマルマルパクリw)です。
デジタル出力の追加と、ATTiny13Aへの最適化だけ実施しています。
// +-----+
// ADC0 PB5 | | VCC
// (SENSOR-IN) ADC3 PB3 | | PB2 ADC1 (LED/DigitalOut)
// (SENSOR-OUT) ADC2 PB4 | | PB1 (N/A)
// GND | | PB0 (BUTTON)
// +-----+
#define PINBD0 0x01
#define PINBD1 0x02
#define PINBD2 0x04
#define PINBD3 0x08
#define PINBD4 0x10
#define PINBD5 0x20
void setup( ) {
DDRB &= ~((PINBD0)|(PINBD3));
DDRB |= ((PINBD2)|(PINBD4));
}
int cnt = 0; // センサー出力から入力までのカウント
int val = 0; // 計算用。
int comp = 10; // この値以上ならON。以下ならOFF
void loop( ) {
byte p;
p = PINB; // digitalRead()全部w
// Button Input
if((p & PINBD0)!=0){ // ボタン押された?
comp = val + 8; // キャリブレーション(超雑)
}
cnt = 0;
// Sensor Output
PORTB |= PINBD4; // digitalWrite(4,HIGH)
while(1){
p = PINB;
if(p & PINBD3){ // digitalRead(3)
break;
}
cnt ++;
}
PORTB &= ~PINBD4; // digitalWrite(4,LOW)
val += (cnt - val)/2; // ならす。
if(val > comp){ // 触った?
PORTB |= PINBD2; // digitalWtite(2,HIGH)
}else{ // 触ってない
PORTB &= ~PINBD2; // digitalWtite(2,LOW)
}
}
ちょっとArduinoっぽくない書き方ですが、これでもArduino IDEで動くスケッチです。
digitalRead()
やdigitalWrite()
結構大きいので、上記のように書いた方が小さくできます。
使い方。何か接続した後に、1度キャリブレーション用のスイッチを押してLEDを消す
Arduino UNO側のプログラムの前に、このセンサーデバイスの使い方を少し説明しておきます。
キャリブレーションは自動じゃなく、手動で、かつ、超シンプルなコードで実現しています。
センサーデバイスを通電させると、最初、何も接続してない時はLEDが消えていますが、例えばワニ口クリップを繋いだだけでセンサーが「触った!」と判定してしまい、LEDが点灯すると思います。
これでは、実際に触る前に反応していることになり、タッチセンサーとして使えません。
そこで、実際に手で触るもの(例えばリンゴなど!)を接続後、一度キャリブレーション用のスイッチを押してLEDを消しましょう。
1度で消えないかもしれないので、何度か消えるまで押しましょう。
Arduino UNO側のプログラムを作る
それでは、Arduino UNO側を作りましょう。
こちらは、はじめにMIDIデバイス化しておく。
再掲になりますが、Morecat_Labさんの「Midi Firmware for Arduino Uno (Moco)」を使って、Arduino UNOに搭載された ATMega16u2を書き換えて、MIDIデバイス化しておきます。
「超簡単!Arduino UNOをMIDIコントローラーにしよう!」にやり方を書いたのですが、「Arduino UNO R3 + dfu-programmerって、みんなどうしてるの?」で書いたようなハードルもあるので、SlideShareにArduinoで作るMIDIコンというスライドも用意しました。
もう、どこまでMIDIデバイス作らせたいんだ!とw
というわけで、成功祈っています。是非挑戦してくれたらうれしい。
ソース
Morecat_LabさんのdualMocoが無事Arduino UNOへ書き込めたら、次はいよいよスケッチを書きます。
ハッカソンで使ったモノは、これ以外にAnalogRead()でヘンテコな処理入れてたりしたのですが、
今回の主旨の部分じゃないので、ATTiny13Aのセンサーデバイスが8個繋がってる想定で、そこの入力に応じたMIDI NOTE情報を出力する部分だけを抜粋しています。
#include <MIDI.h>
#define SWITCH1 4
#define SWITCH2 5
#define SWITCH3 6
#define SWITCH4 7
#define SWITCH5 8
#define SWITCH6 9
#define SWITCH7 10
#define SWITCH8 11
#define DARK 40
int stat = 0;
int ostat = 0;
byte dnotes[8] = {24,32,40,48,56,64,72,80};
void setup(){
pinMode(SWITCH1, INPUT);
pinMode(SWITCH2, INPUT);
pinMode(SWITCH3, INPUT);
pinMode(SWITCH4, INPUT);
pinMode(SWITCH5, INPUT);
pinMode(SWITCH6, INPUT);
pinMode(SWITCH7, INPUT);
pinMode(SWITCH8, INPUT);
MIDI.begin(1);
}
void loop(){
int value;
int cnt;
byte midich = 1;
byte outnote = 0;
for(cnt= 0;cnt<8;cnt++){
value = digitalRead(cnt+4);
if(value == HIGH){
stat |= (1 << cnt);
if((ostat & (1 << cnt))== 0){
MIDI.sendNoteOn(dnotes[cnt],100,midich);
}
}else{
stat &= ~(1 << cnt);
if(ostat & (1 << cnt)){
MIDI.sendNoteOff(dnotes[cnt],0,midich);
}
}
}
ostat = stat;
}
こちらは、ATTinyの時とうって変わってpinMode()
やdigitalRead()
を普通に使ってて、Arduinoっぽい感じで書いてみました。
ATMega328Pは容量余裕なのでw
まとめ。動いたかな?
私が作ったのは、中身こんな感じになりました。
まとめると、
- 金持ちで工作したくない人で、タッチセンサー風に変なことやりたい人は MaKey MaKeyを検討しよう!
- Arduino UNO持っててMaKey MaKey真似したい人は、回路図見ればそれはそれで簡単に作れる!
- 「ワンタッチ」にコダワリたい人は、ATTiny13A(50円)で簡単に作れる静電容量式タッチセンサーを検討しよう!
- dualMocoのお陰でArduino UNOがあればMIDIデバイスは簡単につくれる!(しつこい)
- 見せ方も大事だぞ!w (実は回路を作るより、洗濯バサミ工作する方が時間かかってたりw)
というわけで、今回も短くまとめられませんでしたが、最後までおつきあいいただきありがとうございました!
次回はPixi.jsの話でも
ハッカソンで作ったWeb側ですが、以前Qiitaに書いたPixi.js(WebGLライブラリ)のサンプルをベースにでっちあげたものです。
当日、Pixi.jsのフィルタで遊んで結構面白かったので、こちらについても少し紹介しようと思います!
せっかくなので、今話題のWeb MIDI APIを使ってみよう
せっかくMIDIデバイスが作れたのなら、楽器とつなぐだけだともったいないよ!
Web MIDI APIを使ってブラウザと繋いで、かっこいい画面とか作って遊ぼう。
ということの役に立ちそうな情報をいくつか。
(昨日ハッカソンで教えてもらったリンク貼るだけの楽な仕事ですけどね!w)
- サクっと判った気になりたい乱暴者向けの記事
- もっとちゃんとした人向けの記事。Web Browser VJ チュートリアル by サスカッチさん
- 乱暴者も読め、なレベルの重要な記事。将来Web MIDI APIの書き方が変わる内容と具体的な対応方法についての解説 by とよしまさん
Let's Enjoy Web Music!