ホーム > 音楽 > MIDI Chord Helper > MIDI Chord Helper ハードウェア化計画 > 電子楽器 CAmiDion 1号機

電子楽器 CAmiDion 1号機

CAmiDion 1号機

2009年5月に作り始めて以来、色々実験しながら改造に改造を繰り返していった初代機です。

電池 (充電式 1.2V NiMH x 4 本) で動き、持ち運びも簡単。 卓上式の楽器としてだけでなく、肩からぶら下げてショルダーキーボードとしても使える。 簡易リズムマシン機能(バスドラム音を鳴らす)も内蔵、 外付けのカセットケース入りメーターネギ振りはちゅねミクも装備。 ノートパソコンがなくても、外出先で手軽にコード演奏を楽しめるようになりました。

[ハードウェア(回路図)] [スケッチ(C++ソース)]

ハードウェア構成

筐体のサイズ

おおよそ 15cm x 25cm x 3cm くらい(アクリル板の厚み含まず)。 アクリル板は 3mm 厚のものを使用しています。

使用しているArduinoハードウェア

初期版からずっと Duemilanove を使っていましたが、 2010年7月、自作 Arduino 互換機を組み込むよう改造しました。 ブートローダーの焼き方はこちらのページを参考にしました。

電源

単3 1.2v NiMH x 4 (1600mAH) = 4.8v(1.5v 電池使用不可:ATMEGA328P の絶対最大定格 6V を超えると壊れる恐れがあるため)

3端子レギュレータなしで動作させているため NiMH 専用となっています。 USBは外付けです。スケッチを流し込んだり電源をPCから取るときのみ、 ATMEGA328P の1〜8番ピンのところに差し込んで使います (モバイル楽器として独立して動かすときはUSB不要なので)。

消費電流:50mA程度

押しボタン

MIDI Chord Helper のコードボタンと同じようなボタンを用意します。

横方向が25マス(五度圏2周分)もありますが、ボタンが多いとその分サイズも大きくなってコストもかかるため、 13マス(五度圏1周分)だけに絞りました。

Chord button

LED の色は MIDI Chord Helper の背景色と全く同じ意味で、 赤の中央を基準としたときのコードの雰囲気を表しています。 MIDI Chord Helper と違って色が固定されているので、代わりに ボタンに割り当てられるコードの並びをシフトさせるようになっています。 シフト位置は C/Am のある列の LED を点滅させることによって表し、さらに 7セグメントLEDにも調号として表示させることができるようになっています (#はHで表し、5個以上は5♭とか5Hのように表す)。 表面は黒いアクリル板で覆っています(写真はこちら)。

シフトキーのように使う切り替えボタンは、次の6種類を用意します。

MIDI Chord Helper と同様、-5, M7, 7 の組み合わせで、通常使う種類の4重和音は ほとんど鳴らすことができます。 3つを全部押しながらマイナーコードボタンを押すと m6(-5) という組み合わせになりますが、 通常これは dim7 というコード名で表され、m7(-5) と区別されます。

コードボタンを押して鳴らすと、7セグメントLEDにコードが「それっぽく」表示されます。 例えばマイナーは m ですが、真ん中の棒は表示できないので省略して n のように表示しています。 同様に、メジャー7th を M7 で表すときの M を縦長の n で表示しています。 sus4 は、そのまま表示すると4桁の7セグメントLEDを埋め尽くしてしまうので、 5 と紛らわしい s を省略して u4 で表しています(例:F#sus4 → FHu4)。 add9 も桁が多いので A9 で表しています。 #や♭がつくとそれでも表示しきれないことがありますが、この場合は右側をカットしています。 さらに、ダブルシャープやダブルフラットっぽい文字までも7セグメントLED1文字で表示させています。 詳細はファームウェアのソースに書かれたコメントを参照してください。

チャタリングによる誤動作への対策は、ソフトウェアで行うと簡単です。 電圧を検出してもすぐに反応せず、何回か検出して全部同じ値なら受け入れる、 という方法で簡単に実装できます。

押しボタンの実装方法

検出方法ですが、数十個ものボタンを Arduino のデジタルピンに全部1個ずつ割り当てるのは無理なので、 少ないピン数で多くのボタンの状態を検出できるような方式で実装する必要があります。

【昔の方法】 電圧で分割 - 分圧回路

現在は改造済みで、この方法を使わないようになりましたが、 製作を始めた当初はこの方式で実装していました。

スイッチの回路図

図のような分圧回路を組んで Vout をアナログ入力ピンにつなぎ、電圧(0〜5v)を analogRead() で 0〜1023 の整数として読み取ることによって押されたボタンを判定する、 という方式です。

ボタンが何も押されていなければ Rx = ∞ と同じことなので 0v になります。

Rx = 0Ω(抵抗なしで直結)にした場合は 5v になりますが、このパターンは避けたほうがよいです。 なぜなら、アナログ入力ピンpinMode() を実行するとデジタル出力ピンとしても使えるので、 うっかりこれを実行するプログラムを組んでしまうと、直結した箇所でショートする恐れがあるためです。 出力電流が絶対最大定格 40mA を超えてしまうと、ピンの出力トランジスタが (最悪の場合 ATMEGA チップ全体が)破壊される恐れがあります(このページ DigitalPins の Pins Configured as OUTPUT のところに書いてあります)。 こういう状況を避けられそうな Rx は 5V / 40mA = 125Ω が下限。 同時押しなどを考えるともう少し余裕みておくと安心です。

一つのアナログピンの電圧値を16等分し、レベルが0(最小)または16(最大)で OFF、 1〜15で押されたコードボタン、として認識できるようにします。 レベルは以下の計算式(割り算は切り捨て)で求めることができます。

レベル = 16 - ( analogRead(アナログピン番号) + 32 ) / 64

これで、電圧に多少の誤差があっても16段階に丸められることになります (レベルが高いほど電圧が低いことに注意してください)。

出力電圧 Vout は、入力電圧 Vin と抵抗値によって次の式で決まります。

Vout = Vin * Rx / (R1 + Rx)

この式を Rx を求める式に変形します。

Rx = R1 * Vout / (Vin - Vout)

Vout を16等分した値ごとに Rx を計算します。 手持ちの抵抗器にE12 系列の抵抗値が多かったことから、計算した Rx に最も近い E12 系列の値に決めた結果、 下記のようになりました。

レベル01 2345 6789 10111213 141516
コード (使用しない) (切替ボタン) G♭D♭A♭E♭ B♭FCG DAEB F# (切替ボタン) (OFF)
E♭mB♭mFmCm GmDmAmEm BmF#mC#mG#m D#m
Rx[Ω]0(ショート)680 1.5k2.2k3.3k4.7k 5.6k8.2k10k12k 18k22k33k47k 68k150k∞(開放)

上記の行を、メジャー、マイナー、sus4、のそれぞれに割り当て、3つのアナログ入力ポート (0〜2)に割り当てます。一方、シフトキーのように使うボタンは下記のようにアナログ入力ポート3、4を使います。

ボタンに割り当てる抵抗器は Rx = 10 [kΩ]、15 [kΩ] の2種類。 同時に押すと、1 / (1/10 + 1/15) = 1 / (2/30 + 3/30) = 30/5 = 6 [kΩ] となります。 ボタンを押さないと ∞ になるので、全部で4種類の値を表現することができます。

ただ、この方法で実装して使っているうちに、次のようなデメリットに気づきました。

もちろん、同時押しできなくても問題ない用途であれば、ピン数を大幅節約したいという場合には 有効な方法でしょう。例えばこちらのブログ記事 I/Oピン一つで読み取れるキーパッドの製作(しなぷすのハード製作記 2014/01/08) では、 同時押しされたら後から押されたボタンを無視するという方法で誤動作を避けるアプローチをとっています。 いわば抵抗膜方式で実装されたタッチパネルの1軸版ともいえる実装方法です。

でも CAmiDion では同時押しできるようにしたかった… というわけで、2009年が終わろうとする頃から次のような方法に切り替えました。

【現在の実装】 時間で分割 - キーボード・マトリックス・スキャン

パソコンのキーボードなどで一般的に使われている方式です。 縦方向と横方向を束ねて、どちらか一つの方向について順次出力電圧をかけてスキャンし、 同時に1行ずつ入力から読み込む、ということを CPU が暇なときにずっと繰り返していくという方法です。 電圧を分割するのと違って、タイミングさえ合っていれば、ずれる心配もありません。

次のページが参考になります。

少なくとも、出力ピンの列ごとにダイオードを入れておく必要があります。 これがないと、同時押ししたときに、電圧の異なる出力ピン同士がショートして、 ピンを壊してしまう恐れがあります。 あと、ダイオードを入れると一方向はハイ・インピーダンスになるので、プルアップ(またはプルダウン) 抵抗で電圧が不安定にならないようにする必要があります。スキャン出力は 74HC154 で どこか一つだけが low-active なので、ダイオードの向きを出力側に向け、 入力側はプルアップ抵抗で安定させますが、幸いなことに、Arduino の入力ピンには digitalWrite(HIGH) でデータを「HIGH レベルとして出力」しようとすると、代わりに AVRマイコン内蔵20kプルアップ抵抗(pullup resistor)を ON にしてくれるという便利な機能がついています。 これを活用すれば、新たに抵抗器を設置する必要がなくなるので部品点数を減らせます。

必要最小限のダイオードだけでは、3つ以上の同時押しに対応できないパターンが出てきます。 例えば、マトリックスの座標 (2,5) (3,1) に加えて (5,1) が押されると、 同時に (2,3) が押されたものとみなされてしまいます。 これはゴーストとかファントムキー(phantom key)などと呼ばれる現象で、一般的なパソコンのキーボードでもよくみられます (部品点数を減らすためにダイオードを「手抜き」していることが多いため)。 例えば、MIDI Chord Helper のように、 パソコンのキーボードをミュージックキーボードとして使えるようにしたソフトを使って 和音を弾こうとすると、このような現象に遭遇することがあるかも知れません。

コードボタンの縦横でマトリックスを組んだ場合、単音モードで C G Em のボタンを押すと、 Am のボタンも押されたものとして検出され、C (C,E,G) のコードを出したつもりが Am7 (A,C,E,G) のコードになってしまいます。

B♭FCG
GmDmAmEm

単音モードの場合は G の代わりに Gm のボタンで代用することで解決できますが、 ちょっと遠くなってしまいます。

B♭FCG
GmDmAmEm

そこで、ボタン1つにダイオードを1つずつ直列接続しました(回路図は後述の LED 表示のところを参照)。 これで、どのボタンを同時に押しても正しく認識するようになります。 ちなみに普通の音楽用キーボードでは、出せない和音の組み合わせが発生してしまうと困るので、 きっとこの方式で実装されているものと思われます。

マトリックス方式を採用した結果、後述の 74HC154 の出力 16 本の LED スキャンと共用して、 16 x 3 = 最大48個のボタンを3本の入力ピンでまかなえるようになりました。 これだけあれば 7th ボタンからキー移動ボタンまでカバーできます。 分圧方式を使っていた頃と違って、アナログ入力ピンが2本余るようになったので、 別の用途に使うことができるようになりました。

アナログ入力 - 調整つまみ、および傾斜スイッチ
Velocity VR schematic

各種調整用に使っています(オクターブ、MIDI出力ベロシティ、エンベロープ周期)。 VRは10kΩ〜50kΩくらいのものを使っています。 また、うっかり出力ピンに設定してしまったときの安全策として 330Ω の抵抗を介して接続しています。 もし直結してしまうと、意図せずに出力ピンになっている状態で VR が最大または最小の状態に なったときにショートしてしまうためです。

傾斜すると自動的に ON になるスイッチ(ティルトスイッチ)がついています。 これは、ショルダーキーボードとして使った際、7セグメントLED表示を自動的に反転させて 演奏を聴いている側から見て正立しているように見せるためのものです。 (これはデジタル入力でもよいので、余ってさえいればアナログピンじゃなくても使えます)


LED表示とサウンド生成

LED表示

限られたピンで多くの LED を点灯できるよう、シフトレジスタ 74HC595 を用いて実装しました。 これにより、Arduino の ShiftOut() で簡単に出力することができます(参考ページ)。 ダイナミック点灯方式で光らせています。 下の4ビット(QA〜QDピン)をデコーダ(74HC154)に通して16個に拡張していますが、 デコーダの出力では同時に1個だけしか光りません。しかし、点灯するLEDを次々とすばやく変化させれば、 全部光っているように見せることができます。

LED and chord button schematic

QE〜QG ピンのいずれかが LOW(アクティブ)になると、 トランジスタ 2SA564 が ON になって導通し、LEDアノード側に +5v がかかります。 一方、LEDカソード側は 74HC154 の出力(負論理)に従って、どれか一つだけが LOW になります。 この両方の条件が揃った LED だけが光ります。

トランジスタ 2SA564 を介している理由は、負論理を正論理にするためだけでなく、 逆電圧に弱い LED を保護するために LED のアノード側を LOW ではなく 「切断」(ハイ・インピーダンス)状態にしたかったからです。

リセット前(スケッチ読み込み中など)に特定の LED が点灯したままにならないよう、 後述の MIDI ON 信号(Arduino D13 ピンを使用)をトランジスタで反転させ、 起動後に初めて 74HC595 の出力がイネーブルになるよう制御しています。

最後に残ったQHピンは、リズム音発生器で使うパルス出力として使っています。

Arduino の入力ピンについている330Ωの抵抗は、うっかり出力ピンにしたままボタンを押しても (ダイオードを介して)ショートしないようにするための保護用です。内蔵プルアップ20kよりも 十分に小さいので、LOW になったときの電圧を十分に低く抑えられます。


Sound schematic
音源

音源は、矩形波を出すサウンドジェネレータ(SSG)YMZ294(秋月電子で売っている)を2個装着しています。 1個で3重和音なので、2個で6重和音まで出せます。 これなら、コード C9(7th、9th がつくので5重和音)を ベース音つきで6重和音として出すのにも十分足ります。

YMZ294 x 2

SSG へのデータ伝送を行うには8ビットバスが必要ですが、こちらにも シフトレジスタを使うことにより、使用する Arduino のピンが少なくてすみます。 SSG の場合は書き込み信号の線があるため、74HC595 のようなラッチ機能は不要です。 このため、ラッチ機能のないシフトレジスタ 74LS164 を使っています (本当は74HC164でも十分なのですが、横浜エジソンプラザには74LS164しか置いてなかったんです…)。 でもシフトレジスタであることに変わりはないので、74HC595 と同様、ShiftOut() で出力できます。

【注意点】YMZ294 のアナログ出力(SO 端子)に、そのまま圧電スピーカーをつないだだけでは、音が出ません。 抵抗器を並列につなぐなどして、負荷をかける(電流を流す)ようにしないと 電圧が変化しないためか、圧電スピーカーを鳴らすことができないのです。 ひょっとして...ひそかに、オープンコレクタ(またはオープンドレイン)になっている... なんてことはないでしょうね??(データシートを探しても、そんなこと、何も書いてない...orz)
※ コイル式のスピーカーは電流で駆動するタイプ(低インピーダンス)ですが、 圧電スピーカーは電圧で駆動するタイプの素子(高インピーダンス)である点が大きく違います。

SO 端子の両隣には電源(+5V)とGNDがありますが、ここをショートさせないよう注意しましょう (YMZ294 が壊れる恐れがあります)。

音階を作る

YMZ294 では、音の周期を 12bit の値(TP = 0〜4095)で設定します。 数式は、秋月電子で買ったときに付属していたデータシートに書かれていますが、 クロック周波数が 4MHz なので、周波数 f は

f = 4MHz / (16 * TP)

で表されます。音階の周波数については音楽理論のツボ:12平均律で説明している通り、

f = 440 * pow( 2, ( d - 69 ) / 12 )

という式で表せます(d は MIDI ノート番号で表される音階)。これにより以下の式が得られます。

TP = 250,000 / ( 440 * pow( 2, ( d - 69 ) / 12 ) )

ここで、周期が2倍になると1オクターブ下がるという関係を利用し、定数を調整します。 音階を d = 0〜11 の範囲に限定し、TP が 4095 を超えない最大値になるように定数を決めると、 以下のような式になります。

TP = 250,000 / ( 110 * pow( 2, ( d - 9 ) / 12 ) )

この関係式で d を添字とした配列を作ります。

static const unsigned int tp12[] = {
  3822, 3608, 3405, 3214, 3034, 2863,
  2703, 2551, 2408, 2273, 2145, 2025,
};

ここで、d = 0 の値 3822 が一番低い「ド」、d = 11 の値 2025 が「シ」にあたる周期の値です。 1オクターブ上げるには、値を半分にするだけでOK。そのためには 右シフト演算子 >> を使って 次のようにプログラムを書けば、簡単かつ高速に計算できます。

求める周期 = tp12[d] >> 上げたいオクターブ数

Stereo amplifier top view
スピーカーアンプ
Stereo amplifier VR

スピーカーは LM386 で増幅して駆動。最初は増幅せずに圧電スピーカーをつないでいたのですが、 音量調節ができるよう、増幅して8Ωスピーカーを鳴らすようにしました。 外部スピーカージャック、LINE IN、LINE OUT も装備しているので、ヘッドフォンで聴いたり、 パソコンやラジカセなどの LINE IN、LINE OUT につなぐことができます。

イヤホンジャックは以前(2009川崎で展示した頃)はモノラルだったのですが、 ステレオに変え、スピーカーも増設。実はこのスピーカー、元々はジャンクのノートパソコンから 外したもので、当然のことながらステレオだったため、同じものがもう1個残っていたのです。 そこでこれを有効活用することにしました。その後、スピーカーをより高音質なものに付け替えています。

さらに、オーディオ入力ジャックも追加し、ステレオスピーカーアンプとしても 使えるようになりました。これで、ポータブルMP3プレーヤーにつないで曲を聴きながら、 それに合わせてコード演奏して楽しむこともできるようになりました。 いわば、ミキサーを内蔵しているようなものです。 SSG音源とオーディオ入力のボリュームを別々に、かつ左右同時に コントロールできるようにするため、2連タイプの可変抵抗器を2個装備しています。

SSGが2個あるので、これも左右に分離するようにしました。 3ピンヘッダを用意し、中央をGNDにすることで、逆刺しで左右を入れ替えられるようになっています。

低音を強めにするために(BASS BOOST)、高音を5番ピンから1番ピンへ負帰還させています。 高音が弱くなるだけなので、ボリュームをその分上げないと元の音量は得られませんが、 これでも十分な利得が出ています。1番ピンと8番ピンの間に10μFの電解コンデンサをつけると 20倍だった利得が200倍になりますが、拾ったノイズが大きくなるだけで、あまり効果はないようです。

データシートには「良好な安定動作を得るための最低値はピン8が開放されている場合にR=10kΩ」 と書かれていますが、こりんとさんのLM380とLM386を参考に、ちょっと控えめの22kΩにしてみました。


Stereo mixer schematic Stereo amplifier schematic
リズムマシン
Rhythm schematic

2010年8月22日ごろ、新たに追加しました。

ツインT型発振回路を使ったバスドラム音発生器です。 この発振回路は、自己バイアス型増幅回路の B-C 間の抵抗を、ツインT型ノッチフィルタに置き換えたもので、 1石で正弦波を出せる回路としてよく使われます。

左の回路図の定数で周波数50Hzくらいの音が出ます(AC電源のハム音に近い周波数です)。 出力が弱いので、自己バイアス型のアンプで増幅して利得を稼いでいます。

なぜこれで発振するのか?それは以前自分がtwitterでつぶやいた通りで、中心周波数は一番通しにくいにもかかわらず、 位相が大きくずれて180度に近いため、負帰還が正帰還に置き換わって、 その中心周波数で発振を起こします。中心周波数を大きく外れているところでは、 位相のズレがほぼ0になるので、自己バイアスと同じような負帰還になり、 発振には寄与しません。

LEDの制御用に使っている74HC595の余った出力ピンからリズムパルスを出力させることで、 コンデンサを通して微分 → ダイオードで立ち上がりだけ抽出 → ツインT型フィルタをつっついて一瞬だけ発振させる、という仕組みです。

左側のトランジスタの hFE(直流電流増幅率)は高めものがよいようです。 同じ型番でも hFE ランクの違うものがあったりするので、 できれば hFE 測定機能のついたテスターで測って確認してみることをおすすめします。 リズムマシンの場合「ボッ、ボッ」というリズム音にしたいので、一瞬だけ発振させたいものですが、 もし連続して発振してしまう場合は、エミッタ側に2.2kΩくらいの可変抵抗を入れて 増幅率を調整するとよいでしょう。 いずれにしても、これは一度ブレッドボードで実験してみてから定数を決めていったほうがよいです (近辺の値の部品を揃えたうえで調整するとよいでしょう)。

右側のトランジスタは、リズムに合わせてVUメーターを振らせるためのものです。 VUメーターの針に「ネギ」を取り付け、はちゅねミクにネギ振りをさせます。立てるとネギの重みで遅延しやすいですが、 寝かせると遅延は軽減されます。ほどよい力でネギ振りができるよう、実験的に抵抗値を選びました。


デジタルピン0・1:MIDI入出力(USB兼用)、デジタルピン13:MIDI ON/OFF

MIDI OUT

MIDI OUT は比較的簡単な回路で動きます。基本的には Arduino の Tx(D1) 端子を UART 出力とみなし、MIDI 本家の Tech Specs & Info MIDI-DIN Electrical Specification を参考にして 220Ω の抵抗を2本接続するだけ。 「Gates "A" are IC or transistor」は三角の部分を指しますが、 定格をオーバーしなければ、省略しても一応動きます(5V / 220Ω = 約23mA ということで 40mA オーバーは避けられる)。

MIDI IN、MIDI THRU - フォトカプラを使う

MIDI IN や MIDI THRU を実装する場合はフォトカプラ(英語では opto-isolator とも呼ばれる)が必要ですが、まだ購入していなかったため 最初は MIDI OUT だけを装着し、あとで増設できるよう余分に穴を開けておきました。

MIDI信号のビットの周期は 1/31250[bps] = 32μs しかないため、 フォトカプラにおける立ち上がり・立ち下がりの応答時間の差が 20μs もあると 波形が崩れて通信エラーの原因になります。スイッチング特性のグラフとか見ていると、 負荷抵抗が大きいと応答が遅れやすいようです。 できれば ns 単位で応答する高速タイプのものを使うとよいでしょう。例えば 6N138、6N139、TLP552、PC-900、PC-910L...あたりかな? 検索するとデータシートがあると思います。 今回は TLP552 を使ってみました。

フォトカプラの応答速度について参考になるページ

シリアルポートは MIDI だけでなく USB でも使っている - どうやって共存すればよいか?

Arduino Duemilanove の説明(英語)にある回路図(schematic)を見るとわかりますが、 Arduino Duemilanove の Rx(D0) と Tx(D1) 端子(UART 入出力)は 1kΩ の抵抗を介して USB コントローラーに直接つながっています。 このため、USB からデータが来ると MIDI OUT 側にも信号が流れ、 逆に MIDI IN から MIDI 信号が来ると USB 側にもデータが流れてしまうことになります。

実際、単純な回路で実験していたら、PC からスケッチ(プログラム)をアップロードしたとき、 MIDI Chord Helper が変な音を出してフリーズする...といった現象が起きていました。 原因は USB に流れたスケッチが MIDI に回り込んだためでした。 このときは、アップロード時だけ MIDI ケーブルを抜く、といった対応をしていました。

受信のケースでも同様の対応が必要なようです。これについては長嶋洋一氏Arduino日記に実験レポートがあります。

Arduino には、USB から RTS、DTR といったフロー制御ラインを通じて リセットをかける仕掛けがあります(ボタンでのリセットと全く同じ)。 PC 側の開発環境でスケッチをアップロードするとき、 まず PC 側から USB を通じてリセットをかけます。このとき Arduino は 一定時間新しいスケッチを待っているので、このタイミングでスケッチを送り込みます。 するとスケッチが更新され、Arduino が自動的に新しいスケッチを実行します。

Arduino MIDI schematic Opto-isolator and NAND gate

2010/07/02 回路図訂正 - この回路図の MIDI IN フォトカプラ発光部の接続で、 220Ωの抵抗と4番5番ピンの接続が誤って逆になっていたことが判明したので訂正しました。 改造中にフォトカプラを再配置して接続した際、どうもうまく受信できないな... と思って調べてみて気づきました。4番ピンがいつも+側・220Ωというふうに 覚えておくとよいようです。MIDI♀コネクタを裏側(ハンダ付け側)から見たとき、左が5番、右が4番です。

Arduino playground にあるMIDI Library を活用しています。

MIDI IN に使うフォトカプラ TLP552 の電源は、+5vへ直接つなぐのではなく、 Arduino のピンからとるようにしているので、スケッチから ON/OFF をコントロールできます。 MIDI THRU や MIDI OUT にも NAND ゲート経由でつないでおけば、これらの端子も同時に ON/OFF することができます。 4つの NAND ゲートがあれば足りるので 74HC00 1個で実現できます。

TLP552 の出力はオープンコレクタなので、抵抗でプルアップする必要がありますが、 実はここにも落とし穴が。

Arduino 側についている抵抗との間で「分圧」されてしまい、USB からの受信信号電圧が落ちるため、 アップロード(スケッチの受け取り)に支障が出ることがあるようです。 この問題については「やまだの人blog」2009/06/20 の記事 - Arduino用MIDIインタフェース改良に詳しく書かれていて参考になります。ダイオード1本追加することでプルアップ抵抗を 「一方通行」にすることで、簡単に解決できます。

リセットされてから USB 経由でのスケッチ書き換え中は、Arduino の D13 ピンは「入力ピン」になっています。 一見、D13 ピンの電圧は不定に見えますが、実際はフォトカプラの Vcc - GND 間の内部抵抗や、 D13 ピンに接続された Arduino 内蔵 LED が「プルダウン抵抗」として働くので、LOW 状態で固定されます。 これは NAND ゲートの入力にもつながっていて、LOW で NAND ゲートが閉じます。 これなら、Tx にスケッチなどの信号が回り込んだとしても、MIDI OUT へ伝わることはありません。 フォトカプラも OFF 状態なので、MIDI IN からの信号が Rx に伝わることもありません。

また、Rx にスケッチなどの信号が回り込んだ場合、ダイオードに逆電圧がかかるので、 それと直列につながった1kΩのプルアップ抵抗ごと OFF 状態になります。 これなら受信信号が分圧されてしまうこともありません。NAND ゲートも閉じているため、 回り込んだ信号が MIDI THRU に伝わってしまうこともありません。

スケッチの実行が開始されると、D13 ピンが HIGH になります。 すると、先ほどとは逆にフォトカプラとプルアップ抵抗が有効になり、NAND ゲートも開きます。 これによりすべての MIDI 端子が有効(=信号が伝わる状態)になります。

これでもう、スケッチの書き換えのたびに MIDI ケーブルを抜き差しする必要はありません。


回路図は EScad というフリーソフトで書いてます。新しい回路記号を自分で作れたりします。

ソースプログラム(スケッチ)

Arduino の開発環境で使う言語は C++ ベースになっているようで、 C++ の文法でクラスを定義できたりします。

KB 単位に達する大きいMIDIデータを const byte sequenceXX[] = {...} のように 埋め込むと、SRAM の制限を簡単にオーバーしてしまい、スケッチが暴走することがあります。 このようなデータは Flash メモリー上(スケッチと同じ領域)に置く必要があります。 そのためには PROGMEM を使って宣言し、専用の読み出し関数でアクセスする必要があります。 詳細はArduinoのメモリーのページを参照してください。

傾斜センサーを使って7セグメントLEDに表示される文字(音楽のコード名など)が 自動的に正立するようにしてあります。

MIDI Library v3.1 で新たに追加されたコールバック関数を使って実装しています (これより古いバージョンの MIDI Library ではコンパイルに失敗します)。

Arduino 1.0 でコンパイルを確認しています。 ただし MIDI Library のほうは、#include している WProgram.h や WContent.h を Arduino.h に書き換える必要があります (Arduino 1.0 からはヘッダ名が変わっています)。

スケッチは OSDNの作業部屋に置いてあります。


[ページ先頭へ戻る]