2021.8.7 SRF-02の使い方

本日のトピック

今回は、超音波センサSRF-02のコマンドについて調べました。

まず、SRF-02の通信には二つのモードがあり、I2CとUARTがありますが、今回はI2Cに焦点を当てて説明します。

まずは、SRF-02の主な特徴です。

◆主な仕様
・使用マイコン:16F687-I/ML
・測定範囲:16cm~6m.
・電源:5V(消費電流4mA Typ.)
・使用周波数:40KHz.
・アナログゲイン:64段階の自動ゲインコントロール
・接続モード:モード1=I2C、モード2=シリアルバス
・全自動調整機能:電源投入後キャリブレーション不要
・測距タイミング:エコー時間計測、ホストによるタスクコントロール
・測定単位:μS(マイクロ秒)、ミリ、インチ
・サイズ:24mmx20mmx17mm
・入出力端子:5ピン
・重量:4.6グラム

SRF-02の主なコマンド

次に、SRF-02で使用される主なコマンドです。

コマンドの通信方法は、ArduinoのWireライブラリを使って通信します。詳細は、以前のブログを参照してください。

I2Cでの通信方法

SRF02をI2Cモードで使用するには、モードピンをオープンにします。

I2Cの通信では、最大16個まで並列で接続できます。並列でつなぐので、それぞれのSlave(超音波センサ)にアドレスを振り分けます。
SRF02の出荷時のアドレスは0xE0です。アドレスはユーザによって変更することができ、最大16個(E0、E2、E4、E6、E8、EA、EC、EE、F0、F2、F4、F6、F8、FA、FC、FE)のアドレスが使用できます。

 

レジスタ

SRF-02には6種類のレジスタがあります。

ロケーション 読む書く
0 ソフトウェアリビジョンコマンドレジスタ
1未使用(0x80を読み取ります)該当なし 
2測定値 上位バイト該当なし
3測定値 下位バイト該当なし
4オートチューン最小-上位バイト該当なし
5オートチューン最小-下位バイト該当なし
レジスタ

 

6個あるレジスタのうち、Masterから書き込むことができるのは、0番のレジスタのみです。

すべて、0番のレジスタに数値を入れることでSRF-02の様々な設定ができます。

0番から読み出す場合は、ソフトウェアリビジョンを返されます。1番は使用していない空きピンです。

2,3番のレジスタが、測定した数値を返すレジスタです。測定値は最大2byteの容量で返します。レジスタ1個は1byteですので、レジスタが二つ(2,3)必要なわけです。この測定値は、設定の状態によって、インチ、センチ、マイクロ秒などで返します。

4、5番のレジスタは、16ビットの符号なし最小範囲です。これは、ソナーが測定できるおおよその最も近い範囲です。

つまり最初0番で指定をしたら、あとは2,3番のレジスタで測定値を参照すればよいということです。

 

SRF-02のコマンド

下記が、SRF-02の0番に指定するコマンドです。

  2進数    16進数  動作
800x50Real Ranging Mode – Result in inches
810x51Real Ranging Mode – Result in centimeters
820x52Real Ranging Mode – Result in micro-seconds
860x56Fake Ranging Mode – Result in inches
870x57Fake Ranging Mode – Result in centimeters
880x58Fake Ranging Mode – Result in micro-seconds
920x5CTransmit an 8 cycle 40khz burst – no ranging takes place
960x60Force Autotune Restart – same as power-up. You can ignore this command.
1600xA01st in sequence to change I2C address
1650xA53rd in sequence to change I2C address
1700xAA2nd in sequence to change I2C address
コマンド

必要に応じて、上記のコマンドを1番のコマンドレジスタに書き込み、必要な時間待機して結果を読み取ります。エコーバッファは、各レンジングの開始時にクリアされます。レンジングは最大66m秒持続します。この後、測定値を2,3番のレジスタから読み取ります。

SRF-02の命令方法

MasterからSRF-02に命令する場合、どのようにしたらよいでしょうか。

下記が、参考に、測定値をcmにするプログラムです。

Wire.beginTransmission(226); //通信先のアドレス
  Wire.write(0x00);    //レジスタを選ぶ
  Wire.write(0xA0);  //コマンドを選ぶ
  Wire.endTransmission();

順番としては、まず Wire.beginTransmission(226); で、Slaveのアドレス(226)を指定。

次に送信するものは、接続するレジスタになります。なにか設定などをする場合は、

0番のレジスタにアクセスするため、Wire.write(0x00);で0を送ります。

次に、送るものが設定するコマンドです。

例えば、測定値をcmで返す設定をする場合は、コマンド0x51を送ればよいので、

Wire.write(0x51);となります。

設定はこれで終了なので、 Wire.endTransmission(); で今回の通信を終わります。

コマンドの内容にもよりますが、基本は、レジスタを指定→そのレジスタのコマンドを送る、の流れです。

 

SRF-02の測定値を読み出すプログラム

次に、SRF-02から測定値を読み出す方法です。

      Wire.beginTransmission(0xE0); // transmit to device #112
      Wire.write(byte(0x02));      // sets register pointer to echo #1 register (0x02)
      Wire.endTransmission();      // stop transmitting

     
      Wire.requestFrom(0xE0, 2);    // request 2 bytes from slave device #112
    
      if (2 <= Wire.available())   // if two bytes were received
      {
        reading = Wire.read();  // receive high byte (overwrites previous reading)
        reading = reading << 8;    // shift high byte to be high 8 bits
        reading |= Wire.read(); // receive low byte as lower 8 bits
        Serial.print(reading);   // print the reading
        Serial.println("cm");
      }

まず、SRF-02から数値を読み出す場合、2番目のレジスタ0x02にアクセスします。それが、3行目までのプログラムです。

次に、SRF-02からデータを受信する準備をします。それが、 Wire.requestFrom(0xE0, 2); です。

これは、アドレスE0のSlaveから、2byteのデータを受け取りますという意味です。

あとは Wire.read();で、データを受け取ることが出来ます。しかし、2byteあるため、そのまま受け取ると下位ビットが上書きされます。そのため、まず、上位8ビットのデータを受け取り( reading = Wire.read(); )、readingのビットを (reading = reading << 8; )8bit高い位にシフトさせてから、次に飛んでくる数値(下位ビット)を ( reading = Wire.read(); ) で受信します。

Slaveで分割されたデータは、上位ビットから書き込まれる

そのまま下位ビットを書き込むと上書きされてしまう

そこで、最初に書き込まれた上位ビットを8ビット上にシフト

そのあとで下位ビットを書き込めばすべて正しく送れる

 

 

SRF-02のアドレス指定

次に、SRF-02のアドレス指定手順です。方法は簡単で、上記コマンドの0xA0, 0xAA, 0xA5,を順番に送り、最後に新しいアドレスを送ることで、アドレスを指定するモードになります。例えば、もともとのアドレスE0から新しいアドレスF4に帰る場合は下記のプログラムを動かします。とてもシンプルですよね。

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xA0);               //A0を書き込む
  Wire.endTransmission();

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xAA);               //AAを書き込む
  Wire.endTransmission();

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xA5);               //A5を書き込む
  Wire.endTransmission();

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xF4);               //新しいアドレスF4を書き込む
  Wire.endTransmission();

今日は、ここまで。

 

2021.8.7 ひいらぎ

カテゴリーblog

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA