AE-DRV8830 と HC-05を連携させてモーターを制御する(ブレッドボード編) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6964
の続きで、これをユニバーサル基板で作ります。本来ならば、プリント基板を作ってとか、回路図を作ってってことになるのでしょうが、初手なので手作りで半田付け、ってのと最終的には Arduino 用のチップも載せてしまって小型化したかったってのがあります。まあ、やってみた感じでは、ユニバーサル基板で作るのは手作業が大変です…が、感光基盤だと子供がいる家ではできないし、ちょっと考えないと。
材料
- DRV8830 x2 @170円
- HC-05 x1 @1,000 円ぐらい
- オス・メスピン @100円ぐらい?
- ユニバーサル基板 x1 @270円(昔買った)
- 抵抗 10kΩ x2
- コンデンサ 10nF x2
な感じです。まあ、完成品を Amazon.co.jp: Arduino MEGA UNO Duemilanove 最高品質 用の L293D モーター シールド ボード: DIY・工具 あたりで買うのが手っ取り早いのですが(これは、ひどく安いけど、1,000円から2,000円ぐらいです。秋月電子で DRV8830 のキット 650円 を2つ買うってのもありです。本来ならばターミナルブロックを使って給電したり、モーターを回したりすればいいのですが、手元になかったのでピンヘッダで代用。どうせ、Arduino からジャンパーピンを差してテストするので、このほうがやりやすいです。
DRV8830 を使うといいのは、I2C で通信ができるので、通信回線が SCL/SDA の 2本だけで済むことです。L293D を使ったモータードライバだと、モーター2個でGPIO 経由で 4本の線が必要になります。2個くらいだったらそれでもいいけど、4個とか8個とかにふえても SCL/SDA の 2本だけになるから便利ですよね…となっていますが、本当に 4個いけるかどうかは分かりません。モーター駆動のと、信号線の電源が同じになっているので、ノイズが多くてモーターの挙動が信号線に乗ってしまうのは結構問題なんですよね。モーターによってはノイズが乗って、暴走状態になります。もともと、プリンタの駆動系とかを動かすものなので、ミニ四駆とか車輪とかを動かすには向いていないようです。でも、まあ、タミヤのギアボックス付属のモーター FA-130 レベルならば大丈夫でした。
配線
回路図はよくわからないので、ブレッドボードで作ったものを
そのままユニバーサル基板に配置して、
配線します(苦笑)
配線の美意識のかけらもないものですが、まあ、腐ったコードでも動くコードを乗せておくこともあるし、ひとまず動けば ok 的なものなので、これでいいです。ひとまず動きますから。
これを、Arduino とつなげます。
更に、ギアーボックスとつなげます。
ブレッドボードじゃなくてわざわざ基板を使っているのにジャンパーピンが錯綜しているのは、Arduino のシールドになっていないからです。これだと、あまりにも壊れやすいので、もうちょっと頑丈につくらないと駄目なので、昨晩 Arduino 用のシールド基板を注文しました。他にも色々と。
どうやって通信するのか?
HC-05 は Bluetooth 2.0 なので、今流行りの BLE ではありません。なので、iPhone から操作することはできないのですが、単純な SPP 通信(シリアル通信)を使って手軽にパソコンとやり取りができます(最終的には、PS3 Dualshock3 のような既存のコントローラーと通信したいところなのですが、これは Raspberry Pi のほうが非常に簡単なのです。たしか、USB ポートがあってロボットを操作する SBDBT とか)。
Arduino + USBホストシールドの実験。 – robo8080のブログ
http://blog.goo.ne.jp/roboz80/e/9d2fc6e1266932f7ace682b43393217b
でもって、手元の HC-05 は Bluetooth シリアル変換モジュールなので、そのまま Serial を使うことができます。
Arduino のスケッチ
#include <Wire.h> const int DRV8830a = 0xC8 >> 1 ; // 0x64; const int DRV8830b = 0xC6 >> 1 ; // 0x63; const int FAULTn = 13 ; const int LED = 12 ; int writeRegister( byte drv, byte vset, byte data ) { int vdata = vset << 2 | data ; Wire.beginTransmission( drv ); Wire.write( 0x00 ); Wire.write( (vset<<2) + data ); return Wire.endTransmission(); } void clearError() { Wire.beginTransmission( DRV8830a ); Wire.write(0x01); Wire.write(0x80); } void checkError() { if ( digitalRead(FAULTn) == HIGH ) { return ; } Wire.beginTransmission( DRV8830a ); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom( DRV8830a, 1 ); byte error = Wire.read(); Serial.println( error, BIN); if ( error & 0b00000011 ) { Serial.println("over current" ); } else if ( error & 0b00000101 ) { Serial.println("under voltage" ); } else if ( error & 0b00001001 ) { Serial.println("over heat" ); } else if ( error & 0b00010001 ) { Serial.println("limit current" ); } clearError(); } int mode = 0; void setup() { // put your setup code here, to run once: pinMode( FAULTn, INPUT ); pinMode( LED, OUTPUT ); Wire.begin(); Serial.begin(9600); Serial.println( "Motor Standby" ); Serial.println( DRV8830a, HEX); Serial.println( DRV8830b, HEX); writeRegister( DRV8830a, 0x00, 0x00 ); writeRegister( DRV8830b, 0x00, 0x00 ); delay( 2000 ); } void loop() { // put your main code here, to run repeatedly: int len = Serial.available(); if ( len < 2 ) return ; int type = Serial.read(); // M or L int num = Serial.read(); // MF/MB/M0, L0/L1 if ( type == 'M' || type == 'N') { int mode = 0; switch ( num ) { case '0': mode = 0; break; case 'F': mode = 1; break; case 'B': mode = 2; break; default: mode = 0; break; } switch ( mode ) { case 0: Serial.println("motor standby" ); writeRegister( type == 'M'? DRV8830a: DRV8830b, 0x00, 0x00 ); break; case 1: Serial.println("motor forward" ); writeRegister( type == 'M'? DRV8830a: DRV8830b, 0x15, 0x02 ); checkError(); // delay( 2000 ); break; case 2: Serial.println("motor back" ); writeRegister( type == 'M'? DRV8830a: DRV8830b, 0x15, 0x01 ); checkError(); // delay( 2000 ); break; } } if ( type == 'L' ) { Serial.println("LED on/off" ); int mode = 0; switch ( num ) { case '0': mode = 0; break; case '1': mode = 1; break; default: break; } if ( mode == 0 ) { digitalWrite(LED, LOW ); } else { digitalWrite(LED, HIGH ); } } }
ブレッドボード用に作ったものなので、エラーチェックの FAULTn と LED のコードが入っていますが、”MF” とか “MB” とかいう自作のコマンドを使ってモーターをコントロールします。
Windows ストアアプリから操作する
Android からやるのが見栄えがいいのですが、まずは Windows ストアアプリからやります。
Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6819
と同じように Package.appxmanifest を設定したあとに、接続とコマンド送信部分を書きます。
private async void btn_findDevice_Click(object sender, RoutedEventArgs e) { string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid)); DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector); if (collection.Count > 0) { DeviceInformation info = collection.First(); rfcommService = await RfcommDeviceService.FromIdAsync(info.Id); socket = new StreamSocket(); await socket.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName); writer = new DataWriter(socket.OutputStream); reader = new DataReader(socket.InputStream); textOut.Text = "接続しました"; } else { MessageDialog dialog = new MessageDialog("デバイスが見つかりませんでした"); await dialog.ShowAsync(); } } private async void clickMF(object sender, RoutedEventArgs e) { writer.WriteString("MF"); await writer.StoreAsync(); } private async void clickMB(object sender, RoutedEventArgs e) { writer.WriteString("MB"); await writer.StoreAsync(); } private async void clickM0(object sender, RoutedEventArgs e) { writer.WriteString("M0"); await writer.StoreAsync(); } private async void clickNF(object sender, RoutedEventArgs e) { writer.WriteString("NF"); await writer.StoreAsync(); } private async void clickNB(object sender, RoutedEventArgs e) { writer.WriteString("NB"); await writer.StoreAsync(); } private async void clickN0(object sender, RoutedEventArgs e) { writer.WriteString("N0"); await writer.StoreAsync(); }
画面はボタンを並べただけ。
これだと、Arduino 側からフィードバックがないので、様子がわからないのですが、それなりに動きます。あと、DRV8830 はモーターに流れる電圧を変えることができるので前進後進だけではなく、スピードを変えることができます。このあたりを入れて Arduino のスケッチとストアアプリのコードを変えると結構いけるかなと。ああ、あとバーンと鳴るとか、LED を光らせるとかギミック用のコマンドもいれないと。
で、これは Windows ストアアプリで作ったけど、デスクトップアプリ(WinフォームとかWPFとか)でも作れます。次は、Windows のコンソールアプリで RFCOMM を利用する | Moonmile Solutions Blog を使って WPF アプリに書き直してみます。
you did well even if i cant understand ur language,the picture are enough,, please can you tell me how to configure bluetooth
You can setting at command in HC-05.
please refer
How to enter AT mode in HC-05 bluetooth module
http://forum.arduino.cc/index.php?topic=128991.0
Arduino with HC-05 (ZS-040) Bluetooth module – AT MODE | Martyn Currey
http://www.martyncurrey.com/arduino-with-hc-05-bluetooth-module-at-mode/
Configuring your Bluetooth Module for the Communication between Scratch and Arduino | Iniciativa Computação na Escola
http://www.computacaonaescola.ufsc.br/?page_id=536&lang=en