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