■ホビーロボット部品の製造・販売 
  モータコントローラ、センサ、音声、画像、無線モジュールなど、
■ホビーロボット制作記事のページ (各種マイコン、PCとの接続事例)
■特殊メイク、特殊材料の販売 ※特殊メイクのコーナーはこちらに移りました。
Top(お知らせ) 製品紹介 使い方とサンプルプログラム 通信販売 リンク ロボット掲示板 会社案内
 Easy Robotics for all enthusiastic people!!!  ---HOBBY ROBOT PARTS SHOP ASAKUSAGIKEN---   Since 2003...

Visual C# 2005 を使ってPCから感圧センサーを駆動してみる
はじめに

 
マイクロソフトのWindowsアプリ開発環境が、xx2005にバージョンアップし、特定の言語だけなら無償で入手できるようになりました。また、PC−ロボット間の通信でよく使われるシリアルポートを駆動する、SerialPortコンポーネントも標準装備になって、ますますホビーロボット製作のツールとして使いやすくなってきました。

 ここでは VisualC#2005(以下VC#)を使って浅草ギ研製感圧センサーボード「AGB65−4FS(4 point Force Sensor)」をPCから駆動してみます。
 尚、C#以外の言語でも基本的な考え方は同じですのでこのページを参考にしてください。


 VC#2005のインストールについてはこちらを参照願います。

 VC#2005でシリアル通信をする方法、シリアル通信、RS232Cについてはこちらを参照願います。


 ※このページで紹介する内容はあくまでも一例です。個別の作成のご相談ご質問はお答えできませんのでご了承下さい。このページと同じ内容についてのご質問についてはロボット掲示板にてお願いいたします。

 ※ここではビギナー向けに解説していますが、このページは、プログラミング技術の向上を狙っておりません。VC#に関する質問はご遠慮下さい。(他所で良いページがたくさんありますのでインターネットで調べてください。もしくは本を買って勉強してください。プログラム本は高いですが、図書館に申請すると無料で読めます。ついでにギ研の本も申請してもらうとありがたいです。)


AGB65シリーズとAGB65−4FS

 ロボット神経システムAGB65シリーズはPCやマイコンのシリアル通信機能を使えるスキルがあれば簡単に動かすことのできるモータコントローラ、センサー群です。1つのシリアルラインを複数のAGB65シリーズで共有でき、取り外しや追加も簡単に行えますのでPCをホストコンピュータとしたロボットの作成が容易にできます。

 AGB65シリーズについてはこちらにも情報があります。

 今回使用するAGB65−4FSは1つのセンサーボードに4つの感圧センサーを付けて、それぞれの荷重情報だけでなく、4点内の重心位置をXY座標で出力する機能もついています。

 4点感圧センサー AGB65-4FSの詳細はこちらを参照願います。<−このページは必ず参照してください。
  (以後、このページを4FSのページといいます)

 PCとマイコンのシリアル通信の電圧は違いますが、AGB65シリーズは標準ではマイコンと接続するようになっておりますのでこれを変換する必要があります。変換にはAGB65−232Cというオプションボードが用意されております。

 

 COMポートが無いノートPCなどは、USBシリアルアダプタを使用することになります。市販の簡易的なUSBシリアルアダプタの場合は正常に通信できないものがありますのでご注意ください。浅草ギ研で販売しているものは確認済みです。


実際の接続

 まずは測定するためにセンサーを固定する必要があります。4FSのページに取り付け寸法がのってますので、作業場に有った適当なアルミ板に取り付け穴をあけました。実際にはロボットの足裏や、外装の内側に取り付けることになります。
  

4点と取り付けたところです。真ん中に4箇所ネジ穴が開いてますが、これはこの裏にモジュール部を取り付けるためにあけました。モジュールの取り付け穴ピッチは25x25mm間隔です。AGB65の取り付け穴ピッチは5mm単位なので、製図をせずに、方眼紙を板に貼りつけても正確な穴があけられるかと思います。モジュール部のサイズも、ロボットへの取り付けを考慮して29x29mmと非常に小さく作りました。
  

裏面にモジュール部を取り付けたところです。
  

上の図のように、PCと接続する場合はシリアル通信の電圧変換をする必要がありますので、オプションのAGB65−232Cを経由して接続します。
  
モジュールは内部5Vで動いており、7.5V以上(25Vまで)の電源が必要です。添付されている電源ケーブルは9V乾電池用のスナップがついてます。
プログラミング中はずっと通電することもあるかと思いますので乾電池を使いたくない場合はケーブルを加工して外部電源化するのもよいでしょう。私は開発の9V電池の代わりは、1Aぐらいの出力のACアダプタを使ってます。ACジャックは秋葉の電子部品店などでも売ってます(私は千石電商で買いました。)。ACジャックと、4FSに添付されている9V乾電池用のケーブルを切ってハンダ付けしたのが下の右の写真です。
  

その他細かい接続や注意点は4FSのページを参照願います。


プログラミング〜各センサの値を読んでみる

以下、プログラミング経験がある方を想定して進めます。C#や.NET環境をまったく使ったことが無い方は前のページ(ココココ)を見てください。VC#2005はマイクロソフトより無償で入手できます。VBもC++もJ#も無償ですが、以下C#ですすめます。

C#は大文字と小文字を判断しますので、打ち間違いに注意してください。 textBox と TextBox は別ものと判断されます。

まずは簡単に、4FSに接続された4つのセンサの荷重情報を読み取ってみます。読み取る段取りとしては

「読み取る命令を出す」−>「受信バッファを確認する」−>「出した命令の返答だったら値を表示」

という形になりますので、シリアルポートからの送信と受信のプログラムを組むことになります。
では、命令と返答のフォーマットを確認してみます。

4FSのページを見ると、

<4点の値を測定>
 [255] [ID] [長(1)] [命令(30)]

<結果のフォーマット>
 [255] [ID] [長(5)] [命令(30)] [P1] [P2] [P3] [P4]

命令を送信するボタンを押して結果が表示されるものを作ればよい感じです。
ということでWindowsアプリケーションでプロジェクトを作り、必要なコンポーネントを貼り付けたのが下になります。コンポーネントはツールボックスからドラック&ドロップで簡単に貼り付けられます。


初期値で名前などが button1 のようにC#側でつけられていますが、このままだとわかりづらいのでわかりやすい名前と表示に変更します。変更するにはそれぞれのコンポーネントを指定(クリック)した状態で画面右下のプロパティを変更します。名前は(Name)、表示はTextのところで変えます。(Name)はプログラム内で識別するもので、普通は半角英数にします。Textは自分でわかりやすいものにします。大きさはデザイナ画面(上の画面)でマウスで調整します。

旧(Name) 変更したプロパティ
Form1 Text:AGB65-4FSのテスト
comboBox1 (Name):id
Items:"100"から"115"を追加
Text:100
label1 Text:P1
label2 Text:P2
label3 Text:P3
label4 Text:P4
textBox1 (Name):p1Result
textBox2 (Name):p2Result
textBox3 (Name):p3Result
textBox4 (Name):p4Result
button1 (Name):readButton
Text:4点読み取り
※それぞれの設定方法はヘルプを参照してください。

設定後は下のようになります。ここで「F6」でビルドして「Ctrl」+「F5」で実行すると、このフォームが実行され、フォームの実体が表示されます。

実際のプログラミングでは、入力チェック、たとえば半角数字を入れなくてはならないところに全角が入ってないかとかバイト変数に代入する値なので0〜255しか許可しない、などのチェックを入れないといけないのですが、プログラムがややこしくなるので割愛します。以後、操作するときは上のテキストボックスには0〜255の範囲で半角で入力してください。

IDは4FSのIDが出荷時に100に設定されているので初期値を100にしてます。モジュール上のロータリースイッチを変えることによりこのIDは100〜115の16種類に切り替えできます。(つまり、1つのPCのシリアルポートに16個のモジュール、64個のセンサがつけられることになります。)


さて、シリアルポートからデータを送信するのでシリアルポートコンポーネントも配置します。

ツールボックスを探すとSerialPortコンポーネントが見つかります。


フォームにドラック&ドロップすると、画面下の方に表示されます。実際にフォームに表示しないコンポーネントはこのように画面下のフォーム外に配置されます。そこをクリックするとプロパティが見れます。


プロパティを見ると次のようになっています。

一番重要な通信設定ですが、SerialPortコンポーネントの初期値は上のように

速度:9600bps
データ長:8ビット
パリティ:なし
ストップビット:1
フロー制御なし:

という設定です。これは4FSの初期設定と同じなので、プロパティなどは特に変える必要はないでしょう。変える可能性のあるのは、4FSはボーレート115kも設定できますのでボーレートの設定ぐらいでしょうか。115Kで通信する場合は上のBaudRateを115200に変えて、RSCのBPSジャンパをONにします。(が、ここではとりあえずやらない方が良いです。9600で動くのを確認してから115Kを試してみてください。)

このコンポーネントの名前が serialPort1 というのを覚えておきます。

では実際に送信するプログラムのコーディングに移ります。
Windowsのプログラムはイベントをきっかけに動きますので「ボタンをクリック」というイベントが発生したらデータを送るようにします。
下記の手順でボタンのイベントを表示させ、 Clickイベントの右をダブルクリックすると、Clickイベントの入力画面になります。


こんな感じで必要な部分が自動生成され、表示されます。実際にはフォームを定義する部分やいままでコンポーネントを貼り付けたりプロパティを設定した部分も必要ですが、そのあたりはコンストラクタ(起動時の処理をするところ。)内の InitializeComponent() で定義されています。この中身はForm1.Designer.csとい名前で別ファイル内にかかれてます。余計なところは隠しておくという感じでしょうか。前バージョンよりすっきりしてよいと思います。


さて、ここまできたら後はC#の初級本に書いてある内容だけで組めるかと思います。とりあえず、ボタンクリックで4FSに読み取る命令を送る部分を書いたのが下になります。

※ほとんどのPCはこれで動きますが、シリアルバッファが極端に少ないPCや、非常に高速なPCの場合は、4点読み取りボタンを押したイベント内で4バイトバッファに格納されるまえに処理が終わってしまう可能性もあります。この場合は一瞬結果が表示されてから0が表示されるような状態になります。対策としては1バイトづつ読み込んで判定する方法があります。下の方でこの方法で読み込んでます。今回は簡単に説明するためにこの処理を省略。

コンストラクタは起動時の処理を行うところですが、ここでシリアルポートをオープンしてます。シリアルポートについてはVC#2005でシリアル通信をする方法 のページに詳しく書いてあります。

クリックイベント内でデータをセットして送信してます。SerialPortコンポーネントがあるので簡単に記述できます。送信フォーマットは4点測定の命令は [255] [ID] [1] [30] のようになりますので、変数はID部分だけです。IDはコンボボックスのTextから取ってきますが、送信データは数値データなので Convert.Tobyte( ) で8ビット数値データに変換してます。

これでボタンを押したら命令が送られるようになりましたので次は、受信です。

 命令送信後、4FSからいつ結果が返されるかPC側ではわかりませんが、SerialPortコンポーネントに、受信がきたときに発生するイベントがありましたのでこれを利用します。デザイナ画面に戻り、貼り付けられている serialPort1 を選択(クリック)し、イベントボタン(イナズマアイコン)を押してイベントを表示させます。


 SerialPortコンポーネントの場合は、自動生成されるイベントの構文が若干違います。引数のところの記述が変わってますが、あまり気にしないでください。C#を追求するとこのあたりを操作できてさらにいろいろなことができるというものです。普通に通信する場合はいじりません。


さて、もう一度、4FSから返送される結果のフォーマットを見てみます。

<結果のフォーマット>
 [255] [ID] [長(5)] [命令(30)] [P1] [P2] [P3] [P4]

ということでできたのが下のプログラムになります。点線が追加部分です。


テキストデータはこちら FS1.txt

※本格的に使う場合はエラー処理を入れたり、ディスポーズ内でポートを閉じる(seralPort1.Close( ))を追加してください。上はあくまでもわかりやすい例ということで簡単に作ってます。ポートクローズしないと、PCの電源を切らないとポートが開放されない場合がありますので注意してください(可能性は低いですが。)。


では早速実行してみましょう。「F6」でビルドして「Ctrl」+「F5」で実行しますと、作成したフォームが表示されます。
  

各センサの最低反応荷重は200G以上なので800g以上のものをのせてみます。ちょうど、重さが1kgぐらいのKHR−1があったので、上に板をしいて載せてみました。

一方に体重をかけるとこんな感じ、


逆にするとこんな感じです。


荷重ですが、単に板をしいただけだと、荷重が片寄ったときに逆側が浮いて荷重が200g以下になってしまい、値がでません。実際にロボットに取り付ければ問題ないと思います。


プログラミング〜12bitモードで各センサの値を読んでみる

4FSでは12ビットでセンサーの値を読み取ってますので、12ビットで出力することもできます。12ビットなので解像度は4046段階になります。シリアル通信では8ビット単位でデータをやりとりするので、4FSでは8ビットx2で1つのデータを表しています。

ここでは上で作ったプログラムを12ビットモード対応にしてみましょう。点線部分が今までとの違いです。

ある一定の時間なにもしないで待つ、という作業が必要になってきましたのでThreadingクラスのThread.Sleepメソッドを使用してます。
これはマイコンのウェイトのような関数で、mS単位で指定した時間待つというものです。Threadingを使う場合ははじめの方でUsingでインクルード(組み込み)する必要があります。
※とりあえずプログラムを簡単にするためにウェイトしてます。実際には次でやるように1バイトづつ読み込んで判定しながらデータを取り込みすると無駄な時間がかかりません。

どこでそれを使っているかというと、まず、起動時にシリアルポートのオープンと、12bitモードの命令送信を行ってますが、ポートオープンしてすぐにポートが使えるかどうかわからないので100mS待ってから命令を送ってます。

次にserialPort1の受信イベント内で、12bitモードの時は返信データの量が多いので、バッファに全て返信が入るまで待ってから計算処理を行っています。20mS待ってますが、9600bpsの場合は1バイト1mSで計算します。1バイト=8ビットですが、前後にスタート&ストップビットがつきますので結局1バイト送るのに10ビット分の時間がかかります。

計算は、8ビットの結果2つを合体させるのですが、C#の標準的な変数はint型なのでintで計算してます。
どのようにして合体するかですが、上のfor文内の2行は次のような処理になっています。

【8x2−>12ビットへの合体の例】
まず、たとえばP1の結果はrcvData[4]とrcvData[5]に分割されて入りますが、

rcvData[4]=xxxx 0110
rcvData[5]=0011 0010

という感じだったとしましょう。xは結果とは関係ないビットを表してますが、4FSからの返信データはここにはかならず0が入ります。
まず、それぞれは8ビット型の変数なので12ビット以上の入れ物に入れなおします。先に上位ビットのrcvData[4]を代入します。

tempData[0] = (int)rcvData[4] = 00000000 00000000 00000000 xxxx0110

次に、このrcvData[4]は上位バイトなので1バイト分シフトします。

(tempData[0] << 8) = 00000000 00000000 xxxx0110 00000000

最後に下位バイトを追加します。合体させるには + でも |(or) でも同じです。

tempData[0] + rcvData[5] = 00000000 00000000 xxxx0110 00000000 + 00110010

最終的にはこのようになります。

tempData[0] = 00000000 00000000 xxxx0110 00110010

ここで、int型ではなく、ushort(16bit)などでやった方がよいと思いますが、初めは上のプログラムのintのところをushortにしたらコンパイルエラーとなりましたのでintにしてます。原因は追究してません。すいません。(なんか、「暗黙に型変換できない」と言われた。)

実際に動かしてみたところが下のようになります。

このように0〜4095の間の値が出るようになり、解像度が上がります。
上の写真ですが、紙コップにネジを入れて800gぐらいのおもりを作ったら、反応が255以下で意味なかったので手でかるく押してます。

12ビットモードはデータ量が倍になり、通信時間が増えますが、このように解像度が上がり、軽い変化でも値が反応します。



プログラミング〜常に重心を表示するプログラム

 4点内の重心を返す命令もあるのでそれを使って見ます。今回はボタンを押さなくても、タイマを使って定期的に数値をアップデートするようにしてみます。

  また、今まではかならず決まった長さのデータが返されることが前提の受信プログラムでしたので、1バイトづつ受信してフォーマットを確認しながら受け取るというプログラムにしてみます。これだと複数のAGB65からの回答(センサなどによって返信バイト数が違う)も受信することができます。

 前のものに追加するとプログラムが長くなるので新規で作りました。まずは必要なコンポーネントを追加しました。


プロパティを次のように変更しました。
旧(Name) 変更したプロパティ
Form1 Text:AGB65-4FS 重心表示
comboBox1 (Name):id
Items:"100"から"115"を追加
Text:100
label1 Text:ID
label2 Text:X
label3 Text:Y
textBox1 (Name):xResult
textBox2 (Name):yResult
serialPort 変更なし
timer1 変更なし




新しく使用するTimerコンポーネントですが、これはプロパティで設定した時間の間隔でイベントを発生させるというものです。決まった間隔で4FSに命令を出して、結果をXとYに表示させます。
ということでまず、上でやったようにtimer1を指定してイベントアイコンを押します。Timerコンポーネントにはイベントは

このように Tick イベントしかありません。ここをダブルクリックして命令送信プログラムを入れます。

重心読み取りのフォーマットを確認しますと、

<命令送信フォーマット>
[255] [ID] [長(1)] [命令(60)]

<結果返信フォーマット>
[255] [ID] [長(3)] [命令(60)] [X] [Y]

のようになっています。命令送信部はいままでと同じなので簡単ですね。 Tickイベントと受信イベント(先にやったやつ)を記述したのが次になります。


テキストデータはこちら Form1.cs (右クリックで保存)

■ポイント1
 static型のフィールド変数はクラス内で参照されます。これは宣言されたときに実体化されてます。staticにしなくても良いのですが、このようにすると後々、フォーム内の別なところでこのxyデータを使うことができます。グローバル変数のようなものですね。

■ポイント2:timer1の起動時の設定
 Enebledをtrueにしないと、インターバルをセットしてもタイマは動かないようです。ついでにStart( )というメソッドも発見しましたので一応入れておきます。(インテリセンス(途中まで打つと候補が出てくる機能)だけを見てやってます。ヘルプも参照してませんが、使ったことが無いコンポーネントでもいじってるとなんとなく使えるようになります。)

■ポイント3:Tickイベント
 プロパティでtimer1のイベントを出してダブルクリックすると、イベントの記述が自動生成されますので、4FSに対する命令を埋め込みます。ここはtimer1のプロパティで設定した間隔でイベントが発生します。

■ポイント4:読み込みタイミング
 4FSからの返答は、
 [255] [ID] [命令長] [命令] ...
 というフォーマットで送られてきます。AGB65シリーズは種類や命令によって返信データが違いますので、単なる受信イベントではイベント発生時にどのぐらいの長さを受信したらよいかわかりません。よって、上のように1バイトづつ読み込んで判定しながら結果を取り込む必要があります。順調にいけば3バイト目が「その後読み込むバイト数」を表すので、この回数ループして結果を格納します。


では早速実行してみましょう。「F6」でビルドして「Ctrl」+「F5」で実行しますと、作成したフォームが表示されます


紙コップにネジ1kgぐらいを入れて真ん中あたりにおいてみました。
今度はなにも操作しなくてもXYのところに値が表示されるかと思います。(上は中心付近におもりをのせた結果。8bitモードなので0〜255の範囲で127が中心位置)


プログラミング〜実際にロボットに取り付けて使用する場合(命令70、80)

 実際のロボットに取り付けてみるとわかりますが、取り付け方法によって重心結果の値は大きく左右されます。各センサからの個別データをマスタ側で計算するのであればソフト的に補正することができますが、せっかく重心計算を4FS側で計算できるので、取り付け方法などに左右されないで測定したいものです。

 このような場合の為に、現在の重心を記憶して、その重心を中心位置とした場合の相対位置XYで結果を出力するモードもあります。これらは命令70と80のくみあわせになります。詳しくは4FSのページを参照してください。


 実際に私の方でロボットに組み込んでテストした結果、ほとんどの用途で命令70と命令80だけで済むことがわかりました。4FSにはいろいろなモードをつけてみましたが実際にはこの2命令しか使う機会は無いと思われます。

 取り付け時のポイントですが、センサー部は点なので、接触部がその点以外の場合は当然荷重を検知できません。この場合、たとえば二足歩行ロボットの足裏につける場合は、足裏が床と平行に接触する場合でないと全センサーポイントからの値を読むことができません。床が水平でない場合も同様です。これではせっかくセンサーを付けた意味が無いので、全ポイントに荷重されるように構造的に改善するしかないかと思われます。
 これは重要なポイントなので、浅草ギ研では引き続き、対象物が水平でなくても4点に荷重されるようなパーツを検討していきます。これらの情報については開発が終了しだい、4FSのページにてお知らせいたします。


おわりに

 VC#2005になったおかげで、このような感じで簡単にPCからシリアル通信で動く機器をコントロールすることができます。

 また、浅草ギ研では、同じようにコントロールできるセンサやコントローラを順次リリースする予定があります。感圧センサーだけでなく、他のセンサーやサーボモータコントローラも同様にコントロールできますのでロボットのアプリケーション開発に注力できます。これらを使って、是非、高度なロボットを作成してみてください。


2006年4月1日

 
(C)Copylight 2003. 有限会社浅草ギ研 | 通信販売の法規(訪問販売法第8条)に基づく通信販売業者の表示