こんにちは。石川高専の長田です。前回に引き続き、Beetle Moduleについて書いていきます。
Beetle Moduleには、定期的に通信相手に信号を送り、必要のないときにはスリープ状態にするモードが有り、今日はそれを使ってみようと思います。
1. スリープモードに移行する手順
Beetle Module には3種類のモードがあります。
- トランスペアレントモード:1対1の通信を行う。(前回やったのがこれ!)
- ATコマンドモード:ATコマンドを用いて端末の設定を行う。
- 間欠モード(スリープモード):スリープしつつ定期的にデータを送信する。
スリープモードへ移行するためには、まずATコマンドモードに移行してから、スリープモードへ移行するためのコマンドを実行します。
2. ATコマンドモードへの移行および操作
PCからシリアルポートを通して端末に「+++」という文字列を送ると、ATコマンドモードへと移行します。
ATコマンドモードで設定できる項目は多数ありますが、今回はスリープモードへ移行するコマンドと、ATコマンドモードを終了するコマンドのみを紹介します。
ATと入力した後ろに行いたい処理に対応するコマンドを打ち、OKと表示されれば受理されているのでCRで締めます。
SMコマンドでスリープに関する設定をして、CNコマンドを実行するとATコマンドモードを終了します。
TeraTermでやるとこんな感じです。SMコマンドの後ろの"1"は引数を表しています。1を指定することでスリープモードへ移行し、0を指定することでスリープモードを解除します。ちなみに"2"でもスリープモードに移行しますが、スリープ開始と復帰のトリガーが逆になります。
図でスリープモードに移行しているので、あとは起こすまで何か打っても反応しません。
3. スリープモードでの動作を確認
前回と同じように、2つのモジュールを無線で接続して、送受信の様子を見てみます。
前述したとおり、スリープモード中は一定時間ごとに相手にデータを送ります。
こんな感じです。
この画像だと時間の動きがわかりづらいですが、「10D0」というデータを先頭とする5行のデータが、一定時間ごとに受信されています。この画像だとおよそ4回分になります。
この文字列……いったいなんの値だろう。とお思いのことと思いますが、これは、Beetle Moduleの特定のピンに入力されている信号の値を表しています。それについては後述します。
とりあえず一定時間ごとに通信していることがわかったので、スリープモードを解除します。
Beetle Module には0~20のピンがありますが、その中の9番ピンが「SLEEP RQ」という機能ピンになっており、このピンにHIGHかLOWを入力することで、モジュールを眠りから起こすことができます(HIGHで起きるかLOWで起きるかはSMコマンドの引数による)。あとはその状態でATコマンドモードに移行しスリープモードを解除すれば完了です。
ここで、どんな文字を送ればそんな特定のピンに信号を入力できるんだ…と自分は悩んでしまいましたがここでArduinoの出番です。
Arduinoにスケッチを書き込んで、9番ピンが常にHIGHになるようにします。スケッチはこんな感じ。
void setup() {
pinMode(7,OUTPUT);
}
void loop() {
digitalWrite(7,HIGH);
}
実にシンプルですが、ArduinoのDIGITALピンの7番ピンとBeetle Moduleの9番ピンを接続してこのスケッチを書き込めば常に起きっぱなしの状態になり、ATコマンドモードへの移行が可能になります。
4. Arduinoを使って入力データを制御する
さて、次にArduinoを使ってピンに入力する値を制御し、PC側で出力されるデータを制御します。先ほどの出力された文字列の一部を抜粋します。
一定時間ごとに、このように5行ずつ出力されています。最初の1行以外、似たような値が出力されていますね。
下の4行については、マニュアルによると、4つのADC0~3ピンそれぞれに入力された電圧値が0~1024の間で、16進数で表示されています。
最初の1行については、5つのDIピンに入力された信号がHIGH(1)かLOW(0)かを見て、その値を16bitの整数の対応した位に代入して表示しています。
対応図は以下のようになっています。
0
|
0
|
0
|
1
|
0
|
0
|
0
|
0
|
1
|
1
|
0
|
1
|
0
|
0
|
0
|
0
|
|
|
|
DI12
|
DI11
|
|
|
|
DI7
|
DI6
|
|
DI4
|
|
|
|
|
今回は、DI4、DI6、DI7、DI12のピンがHIGHなので1、DI11がLOWなので0となり、表の数値が16進数に変換されて10D0が出力されている、というわけです。
作成したArduinoのスケッチを以下にまとめます。
【Io_output.ino】
int pin_AD0=3;
int pin_AD1=4;
int pin_AD2=5;
int pin_AD3=6;
int pin_SLEEPRQ=7;
int pin_DI4=8;
int pin_DI6=9;
int pin_DI7=10;
int pin_DI11=11;
int pin_DI12=12;
void setup() {
pinMode(pin_SLEEPRQ,OUTPUT);
pinMode(pin_DI4,OUTPUT);
pinMode(pin_DI6,OUTPUT);
pinMode(pin_DI7,OUTPUT)
pinMode(pin_DI11,OUTPUT);
pinMode(pin_DI12,OUTPUT);
pinMode(pin_AD0,OUTPUT);
pinMode(pin_AD1,OUTPUT);
pinMode(pin_AD2,OUTPUT);
pinMode(pin_AD3,OUTPUT);
}
void loop() {
digitalWrite(pin_SLEEPRQ,LOW);
digitalWrite(pin_DI4,HIGH);
digitalWrite(pin_DI6,HIGH);
digitalWrite(pin_DI7,HIGH);
digitalWrite(pin_DI11,HIGH);
digitalWrite(pin_DI12,HIGH);
analogWrite(pin_AD0,20);
analogWrite(pin_AD1,80);
analogWrite(pin_AD2,150);
analogWrite(pin_AD3,255);
}
今回は、DIピンはすべてHIGHにして、ADピンにはそれぞれ入力値を変えて電圧をかけます。analogWrite関数の引数2はデューティー比となっており、AD3の255が最大値で、出力値は1023になります。これをArduinoに書き込んで読み取ったところ、図のようになりました。
DIデータの読み取りはすべてのピンがHIGHなので18F0と正しい数値が表示されていますがADCデータの読み取りが、思っていたのと違う結果に…
DI0が1番小さく、順に値が大きくなりDI3で最大値が表示されるはずでしたが、DI0,1はほぼすべて0で、DI2は0か03FF(10進数で1024)になっており、正しい値が出力されているのはD3のみです。
これは不思議だ…と思って少し悩んだんですが、これはおそらくArduinoの仕様によるものだと思います。
Arduinoのアナログ出力は、厳密なアナログ信号ではなく、PWM制御を使っています。つまり、設定したデューティ比に応じて単位時間あたりにパルス波がHIGHとなっている長さを変えることで、疑似的に電圧値を制御しています。
なので、ADデータを読み取った瞬間にHIGHならば03FF、LOWならば0が出力されてしまっているのだと予想してみます(あくまで予想です)。なのでデューティ比が最大値に設定されているDI3は常に03FFが出力され、デューティ比が高めのDI2は時々03FFを出力、デューティ比の低いDI1とDI0はほぼ常に0です。
これをうまく使って何か面白いことできないかな~とか密かに思ったりしてます。
今日はここまででしたが、これでArduinoのスケッチを使ってBeetle Moduleの送信値をある程度操作できるようになったので、次回はこれを使って何かシステムを作ってみようと思います。