8pino を無線化してモータを動かす

手元の Arduino Uno の SCL/SDA の調子が悪いので(先日、モータードライバーを焼き切ったときに一緒にやられた?)、代わりに 8pino を使って動作検証していました。

image

ブレッドボードの左にあるのが 8pino のつもり(ATTiny85互換なので、そのまま利用)。

モータードライバの DRV8830 の SCL と SDA は、8pino の #2 と #0 に差せば ok。シリアル通信は、8pino の #3 と #4 を使って HC-05 と通信させる。8pino に 5V を給電させれば、ひとまず HC-05 は動くようになりました。通信がうまく動かなかったのは電源のところに 10μF 程度のコンデンサを置くことで解消した模様。モーターへの給電は、1.5V を送ってしまうと、通信が止まってしまうので、0.6 V ぐらいに抑える。そうすると、Bluetooth から制御して、モーターが動いた状態でも止まらなくなる。

ただ、これだとモーターの動力源的には足りないので(ちょっと動かすぐらいらば大丈夫だけど)、別電源を用意したほうがよさそう。

https://pbs.twimg.com/media/CAv9gOtUIAATNpi.jpg:large

スケッチはこんな感じ。

 
#include <SoftwareSerial.h>
#include <TinyWireM.h>
const int DRV8830 = 0xC8 >> 1 ; // 0x64;
SoftwareSerial mySerial = SoftwareSerial(3, 4);  // RX, TX
void writeRegister( int drv, byte vset, byte data ) 
{
  int vdata = vset << 2 | data ;
  TinyWireM.beginTransmission( drv );
  TinyWireM.send( 0x00 );
  TinyWireM.send( (vset<<2) + data );
  TinyWireM.endTransmission();
}
void setup() {
  // put your setup code here, to run once:
  TinyWireM.begin();
  writeRegister( DRV8830, 0x00, 0x00 );
  mySerial.begin(9600);  
  delay( 2000 );
  
}
void loop() {
  int len = mySerial.available();
  if ( len < 2 ) return ;
  int type = mySerial.read();   // M or L
  int num  = mySerial.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: 
         writeRegister( DRV8830,  0x00, 0x00 );
        mySerial.print(&quot;stop----&quot;);
        break;
      case 1:
        writeRegister( DRV8830,  0x0A, 0x02 );
        mySerial.print(&quot;forward-&quot;);
        break;
      case 2:
        writeRegister( DRV8830,  0x0A, 0x01 );
        mySerial.print(&quot;back----&quot;);
        break;
    }
  }
}

 

ATTiny85 は Wire をそのままは使えないので、TinyWireM.h を使う。Bluetooth モジュールへのシリアル通信もポート番号が異なるので、SoftwareSerial を使う。

Bluetooth はシリアル通信を使っているので、コントロールしているストアアプリのほうへ、mySerial.print すると応答を返せる。通常 8pino のような小さい arduino はデバッグ用のシリアルポートがつなげなくて困るのだけど、こんな風に Bluetooth 経由で情報を取り出せるのはいいかなと思う。

これを netduino で動かしたいんだが、まだ I2Cがうまく動いてない。

カテゴリー: Arduino, Bluetooth | 8pino を無線化してモータを動かす はコメントを受け付けていません

Arduino を無線化(Blutooth)して戦車を作る(ユニバーサル基板編)

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 レベルならば大丈夫でした。

配線

回路図はよくわからないので、ブレッドボードで作ったものを

20150310_02

そのままユニバーサル基板に配置して、

image

配線します(苦笑)

image

配線の美意識のかけらもないものですが、まあ、腐ったコードでも動くコードを乗せておくこともあるし、ひとまず動けば ok 的なものなので、これでいいです。ひとまず動きますから。

これを、Arduino とつなげます。

image

更に、ギアーボックスとつなげます。

image

ブレッドボードじゃなくてわざわざ基板を使っているのにジャンパーピンが錯綜しているのは、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(&quot;over current&quot; );
  } else if ( error & 0b00000101 ) {
    Serial.println(&quot;under voltage&quot; );
  } else if ( error & 0b00001001 ) {
    Serial.println(&quot;over heat&quot; );
  } else if ( error & 0b00010001 ) {
    Serial.println(&quot;limit current&quot; );
  }
  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( &quot;Motor Standby&quot; );
  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(&quot;motor standby&quot; );
        writeRegister( type == 'M'? DRV8830a: DRV8830b,  0x00, 0x00 );
        break;
      case 1:
        Serial.println(&quot;motor forward&quot; );
         writeRegister( type == 'M'? DRV8830a: DRV8830b,  0x15, 0x02 );
        checkError();
        // delay( 2000 );
        break;
      case 2:
        Serial.println(&quot;motor back&quot; );
         writeRegister( type == 'M'? DRV8830a: DRV8830b,  0x15, 0x01 );
        checkError();
        // delay( 2000 );
        break;
    }
  }
  if ( type == 'L' ) {
    Serial.println(&quot;LED on/off&quot; );
    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 = &quot;接続しました&quot;;
    }
    else
    {
        MessageDialog dialog = new MessageDialog(&quot;デバイスが見つかりませんでした&quot;);
        await dialog.ShowAsync();
    }
}

private async void clickMF(object sender, RoutedEventArgs e)
{
    writer.WriteString(&quot;MF&quot;);
    await writer.StoreAsync();
}
private async void clickMB(object sender, RoutedEventArgs e)
{
    writer.WriteString(&quot;MB&quot;);
    await writer.StoreAsync();
}
private async void clickM0(object sender, RoutedEventArgs e)
{
    writer.WriteString(&quot;M0&quot;);
    await writer.StoreAsync();
}

private async void clickNF(object sender, RoutedEventArgs e)
{
    writer.WriteString(&quot;NF&quot;);
    await writer.StoreAsync();
}
private async void clickNB(object sender, RoutedEventArgs e)
{
    writer.WriteString(&quot;NB&quot;);
    await writer.StoreAsync();
}
private async void clickN0(object sender, RoutedEventArgs e)
{
    writer.WriteString(&quot;N0&quot;);
    await writer.StoreAsync();
}

画面はボタンを並べただけ。

image

これだと、Arduino 側からフィードバックがないので、様子がわからないのですが、それなりに動きます。あと、DRV8830 はモーターに流れる電圧を変えることができるので前進後進だけではなく、スピードを変えることができます。このあたりを入れて Arduino のスケッチとストアアプリのコードを変えると結構いけるかなと。ああ、あとバーンと鳴るとか、LED を光らせるとかギミック用のコマンドもいれないと。

で、これは Windows ストアアプリで作ったけど、デスクトップアプリ(WinフォームとかWPFとか)でも作れます。次は、Windows のコンソールアプリで RFCOMM を利用する | Moonmile Solutions Blog を使って WPF アプリに書き直してみます。

カテゴリー: Arduino, Bluetooth, WinRT | 2件のコメント

AE-DRV8830 と HC-05を連携させてモーターを制御する(ブレッドボード編)

昨晩、AE-DRV8830 を使ってモーターが動いたので、そのまま HC-05(Bluetooth)と連携させてテスト、そのまま、もうひとつ AE-DRV8830 をつなげて、2個のモーターを動かすことができました。

20150310_02

これで、先に作った RasPi 戦車を自作のモータードライバ版に置き換えられます。AE-DRV8830 は、秋月電子で買えば 170円なので、2個買っても 340円と非常に安いです。一般的な Raspberry Pi のモーターシールドが 3000円強するので、これを使えばかなりモーターが制御できるようになります。ただし、Arduino に限って言えば Amazon.co.jp: Arduino MEGA UNO Duemilanove 最高品質 用の L293D モーター シールド ボード: DIY・工具 なんてのが出ていて、なんかひどく安いです。IC に L293D というのを使っていて、一時期大量生産したのか中国でコピーものが広まったのかよくわかりませんが、えらく安く手に入ります。ただし、レビューを見ると品質的に問題があって、動いたり動かなかったりする外れもあるみたいなんですが。

実は、L293D の IC って、日本向けには売っていないんですよね。

L293D | ペリフェラル・ドライバ/アクチュエータ | 他のインターフェイス | 概要と機能一覧
http://www.tij.co.jp/product/jp/L293D?keyMatch=L293D&tisearch=Search-JP-Everything

まあ、eBuy 経由か、どこか適当なところから買えば安く手にはいるので問題はなさそうです。海外の作例を見ると L293D を使っている例があって、手元の Raspberry Pi のモーターシールドにも L293D を使っているので回路を組んではみたいと思ってます。1つのICで、2つのモーターが制御できるので、AE-DRV8830 を 2つ使わなくてもよい、という利点があります。他にも色々違いはあると思うのですが。

それはさておき、

  • Arudino で、DRV8830 に Wire 送信する。
  • Arduino で、HC-05/Bluetooth シリアル受信する。
  • Windows ストアアプリから HC-05 へシリアル送信する。

のプログラムを組んで、無事無線でモーター制御が完了。コードは後日まとめます。Arduino のチップを抜き出して小型すれば、そのままプラレールの電車に乗せられそうです(電池は2両目から供給ってことになりそうですが)。

実際に配線したところはこちら。えらいごちゃごちゃしているのは、ジャンパーピンでやっているからですね。LED がついているのは、Bluetooth でのシリアル通信の確認用です。

image

タイマ IC 555 を 2つ使ってモーターを制御できる

DRV8830 は I2C を使っているので、たくさんの IC を使っても一組の SDA/SCL で済みます。まあ、それでもチップが小さすぎるので本格的に小型化するとき(基板に乗せるとき?)はいいんでしょうが、1,2 個のモーター制御だけだとちょっと大げさな感じがします。

で、Frizing のページを Bluetooth で検索していたら、タイマ IC を 2個使ってモーターを制御している例がありました。

Fritzing Project – Arduino Android Bluetooth Panzer
http://fritzing.org/projects/arduino-android-bluetooth-panzer
New Project: Projects in Motion: Control Three Types of Motors with 555 Timers – Make: | Make:
http://makezine.com/projects/projects-in-motion-control-three-types-of-motors-with-555-timers/

555 のタイマー IC は、ひどく安くて 30円とか50円ぐらいのものからあります。Arduino からのピン制御の数は増えてしまいますが、モーターだけを制御したい場合にはこれで十分かもしれません。これはまた別途購入したら試してみましょう。

カテゴリー: Arduino | AE-DRV8830 と HC-05を連携させてモーターを制御する(ブレッドボード編) はコメントを受け付けていません

mbed LPC1114FN28 で Lチカする

mbed LPC1114FN28 – スイッチサイエンス
https://www.switch-science.com/catalog/1714/
mbed LPC1114FN28

勢い(調子に)乗って、mbed も買ってみました。評価キットになっているものはそれなりに値段が高いので、ほとんど素の状態の LPC1114FN28 を使います。ついでに、LPC1114FN28 本体も安い(200円ちょっと)ので 2個ほど手に入れました。これでマイコンを倍増できるぞと思っていたわけですが、手元に届くと結構でかいですね、これ。20x40mm 位あって小さなブレッドボードの半分を占有してしまいます。今あらためてみたんですが、LPC1114FN28 って 32ビットマイコンなんですね。

ブラウザ上でコーディングする

http://developer.mbed.org/ でサインアップして、ブラウザ上でコーディングします。このアドレスは、mbed を USB に接続したときに出てくる、mbed.htm に書いてあります。この中には、デバイスの ID が書いてあるので、サイトでの登録も自動的に行われます。

image

インテリセンスはあまり効きませんが、ダブルクリックをするとヘルプがでます。あまりマニュアルを見なくても、なんとなくコーディングができるのが便利です。あと、色々なサンプルとライブラリがあるそうなので、そのあたり使うと一気に楽になるかも。

コンパイルして mbed にインストールする

メニューにある「Compile」ボタンを押すと、コンパイルが始まって、成功すると出来上がったバイナリファイル(*.bin)をダウンロードできるようになります。このファイルを、mbed がつながっているドライブにドラッグ&ドロップすれば ok です。

あとは、mbed ボードのスイッチを押してリセットすれば完了です。非常に簡単ですね。ブレッドボードを使って Lチカするだけならば、あっという間です。センサーを読み込んだり、サーボを動かしたりするのはそれなりに組まないとだめなんでしょうが、そのあたりは cookbook にありそうです。

image

ひとまず、

  • Raspberry Pi
  • Arduino
  • Netduino
  • PIC
  • mebed

と開発環境を触ってきたので、これで一区切りです。それぞれ得手不得手があるので、Raspi 戦車とか meArm をベースにして書き換えていこうという心づもり。あと Bluetooth LE との組み合わせとか、かなり自分の手が広がった感じ。

そうそう、ターゲットは、Raspberry Pi 2  + Windows 10 + 戦車/ロボットアーム ですからッ!!! これが一気にできると、相当広がるはず、と思ってます。

カテゴリー: mbed | mbed LPC1114FN28 で Lチカする はコメントを受け付けていません

PICでLチカするための環境を整える

やっとこさ PIC までたどり着いた…と思ったら、LPC という ARM のチップがあることを知ったので(mbed って ARM ですね、確かに)、小さくするのならば LPC でもいいかなと思い始めてはいるのですが…ともあれ、どちらもやったことがないので、まずは PIC から。

image

秋月電子で、PICkit3PIC18F14K50使用USB対応超小型マイコンボード を一緒に買いました。PIC のチップだけを買えば、100円もしないのですが、書き込み方がよくわからないのと、USB 書き込み(たぶんシリアル経由ですよね)と ICSP直結(こっちが PICKit3 で書き込む方)自体がよくわからなかったので、まあひとまず、初期投資ということで。それでも RPi を買うよりも随分安いわけですが。

開発環境をインストールする

MPLAB®X IDE | Microchip Technology Inc.
http://www.microchip.com/pagehandler/en-us/family/mplabx/home.html

上記から MPLAB X IDE をダウンロードします。現時点で、v3 のベータ版が出ているのですが、Available Downloads のほうの v2.35 を入れました。

これをインストールすると、コンパイラが自動でダウンロードして…となるハズなのですが、なんか、どうやってもコンパイラは自動ではインストールされていないみたいなので(アセンブラのほうは入った模様なんですが)、自前でダウンロードしてインストールします。これをやらないと、ビルドするときに「対応するコンパイラーがない」というエラーがでます。

| Microchip Technology Inc.
http://www.microchip.com/pagehandler/en-us/devtools/mplabxc/home.html

この中の MPLABR XC8 Compiler v1.34 をダウンロードすれば ok です。Free 版は最適化が弱いのですが、どうせ実験なのでこれで十分です。ビルドサイズに制限があるのかどうかは分かりません。32kb の制限がありそうな気がします。いくつかのブログでは HI-TECH PICC Lite の手順が書いてあったりしますが、Hi-TECH という会社が、Microchip社に買収されて、名前が、XC8 みたいになったようです。MPLAB X IDE の対象のコンパイラに Hi-TECH の名前が残っていますが、それは無視していいようです。

プロジェクトを作る

Visual Studio のようにいくつかのテンプレートが用意されています。PIC18F14K50 の場合は、Samples > Microchip Embedded > PIC18 C Template を選択すればよいでしょう。

image

そうすると、こんな風にいくつかのファイルを自動的に作ってくれます。使うところは main.c だけなんですが、

image

プログラミングする

Arduino とか Netduino のように、なんとなく勘で(苦笑)と思ったのですが、あえなく挫折しました。LED を光らせるにしてもポートの指定の仕方が分からないし、ポートの指定にしても PIC の種類によって違うらしく、目的のものを見つけないと難しい。

PIC18F14K80 の特徴 入門と応用
http://sky.geocities.jp/home_iwamoto/page/P14K50/P14_00.htm

そんな訳で、PIC18F14K80 でひたすら検索して、ずばりそのものを引き当ててコードを丸写しして動かしました。こりゃ大変だわ、と思って先人の感謝です。どうやら USB 内蔵の高性能 PIC らしいんですが、そこまで使い込めるかどうか自信がありませんw。まあ、練習用なので。

以下のコードでLチカができています。たぶん、#pragma のあたりはいらないのでしょうが…と思ったけど無いと動きません。そのままコピペです。

/******************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/

#if defined(__XC)
    #include <xc.h>        /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>       /* HiTech General Include File */
#elif defined(__18CXX)
    #include <p18cxxx.h>   /* C18 General Include File */
#endif

#if defined(__XC) || defined(HI_TECH_C)

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */

#endif

#include &quot;system.h&quot;        /* System funct/params, like osc/peripheral config */
#include &quot;user.h&quot;          /* User funct/params, such as InitApp */

/******************************************************************************/
/* User Global Variable Declaration                                           */
/******************************************************************************/

/* i.e. uint8_t <variable_name>; */
#define LED LATCbits.LATC0

#pragma config FOSC = IRC    
#pragma config USBDIV = OFF, CPUDIV = NOCLKDIV
#pragma config IESO  = OFF, FCMEN = OFF, PLLEN  = ON
#pragma config BORV  = 30,  BOREN = OFF, PWRTEN = OFF
#pragma config WDTPS = 32768, WDTEN = OFF
#pragma config MCLRE = OFF, HFOFST = OFF, XINST  = OFF
#pragma config BBSIZ = OFF, LVP    = OFF, STVREN = ON
#pragma config CP1  = OFF, CP0  = OFF, CPD  = OFF, CPB  = OFF
#pragma config WRT1 = OFF, WRT0 = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR1 = OFF, EBTR0 = OFF, EBTRB  = OFF

#define _XTAL_FREQ 12000000

/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/

void main(void)
{
    /* Configure the oscillator for the device */
    ConfigureOscillator();

    /* Initialize I/O and Peripherals for application */
    InitApp();

    /* TODO <INSERT USER APPLICATION CODE HERE> */
    OSCCON = 0x40; // 4MHz
    TRISC  = 0x00; // Degital mode

    while(1) {
        Delay1KTCYx(500);
        LED = 1;
        Delay1KTCYx(500);
        LED = 0;
    }
}

トラブルシューティング

最初はなかなか動かなくて苦労しました。で、もう一度動かそうと思って苦労してたりするので、ハマりどころが多いのかもしれません。

コンパイルができない

最初に嵌った穴で、MPLAB X IDE をインストールしただけではダメです。コンパイラ MPLABR XC8 Compiler v1.34  も手動でダウンロードしてインストールします。たぶん、以前から使っている場合は、HI-TECH PICC Lite が入っているので大丈夫っぽいのですが、新規にインストールするときはコンパイラを忘れずに

PICKit3 から書き込めない

Connect できないパターンは、私の場合は3つの落とし穴でした。

  • PICkit3 は USB 2.0 に差すこと(USB 3.0のコネクタでは動かない)
  • PICkit3 の電源のため、USB ハブではなくて、PC の元に差すこと(これはマニュアルにも書いてありました。電力が結構必要なようです)
  • PIC 自身に電源供給をしないと駄目。PICkit3 から PIC のチップへ給電するモードもあるのですが、安定せずに何回か失敗します。

PIC への書き込みも、種類によって 3V から 9V まで必要な電圧が違うそうなので、USB の 5V だけでは足りない場合もあります。そのときは、外部電源として電池を使うのがいいんでしょう。

何かを壊して、書き込めないときがある

よくわからないのですが、The programmer could not be started: Could not acquire hardware tool communications resources: PICkit3PlatformTool SN# のようになって、何度やっても書き込めないときがあります。どうやら、ブートローダーか何かを壊したらしく、そのままでは書き込みができません。同じようなプロジェクトを作って、焼き込みをすると直るという不思議な現象なのですが、そういうものみたいです。ドライバーを再書き込みすればいいみたいです。

そんな訳でやっとこさ Lチカまで。

image

この後、mbed を試したのですが、これはすんなりといきました。ああ、セッティングをしなくていいいってのは mbed の素晴らしところですね。

カテゴリー: PIC | PICでLチカするための環境を整える はコメントを受け付けていません

Raspberry Pi で Wii コントローラを認識させる準備

Wiimote という python スクリプトがあって、これを使うとさっくりと Wii コントローラーを試せます。となるハズです。「ハズです」というのは、どうやら Wii コントローラ自体の個体差があって、すんなり繋がったり繋がらなかったりするらしいんですね。ちなみに、私の手元の Wii コントローラは「Wii MotionPlus INSIDE」というやつなのですが、すんなり繋がらないほうです。

Raspberry Pi – How to use a Wiimote! – YouTube
https://www.youtube.com/watch?v=bO5-FjLe5xE&list=UUfY8sl5Q6VKndz0nLaGygPw

にある通り、

– Bluetooth ドングルを RasPi に差しておく
– git clone https://github.com/the-raspberry-pi-guy/Wiimote でサンプルコードを取得
– sh setup.sh で bluetooth 関連を apt-get する
– python wiimote.py を起動したら、Wii コントローラの 1,2 ボタンを同時押ししてペアリングを行う。

そうすると、うまく接続できればペアリングが実行されて、各種のボタンを認識します。

ペアリングできない

しかし、私の手元にあるもので試すと、何度やってもペアリングができません。lsusb で確認したりしたのですが、No wiimotes found となって、認識しません。

Wii コントローラ自体が壊れているのかと思ったのですが、hcitool scan をすると MAC ID が取得できます。

ちなみに、実は Wii MotionPlus の場合は 1+2 ボタンの同時押しではペアリングできなくて、後ろの Sync ボタンを押さないとペアリングできないそうです。youtube の画像は 1+2 ボタンの同時押しでうまくいっているので、北米版と日本版との違いとか販売時期で違いがあるのかもしれません。手元にあるのは去年の夏に買ったものです。

CWiiDを直接調べる

最終的に使うのは、python ではなくて、C# から使いたいので、先の setup.sh でインストールしたライブラリを直接使う必要があります。

sudo apt-get update
sudo apt-get install --no-install-recommends bluetooth -y
sudo apt-get install python-cwiid

wiimote は、ライブラリに python-cwiid を使っていて、これが cwiid を使っています。

CWiiD – Community Help Wiki
https://help.ubuntu.com/community/CWiiD
abstrakraft/cwiid
https://github.com/abstrakraft/cwiid

github にコードが公開されているので、ビルドし直すかデバッグを入れればなんとかわかるだろうと思ったわけです。
cwiid 自体のビルドにちょっと苦労しましたが、以下のようにパッケージをインストールしておけば ok です。現在の RasPi は Gtk3 が入っているのですが、cwiid は Gtk2 を要求するので、パッケージを改めていれておきます。

apt-get install flex bison libgtk2.0-dev

で、結論から言えば、libcwiid/process.c にある process_write 関数での wiimote->rw_status の判別をコメントアウトしてしまいます。

cwiid/process.c at master ・ abstrakraft/cwiid
https://github.com/abstrakraft/cwiid/blob/master/libcwiid/process.c#L284-L287

int process_write(struct wiimote *wiimote, unsigned char *data)
{
        struct rw_mesg rw_mesg;
/*
        if (wiimote->rw_status != RW_WRITE) {
                cwiid_err(wiimote, &quot;XXX Received unexpected write report&quot;);
                return -1;
        }
*/
        rw_mesg.type = RW_WRITE;
        rw_mesg.error = data[0];

        if (write(wiimote->rw_pipe[1], &rw_mesg, sizeof rw_mesg) !=
          sizeof rw_mesg) {
                cwiid_err(wiimote, &quot;RW pipe write error&quot;);
                return -1;
        }

        return 0;
}

どうやら、手元にある wii コントローラだと wiimote->rw_status の値が RW_WRITE にならないみたいなのです。すんなり動くパターンもあるので、どこかのコードの判別だと思うのですが、ひとまず、ここをコメントアウトしてしまうと普通に通るようになります。

wmdemo で試してみる

これも 1+2 同時押しが効かない関連なのかもしれませんが、手元のものだと自動検索が効かないらしく Wii コントローラーの MAC アドレスを直接指定します。先に hcitool scan で探し出しておいた MAC ID を引数にして起動します。

wmdemo 8C:CD:E8:6B:B4:3A

そして、Wii コントローラの裏にある Sync ボタンを押すと、無事ペアリングが行われます。LED が常にちかちかした状態になってしまうのは、このあたりの不具合のせいなのかもしれませんが、一応ボタンなどのデータが取れます。

受信データは、以下のコメントアウトを戻せば表示されます。

cwiid/thread.c at master ・ abstrakraft/cwiid
https://github.com/abstrakraft/cwiid/blob/master/libcwiid/thread.c#L59-L62

データ長さは、4バイトか6バイトのようです。-/+ ボタンや方向ボタンを押すとビットが変わるので、これを取れば他のプログラムと連携することができます。

Windows で動く wiimote がある

あれこれと探していたら、以下に C# での実装がありました。

Managed Library for Nintendo’s Wiimote | Coding4Fun Articles | Channel 9
http://channel9.msdn.com/coding4fun/articles/Managed-Library-for-Nintendos-Wiimote
Managed Library for Nintendo’s Wiimote – Home
http://wiimotelib.codeplex.com/

試してみると、私の wii コントローラでは動かない(コード自体は wii remote 対応らしく微妙に違うみたい)のですが、コードがあるのでなんとかなりそうです。

ちなみに、Windows 8.1 では wii コントローラは認識されます。

Bluetooth でのペアリングで、PIN コードは何のか?と悩んだのですが、「何もいれない」まま次へボタンを押せば ok です。PIN コードが設定されていないので、そのままペアリングが成功します(むしろ、入れるとエラーになります)。

Bluetooth での認識では、Nintendo RVL-CNT-01-TR となっていて、サービスは、HID になっていますね。いくつか調べていくと、HID と SPP と両方が対応しているようなので、RasPi の cwiid では SPP を使っているような感じがします。このあたりは、PS3 の Dualshock3 のコードと後から見比べてみます。

デバイス – Windows app development
https://msdn.microsoft.com/ja-jp/library/windows/apps/bg182882.aspx#one

にストアアプリから HID を扱う方法があるのですが、これがそのまま wii コントローラで使えるかどうかは謎です。

Dolphinで実機のWiiリモコン(周辺機器)を使う – GC+Wiiエミュレータ Wiki*
http://wikiwiki.jp/gcwiiemu/?Tips_Connect_RealWiimote

Wii エミュレータをインストールして、ドライバー部分だけ使うっていう方法もあるみたいなんですが、動作確認はしていません。
Windows 10 だと Bluetooth 周りが楽になっているハズなので、そっちのほうは後で確認。

追記 Wii リモートで接続

気になったので、中古で Wii Remote を買ってきました。そうすると、あっさりつながりますね。managed 版の wiimote もあっさり認識するので、使うならばこっちのほうが良さそうです。これの話は後日。

カテゴリー: RaspberryPi | 5件のコメント

Raspberry Pi で戦車を作る(拡張編)

ひと通り、Raspberry Pi で動く戦車ができたのでおしまい…という訳ではなくて、これを拡張/派生させていきます。RasPi 戦車の最大の目的は、

  • リモコンで動くこと
  • モーターが制御できること

の2点なので、有線ケーブル(USBケーブル接続など)は対象外です。あと、戦車自体を「動かす」ことが私の目的なので、Raspberry Pi に外部電源を乗せています。これは、拡張先である Arduino なども同じです。メインチップに供給する電源とは違うところから取ってくるってのが必須。

image

以前、LEGO Mindstorms EV3 で作った時のノウハウを使っているので、PS3 Dualshock3 のコントローラーで Bluetooth 接続させています。モータードライバは手早く済まそうと思って購入してしまいました(本当は自作する予定だった)。制御フローでいえば、5つのブロックに分かれているわけで、これを切り替えることで、拡張できますよね。というか、もともとそのつもりでプログラムの作っています。

ざっと、今考えているところを書き出すとこれだけあります。

image

Bluetooth 付きのコントローラーとして Wii コントローラーを使う方法があります。また、Android のスマートフォンを使って RFCOMM で繋ぐ方法もありますよね。通信方法も、Bluetooth よりも WiFi のほうが手軽です。更に、赤外線を使うと非常に安くできます。Dualshock3 が 4,000円を超えますが、赤外線だと500円ぐらいでできそうです。

また、本体は、Raspberry Pi で動かしてますが、Arduino を使ってもできるハズです。これもシリアル通信にすれば結構いろんなことができるし、赤外線通信も可能です。ライントレーサーのような自動で動く仕組みでもいいんですが、ここはコントローラーで動かしていきたいですね。

モータ制御のところも、現在の ON/OFF だけではなくて、PWM 制御にすれば高速/低速で動かせます。このあたりはラジコンカーの制御も合わせると色々種類があります。また、コントローラ自体が多様(スマートフォンからの動かせるし)なので、従来のラジコンよりも色々な操作をひとつのコントローラに詰め込めます。動力のモーターと、サーボを同時に動かすこともできるだろうし、LEDや音を鳴らすこともできるでしょう。そのあたりのギミックが無線でもやりやすくなっています。

Raspberry Pi 2 自体は 5,000円近くするので、数台用意して実験するのは大変ですが、Arduino のボードを使って半額ぐらいで済ますことも可能です。更に言えば、Arduino で使っているチップを取り出して、必要な部分だけ基板で組めばもっと安くできそうです。このあたりはもうちょっと探っていきたいところです。

Arduinoブートローダ書き込み済みATMega328P-PU(内蔵CR発振8MHz版) – スイッチサイエンス
https://www.switch-science.com/catalog/1414/
Arduinoブートローダ書き込み済みATMega328P-PU(内蔵CR発振8MHz版)

こんな感じで、ブートローダーが書き込んだものが 400円弱で手に入るのだから、モーター制御だけの専用基板に組み込めば、かなり小さく&安くできそうな感じです。そうすると、1台だけじゃなくて、5,6台は一気に作れそうですよね。5台ぐらいあると、個々に赤外線センサーや距離センサーを乗せて、相互に自動で動かしたりかなりおもしろいことができそうです。まあ、1万円/台で作ってもいいんでしょうが、そこは創意工夫と頭を使って製作費を下げる努力をするということで。

カテゴリー: RaspberryPi | Raspberry Pi で戦車を作る(拡張編) はコメントを受け付けていません

Raspberry Pi で戦車を作る(リモコン編)

ゲームコントローラーで戦車のモーターを制御するということで、以下の2つをくっつけます。

Raspberry Pi で戦車を作る(Bluetooth/PS3 Dualshock3編)
http://www.moonmile.net/blog/archives/6898
Raspberry Pi で戦車を作る(モーターシールド編)
http://www.moonmile.net/blog/archives/6910

ジョイスティックをイベント化する

https://github.com/moonmile/RaspiTank/blob/master/RaspiRobot/BPiJoystick.cs

– ジョイスティックの変更イベント OnChangedJoystick
– ボタン状態の変更イベント OnChangedButton

を作成します。ジョイスティックの場合は、XY軸がちょっとずれただけでイベントが発生するので、ボタンのON/OFFとは別にイベントを発生させます。

protected void OnLoop()
{
    while (this.IsLoop)
    {
        js_event js;
        js.time = _br.ReadUInt32();
        js.value = _br.ReadInt16();
        js.type = _br.ReadByte();
        js.number = _br.ReadByte();
        // Console.WriteLine(js.ToString());

		bool changedJoystick = false;
		bool changedButton = false;
        if (BPiJoystickData.IsAxis(js.type))
        {
            if (this.Joystick.GetAxisValue(js.number) != js.value)
            {
                Joystick.SetValue(js.type, js.number, js.value);
				changedJoystick = true;
            }
        }
        else if (BPiJoystickData.IsButton(js.type))
        {
            if (Joystick.GetButtonValue(js.number) != (js.value != 0))
            {
                Joystick.SetValue(js.type, js.number, js.value);
				changedButton = true;
            }
        }
        // filter
        if (BPiJoystickData.IsAxis(js.type) && js.number >= 6) changedJoystick = false;
        if (BPiJoystickData.IsButton(js.type) && js.number >= 16) changedButton = false;

        // raise value change event
		if (changedJoystick)
        {
            if (OnChangedJoystick != null)
            {
				OnChangedJoystick(this, new JoystickEventArgs()
                {
                    Joystick = this.Joystick,
                    Raw = js
                });
            }
            // Console.Write(&quot;{0} {1} {2} &quot;, js.type, js.number, js.value );
            // Console.WriteLine(j.ToString());
        }
		if (changedButton)
		{
			if (OnChangedButton != null)
			{
				OnChangedButton(this, new JoystickEventArgs()
				{
					Joystick = this.Joystick,
					Raw = js
				});
			}
			// Console.Write(&quot;{0} {1} {2} &quot;, js.type, js.number, js.value );
			// Console.WriteLine(j.ToString());
		}
    }
    this._br.Close();
}

コントローラーの動きでモーターを制御する

アナログジョイスティックやボタンを押したときのモーター制御やLED点灯を行います。

https://github.com/moonmile/RaspiTank/blob/master/RaspiRobot/Program.cs

class Program
{
	static void Main(string[] args)
	{
		new Program().main();
	}

	BPiJoystick js;
	RaspiRobotNet.RaspiRobot robot;
		
	public void main()
	{
		robot = new RaspiRobotNet.RaspiRobot();

		js = new BPiJoystick();
		js.OnChangedJoystick += js_OnChangedJoystick;
		js.OnChangedButton += js_OnChangedButton;
		js.Setup();
		Console.WriteLine(&quot;any key is stop.&quot;);
		var key = Console.ReadKey();
	}

	/// <summary>
	/// ボタンが変更された
	/// </summary>
	/// <param name=&quot;arg1&quot;></param>
	/// <param name=&quot;arg2&quot;></param>
	void js_OnChangedButton(object sender, JoystickEventArgs e)
	{
		if (e.Joystick.Up == true) robot.Forward();
		else if (e.Joystick.Down == true) robot.Back();
		else if (e.Joystick.Left == true) robot.Left();
		else if (e.Joystick.Right == true) robot.Right();
		else
		{
			if (e.Joystick.Up == false && e.Joystick.Down == false &&
				e.Joystick.Left == false && e.Joystick.Right == false)
				robot.Stop();
		}

		/// LED1,2 を点灯する
		robot.SetLED1( e.Joystick.Circle );
		robot.SetLED2( e.Joystick.Cross );
	}
	/// <summary>
	/// ジョイスティックを変更
	/// </summary>
	/// <param name=&quot;sender&quot;></param>
	/// <param name=&quot;e&quot;></param>
	void js_OnChangedJoystick(object sender, JoystickEventArgs e)
	{
		int ly = e.Joystick.LeftAxisY;
		int ry = e.Joystick.RightAxisY;
		Console.WriteLine(&quot;joystick {0} {1}&quot;, ly, ry);
		int sp1 = ly / (32767 / 200);
		int sp2 = ry / (32767 / 200);
		if (e.Joystick.Up == false && e.Joystick.Down == false &&
			e.Joystick.Left == false && e.Joystick.Right == false)
		{
			move_bot(sp1, sp2);
		}
	}
	void move_bot(int sp1, int sp2)
	{
		if (sp1 > 0 && sp2 > 0) { robot.Forward(); }
		if (sp1 < 0 && sp2 > 0) { robot.Right(); }
		if (sp1 > 0 && sp2 < 0) { robot.Left(); }
		if (sp1 < 0 && sp2 < 0) { robot.Reverse(); }
		// 停止
		if (sp1 == 0 && sp2 == 0) { 
			robot.Stop(); 
		}
		// 右だけ動かす
		if (sp1 == 0)
		{
			if ( sp2 > 0 )
				robot.SetMotors(false, false, true, false);
			if (sp2 < 0)
				robot.SetMotors(false, false, true, true);
		}
		// 左だけ動かす
		if (sp2 == 0)
		{
			if (sp1 > 0)
				robot.SetMotors(true, false, false, false);
			if (sp1 < 0)
				robot.SetMotors(true, true, false, false);
		}
	}
}

このプログラム自体はターミナルで起動することを想定しているので、最終的には /etc/ini.d を利用して初期起動させます。WiFi のドングルが結構な電力を食っているので、これを外すだけでもかなり RasPi の動作が安定します。ただし、外側から RasPi の状態が見えなくなってしまうので、何らかのモニタリングが必要ですよね。あとで、RasPi にミニ液晶を付けて状態を監視できるようにします。

上記ではジョイスティックといくつかの○×ボタンを単独で感知していますが、同時押しとかR/Lボタンも取得ができます。ちなみに、ジョイスティックの傾きも取れるので、スマートフォンを傾けたときのような動作も可能です。このあたりは、RasPi 戦車に限らず、RasPi 自体を媒介させることで、ゲームコントローラー -> RasPi -> Windows PC というパターンが組めます。Windows 自体はゲームコントローラを認識するのですが、なぜか 8.1 から PS3 Dualshock3 は認識しないんですよね。

カテゴリー: C#, RaspberryPi | Raspberry Pi で戦車を作る(リモコン編) はコメントを受け付けていません

Raspberry Pi で戦車を作る(モーターシールド編)

Raspberry Pi用モータードライバボード(キット) – スイッチサイエンス
https://www.switch-science.com/catalog/1239/

今度は、モータードライバーを使ってモーターを動かします。今回使っているのは Raspberry Pi 用のモータードライバーシールドで、4,000円弱という RasPi が買えるかもしれません、というお値段で結構します。慣れれば自作できるようなんですが、手始めにひとつ買ってためしています。ちなみに、このキットは v2 が出ていて adafrutit などから購入できます。

RasPi Robot Board v2 by MonkMakes ID: 1940 – $29.95 : Adafruit Industries, Unique & fun DIY electronics and kits
http://www.adafruit.com/product/1940

動作させるためのサンプルコードは以下にあります。

simonmonk/raspirobotboard2
https://github.com/simonmonk/raspirobotboard2

9V(乾電池6個)を給電すると、RasPi に 5V 給電してくれるので、RasPi 本体への USB 給電がいらなくなるみたいです。私の場合は、両方に 5V ずつ給電しているので、今度試してみましょう。

サンプルコードを追っていくと

– ボード上の LED1,2 を光らせる
– ボード上の SW1,2 を ON/OFF できる
– モーター1,2 を回転/逆回転できる

ことが分かります。残念ながらスピード制御はできないので、戦車のようなキャタピラ式のものとか、ギア比を変えてアームを動かすとかに使えますね。PWM制御(パルス制御)のほうは、別途回路を組んで実験していきます。

両輪のギアーボックスを使うと、右左の車輪を別々に制御できるので、車体を右左に曲げることができます。普通の車のようにハンドル+後輪駆動みたいにしたい場合は、別途サーボ制御が必要になるのですが、キャタピラ式はこれで十分だったりします。まあ、普通のラジコンカーを作るのも今後の課題ですね。

ピンを調べる

さて、ON/OFF のピンは、サンプルの python スクリプトを見ると以下のようになっています。

https://github.com/simonmonk/raspirobotboard/blob/master/raspirobotboard.py

LEFT_GO_PIN = 17
LEFT_DIR_PIN = 4
RIGHT_GO_PIN = 10
RIGHT_DIR_PIN = 25
SW1_PIN = 11
SW2_PIN = 9
LED1_PIN = 7
LED2_PIN = 8
OC1_PIN = 22
OC2_PIN = 21

RasPi 専用のシールドなので、GPIO のピンは RasPi に合わせてあるわけですが、この GPIO の番号と Arduino のそれとを合わせてやれば、Arduino でも使うことができると思います。まあ、Arduino 専用のものを買ったほうが早かったり、自作したほうがいい気もしますが。

C# で使えるように書き直す

後で整理して git にアップしますが、python のコードを C# に書き直したのが次のものです。
内部的に

AlexSartori/RaspberryGPIOManager
https://github.com/AlexSartori/RaspberryGPIOManager

をちょっと改変して使っています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RaspberryGPIOManager;
using System.Threading;

namespace RaspiRobotNet
{
    public class RaspiRobot
    {
		const int LEFT_GO_PIN = 17;
		const int LEFT_DIR_PIN = 4;
		const int RIGHT_GO_PIN = 10;
		const int RIGHT_DIR_PIN = 25;
		const int SW1_PIN = 11;
		const int SW2_PIN = 9;
		const int LED1_PIN = 7;
		const int LED2_PIN = 8;
		const int OC1_PIN = 22;
		const int OC2_PIN = 21;

		public GPIOPinDriver LED1 { get; set; }
		public GPIOPinDriver LED2 { get; set; }
		public GPIOPinDriver OC1 { get; set; }
		public GPIOPinDriver OC2 { get; set; }
		public GPIOPinDriver LEFT_GO { get; set; }
		public GPIOPinDriver LEFT_DIR { get; set; }
		public GPIOPinDriver RIGHT_GO { get; set; }
		public GPIOPinDriver RIGHT_DIR { get; set; }

		public RaspiRobot()
		{
			this.LED1 = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO7, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.LED2 = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO8, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.OC1 = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO22, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.OC2 = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO21, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.LEFT_GO = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO17, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.LEFT_DIR = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO4, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.RIGHT_GO = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO10, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
			this.RIGHT_DIR = new GPIOPinDriver(GPIOPinDriver.Pin.GPIO25, GPIOPinDriver.GPIODirection.Out, GPIOPinDriver.GPIOState.Low);
		}

		public void SetMotors( int left_go, int left_dir, int right_go, int right_dir )
		{
			this.SetMotors(left_go != 0, left_dir != 0, right_go != 0, right_dir != 0);
		}
		public void SetMotors( bool left_go, bool left_dir, bool right_go, bool right_dir )
		{
			this.LEFT_GO.State = left_go  ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
			this.LEFT_DIR.State = left_dir ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
			this.RIGHT_GO.State = right_go ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
			this.RIGHT_DIR.State = right_dir ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
		}

		public void Stop()
		{
			this.SetMotors(false, false, false, false);
		}
		public void Forward(float sec = 0.0f)
		{
			this.SetMotors(true, false, true, false);
			if (sec > 0.0f)
			{
				Thread.Sleep((int)(sec * 1000.0));
				this.Stop();
			}
		}
		public void Left(float sec = 0.0f)
		{
			this.SetMotors(true, false, true, true);
			if (sec > 0.0f)
			{
				Thread.Sleep((int)(sec * 1000.0));
				this.Stop();
			}
		}
		public void Right(float sec = 0.0f)
		{
			this.SetMotors(true, true, true, false);
			if (sec > 0.0f)
			{
				Thread.Sleep((int)(sec * 1000.0));
				this.Stop();
			}
		}
		public void Reverse(float sec = 0.0f)
		{
			this.SetMotors(true, true, true, true);
			if (sec > 0.0f)
			{
				Thread.Sleep((int)(sec * 1000.0));
				this.Stop();
			}
		}
		public void Back(float sec = 0.0f)
		{
			this.Reverse(sec);
		}

		public void SetLED1( bool sw ) {
			this.LED1.State = sw ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
		}
		public void SetLED2(bool sw)
		{
			this.LED2.State = sw ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
		}
		public void SetOC1(bool sw)
		{
			this.OC1.State = sw ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
		}
		public void SetOC2(bool sw)
		{
			this.OC2.State = sw ? GPIOPinDriver.GPIOState.High : GPIOPinDriver.GPIOState.Low;
		}
	}
}

でもって、F# でテストコードを書いてみます。

open System
open RaspiRobotNet
open RaspberryGPIOManager

[<EntryPoint>]
let main argv = 
    printfn &quot;Hello RaspiRobotNet&quot;

    let robot = new RaspiRobot()
    let mutable loop = true
    while loop do
      let key = Console.ReadKey()
      match key.KeyChar with
      | 'e' | 'q' -> loop <- false
      | 'f' -> robot.Forward(1.0f)
      | 'b' -> robot.Back(1.0f)
      | 'r' -> robot.Right(1.0f)
      | 'l' -> robot.Left(1.0f)
      | 's' -> robot.Stop()
      | '1' -> robot.SetLED1( robot.LED1.State = GPIOPinDriver.GPIOState.Low )
      | '2' -> robot.SetLED2( robot.LED2.State = GPIOPinDriver.GPIOState.Low )
      | '3' -> robot.SetOC1( robot.OC1.State = GPIOPinDriver.GPIOState.Low )
      | '4' -> robot.SetOC2( robot.OC2.State = GPIOPinDriver.GPIOState.Low )
      | _ -> ()
    0 // 整数の終了コードを返します

Tera Term で接続して、WiFi 経由で制御ができます。
F# のインストールは、以下を参考にしてください。

Raspberry Pi 2 に F# をインストールする | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6870

これで、モータードライバーの制御は作れたので、これをゲームコントローラーで制御できるようにしていきます。

カテゴリー: C#, F#, RaspberryPi | Raspberry Pi で戦車を作る(モーターシールド編) はコメントを受け付けていません

MySQL の謎なアップデータを止める方法

正月あたりから、真夜中に謎の黒い画像が出てきて、なんかやって止まるという現象が起きていました。謎な黒い画面ってのは cmd の画面で、なんか流れて1秒経たずに消えてしまうのでなんだか分からなかったんですよね。

それを昨晩、やっとこさ捕まえました。

image

どのプロセスか分からなかったのですが、

C:Program Files (x86)MySQLMySQL Installer for WindowsMySQLInstallerConsole.exe

です。MySQL の何かのアップデートのようで、検索していくと

MySQL :: MySQL Installer Guide :: 2.1 MySQL Product Catalog
http://dev.mysql.com/doc/mysql-installer/en/mysql-installer-catalog.html

なところでカタログのスケジューラが動いているとのことです。左上のアイコンを押して、MySQL Installer Options でスケジュールのチェックを外せば ok ですね。どうやら、MySQL 関連のバージョンアップデートしたかどうか毎日チェックするツールなようです。ええ、毎日チェックしたって、そうそうバージョンアップするものではないし、止めておいてもよいでしょう。

以前はなかったものなので、たぶん最新の MySQL Workbench を入れたときのような気がします。サーバー系ではチェックが必要なんでしょうが、開発用 PC で一瞬だけでるのはやめて欲しいところですね。

ちなみにコマンドプロンプトで schtasks と打っても出てきます。at コマンドってなくなったんですね、ってに今更気づきました。

image

そんな訳で MySQL のカタログスケジューラを止めると、真夜中の謎な黒い画面(cmd)が消えます。カタログ自体は手動でアップデートすればよいので、これで十分です。

カテゴリー: MySQL | MySQL の謎なアップデータを止める方法 はコメントを受け付けていません