はじめに
プチロボ制御基板WR-XXには、アナログセンサーの入力ポートが4つあります。センサーの値は、「コマンド5」を送信すると返信してきますので、このデータをプログラム上で使えるように取り出す方法を考えてみました。
本当は、C言語で書きたいのですが、Arduino IDEの使い勝手の良さに負けました。Arduinoには、とりあえず、早く形にしてみたいというプロトタイプ志向ならではの準備の良さというか、痒い所に手が届く感があります。Arduinoの魅力に今更ながら気づかされたというところでしょうか。
出力データの仕様
ADは常時計測されています。コマンドを受信したとき、最新のデータを送信します。
A/Dの基準電圧は3V(誤差±5% RG1に依存)で8ビット分解能となっています。
● [ADx] 2バイト = A/ 変換値をアスキーコード”30”~”39”、”41”~”46”でセットされます。
データ展開 ”38” ”30”の場合
①アスキーコードを16進数に戻す。
”38” = 8 “30” = 0 なので”80”
②16進数を10進数に戻す。
8 x 16 = 128 [16は固定値]
0 x 1 = 0 [ 1は固定値]
出典:WR-XX 通信プロトコルガイド(第2版)共立プロダクツ
使用するセンサー
プチロボWR-MS5Lのスクラッチサンプルの記事に使用されているモジュールです。WR-MS3Lのアームの先端に、プッシュゴムの代わりに取り付けています。
- 測距モジュール(距離センサー) GP2Y0A21YK x 1
シャープの赤外線を使用した測距モジュールです。赤外線LEDとPSD(position sensitive detector)を使用して、非接触で距離を検出することができます。
・用途:ロボット・アミューズメント等
■主な仕様
・測距範囲:10~80cm
・出力:アナログ電圧出力
・パケージサイズ(突起部を除く):29.5×13×13.5mm
・電源:4.5~5.5V
出典:秋月電子
なお、WR-XX基板にセンサーを接続して、基板のデータを直接Windows PCに送信すれば、このキットのプログラムCDの中にある、「プチロボブリッジ」という実行ファイルでセンサー動作を簡単に確認できるのでお勧めです。もともとは、プチロボをスクラッチで操作するためのデータ変換モジュールのようですが、画面右下の「A/D入力」の数値はリアルタイムに変更されますので、プログラムのデバッグをする上での励みになります。
プログラム上でやっていること
(手順)
- ArduinoからWR-XXに「コマンド5」を送信する(ソフトウェア・シリアル通信)
- 返信を受け取る
- 受け取った返信の数値をバイトごとに配列に振り分ける
- A/Dデータの該当バイトを使用に合わせて計算して10進数に戻す
- ArduinoからPCにセンサーの値を送信する(ハードウェア・シリアル通信)
PC上のデータの表示はArduino IDEのシリアルモニタで表示できます。
ソースコード
# include <SoftwareSerial.h>
# define BAUDRATE 38400
# define LEN 27
# define TXS 3
# define RXS 2
# define TRUE 1
SoftwareSerial mySerial(RXS, TXS);
int val = 0;
int buf[LEN];
void setup() {
Serial.begin(BAUDRATE);
mySerial.begin(BAUDRATE);
}
void loop() {
int c = 0, i = 0, j = 0, k = 0, n = 0;
byte myComand[5] = {253,4,5,254};
byte ad[4] = {0,0,0,0};
mySerial.write(myComand,4);
c = mySerial.available();
if (c > 0) {
for (i = 0; i <= c; i++) {
n = mySerial.read();
if (n == 253){
j = i;
k = TRUE;
};
if (k == TRUE && (i - j) >= 3 && (i - j) <= 12 ){
buf[i - j] = n - 48;
if (buf[i - j] > 9)
buf[i - j] = buf[i - j] -7;
Serial.print(i - j);
Serial.print('=');
Serial.print(buf[i - j], DEC);
Serial.print(' ');
};
};
Serial.print('\n');
ad[0] = buf[3] * 16 + buf [4];
ad[1] = buf[5] * 16 + buf [6];
ad[2] = buf[7] * 16 + buf [8];
ad[3] = buf[9] * 16 + buf [10];
Serial.print("AD値");
i = 0;
for (i = 0; i < 4; i++) {
Serial.print(i);
Serial.print(':');
Serial.print(ad[i]);
Serial.print(" ");
};
Serial.print('\n');
};
}
シリアルモニタ上のデータ(出力サンプル)
X=Yという表示は、返信されてきたデータの配列位置:Xと実際の数値:Yになります。第1アナログ入力ピンのデータは、配列の[3]と[4」に保管されている、という意味になります。あくまでデバッグ参照用の出力です。
その下のAD値0:23
というのが第1アナログ入力ピンから取り出した計算済みのデータになります。
3=1 4=4 5=2 6=15 7=15 8=15 9=15 10=15 11=0 12=1
AD値0:20 1:47 2:255 3:255
3=1 4=5 5=2 6=2 7=15 8=15 9=15 10=15 11=0 12=1
AD値0:21 1:34 2:255 3:255
3=1 4=7 5=2 6=0 7=15 8=15 9=15 10=15 11=0 12=1
AD値0:23 1:32 2:255 3:255
反省
WR-XXの「通信プロトコルガイド」でデータの仕様を読んでいて、最初、何のことかわからず、またなんでこんな面倒なことをしているんだろうと不思議だったのですが、おそらくは、PIC側からシリアル通信する上で、データの桁数を増やすために使われる手法のようで、ネット上にもなんとなくそんな前提で書かれたと思われる記事が散見されました。
PICとのシリアル連携が理由であれば仕方がないので計算方法や関数をいろいろ調べたのですが、それらしいものはなく、どうしてもうまく計算が合わない理由がわからず、半分徹夜のようになってしまい頭が朦朧となっていたところで、センサー回路を短絡させてしまい、WR-XX基板から文字通り煙が・・・
上記のデータサンプルで、本来は、AD値 1:32は、センサーを取り付けていないときには計測対象ピンと電源+ピンを短絡すると255
になるはずですが、あたかも短絡されていないかのようなデータになります。この記事を書いている途中で気になってセンサーピンを使用してみると、センサーを手で遮るととりあえず数値が変わるようなので、センサーピンとしてだけは使えるかもしれません。結局、至極単純なif文
で十分だということに気づくのに半日分の時間がかかりました。
寝不足や無理をしてもミスが増えるばかりで生産性が悪いことを痛感し、大いに反省しました。
データ表示もできそう?!
アナログセンサーのデータが使えるようにとなると、今度はデジタル出力ピンの方も使ってみたくなります。もちろん、本来は、アナログデータはサーボモータのコントロールに使えるように準備されているのだとは思います。でも、そのためには、まだまだ理論上も学ぶことがおおいので、すぐには活用できそうにありません。たとえば、センサーからの値を4桁の7セグLEDで表示するとかであれば、今の自分の知識でもできそうです。「Raspberry Piで学ぶARMデバイスプログラミング」に紹介されているLEDドライバーIC「74HC4511」をつかえば出力ピンが4つあれば操作できるはずです。これは、近日中にぜひ試してみたいと思います。でも、回路は、ICを3つも使うし、4桁の7セグLEDは本体が大きいので、ブレッドボード上のままにしようか・・・、やっぱりこれを機会に作っちゃおうか。いろいろと他の用途でも使えるし・・・