ラベル 測距 の投稿を表示しています。 すべての投稿を表示
ラベル 測距 の投稿を表示しています。 すべての投稿を表示

2025年12月5日金曜日

超音波距離計(その5)

 基本的な機能は実現できたので、次に実際の利用に合うようプログラミングを行う。基本的なロジックは、

  1. センサー部から200ms毎に送られてくる測距データを表示する。 
  2. 7セグメントLEDは測距データを3桁の数字で表示する。但し超音波センサーの最大探知距離が 400cmなのでそれより大きな値が来たときはエラーとみなし3桁ともマイナス(-)を表示する(センサーがエコーを捉えられなかった場合を含む)。逆に0cm或いはそれ以下だった場合(センサーの取付位置のオフセットを設定すると負の値もあり得る)は下線(_)を表示する。
  3. RGB-LEDは距離に応じた色を表示する。また距離が短い場合は点滅表示を行う。これは7セグメントLEDを瞬間的に見た場合に読み間違いの可能性がある為だ。
  4. センサー部からのデータが途切れた場合は7セグメントLEDはドットを表示し、RGB-LEDは消灯する。

RGB-LEDは各色8ビットの諧調つまり24ビットの表示能力を持っている。 3,ではこれについて最初に距離に応じた連続的な色変化を試したが、そうすると逆に変化が認識しずらい。また輝度が高い場合の明るさの変化も認識しずらい。そこで距離に従って色を決める事にした。5つのLEDは同じ色を表示させる。具体的には100cm以上は青、100cm~40cmは緑、それより近い場合は赤を表示。各色の諧調は8程度で、距離が短いほど指数関数的に明るくなるようにした。さらに70cm以内では距離応じて点滅、距離が近いほど早く点滅するようにした。また緑は輝度が高いので値を約半分に抑えるようにしている。

4,ではタイマーを使って監視し、センサーからの信号が2秒以上来なかった場合に途切れたと判断している。



400cm以内にエコーが無い場合はマイナス(-)(距離が0cm以下の場合は下線(_)とする)。
 

センサー部からのデータが途切れた場合。


とりあえず当初の機能目標は達成したので、これらを格納する箱探しを行った。

一応百均で大きさの合いそうな物を探した。表示部はディスプレイケースを加工したが下部の長さが不十分でコネクタを挿すとはみ出すため更なる工夫が必要だ。センサー部はラップ用ボックスを逆さまにし21mmの穴を開けてセンサー用の窓とした。背面にマグネットが付いているのでそのまま金属に付けられる。中には吸音材を入れている。防水性が気になりスーパーで買った商品を包む薄い袋を被せてみたが、最大探知距離が1.5mくらいに低下した。


 (終り) 


 



2025年12月2日火曜日

超音波距離計(その4)

 

 RGB-LED(PL-9823)は次のような特殊なPWMパルスを作って駆動する必要がある。このデータは信号が0→1になる所からスタートし、全てのビットを送り終える最後のビットの最後は0→1で終了する。であるなら全てのデータを送った後のアイドルの状態は0なのか1なのか? スタートの条件を考えれば0であるが図からは最後は1で終わるように見える。たぶん最後は0を延長したRETコードをアイドル状態として使うのだろうと推測する。

このパルスの厳密なタイミングには幾つかの情報があり曖昧であるが次の情報が確からしい。実際には動かして確かめる必要があるがHとLが概ね1:3あるいは3:1の比率であれば成立しそうだ。

またビットの並びはMSBファーストで、次の様にRGBの順だという資料もあるがGRBという資料もあり、これも実機で確かめる必要がある。

RGB-LEDはカスケード接続で複数を制御できる優れものである。今回はこれを5個を使う。

データの転送時間は上のタイミングから1ビット当たり1.25μsかかり(転送レート800Kbps相当)、1つのLEDに30us、5個のLEDを合わせると150μsかかる。

この信号をどうやって生成するかであるが、NOP命令を挿入してタイミングを取るソフト的な方法と、ハードロジックで信号を作成する方法が考えられる。MicrochipのアプリケーションノートAN1606にはPIC16F1509のCCPを使ってWS2811を駆動する例が示されており、これが参考になりそうである。しかし何れも時間的にかなりシビアで先人の例でも涙ぐましい苦労の跡が見える。特に回路の遅延などに伴うヒゲの発生には十分注意する必要がある。開発にはロジックアナライザを活用する必要があろう。

 ソフト的にやるのは後回しとして、とりあえずハードロジックを検討してみる。PL-9823はAN1606で示されたWS2811とは必要とする波形が違うので、それに合わせる必要がある。

信号の基本はSPIの出力である。PL-9823ではSPIの1つの出力ビットを4つに分けて1:3(0 code)又は3:1(1 code)の比率のPWMパルスを生成すれば仕様に合う。SPI出力が800Kbpsなら800KHzと1.6MHzの方形波があれば合成できる。SPIを駆動するクロックはFosc/4を分周したものであるため、3.2MHzの2^n倍のFoscが必要であるが一方PIC単体で発生できるクロックは限られており最も近い値として12MHzを4分周してFosc=3MHzとして使うのが適当だろう。ということで転送レート 750Kbps(=3MHz/4)で検討したい。

 AN1606に準じて考えると、SPIの出力(SDO)、SPIのクロック(SCK)、それにSCKの元となるクロックFosc/2から合成できそうだ。Fosc/2はCLKRを使ってFoscを2分周して生成した。

0 code = /SDO & SCK & Fosc/2

1 code = /(/SDO + /SCK + /Fosc/2)  

 PWMパルス = 0 code + 1 code

 この式で & は論理積、+ は論理和、語頭の/ は否定を表す。

この式ならCLKRとCLC各1個で実現できそうである。ということでこれを実際やってみたところ、SPIで送信するバイトの最後のビット(lsb)がSDOではアイドル状態まで引きの伸ばされるためlsbが1だとアイドル状態でもFosc/2がPWMパルスとして出力されAN1606のように上手くは行かない。強制的にlsbを0として7ビットのデータとするなら上手く行きそうだが。そこで悩んだ末に何とか窓信号を作り論理積をとる事とした。

具体的にはもう一個のCLCを使ってSCKをFosc/2の立下りでサンプリングすることで25%遅らせたSCK2を作り、SCKとSCK2の論理和を窓信号とする。つまり、 

     1 code = SDO & ( SCK + SCK2 ) 

 とする。これで上手く行きそうだ。そして、次の通り上手く光ってくれた。

実際に出来た波形を観測すると、 SPIの出力は1バイト(8ビット)送出した後次のバイトを送出までに隙間が出来る。つまりSPIではバイトを跨ぐ連続送信は出来ずバイト間では T0L や T1L が長く引き延ばされている状態になる。この隙間の大きさの規程は無いがRETコード、つまり(確かめた訳ではないが)50usを超えなければ問題ないようである。

 ここまでで基本的な機能は実現できたので、あとは受信した測距データをもとに表示内容を決めていきたい。

参考までにPWMパルスを作成するためのCLKR、SPI1、CLC1、CLC2の初期設定部分は次の様にした。

    //
    // CLKR Fosc(3MHz) to 1.5MHz
    //
    CLKRCONbits.CLKRDC  = 2;        // Duty is 50%
    CLKRCONbits.CLKRDIV = 1;        // divide by 2
    CLKRCONbits.CLKREN  = 1;
    //
    // SPI1
    //
    SSP1CON1            = 0x0;      // clear SSPEN
    SSP1CON1bits.CKP    = 0;        // IDLE Clock is Low
    SSP1CON1bits.SSPM   = 0x0;      // SPI with Clock = Fosc/4
    SSP1STATbits.CKE    = 0;        // trans. at clk idl->actv 
    PIR1bits.SSP1IF     = 0;        //        
    SSP1CON1bits.SSPEN  = 1;
    //
    // CLC1
    //
    CLC1CONbits.LC1MODE = 0;        // AND-OR
    CLC1SEL0            = 0x13;     //1 SPI1 SDO
    CLC1SEL1            = 0x12;     //2 SPI1 SCK
    CLC1SEL2            = 0x0B;     //3 CLKR = Fosc/2
    CLC1SEL3            = 0x05;     //4 CLC2 = SCK2
    CLC1GLS0            = 0x16;     // 0 code = /SDO & Fosc/2
    CLC1GLS1            = 0;        // T
    CLC1GLS2            = 0x02;     // 1 code = SDO
    CLC1GLS3            = 0x88;     //          &  /(/CSK & /SCK2 )  
    CLC1POL             = 0x03;
    CLC1CONbits.EN      = 1;
    //
    // CLC2 - MAKE DELAYED SCK
    //
    CLC2CONbits.LC2MODE = 4;        // 1 input D-ff with S & R
    CLC2SEL0            = 0x12;     //1 SPI1 SCK
    CLC2SEL1            = 0x0B;     //2 CLKR = Fosc/2
    CLC2SEL2            = 0;
    CLC2SEL3            = 0;
    CLC2GLS0            = 0x4;      // CK: /SEL1 = /Fosc/2
    CLC2GLS1            = 0x2;      // D:  SEL0 = SCK
    CLC2GLS2            = 0;        // R: F
    CLC2GLS3            = 0;        // S: F
    CLC2POL             = 0x00;
    CLC2CONbits.EN      = 1;
 

SPIは同時双方向通信という特徴があり、送信のみや受信のみという動作は無い。通常のシリアルインターフェイスの送信だと送信バッファーが空になるのを待って送信バッファーにデータを書き込むが、SPIでは送受のバッファーが共通になっており、送受信が完了したというフラグしかない。従ってSPI(マスターモード)でデータを送信する場には先ずバッファーに送信データを書き込み、送受信完了のフラグを待って次のデータを書き込むというプログラミングをする必要がある(受信の動作はダミーとなる)。このとき送受信完了のフラグは自動的にクリヤーされないのでソフトでクリヤーする必要がある。具体的に5個のLEDにデータを送るのは次の様にした。なお割込みが起きる事でタイミングが狂わないようこの部分は割り込み禁止としている。

void rgbSetLeds(byte *clr_r, byte *clr_g, byte *clr_b){
    byte GIEBitValue = INTCONbits.GIE;
    INTCONbits.GIE   = OFF;          // di()-----------------              for(byte i=0; i<5; i++){
        PIR1bits.SSP1IF = 0;
        SSP1BUF     = *clr_r++;     
        while(PIR1bits.SSP1IF==0){} PIR1bits.SSP1IF = 0;
        SSP1BUF     = *clr_g++;     
        while(PIR1bits.SSP1IF==0){} PIR1bits.SSP1IF = 0;
        SSP1BUF     = *clr_b++;     
        while(PIR1bits.SSP1IF==0){}
    }
    INTCONbits.GIE = GIEBitValue;    // ei()-----------------

}

これを誤って最初を、UARTの送信のように

        while(PIR1bits.SSP1IF==0){} 
        SSP1BUF     = *clr_r++;     
 

とするとSPIでは永久の待ちとなりデータは送信できない。

(続く) 

 

2025年11月30日日曜日

超音波距離計(その3)

1週間ほどで基板が届き、組み立てた。RGB-LEDのピンの間隔が狭くブリッジが出来て上手くハンダ付けができない。ブリッジの場所を探し出すのにパターンを切ったりして苦労したのでこれ以上ショートしないようUVレジンで固めた。その結果が次の写真である。ここではRGB-LEDのピンを左右に開くなどパターン作成に工夫が必要だ。


この 表示部はセンサー部から送られてきた測距データを表示する。

センサー部から送られる測距データは行が'='で始まり3文字目から測距結果を格納する。7セグLEDは実際に測定した距離を表示し、RGB-LEDは距離に応じて色を決めるようにする。

 7セグメントLEDは100回/秒くらいのレートでリフレッシュ出来れば十分なので10msに一回、つまり3桁で割って約3msくらいで割込み処理すれば充分だろう。という事で比較的簡単に実現できた。

表示用の割込み処理は次のようなものである。

static const byte swp_pos[3] = { 0x10, 0x20, 0x40 };
static byte dsp_dat[3] = { 0, 0, 0 };
static byte dsp_pos = 0;

void sevenSegLed_Isr(){
    LATC        = dsp_dat[dsp_pos];
    LATB        = swp_pos[dsp_pos++] | (LATB & 0x8f);
    if(dsp_pos >= 3)  dsp_pos = 0;
}

dsp_dat[]は7セグLEDに与えるビットパターンを格納している。

ちなみに数字を表すビットパターンは、

 static const byte SvnSegPtn[16] = {
        0x7e, 0x30, 0x6d, 0x79,  0x33, 0x5b, 0x5f, 0x70,    // 0..7
        0x7f, 0x7b, 0x77, 0x1f,  0x0d, 0x3d, 0x4f, 0x47     // 8..F
    };
を使っている。

(続く)

 

2025年11月19日水曜日

超音波距離計(その2)

 表示部は車の後窓付近に置きたいので、大き目の7セグ赤色LEDとワゴンセールで安価に入手したマイコン内蔵RGBLED(PL-9823、以下RGB-LED) を使う事とした。障害物との距離が近い場合は数字より色の方が感覚に訴える。

RGB-LEDはシリーズに繋ぐだけで使うことが出来る優れものである。 

7-セグLEDをアノードコモンにするかカソードコモンにするかであるが、コモン端子には大電流(最大160mA=各セグメントで20mA)が流れるのでPICでは直接駆動できなく適切なICが見付からなければトランジスタで駆動する事にする。このときアノードコモンだとPNPトランジスタを使う事となりそれをNPNでドライブするのでトランジスタの数が増える。一方カソードコモンだとNPNトランジスタだけでPICから駆動できる。 

各セグメントの駆動には電流制限のため(抵抗で済ますことも出来たが)試しに定電流ダイオードを使うが電圧降下が4V以上あり電源の5V供給では足りないため電源に12Vを使うこととなりPICには直結できない。そして次のような回路とした。(後で考えると電流制限は抵抗で済ませたほうが簡単で安価だった。)また20ピンのPICの抜き差しは面倒なのでプログラムはPicKitで直接書き込むようにした。

 電源は車のアクセサリー等から12Vを引いて使う予定だが上の回路図からは電源部は省略している。

そして次のような基板を設計し発注した。 

あとはソフトの制作だ。

(続く) 

 

2025年11月12日水曜日

超音波距離計(その1)

 以前作った超音波測距モジュールからブランチして超音波距離計を作れないか相談を受けた。車のバックセンサーとして使いたいというものだ。ならば車外のセンサー部と車内の表示部という構成にする必要があろう。先ずセンサー部だ。

超音波センサーには秋月で安価に売っているHC-SR04とUS-015があり、コネクタには互換性がある。HC-SR04はGPIOインターフェイスのほかI2CやUARTにも対応しているがUS-015はGPIOのみであり、ここでは両方使えるよう、また後処理を考えてGPIOを使うようにした。

単に距離を測れれば良いならば簡単なものだ。そこでPIC16F18313を使ってプロトタイプを作った。 電源は表示部から供給する。

簡単な回路なので、であっという間に完成した(電源のバイパスコンデンサやLEDランプは回路図からは省略している)。

ソフトも、距離だけ測れば良いので以前PIC16F18346用に作ったものをPIC16F18313用に簡略化して1日で出来上がった。PIC16F18313は内蔵タイマーが少ないのでTMR0を200ms毎の測定開始用、TMR1をエコー時間測定用、TMR2を100msのタイムアウト用として使っている。測定は毎秒5回行い、過去4回分を平均して結果として報告するようにしている。次は実際に動かしてみた結果の一例である(結果はcm単位)。

US Ranging313-3.01.013 for RH-Kager3 US-Sensor Rev0.1
Copyright(C) 2025 MYcrosLip.
= 56
= 56
= 45
= 33
= 21
= 21
= 33
= 45
= 56
= 60
= 83
= 111
= 122
= 156
= 190
= 205
 

超音波センサーの最大探知距離4mより大きな値は999cmとし、センサーから100ms以内に応答がない場合は998cmとして報告するようにしている。


センサー部は出来上がったので、次は表示部の検討を行う。

(続く) 

 

 

 

 

2025年4月16日水曜日

出入り検知器をPCB化する(その24)・超音波測距4

 前回まで超音波測距センサーを3個使う3チャネルの測距モジュールを作り、使い勝手を良くするためにトレーニング機能を追加した。さらにトレーニングを起動するためにプッシュボタンを追加した。その成果を踏まえ今回新たに超音波測距センサーを5個まで使える5チャネルのモジュールを作った。というのは超音波センサーの半値幅が30度なので3個でカバーできる範囲は90度にしかならたいため、これをもっと広範囲まで拡張したかったからである。超音波測距センサーを5個使うことで150度までカバーできる。3チャネルモジュールのPICには14ピンの18326を使ったが5チャンネルでは信号線(足の数)が足りないため20ピンの18346を使った。

ソフトは3チャネル用の物を少し改造した。トレーニング時にセンサーの付いていないチャネルを検知してOFFにするようにした。

US Ranging346-2.036.48
Copyright(C) 2025 myname.
*** Start Training.
+++ Trained Max Range(raw) -  A:167 B:500 C:41 D:500 E:119
*** US Sensing parameters:
  Ch-A: ON : 010 - 162
  Ch-B: OFF
  Ch-C: ON : 010 - 036
  Ch-D: OFF
  Ch-E: ON : 010 - 114
  MODE = Range Data with Zero Suppress.
_00,--,34,--,00
_00,--,31,--,00
_00,--,30,--,00
_00,--,29,--,00
_00,--,30,--,00
_00,--,29,--,00
_00,--,29,--,00
_00,--,30,--,00
_00,--,30,--,00
_00,--,33,--,00
_00,--,00,--,00
 

ここで1文字目の'_'は表示モード、またOFFのチャネルの測定結果は'--'で、範囲外のデータは'00'で表示している。このモードでは対象物がある時だけ表示する(反射が無くなると反射ゼロを1回だけ表示)。

表示モードにはこのほか、生データ表示モード、

#00b2:0000:0063:0000:001f
#00b2:0000:0063:0000:0021
#00b2:0000:0063:0000:0022
#00b2:0000:0064:0000:001f

連続データ(1秒に2回程度)表示モード、

>00,--,00,--,00
>00,--,00,--,00
>00,--,31,--,00
>00,--,31,--,00
>00,--,28,--,00

最も近い反射物のデータを表示するモード、

=C13
=C15
=E16
=E13
=E12

等が可能で、目的別に使い分けできる。

このほか記号'!'を送ると(改行不要)直ぐにIDを返すようにしている。

$$$346.2036+-+-+

これはホストからの生存確認を簡単にするためであり、最初の3文字で'!'に対するレスポンス'$$$'を、その後バージョン、超音波センサーの稼働状態を表している。

 今後、対象物の大まかな移動ベクトルを算出する事も考えている。

(続く)

 

 

2025年2月27日木曜日

出入り検知器をPCB化する(その23)・超音波測距3

 インテグレーションを目指して実際に超音波測距センサーを使ってみると、特に室内では反射物が多く場所を少し変えるごとに状況が変わり閾値の設定がものすごく面倒で、容易に置き場所や周囲の状況を変更できない。そこで新たにトレーニング・モードを設けた。立ち上げ時に周囲を何回かスキャンし、各方向のセンサー毎にエコーの最近値からマージン(とりあえず5cm)を引いて閾値(最大探知距離)として自動的に設定する。

*** Start Training.
*** Trained Max Range R:178 F:98 L:50
  US Sensing parameters:
        Mode = Range Data with Zero Suppress.
        Ch-R: ON : 010 - 173
        Ch-F: ON : 010 - 093
        Ch-L: ON : 010 - 045

この効果は絶大で、何処でも簡単に設置でき、トレーニングが終われば人などが前を通過したときちゃんと反応する。 

_10,0,0
_10,20,0
_0,20,0
_0,20,0
_0,23,0
_0,0,21
_0,0,23
_0,0,0
 

エコーが無くなった事を表すため最後には 0,0,0 を出力させている。

さらに状況が変化した時はいつでも再度トレーニングを実行できるようボタンを追加した。

これでいつでも再トレーニングできるようになり、室内でも使い勝手が随分良くなった。

超音波センサーモジュール込みの消費電流を測ってみたが、電源電圧5Vで約7mA、3.3Vで5mAであった。

 (続く)

 

2025年1月13日月曜日

出入り検知器をPCB化する(その21)・超音波測距2

 年末年始で手を付けていなかった超音波測距だが、ソフトを作って実際に動かしてみた。PICは14ピンのPIC16F18326を使った。


Timer1に入力するクロック(LFINTOSC=31KHz)をプリスケーラで2分周する事で、計測値1カウント当たり1.1cmの測距距離とした。これで1カウント当たりほぼ1cmと考える事ができる。音波の反射や回り込みによる相互干渉を避けるため Right, Front, Left の3つのセンサーを(同時でなく)100ms毎に順番に起動し測距する。これを連続で行うと3回/秒程度の頻度の測定になる。次図で上のトレースは右(R)のセンサーのトリガーであり、100msずつ遅れて起動する他のセンサーのトリガーは見えていない。下のトレースはTimer1のゲート信号で、順に3つのセンサー(R,F,L)のエコーに対応している。
各エコーのパルス幅が測距距離に対応しており、毛布で覆ってエコーが無いと思われる場合は次のような波形になった。

中央の幅広のパルスを生成しているセンサーがUS-015であり、それ以外はHC-SR04である。それぞれUS-015で75ms、HC-SR04で50ms程度あり最大探知距離相当時間の2倍以上は確保されている。

 測定結果はシリアルインターフェイスを通じてホストへ送信する。

測定したデータの処理には次の3つのモードを設けた。

  1. 生データ表示モード
  2. 測定結果表示モード
  3. 最接近表示モード

1.生データ表示モードはデバッグ用で、測定した3方向の生データを16進表示する。

#0049:0021:001e
#0049:0022:001f
#0049:0022:001f
#0049:0021:001e
#004a:0023:001e

2.測定結果表示モードでは測定した3方向のデータを10進表示するが、この時測定したい距離の閾値(最大距離、最小距離)を適用し、その範囲外のデータは0とする。これは近くにある固定された反射物を避けるとともに、とくに最大探知距離より大きな値(無エコー、誤データ)を排除する為である。

> R:144 F:63 L:32
> R:144 F:63 L:31
> R:73 F:33 L:31
> R:73 F:34 L:32
> R:73 F:32 L:31
> R:144 F:64 L:32
> R:144 F:63 L:31

3.最接近表示モードでは、3方向のうち最も距離の近い対象までの向きとデータ(≒距離)を表示する。3方向とも範囲内に対象物が検知されなかった場合は何も表示しない。

=L23
=L30
=F51
=F53
=F48
=F52
=R71
=R71

基板上の3つのLEDは夫々のセンサーが対象範囲(閾値)内にエコーを捉えていると点灯する。 

3つのセンサーのデータをAI(機械学習)で学習すれば前を通る人の動きを認識出来るかも知れないが、今回はそこまでやらない。

このセンサーユニットを、これまで作った回路と組み合わせることで纏まった動作をさせるよう今後インテグレーションしたい。


(続く)

 

 

2024年12月25日水曜日

出入り検知器をPCB化する(その21)・超音波測距1

 出入り検知器は元々20cm離れた2本の赤外線を人が横切る事を検知するよう考えていた。これは狭いゲートを通過する人を検知するような使い方を前提としていた。一方、目前の歩道を通り過ぎるような人の動きを検知して働くような機能の方がより汎用的に使えるだろうと、そのようなセンシングを考える事とした。

このような動きを捉えるには画像認識以外には次のような幾つかの方法が考えられる。それぞれ対象物との絶対的な距離を測れるものと、距離の変化を捉えるものがある。

  1. 焦電センサー
  2. 赤外測距センサー
  3. 超音波測距センサー
  4. ミリ波センサー 

これらのうち秋月で入手が容易な(比較的安価な)センサーについて特性を調べた。1.焦電センサーは人体から放射される赤外線を捉え、その量の変化が閾値を超えた場合に反応するが屋外では太陽光やその反射光、風が吹いても反応する事があり屋外での特に昼間の利用には不向きである。2.は自ら赤外線を発射し、その反射光を受信するまでの時間から対象物迄の距離を測定する。その例として秋月で売っているVL53L0X使用 レーザー測距モジュールを買ってみた。これは Arduino ではライブラリが使えるようだがモジュール自体の仕様は公開されておらずPICからは容易に使えないので今回は扱わない。3.は超音波を使って2と同様な事を行う。4.はミリ波を使って同様な事を行う。最近は車の人感センサーに応用され比較的入手が容易である。ただ電波法で規制されるため認証されたものを使う必要がある。秋月で売っている手頃なものはドップラー効果を応用しているのか人が近づいたり離れたりする動きのみ取り出せるので焦電センサーと変わりない。


取り合えず安価で最も使い易そうな超音波センサーを使ってみる事とした。秋月では手頃な値段のUS-015とHC-SR04という見かけの似た2つの超音波センサーモジュールを販売している。

値段もあまり違わない。インターフェイスも同じGPIOで4ピンの信号割り当ても同じ。但し(マニュアルは中国語で分かり辛いが)HC-SR04はジャンパーを切り替える事でGPIO(PWM)のほかI2CまたはUARTインターフェイスを選ぶ事が出来るようである。汎用性を考え、とりあえずGPIOインターフェイスで使ってみる事にした。次図はGPIOのタイミングチャートである。


GPIOでは Trig端子に10μsのパルスを加えることで測距がスタートする。先ず40KHzの超音波パルスが8回発射され、それが対象物で反射されて帰ってきたエコーを受けてEcho端子に往復時間に対応する時間幅のパルスが出力される。もしエコーが検知されなかった場合は80msのパルスが出力されるとUS-015のマニュアルにあるが、HC-SR04にはそれに相当する記述はない(実際に測定したところでは50ms強であった)。Trig端子に与えるパルスの繰り返し周期は仕様上はUS-015で85ms程度、HC-SR04では200ms以上必要である。

音速を340m/sとし、最大測距距離4mとして試算すると往復時間(Echo端子への出力パルス幅)は23.5msである。厳密には大気中の音速の温度勾配が0.6m/s/T程度あるようであるが、今回の目的には補正は必要ないだろう。もし補正したいならPICに内蔵の温度センサーを使うと簡易な補正はできる。

測定にPIC16F18326を使う場合、カウンタをゲート制御できるTimer1を使うのが適当である。Echo端子の信号をカウンタのゲートに加える。カウンタに加えるクロックにLFINTOSC(31KHz)を使うと距離を(理論的には)約1.1cm単位で測定する事が出来る(往復だと0.55cm)。また無エコー時の80msパルスのカウント値は24,80カウントでありTimer1の16ビットの範囲に収まる。

・・・てな事を考えながら回路を考え基板を発注した(この回路では将来の拡張を考えてPIC16F18346を使っている)。


この基板では3方向の超音波センサーを使う事を想定している。センサーの指向性は±15度なので各センサーは角度の30度離して取り付けるのが良いと思われるが3つ併せても探知範囲は90度しかない。広い範囲を見るためにあと2個追加して探知範囲を150度としたいものである。

(続く)