Arduino制御ピアノロボット:PiBot
コンポーネントと消耗品
> |
| × | 1 | |||
| × | 11 | ||||
| × | 88 | ||||
| × | 2 | ||||
| × | 11 | ||||
| × | 1 | ||||
| × | 11 | ||||
| × | 11 | ||||
| × | 88 | ||||
| × | 88 |
必要なツールとマシン
> |
|
アプリとオンラインサービス
| ||||
| ||||
|
このプロジェクトについて
開始方法:
何年も前に、ヤマハは自動ピアノを導入しました。若くて無邪気な私は、ピアノが楽器店のガラス窓の後ろで音楽を演奏しているのを見ました。
小さな話は十分にありますが、私がこのプロジェクトを始めた理由は、私が望んでいたこと以外に、それほど大きな理由はありません。
概要:
Arduino Megaの1枚のボードの価格は約40ドルで、88個のソレノイドを制御するには2枚必要です。それはかなり高価です。代わりに、安価なArduinoUnoと11個のシフトレジスターを入手してください。シフトレジスタは、少数の出力ピンで多くの出力(通常はLED)を制御する方法です。基本的に、これは11個のシフトレジスタと88個のソレノイドを制御する1つのArduinoです。
Shiftレジスタを使用しているため、PCはMIDIcomではなくArduinoにビットセットを送信します。 MIDIファイルは事前にビットセットに変換されます。
ハードウェア:
中国から直接ソレノイドを入手したとき、これらのソレノイドはピアノの鍵盤を押すのに十分な強度がないことがわかりました。もちろん、一番奥からピアノの鍵盤を押すのは力がかかりますが、ピアノを壊さないのが一番いい方法だと思いました。最終的には、十分な電力を得るために24Vから12Vのソレノイドを押し込みました。
88ソレノイドは多くの電力を消費しますが、高価なPSUを購入することができないため、父の車のバッテリーを使用することにしました。 (彼は今どこにも行かないと思います!)
それが邪魔にならないように、シフトレジスタとMOSFETのそれぞれがコントローラボードに配置されます。
私がそれを燃やす場合に備えて、ソケット付きの右側の595。 (私が一度やったことです。)回路図はここからの例2とまったく同じです。 LEDをMOSFETゲートに交換してください。ご覧のとおり、抵抗を追加するとコストが高くなり、ボードにはんだ付けすると指が溶けるため、プルダウン抵抗はありません。もう少し深刻な面では、これらのMOSFETは5Vで開き、4V程度で閉じます。数え切れないほどのテストを通してそれを確認しました。 (理論的には正しくありません。私に耳を傾けないでください。)
最後に、ソレノイドを接着するためのプラスチックプレートを入手します。ホットグルーとプラスチックプレートを使用することは、熱くなることを考えると悪い考えですが、私が手に入れることができる最高のものです。
次に、ソレノイドワイヤの片側をバッテリーのプラス側に配線します。
ソフトウェア:
最初のステップは、MIDIファイルを取得することです。
2番目のステップは、MIDIをテキスト形式にすることです。これは、次の便利なWebサイトで実行できます:http://flashmusicgames.com/midi/mid2txt.php。
簡単にするために、拍子記号、テンポ、パーは無視してください。テンポは後で時間を掛けることができます。基本的に、次のようなファイルが必要です:
次に、これを使用して、Pythonコード(添付)を実行することにより、時間の経過とともに11セットの8ビットデータを作成します。
COMの処理を通じてArduinoに送信する準備ができています。
添付ファイルを参照して、処理がこれらのデータを送信する方法とArduinoがそれらを処理する方法を理解してください。
*注:私のコーディングの習慣は悪く、これらを読むのは難しいかもしれません。 Arduinoは物理的なピアノでデータを右にプッシュするため、Processingはデータを右から左に送信します。
このことは機能しています:
トラブルシューティング:
プロのエンジニアがこの投稿を見ると、このシステム全体に多くの問題があると彼は考えるでしょう。そして、多くの問題があります。
ソレノイドはプレートに熱接着されていたため、ソレノイドが過熱して熱接着剤が溶けることが大きな問題でした。解決策は、単にそれらを取り外して、150℃まで耐えることができる両面テープと交換することでした。
コード
- 翻訳用のPythonコード
- arduinoにデータを送信するための処理
- Arduinoコード
翻訳用のPythonコード Python
テキスト化されたmifiファイルを取得し、arduinoが取得できるように11セットのバイナリに変換します。output_file =open( "translated.txt"、 "w")input_file =open( "megalocania.txt")raw_input_data =input_file.read ()work_data =raw_input_data.splitlines()result =[] #output_file =open( "result.txt"、 "w")def main():for a in work_data:temp_time =time_finder(a)if result ==[] :result.append(str(temp_time)+ "、")if on_off_finder(a):result [-1] + =set_bit(True、note_finder(a))elif not on_off_finder(a):result [-1] + =set_bit(True、note_finder(a))elif time_finder_comm(result [-1])==temp_time:result [-1] =str(temp_time)+ "、" + set_bit_prev(on_off_finder(a)、note_finder(a)、- 1)elif time_finder_comm(result [-1])!=temp_time:result.append(str(temp_time)+ "、" + set_bit_prev(on_off_finder(a)、note_finder(a)、-1))for b in result:output_file .write(b)output_file.write( "\ n")output_file.close()def set_bit(On、note):#オンかどうかをブール値で取得し、番号をメモします。 #ビットを生成if(note> =21 and note <=28 and On):return str(2 **(note-21))+ "、0,0,0,0,0,0,0,0,0 、0 "elif(note> =29 and note <=36 and On):return" 0、 "+ str(2 **(note --29))+"、0,0,0,0,0,0、 0,0,0 "elif(note> =37 and note <=44 and On):return" 0,0、 "+ str(2 **(note --37))+"、0,0,0,0 、0,0,0,0 "elif(note> =45 and note <=52 and On):return" 0,0,0、 "+ str(2 **(note --45))+"、0、 0,0,0,0,0,0 "elif(note> =53 and note <=60 and On):return" 0,0,0,0、 "+ str(2 **(note-53)) + "、0,0,0,0,0,0" elif(note> =61 and note <=68 and On):return "0,0,0,0,0、" + str(2 **( note --61))+ "、0,0,0,0,0" elif(note> =69 and note <=76 and On):return "0,0,0,0,0,0、" + str (2 **(note --69))+ "、0,0,0,0" elif(note> =77 and note <=84 and On):return "0,0,0,0,0,0、 0、 "+ str(2 **(note --77))+"、0,0,0 "elif(note> =85 and note <=92 and On):return" 0,0,0,0,0 、0,0,0、 "+ str(2 **(note --85))+"、0,0 "elif(note> =93 and note <=100 and On):return" 0,0,0、 0,0,0,0,0,0、 "+ str(2 **(注-93))+"、0 "elif(注> =101およびnote <=108 and On):return "0,0,0,0,0,0,0,0,0,0、" + str(2 **(note-101))else:return "0,0 、0,0,0,0,0,0,0,0,0 "def set_bit_prev(On、note、index):#set_bitと同じですが、以前は認識されていましたtemp =result [index] temp =temp [(temp.find ( "、")+ 1):] if(note> =21 and note <=28):local_temp =temp [0:temp.find( "、")] if(On):return str(int(local_temp) +(2 **(note-21)))+ temp [temp.find( "、"):] if(not On):return str(int(local_temp)-(2 **(note-21))) + temp [temp.find( "、"):] elif(note> =29 and note <=36):local_temp =temp [(temp.find( "、")+ 1):indexTh(temp、 "、" 、2)] if(On):return temp [0:temp.find( "、")+ 1] + str(int(local_temp)+(2 **(note --29)))+ temp [indexTh(temp 、 "、"、2):] if(not On):return temp [0:temp.find( "、")+ 1] + str(int(local_temp)-(2 **(注-29))) + temp [indexTh(temp、 "、"、2):] elif(note> =37 and note <=44):local_temp =temp [(indexTh(temp、 "、"、2)+ 1):indexTh(temp 、 "、"、3)] if(On):return temp [0:indexTh(temp、 "、"、2)+ 1] + str(int(local_temp)+(2 **(注-37))) + temp [in dexTh(temp、 "、"、3):] if(not On):return temp [0:indexTh(temp、 "、"、2)+ 1] + str(int(local_temp)-(2 **(注--37)))+ temp [indexTh(temp、 "、"、3):] elif(note> =45 and note <=52):local_temp =temp [(indexTh(temp、 "、"、3)+ 1 ):indexTh(temp、 "、"、4)] if(On):return temp [0:indexTh(temp、 "、"、3)+ 1] + str(int(local_temp)+(2 **(注--45)))+ temp [indexTh(temp、 "、"、4):] if(not On):return temp [0:indexTh(temp、 "、"、3)+ 1] + str(int(local_temp )-(2 **(note --45)))+ temp [indexTh(temp、 "、"、4):] elif(note> =53 and note <=60):local_temp =temp [(indexTh(temp、 "、"、4)+ 1):indexTh(temp、 "、"、5)] if(On):return temp [0:indexTh(temp、 "、"、4)+ 1] + str(int(local_temp )+(2 **(注-53)))+ temp [indexTh(temp、 "、"、5):] if(not On):return temp [0:indexTh(temp、 "、"、4)+ 1] + str(int(local_temp)-(2 **(note-53)))+ temp [indexTh(temp、 "、"、5):] elif(note> =61 and note <=68):local_temp =temp [(indexTh(temp、 "、"、5)+ 1):indexTh(temp、 "、"、6)] if(On):return temp [0:indexTh(temp、 "、"、5)+ 1 ] + str(int(local_temp)+(2 **(note --61)))+ temp [indexTh(temp、 "、"、6):] if(not On):return temp [0:indexTh(temp、 "、"、5)+ 1] + str(int(local_temp)-(2 **(note --61)))+ temp [indexTh(temp、 "、"、6):] elif(note> =69 and注<=76):local_temp =temp [(indexTh(temp、 "、"、6)+ 1):indexTh(temp、 "、"、7)] if(On):return temp [0:indexTh(temp、 "、"、6)+ 1] + str(int(local_temp)+(2 **(note-69)))+ temp [indexTh(temp、 "、"、7):] if(not On):return temp [0:indexTh(temp、 "、"、6)+ 1] + str(int(local_temp)-(2 **(note-69)))+ temp [indexTh(temp、 "、"、7): ] elif(note> =77 and note <=84):local_temp =temp [(indexTh(temp、 "、"、7)+ 1):indexTh(temp、 "、"、8)] if(On):return temp [0:indexTh(temp、 "、"、7)+ 1] + str(int(local_temp)+(2 **(note --77)))+ temp [indexTh(temp、 "、"、8): ] if(not On):return temp [0:indexTh(temp、 "、"、7)+ 1] + str(int(local_temp)-(2 **(note --77)))+ temp [indexTh(temp 、 "、"、8):] elif(note> =85 and note <=92):#error here local_temp =temp [(indexTh(temp、 "、"、8)+ 1):indexT h(temp、 "、"、9)] if(On):return temp [0:indexTh(temp、 "、"、8)+ 1] + str(int(local_temp)+(2 **(注-85 )))+ temp [indexTh(temp、 "、"、9):] if(not On):return temp [0:indexTh(temp、 "、"、8)+ 1] + str(int(local_temp)- (2 **(note --85)))+ temp [indexTh(temp、 "、"、9):] elif(note> =93 and note <=100):local_temp =temp [(indexTh(temp、 "、 "、9)+ 1):indexTh(temp、"、 "、10)] if(On):return temp [0:indexTh(temp、"、 "、9)+ 1] + str(int(local_temp)+ (2 **(注-93)))+ temp [indexTh(temp、 "、"、10):] if(not On):return temp [0:indexTh(temp、 "、"、9)+ 1] + str(int(local_temp)-(2 **(note --93)))+ temp [indexTh(temp、 "、"、10):] elif(note> =101 and note <=108):local_temp =temp [(indexTh(temp、 "、"、10)+ 1):] if(On):return temp [0:indexTh(temp、 "、"、10)+ 1] + str(int(local_temp)+(2 **(注-101)))if(not On):return temp [0:indexTh(temp、 "、"、10)+ 1] + str(int(local_temp)-(2 **(注-101) ))def indexTh(in_string、find_this、th):#Takes String、string to find、and order to find string to find atその順序#returnsインデックスorder =1 last_index =0 while(True):temp =in_string.find(find_this、last_index)if(temp ==-1):return -1 if(order ==th):return temp order + =1 last_index =temp + 1def time_finder(in_string):#文字列を取得して時間を見つけ、それをintとして返しますtime_end =in_string.index( "")return int(in_string [0:time_end])def time_finder_comm(in_string): #文字列を取得して時間を検索し、intコンマとして返しますtime_end =in_string.index( "、")return int(in_string [0:time_end])def note_finder(in_string):#文字列を取得し、n =を検索します。 n値をintとして返しますnum_start =in_string.index( "n =")+ 2 num_end =in_string.index( "v =")-1 return int(in_string [num_start:num_end])def on_off_finder(in_string):#takes文字列、オンまたはオフを検索し、オンの場合はtrueを返しますstart =in_string.index( "")+ 1 end =in_string.index( "ch =")-1 if in_string [start:end] =="On": True elif in_string [start:end] =="Off"を返します:Falsemain()を返します
arduinoにデータを送信するための処理処理
翻訳されたテキストファイルを読み取り、arduinoに送信します。テンポが50000と異なる場合は、テンポ乗数を変更する必要があります。
左から右にシフトするため、バイトを反転します。 (テキストファイルは右から左を想定しています)
importprocessing.serial。*; Serial myPort; String [] inputLines; void setup(){myPort =new Serial(this、 "COM3"、9600); inputLines =loadStrings( "translated.txt"); run();} void run(){//時間を読み取り、データメソッドint lastTime =0を使用してデータbt行を送信します。 for(int i =0; iArduinoコード Arduino
arduinoのシンプルなコード。シリアルから入力を受け取ります。 888および999は、シフトレジスタの開閉コマンド用に予約されています。プレビューなし(ダウンロードのみ)。
回路図
専門家ではないお絵かきでごめんなさい。これが全体のコンセプトです。 MOSFETを除いて、Arduino-ShiftOutドキュメントの図に違いはありません。私もそれを見ることをお勧めします。 製造プロセス