Raspberry Pi で戦車を作る(Bluetooth/PS3 Dualshock3編)

RasPi 戦車は、PS3 Dualshock3 コントローラーで操作できるようにしてあります。スマートフォンで WiFi 経由とか Bluetooth 経由が多い中で、コントローラーを使っているのは、まあ、ラジコンと同じ風に扱いたかったからです。これだと5歳児でも動かせますからね。PS3 Dualshock3 には、アナログスティックが2つと、上下ボタンと○×ボタン4個と…色々ついているので、車輪だけじゃない制御がしやすいそうってのもあります。サーボを制御してロボットアームを動かす予定もあって、これを使っています。

が、去年買ってみてあまり汎用的ではないので、どうせならば Bluetooth 対応のコントローラーを自作したほうがいいのですが…まあ、手元にあるということで。ちなみ、PS3 のコントローラは持っているけど、PS3 本体は持っていません。PS4 も持ってません。PS4 用の DualShock4 の場合はどうなるのか?は分からないので、持っている方は試してみてください。

Bluetooth の準備

基本は、

BrickPi + LOGO Mindstorms EV3 をゲームコントローラーでコントロールする(前編) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5997

に書いてある手順の通りなのですが、おさらいも兼ねて、もう一度書き連ねておきます。RasPi のレポジトリも新しくなっているので。

apt-get で bluetooth 関連をインストール

sudo apt-get install bluetooth bluez-utils bluez-compat bluez-hcidump
sudo apt-get install libusb-dev libbluetooth-dev

基本は bluetooth だけでいいはずですが、後の QtSixA のために libusb-dev あたりが必要です。

/etc/init.d/bluetooth status

で、きちんと bluetooth デーモンが動いているか確認します。

lsusb

で、Bluetooth ドングルが認識できることを確認。ここでは、Bus 001 Device 004 がそれです。

QtSixA のインストール

PS3 Dualshock3 用のドライバーを入れます。

QtSixA – Browse /QtSixA 1.5.1 at SourceForge.net
http://sourceforge.net/projects/qtsixa/files/QtSixA%201.5.1/

tar -xvf QtSixA-1.5.1-src.tar.gz
cd QtSixA-1.5.1/sixad
make
sudo make install 

今の環境ではきちんとビルドできて、sixpair まで出来上がります。
中身は、bluetooth SPP を解析しているだけだから、C# で書き直すのはそんなに難しくはないと思うんですよね。これは、RasPi で直接 Bluetooth を扱うときに試してみます。

PS3 Dualshock3 とペアリングする

ゲームコントローラーを USB で RasPi につなげて

sudo sixpair

を動かします。

Bluetooth ドングルの MAC ID が表示されます。MAC ID 自体は Windows 8.1 の PC に繋いでデバイスマネージャから確認できます。

動作させる。

ペアリング自体は、最初だけなので、その後はゲームコントローラーの USB を外しても大丈夫です。確か、つなげないで直接 MAC ID を書き込む方法もあります。

sudo sixad -start &

させます。うまく起動したら、ゲームコントローラーの PS ボタンを押せば接続できます。Dualshock3 の MAC ID が表示されます。

通信情報は、/dev/input/js0 に流れてくるので、

sudo cat /dev/input/js0

接続を止める場合は、

sixad -stop

すれば大丈夫です。

コントローラーの通信を解析する

データ自体は以下の構造体で流れてきます。これをうまく読み取ってやれば、各種のボタンの判別がつきます。

public struct js_event
{
	public UInt32 time; /* event timestamp in milliseconds */
	public Int16 value; /* value */
	public byte type; /* event type */
	public byte number; /* axis/button number */
	public override string ToString()
	{
		return string.Format("time:{0} val:{1} type:{2} num:{3}", time, value, type, number);
	}
}

テストコード
https://gist.github.com/moonmile/7c44e5130617c7a76a87

ボタンの割り当てをしたのが上記になります。
このコードは以前書いたもので、ジョイスティックのチェックしかやっていませんが、今回の RasPi 戦車では上下左右ボタンにも対応させています。これは後述します。
同じものが飛んできたら捨てるような処理を入れればいいのです。

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

Raspberry Pi で戦車を作る(材料編)

モーターの制御…というか、モーターってどうやって駆動させるの?の理解に苦労しましたが、ひとまず、コントローラを使って戦車を動かすところまでが完成しました。

https://www.youtube.com/watch?v=LTFYI98lF3c

image

例のごとく Raspberry Pi が固定されていませんが、これはいずれ。土台を LEGO で組んだのですが、ギア部分ががたつくのと RasPi と電源が落ちそうになるので、これも固定式に変えないと駄目です。予定では、この上にアームを乗っけるので。

meArm を使ってサーボモーターの制御はできていたので、今度は足回りの制御です。前に進むだけならば GPIO の ON/OFF でいけるのですが、反転させないといけないので以前に買ったモーターシールドを使っています。RaspiRobot Board 自体は新しいバージョン v2 が出ていることと、もうちょっと頑張れば独自にモータードライバー DRV8830  を買って回路を組めば、もっと安く済みます。

ともあれ、戦車をリモートコントロールで動かす場合は、本体に Arudino/Netduino を使うこともできるし、通信に赤外線/Bluetooth/BLE/WiFi を選ぶことができます。これらの組み合わせは、いずれやっていく予定ですが、ひとまず手元にある/以前やったことがある Bluetooth で試しています。

材料

あとは、土台に LEGO を使っていますが、Amazon.co.jp | 楽しい工作シリーズ No.157 ユニバーサルプレート 2枚セット (70157) | ホビー 通販 を使って組み立てたほうがしっかり作れるでしょう。私ももう一台作るつもりなので、これを買う予定。

という訳で、材料が整ったのでお次は、Bluetooth のセッティングから。

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

Windows で Raspberry Pi のバックアップを取る方法

Raspberry Pi 2 ではSDメモリカードが micro SD になりました。小さくなって飛び出し部分が少なくなった半面、micro SD を無くしやすい(苦笑)という罠が。
ただし、普通の PC とは違って、容量が小さい micro SD カードを丸ごとバックアップしておけば、他の micro SD カードにコピーできて便利です。

バックアップを取る理由

なんかやっているときに、micro SD カードが壊れる。パターンがあります、RPi の USB ケーブルをぶちっと抜いてシャットダウンしないと、壊れる可能性があります。まあ、初代から使っていますが、このパターンで壊れたことがないので、シャットダウンせずにぶちぶち切っていますが(苦笑)。あと、PC の USB ポートに繋いて試していると、PC がスリープして RPi に電源供給ができなくなってそのまま落ちる、ってのもありますけどね。micro SD メモリそのものよりも、中に入っている linux のファイルシステムが壊れる可能性もあってこれが結構面倒です。

実は、仮想環境 QEMU を PC 上で動かすためにも micro SD カードからのバックアップが必要です。VMWare とかの仮想環境の気分でスナップショット的なバックアップを取るとよいでしょう。ある程度、環境構築をしたあとにバックアップを取っておくと、同じ環境がさっくりと作れます。Win32DiskImager を使うと、SD カードの読み書きが簡単にできるので、複数の RPi 用の SD カードを作るときもさっくり作れます。
ちなみ、8GB の SD カードをバックアップしたあとに、16GB の SD カードに書き込みするということもできました。16GB のカードを RPi に差し込んで、raspi-config で SD メモリの全体を利用する設定をすれば、16GB 全てが使えるようになります。

Win32DiskImager を利用する

Win32 Disk Imager プロジェクト日本語トップページ – SourceForge.JP
http://sourceforge.jp/projects/sfnet_win32diskimager/

から Win32DiskImager をダウンロードしてインストールします。

– Read : SD カードから読み込んでイメージファイルを作成
– Write : SD カードへイメージファイルを書き込み

適当なタイミングでバックアップを取っておいて、バージョン管理をしておくとよいでしょう。
SD カードを吸い上げると 8GB のイメージファイルができて結構大きいですが、zip で圧縮すると 2.5GB 位になります。

SDカードの容量を回復する

実は、Raspberry Pi を SD カードにインストールすると、Windows から見える容量が激減しています。これを回復して Windows からすべての容量をつ開けるように SDFormatter を使います。

SD/SDHC/SDXC用 SDフォーマッター4.0 – SD Association
https://www.sdcard.org/jp/downloads/formatter_4/

起動して、フォーマットオプションボタンをクリックして「論理サイズ設定」を ON にして実行をすると、Windows から見える容量が回復します。勿論、中身はフォーマットされてクリアされるので、再初期化したいときに使ってください。

RPi の初期設定

私の環境では、以下の設定だけ行った SD カードのバックアップがあります。

– wifi設定済み
– sudo apt-get install avahi-daemon
– sudo apt-get install xrdp
– sudo apt-get install samba

wifi は、GUI で設定したものを取っておきます。

vi /etc/network/interfaces

auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
        ssid="SSID名"
        psk="パスワード"
        proto=WPA
        key_mgmt=WPA-PSK
        pairwise=TKIP
        auth_alg=OPEN
}

avahi-daemon は、Windows PC から rapi.local のように名前で見えるようにするサービスです。PC 側に iTunes を入れておけば ok です(単体のライブラリもあるけど iTunes を入れるのが手軽らしい)。

xrdp は、リモートデスクトップをするためのサービスです。リモートデスクトップで表示できるので、ディスプレイが無くても大丈夫です。が、欠点として、Scratch が動きません。たぶん、Remote Desktop プロトコルに対応していないみたいです。

samba は Windwos PC からファイル共有をするためのサービス

vi /etc/samba/smb.conf

 [shared]
 path = /home/masuda
 read only = No
 guest ok  = Yes
 force user = masuda

こんな風にすると、raspishared で /home/masuda のフォルダが見えるようなります。私の場合は masuda ユーザーを作っているのですが、pi ユーザーのままにして「force user = pi」のようにするのも良いです。

こういう風にしてバックアップを取っておくと、新しい SD メモリカードを買ってきて Win32DiskImager で書き込めば、さっくりと RPi が動くという状態になります。

# 追記
ただし、各社 SD カードのセクタ数に微妙に違いがあるらしく、書き込み時にセクタ数が足りなくて書き戻せないってことがあります。セクタ数の小さい方にあわせればいいんでしょうが。まあ、同じ会社の SD カード使えばよいんですが、そのあたりは気を付けて。

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

Raspberry Pi 2 に F# をインストールする

初代 Raspi では、メモリが 256M しかなくて、Fsharp をソースからビルドしようとすると途中でこけてしまってうまく出来上がりませんした。今回の RPi2 はメモリが 1GB あるし CPU も早くなっているので、スムースに行くのではないか?と思って試してみました。

結論から言えば、ソースからビルドができません

結論から先に言うと、git から mono と fsharp のソースコードをダウンロードして来てビルドまではできるのですが、実行ができません。おそらく現時点(2015/02/26)の mono のバージョンに F# が対応していないだけだと思うので、適切な mono のバージョンを持って来れば実行ができるハズなのですが、結構面倒そうなのでパスします(苦笑)

mono や fsharp 自体のビルドは可能です。mono は 4時間弱、F# は 1時間ちょっとぐらい掛かるみたいですが、初代 RPi の時は 12時間以上かかっていたので「現実的な」時間になっています。

– mono 4.1.0 https://github.com/mono/mono
– fsharp 3.1 https://github.com/fsharp/fsharp

こんな感じで fsharpi の実行時に例外が発生しています。

ちなみに、fsharp4 のブランチを持ってきてビルドをしようとすると、コンパイルできなくてエラーになります。

レポジトリを追加して apt-get する

Use F# on Linux | The F# Software Foundation
http://fsharp.org/use/linux/

手順自体は、F# のサイトに書いてある「Option 1: Use the F# Debian/Ubuntu packages」の通りです。Rasberry pi のレポジトリには mono のバージョンが古いのと、fsharp 自体がありません。mono 自体がちょっと気になるところですが、sudo apt-key でレポジトリを追加した後に apt-get するとすんなり通ってくれます。

一応、下にコピーをしておきます。

レポジトリの追加

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list

mono と fsharp のインストール

sudo apt-get update
sudo apt-get install mono-complete fsharp

FSharp.Core.dll が見つからなくてエラーになる

たまに(?)、fsharpi を実行しようとすると、/usr/lib/mono/4.5 等に FSharp.Core.dll が見つからない、というエラーがでます。

F# on linux (mint/ubuntu) – dll path – Stack Overflow
http://stackoverflow.com/questions/27041080/f-on-linux-mint-ubuntu-dll-path

にある通り、gac に FSharp.Core.dll をインストールし直せば ok です。タイミング的に Fsharp 3.1 と 3.1.1 が混在しているときにおこるみたいです。

sudo gacutil -i /usr/lib/cli/FSharp.Core-4.3/FSharp.Core.dll

追記 2015/02/27
どうやら、上記の方法はだめみたいです。/usr/lib/cli/fsharp/ のパスから探しているので、シンボリックリンクを作ると動きます。

cd /usr/lib/cli/fsharp/ 
sudo ln -s /usr/lib/cli/FSharp.Core-4.3/FSharp.Core.* .

ただ、この方法も変なので、fsharp のインストーラーが何処かに書き忘れているような気もするのですが、よくわからず。

apt-get できるバージョン

– mono 3.12
– fsharp 3.1

以前、インストールしたときは fsharpi で実行するときにひどく待たされていたのですが、今回は大丈夫です。ひょっとすると、gac がうまくインストールされていなかっただけなのかもしれませんが。
そんな訳で、今回はさっくりと apt-get でインストールが可能です。というかソースからビルドできないのがアレなんですが、まあ良しとしましょう(笑)。

自分は BrickPi まで動かすぞ…と、近いうちに。

カテゴリー: 開発, F#, RaspberryPi | Raspberry Pi 2 に F# をインストールする はコメントを受け付けていません

VPN が繋がらなくなったので devcon 対処する

久しぶりに VPN につなげてみたら繋がらない…ので復旧させました。その作業のメモ書きです。

色々検索すると Windows XP/7 でもある現象で、突然 VPN に繋がらなくなります。手元の環境が Windows 8.1 なので結構探しました。

現象として、VPN が接続せずに、ネットワーク接続で「プロパティ」を見ようと思っても予期せぬエラーが出てプロパティウィンドウがでません。手元の2台の PC が同時になっていたので、先日入れた Bluetooth のドライバーかと思って復旧させてみたのですが、直りませんでした。

image

いくつか調べていくと、サービスで「Remote Access Connection Manager」が動いていないことが原因なのがわかりました。

image

説明にある通り「このコンピューターからインターネットや他のリモート ネットワークへのダイヤルアップ接続と仮想プライベート ネットワーク (VPN) 接続を管理します。このサービスを無効にすると、このサービスに明示的に依存しているサービスは開始できません。」とのことで、VPN に関わっています。これを、手動で開始しようとしたのですが、なかなか起動せずに、途中で「開始中」のまま落ちてしまっています。

image

別の PC で試してみたところ、すんなり立ち上げるので、この2台の PC がおかしいようです。

デバイスマネージャを見ると、「WAN ミニポート(PPTP)」などがあるのですが、これが正しく動いていません。ドライバーの更新をしてみるものの、なにかが引っ掛かってインストールができません。というか、先の Remote Access Connection Manager(Rasman) が悪さをしてインストールできないようです。

image

レジストリ等を弄ってやる方法が定番みたいなのですが、私のところでは直りませんでした。といいますか、WAN ミニポートが削除できない状態になって、どんどん増殖してしまいます。

そんな訳で、解決策としては、

  1. 「Remote Access Connection Manager」の設定を「無効」にして、PC を再起動する。
  2. devcon install を使って、新しく WAN ポートをインストールする(たぶん、IP と PPTP とネットワークモニタだけ有効であれば通じるはずです)
  3. 古い WAN ポートを「無効」にする。
  4. 「Remote Access Connection Manager」を「手動」に変更した後で「開始」させる。ひどく、時間がかかりますが、きちんと立ち上がってくれます。
  5. 「Remote Access Connection Manager」が立ち上がった状態で、VPN を再作成する。

ということで VPN が復旧しました。壊れてしまった WAN ポートが残骸として残っていますが、どうやっても消えないので、これはこのままです。なんだかなーという感じですが、仕方がないですね。

RasMan は、おそらく VPN に接続しようとしたときに自動的に立ち上がるはずですが、うまくいかないときは、あらかじめサービスで立ち上げておきます。

devcon のインストール

Windows Driver Kit (WDK) と Debugging Tools for Windows (WinDbg) のダウンロード にある「WDK 8.1 Update (Windows 8.1、8、7 ドライバー用)」の中に、devcon.exe があります。単体で動くようなので、どこかの PC にインストールして、c:\Program Files (x86)\Windows Kits\8.1\Tools\x64  の中身をコピーしてきても動きます。

devcon のコマンド

動かすコマンドは、以下のどれか。PPTP は、MS_PptpMiniport になります。

devcon.exe install c:\Windows\inf\netavpna.inf MS_AgileVpnMiniport
devcon.exe install c:\Windows\inf\netrasa.inf MS_NdisWanIp
devcon.exe install c:\Windows\inf\netrasa.inf MS_NdisWanIpv6
devcon.exe install c:\Windows\inf\netrasa.inf MS_NdisWanBh
devcon.exe install c:\Windows\inf\netrasa.inf MS_L2tpMiniport
devcon.exe install c:\Windows\inf\netrasa.inf MS_PppoeMiniport
devcon.exe install c:\Windows\inf\netrasa.inf MS_PptpMiniport
devcon.exe install c:\Windows\inf\netsstpa.inf MS_SstpMiniport

いくつか日本語の解説記事もあるので、それを参考にしてもよいでしょう。

ちなみに devcon remove でデバイスインスタンスを指定して削除ができるハズなのですが、WAN ミニポートの類は、ことごとく失敗します。よくわからないのですが、使い捨てみたいな感じで追加していきます。番号が #1, #2 と振られるので、後ろのほうのを残して古い WAN ミニポートは「無効」にしておくといいでしょう。あれこれレジストリを探って消そうとは思ったのですが、

レジストリで削除する

Windows 7 あたりでは、レジストリで削除できたらしいのですが、手もとの Windows 8.1 ではうまくいきませんでした。参考まで

Accent :: (編集中)WANミニポート(IP)!エラー修復メモ
http://www3.kcn.ne.jp/~accent/blosxom/blosxom.cgi/internet/091129100550.htm

のように HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}  配下から削除すると、デバイスドライバの更新ができるようなのですが。

カテゴリー: 開発 | VPN が繋がらなくなったので devcon 対処する はコメントを受け付けていません

Realsense でカメラを表示させる第一歩

RealSense 事始め | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6751

事始めと言いつつ、コンテストも終わってそのままフェードアウトしてしまうのもアカンのです。手元のカメラは6か月ぐらい借りられる(らしい)ので、5月ぐらいまでは大丈夫なのかな。

Realsense はいくつかのサンプルが付いていますが、これが結構難しい。正月の頃にちら見はしていたのですが、ちょっとこれを使いこなすだけで「参加賞がもらえるのでは?」ってなぐらい難しいです。いや、私にとってはそうだった、というだけなのかもしれませんが、カメラの描画を OnPaint で表示させているところがもうなんとも、大変です。

へばりそうになったので、OpenCV 風に簡単にやってみました。

C#のWindowsフォームプロジェクトを作る

最終的には OpenCvSharp との組み合わせがしたかったので C# を使います。まあ、C++ でもいいんですが、ここは C# で(何かのはずみで F# も使えるかもしれないので)。

libpxcclr.cs.dll を参照設定する

C:Program Files (x86)IntelRSSDKbinx64libpxcclr.cs.dll を参照設定します。この中に諸々にライブラリが入っています。ちなみに、名前空間がありませんッ!!! 清い…

ビルドイベントを設定する

プロジェクトのプロパティからビルドイベントを開いて、ビルド後に実行するコマンドに以下を設定します。

if "$(Platform)" == "x86" ( copy /y "$(RSSDK_DIR)binwin32libpxccpp2c.dll" "$(TargetDir)" ) else ( copy /y "$(RSSDK_DIR)binx64libpxccpp2c.dll" "$(TargetDir)" )

c/c++ のライブラリのコピーですね。これは Realsense のサンプルから取ってきたもので、x86 もあるので 32bit版でも動きそうです。

ターゲットを「x64」にする

同じくプロジェクトのプロパティで、プラットフォームのターゲットを「x64」にします。

あまり高度なことはやらないので、「アンセーフコードの許可」は外したままでokです。

カメラを表示するだけのコード

これで準備が整ったので、RBGカメラを表示するだけのコードを書きます。

public partial class Form1 : Form
{
	public Form1()
	{
		InitializeComponent();
	}

	private PXCMSenseManager sm;
	Task _task;
	bool _task_flag = false;

	/// <summary>
	/// 撮影開始
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void button1_Click(object sender, EventArgs e)
	{
		sm = PXCMSenseManager.CreateInstance();
		// RGBの場合
		sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR, 640, 480, 30);
		if (sm.Init() < pxcmStatus.PXCM_STATUS_NO_ERROR)
		{
			// エラー発生
			MessageBox.Show("PXCM_STATUS_NO_ERROR");
			return;
		}
			
		_task = new Task(() =>
		{
			_task_flag = true;
			while (_task_flag)
			{
				if (sm.AcquireFrame(true) < pxcmStatus.PXCM_STATUS_NO_ERROR) 
					return;
				PXCMCapture.Sample sample = sm.QuerySample();
				if (sample.color != null)
				{
					PXCMImage image = sample.color;
					PXCMImage.ImageData data;
					pxcmStatus sts = sample.color.AcquireAccess(PXCMImage.Access.ACCESS_READ, PXCMImage.PixelFormat.PIXEL_FORMAT_RGB32, out data);
					if (sts >= pxcmStatus.PXCM_STATUS_NO_ERROR)
					{
						Bitmap bmp = data.ToBitmap(0, image.info.width, image.info.height);
						image.ReleaseAccess(data);
						pictureBox1.Image = bmp;
					}
				}
				sm.ReleaseFrame();
				/// 30fps程度にあわせる
				Thread.Sleep(33);
			}
		});
		_task.Start();
	}

	/// <summary>
	/// 終了
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void button2_Click(object sender, EventArgs e)
	{
		_task_flag = false;
	}
}

詳しくはサンプルとリファレンスマニュアルを見ていけばいいのですが、なかなか単純な例が見つからないので、さらしておきます。

Intel RealSense SDK Documentation
https://software.intel.com/sites/landingpage/realsense/camera-sdk/2014gold/documentation/html/

別スレッドにしてぐるぐる回すほうが簡単なので、こっちを使っています。まあカメラの fps とずれるという欠点はありますが、結構なスピードで動いてくれるしコードが単純になります。

  1. PXCMSenseManager.CreateInstance() でカメラのインスタンスを作成
  2. sm.EnableStream() でキャプチャするカメラのサイズを決める。RGB と Depth は同時に撮影が可能。
  3. sm.QuerySample() で(たぶん)サンプリングして
  4. sample.color で RBG のデータを取り出す用意をして、
  5. sample.color.AcquireAccess で、PXCMImage 形式にコピーして
  6. data.ToBitmap で Bitmap 形式に直す
  7. pictureBox1.Image = bmp で、ピクチャボックスに貼り付け

という仕組みですね。

実行すると、こんな感じになります。

Bitmap 形式に直したら、そのまま OpenCvSharp を使って背景差分とか特徴量抽出とかができるので結構便利です。

サンプルコード

以下からどうぞ。
https://github.com/moonmile/RealsenseSample/tree/master/SimpleCamera

カテゴリー: 開発, C#, RealSense | Realsense でカメラを表示させる第一歩 はコメントを受け付けていません

Windows のコンソールアプリで RFCOMM を利用する

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6819

では、Windows ストアアプリを使って Bluetooth の RFCOMM を利用したわけですが、これってストアアプリとか Windows Phone からしか出来ないのか?と思っていたのですが、コンソールからもできました。ということは、Windows フォームや WPF からもできます。

デスクトップからWinRTを参照させる

デスクトップアプリからWinRT APIを使用する – 酢ろぐ!
http://blog.ch3cooh.jp/entry/20121204/1354596483
デスクトップ アプリからのWinRT API利用 | ++C++; // 未確認飛行 C ブログ
https://ufcpp.wordpress.com/2012/09/18/%e3%83%87%e3%82%b9%e3%82%af%e3%83%88%e3%83%83%e3%83%97-%e3%82%a2%e3%83%97%e3%83%aa%e3%81%8b%e3%82%89%e3%81%aewinrt-api%e5%88%a9%e7%94%a8/

そうそう、デスクトップアプリから WinRT を参照させれば RfcommDeviceService クラスが使えるかもしれない。ということで上記を参考にして設定をします。

TargetPlatformVersion を 8.1 にして挿入します。8.0 だとデバイス関係がないので「8.1」で。

  <PropertyGroup>
    <Configuration Condition=&quot; '$(Configuration)' == '' &quot;>Debug</Configuration>
    <Platform Condition=&quot; '$(Platform)' == '' &quot;>AnyCPU</Platform>
    <ProjectGuid>{9B7AD65D-3475-4D63-B5AC-6AB73477AC30}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>BluetoothConsole</RootNamespace>
    <AssemblyName>BluetoothConsole</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <TargetPlatformVersion>8.1</TargetPlatformVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>

Windows.winmd を追加します。

System.Runtime.WindowsRuntime.dll を参照設定します。
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1\System.Runtime.WindowsRuntime.dll

Windows ストアアプリ版のコードを書き換えて、コンソールアプリで呼び出せるようにします。ストアアプリではマニフェストの追加が必要ですが、デスクトップアプリの場合は必要ありません。アクセス権が自由なので、これだと作りやすいですよね(配布はしづらいですが)。

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

	Guid serviceGuid = Guid.Parse(&quot;00001101-0000-1000-8000-00805f9b34fb&quot;);
	RfcommDeviceService rfcommService;
	StreamSocket socket;
	DataWriter writer;
	DataReader reader;

	async Task mainAsync()
	{
		/// 接続
		string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid));
		DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector);
		if (collection.Count > 0)
		{
			try
			{
				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);
				Console.WriteLine(&quot;{0} 接続しました&quot;, rfcommService.ConnectionHostName );
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}
		else
		{
			Console.WriteLine(&quot;デバイスが見つかりませんでした&quot;);
			return;
		}
		// 試しに最初のキーを送る
		SendCommand(&quot;start&quot;);
		while (true)
		{
			// コマンド待ち受けfs
			string text = Console.ReadLine();
			if (text == &quot;quit&quot; || text == &quot;end&quot;) break;
			SendCommand(text);
		}
		/// 切断する
		writer.Dispose();
		reader.Dispose();
	}

	async void SendCommand(string text)
	{
		Console.WriteLine(&quot;W:&quot; + text);
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		writer.WriteString(text);
		await writer.StoreAsync();
		// そのまま受信待ち
		var res = await reader.LoadAsync(8);
		var text2 = reader.ReadString(8);
		Console.WriteLine(&quot;R:&quot; + text2 );
	}
}

お次は、iPhone から…と思っていたのですが、調べていくと iPhone からは RFCOMM が使えないことが判明。正確には MFi というのを Apple から取得して作成すれば使えるようになるそうなのですが、個人アプリレベルでは無理話。そうなると Bluetooth LE を使っての接続が必要になるのです。
Arudino に BLE のシールドも無くはないのですが結構高い。2,3台作るとなると結構な値段になるし、ちょっと手が出しにくい(まあ、1個だけは RedBearLab に注文して買うんですけど)。このあたりは、コントローラー自体が iPhone である必要もないので、RFCOMM をそのまま使うか、WiFi でさっくり作ってテストするかって感じですかね。ちょっと思案中。
Xamarin.iOS で BLE はやっておきたいので、これはまた別途。iPhone からノートPCのUSB付けた Bluetooth 4.0 で実験すればよいので。

カテゴリー: Arduino, WinRT | Windows のコンソールアプリで RFCOMM を利用する はコメントを受け付けていません

Android から Bluetooth+RFCOMM を利用してモーター制御をする

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6819

の続きです。
ストアアプリで作ると、ノートPCでちまちま(Surfaceでもいいけど)やらないちけないので、スマートフォンから動かせるようにします。と言いますか、せっかく Xamarin.Android があるんだから、それで RFCOMM してしまおうという訳です。

最近、中古で購入した Galaxy S3 は、Android 4.1.2 までしか上がらないので BLE は使えないのですが、従来の Bluetooth は使えます。まあ、接続先が Bluetooth 2.0 でシリアル通信なのでこれでok。

内容的には、以下を参考にして作っています。

Connect to a Bluetooth Serial Device with Xamarin.Android
http://brianpeek.com/post/Connect-to-a-Bluetooth-Device-with-XamarinAndroid

Android アプリの画面はこんな感じ。

Android で RFCOMM を使う

Xamarin.Forms を使うと、何故か Android.Bluetooth 名前空間が参照できないので、ノーマルな Xamarin.Forms で作っています。
BluetoothAdapter.DefaultAdapter でデフォルトの Bluetooth を取ってきて、CreateRfcommSocketToServiceRecord メソッドで RFCOMM 用のソケットを作ります。データの送受信はこれに対して、OutputStream と InputStream を使えば ok です。

[Activity(Label = &quot;AndroidBluetooth&quot;, MainLauncher = true, Icon = &quot;@drawable/icon&quot;)]
public class MainActivity : Activity
{
	TextView text1;
	EditText edit1;
	protected override void OnCreate(Bundle bundle)
	{
		base.OnCreate(bundle);

		// Set our view from the &quot;main&quot; layout resource
		SetContentView(Resource.Layout.Main);

		// Get our button from the layout resource,
		// and attach an event to it
		Button button = FindViewById<Button>(Resource.Id.MyButton);
		button.Click += button_Click;
		Button btnSend = FindViewById<Button>(Resource.Id.button1);
		btnSend.Click += btnSend_Click;
		text1 = FindViewById<TextView>(Resource.Id.textView1);
		edit1 = FindViewById<EditText>(Resource.Id.editText1);
		Button btn2 = FindViewById<Button>(Resource.Id.button2);
		btn2.Click += btn2_Click;
		FindViewById<Button>(Resource.Id.button3).Click += clickMotorOn;
		FindViewById<Button>(Resource.Id.button4).Click += clickMotorOff;
	}

	BluetoothSocket _socket;
	/// <summary>
	/// 接続
	/// </summary>
	/// <param name=&quot;sender&quot;></param>
	/// <param name=&quot;e&quot;></param>
	async void button_Click(object sender, EventArgs e)
	{
		try
		{

			BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
			if (adapter == null)
				throw new Exception(&quot;No Bluetooth adapter found.&quot;);

			if (!adapter.IsEnabled)
				throw new Exception(&quot;Bluetooth adapter is not enabled.&quot;);

			BluetoothDevice device = (from bd in adapter.BondedDevices
										where bd.Name == &quot;HC-05&quot;
										select bd).FirstOrDefault();
			if (device == null)
				throw new Exception(&quot;Named device not found.&quot;);

			_socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString(&quot;00001101-0000-1000-8000-00805f9b34fb&quot;));
			await _socket.ConnectAsync();
			text1.Text = &quot;接続しました&quot;;
		}
		catch (Exception ex)
		{
			text1.Text = ex.Message;
		}
	}

	async void SendCommand(string text)
	{
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		var buffer = System.Text.Encoding.UTF8.GetBytes(text);
		// 送信
		await _socket.OutputStream.WriteAsync(buffer, 0, buffer.Length);
		// 受信待ち
		var buffer2 = new byte[8];
		for (int i = 0; i < buffer2.Length; i++)
		{
			int n = _socket.InputStream.ReadByte();
			buffer2[i] = (byte)n;
		}
		string str = System.Text.Encoding.UTF8.GetString(buffer2);
		text1.Text = str;
	}

	/// <summary>
	/// 送信
	/// </summary>
	/// <param name=&quot;sender&quot;></param>
	/// <param name=&quot;e&quot;></param>
	void btnSend_Click(object sender, EventArgs e)
	{
		string text = edit1.Text ;
		SendCommand(text);
	}
	void clickMotorOn(object sender, EventArgs e)
	{
		string text = edit1.Text;
		SendCommand(&quot;m1on&quot;);
	}
	void clickMotorOff(object sender, EventArgs e)
	{
		string text = edit1.Text;
		SendCommand(&quot;m1off&quot;);
	}
	/// <summary>
	/// 切断
	/// </summary>
	/// <param name=&quot;sender&quot;></param>
	/// <param name=&quot;e&quot;></param>
	void btn2_Click(object sender, EventArgs e)
	{
		_socket.Close();
		_socket = null;
		text1.Text = &quot;切断しました&quot;;
	}
}

コマンド自体は、Arduino が受けやすいように8バイト固定にしています。
実験して分かったのですが、Arduino からは1バイトずつ送っているので、受信する Android で ReadAsync を使うと最初の1バイトだけ先に受信してしまいます。このあたりはバッファを先読みして8バイト溜まったら読み込めばいいのですが、面倒ので1バイトずつ読み込んでいます。

		// 受信待ち
		var buffer2 = new byte[8];
		for (int i = 0; i < buffer2.Length; i++)
		{
			int n = _socket.InputStream.ReadByte();
			buffer2[i] = (byte)n;
		}

あと、プロジェクトの Android Manifest を開いて BLUETOOTH にチェックを入れます。

20150217_05

 

これがうまくいくと、Android スマートフォンからモーター制御ができるようになります。

ちなみに、上の方に写っている白いボードは「Freaduino UNO Rev1.8」です。Arduino Uno にサーボ用のシールドを作るのが面倒で買ってしまいました。手元の meArm を制御している

Assembly | Adafruit 16-Channel Servo Driver with Arduino | Adafruit Learning System
https://learn.adafruit.com/16-channel-pwm-servo-driver/assembly

とは違うけどデジタルピンに1対1で対応しているので、Arudino IDE で Servo ライブラリがそのまま使えます。

カテゴリー: 開発, Android, Arduino, Xamarin | Android から Bluetooth+RFCOMM を利用してモーター制御をする はコメントを受け付けていません

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う

本来ならば Bluetooth LE を使うところなのでしょうが、価格が高い(苦笑)なので安い方から手を入れていきます。

<b>連載</b>Bluetooth LE (5) Android 4.3 で Bluetooth LE 機器を使う (フェンリル | デベロッパーズブログ)
http://blog.fenrir-inc.com/jp/2013/10/bluetooth-le-android.html
Bluetoothでデバイスと通信するには | garicchi.com
http://garicchi.com/?p=17111

なところで、BLE を使っているのでいずれ追いつこうということで。手始めには、先に作ったモーターの駆動系を Bluetooth で制御していきます。同時に Raspberry Pi の Bluetooth シールドも買ったのですが、まあ、これは要らなかったかも。同じ HC-05 の変換モジュールだけで ok みたいです。

Bluetoothシリアル変換モジュール(マスタ/スレーブ) – Androciti Wiki
http://wiki.androciti.com/index.php?Bluetooth%A5%B7%A5%EA%A5%A2%A5%EB%CA%D1%B4%B9%A5%E2%A5%B8%A5%E5%A1%BC%A5%EB(%A5%DE%A5%B9%A5%BF%2F%A5%B9%A5%EC%A1%BC%A5%D6)

価格的には 1,500円ぐらいですね。スレーブ専用の HC-06 だと 1,000 円ちょっとなので複数使うときに良さそうです。
実は、BLE とそれ以前の Bluetooth の違いを知らなくて、去年 Xamarin のカンファレンスで SensorTag を見せてもらったときに「うーん、Bluetooth なのか」と思ってただけなんですよ。実は、グロサミで解説してもらった(英語だったけど)Rolling Spider も BLE を使っていて、それの SDK を使って Bluetooth 対応のコントローラーで動かした、ってのミソだったんですね…と今更思い直しました。SensorTag は試しに買ってみたので、到着したら試してみる予定です。あと、BLE 対応のシールドも。

シリアルポートでつなげる

とはいえ、Bluetooth に様々なプロファイルがあって、それを使えば様々なことができる、ってことは以前に Bluetooth を調べたときに分かってはいたのですが、その時には具体的な端末がなくて、オーディオ関連とかファイル転送をしてもなぁ、ってな感じでした。あまりハードウェアに詳しくなかったので、何かを制御するには WiFi ぐらいだろうと思っていたわけで、RealSense 絡みも WiFi で作っています。
が、とある人から、がりっちさんの RFCOMM 通信の記事を知って、ちょっと通信部分の制御を変えてみようかと思ったわけです。WiFi+RPi の組み合わせや、Bluetooth+RPi+PSコントローラーのみかと思っていたら、RFCOMM プロトコルでつなげれば、結構手軽に iPhone/Android から繋げられそうです。実は Windows からは Windows Windows ストアアプリから接続しないといけない(デスクトップアプリでもできるはずなんですけどね?)ので、あれこれとややこしいのですが、さっくりと繋がります。
COM ポートとして使えるので、そのまま適当なコマンドを作ってやり取りすれば自前のモーター制御/サーボ制御ぐらいはできそうです。

Bluetooth シリアル変換モジュール(HC-05)をArduinoにつなげる

HC-05 Arudino
RX — TX
TX — RX
GND — GND
VCC — 3.3V

につなげます。RX/TX が送受信でワンセットになっているのと電源用の VCC/GND を差すだけで十分です。これは Raspberry Pi の場合も同じなので、結構さっくりと認識するはずです。

ちなみに、Windows 8 から Bluetooth 機器につなげるときはペアリングが必須なんですが(Windows 10の場合は BLE に対応するので、ペアリングは必要ないらしい?)、Bluetooth 機器だけを認識させる場合は、電源の VCC/GND の間に 3.3V – 6V ぐらい流せば ok です。電波を弱くして Bluetooth 機器の近くに入ったよ、ってのは、これでで十分かもしれませんね(実際、BLE の使い方でそういうのはあると思う)。

Android 側のスケッチを作る

シリアルポートは1バイト単位で読み込むのですが、コマンドっぽく送受信したかったので8バイト単位で受信しています。このあたりはマインドストーム EV3 を制御するときも同じみたいですね。こっちもいずれやってみたいところです。

int ledPin=13;
int mPin  = 8; // モーター

void setup(){
  pinMode(ledPin,OUTPUT);
  pinMode(mPin,OUTPUT);
  Serial.begin(9600);
}
 
void loop(){
  int n = Serial.available();
  if ( n >= 8 ) {
    int ch[8];
    int i;
    // 8バイトずつ読み込む
    for ( i=0; i<8; i++) {
      ch&#91;i&#93; = Serial.read();
    }
    // コマンドを判別
    if ( ch&#91;0&#93; == 'm' ) {
      if ( ch&#91;1&#93; == '1' ) {
        if ( ch&#91;2&#93; == 'o' && ch&#91;3&#93; == 'n' ) {
          // pin8 on
          digitalWrite(mPin,HIGH);
        } else {
          // pin8 off
          digitalWrite(mPin,LOW);
        }
      }
    }
    // 通信時に光らせる
    digitalWrite(ledPin,HIGH);
    delay(300);
    digitalWrite(ledPin,LOW);
    // エコーを送信
    for ( i=0; i<8; i++) {
      Serial.write(ch&#91;i&#93;);
    }
  }
}
&#91;/code&#93;
<ul>
<li>m1on  でモータ-をON</li>
<li>m1off でモーターをOFF</li>
</ul>
<p>
な単純な仕組みです。最終的には、モーター制御とアームのサーボ制御も入れたいのと、対物センサーの受信もいれておきたいですね。ここまで来ると、素直に BLE にしたほうがいいような気もするのですが、まあ、HC-05 モジュールが安いので。
</p>
<p>
<h2>Windows ストアアプリから制御する</h2>
</p>
<p>
Windows 8 の制限から、ストアアプリから制御します。たぶん、Windows Phone からも同じ制御ができるはずです。
</p>
[code lang="csharp"]
public sealed partial class MainPage : Page
{
	public MainPage()
	{
		this.InitializeComponent();
	}
	// RFCOMM のサービスID
	Guid serviceGuid = Guid.Parse("00001101-0000-1000-8000-00805f9b34fb");
	RfcommDeviceService rfcommService;
	StreamSocket socket;
	DataWriter writer;
	DataReader reader;

	// 接続する
	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 void btn_close_Click(object sender, RoutedEventArgs e)
	{
		writer.Dispose();
		reader.Dispose();
	}

	// 送信する
	private async void btn_sendMessage_Click(object sender, RoutedEventArgs e)
	{
		// 8文字にして送る
		string text = textIn.Text;
		await SendCommand( text );
	}
	// コマンド送信
	async Task SendCommand(string text)
	{
		textIn.Text = text;
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		writer.WriteString(text);
		await writer.StoreAsync();
		// そのまま受信待ち
		var res = reader.LoadAsync(8);
		res.Completed = async delegate
		{
			await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
				string text2 = reader.ReadString(8);
				textOut.Text = text2;
			});
		};
	}

	private async void clickM1on(object sender, RoutedEventArgs e)
	{
		await SendCommand("m1on");
	}

	private async void clickM1off(object sender, RoutedEventArgs e)
	{
		await SendCommand("m1off");
	}
}

基本は、がりっちさんの記事 http://garicchi.com/?p=17111 と変わりません。デバイスを見つけて、最初のデバイスに自動的に接続します。最初の1回だけはストアアプリから接続許可を求めるダイアログが出ます。

あと、RFCOMM を使うために Package.appxmanifest に以下のように追加しておきます。

  <Capabilities>
    <Capability Name="internetClient" />
    <m2:DeviceCapability Name="bluetooth.rfcomm">
      <m2:Device Id="any">
        <m2:Function Type="serviceId:00001101-0000-1000-8000-00805f9b34fb" />
      </m2:Device>
    </m2:DeviceCapability>
  </Capabilities>

うまくできあがると、m1on/m1off のボタンを押すことでモーターが動いたり止まったりします。ここは LED で動かしてて確認してもよいですね。ブレッドボード上でモーターが動いても何も面白くない(娘談)なので、ええ、キャタピラを付けてコントローラーで制御するところまでやりますよ。

ちなみに BLE 機器を見つけるだけならばペアリングが不要(通信には必要?)なので、忘れ物タグとかについているんですね。なるほど。これ Windows 8.1 の場合はまだ見つけるだけでもペアリングが必要で、Windows 10 ではそれに対応するらしいのですが…適当な BLE 対応のスマートフォンを媒介すれば、Windows 8.1 でもできるかなと。まあ、半年後に Windows 10 が出るのでそれ待ちってのもあるし、手元のノートPCにWindows 10 TP 版を入れて確かめてみるってのもありですね。

カテゴリー: 開発, Arduino, WinRT | Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う はコメントを受け付けていません

Netduino を壊しながら学ぶ Arduino でモーター制御をする

いや、別に壊す気はなかったのですが、モーター制御の実験をしていて壊してしまいました T_T > Netduino 。グローバルサミットの後、年末に買っていくつかサンプルを作っていたのと、例の RealSense のコンテストで妖怪ウォッチの LED を光らせているのが Netduino plus 2 だったわけで、結構な値段で、ちょっとばかし落ち込んだのですよ。ええ、「Raspberry Pi は壊しても諦められる値段」だけど、Netduino plus 2 はちょっと高いんですよね。と言いますか、仕事で使おうと思ったら予備も含めて、最低2台は必要ですね。

さて、RasPi と Netduino, Arduino を同時にやっているのは、花札認識もそうなんですが、meArm を自走式にしたいからなのです。何がいいのかよくわからないので(最終的にはハイブリットな感じにはなりそうなのですが)いくつか同時に進めています。

で、LED は自由に光らせることができたので(妖怪ウォッチのLEDをリレー電飾っぽく光らせる方法もわかったし)、自走のためのモーター制御です。ラジコンっぽく動かしてみたい。LEGOマインドストームの EV3 と Raspberry Pi + PS3コントローラー の組み合わせでいけることが分かったので、この度はモーターを直接制御しようって話です。

手元にある「Aduino を始めよう」の 058 ページを見ながらモーターを動かそうとしていたのですが、これ Arduino じゃない外部電源を使う場合はどうするんでしょう?と思いつつ、Arduino でモータを動かす:息子と一緒に Makers:So-netブログ を参考にしつつやっていたわけですが、MOSFET がよくわからなくて詰まっておりました。Arudino のピンを使って制御する前の段階で、なんで、PIN で ON/OFF したら、モーターが動くのだろう?って疑問です。たぶん、実地でやってみればわかるだろうと思って、あれこれやってみた途中で netduino を壊してしまうというおまけがついていますが。

image

直ぐ忘れるので、写真を張っておきます。左から、ゲート、ドレイン、ソースです。

image

  • ゲートのほうに、Arduino のピン制御を差し込む(プラス極)
  • ドレインにモーターをつなぐ(プラス極)
  • ソースを GND(マイナス極)につなぐ

モーターと並列に繋いであるダイオードはサージ用なので、逆向きにしておけばok。

で、素直に Arudino に配線して、モーターのオンオフを調べればいいのですが、先の何故ってのが気になっていたので、ピン制御をする部分を電池で代用してみます。こんな感じに、ゲートのところに6Vの電池を置きます。

image

ここで、6V の線をつなぐと、モーターが回りだします。線を外してもモーターは回り続けます。モーターを止めるには、6V のプラス極の線を、GND に設置させて電圧を0Vにしないといけないんですね。ここがよく分からなかったところで、電流を流し続けて続けている間、モーターが回るのかと思ったら、一旦、6V を流しておけば MOSFET 内で接点したままになって、モーターは回り続けます。

で、ここで必要なのは、4V 以上とのことで電池2個分の3Vではスイッチは働きません。

と、ここまで書いて、モーターを回す を見ていたら、ゲートとソースの間に抵抗を挟むことで放電させることができるんですね。そうなると、いちいち電圧を0Vにするために、6Vのプラス極を動かす必要はありません。

image

こんな感じに大き目の抵抗を挟み込むと、6Vの線を抜いた後にモーターが止まるようになります。

ちなみに、Arduino から制御するときは抵抗を挟まなくてもモーターのON/OFFが働きます。

image

モーターの動作自体は、LED の Blick のサンプルをそのまま使ったので、1秒動いて1秒止まっての繰り返しだけです。これを Bluetooth から制御するのと、逆回転の仕組みを作るのが次のステップ。

カテゴリー: Arduino | Netduino を壊しながら学ぶ Arduino でモーター制御をする はコメントを受け付けていません