前回から引き続き、FPGAボード(Sipeed Lichee Tang Primer)と、超音波センサを使った超音波距離計の設計を進めて行きます。
前回検討した内容をおさらいしておくと、今回使用するマイコンには:
でした。必要な機能を備えたマイコンを、NHOC113DM0408として作成しました。以下リンクより、デザインをダウンロードできます。
FPGAボード(Sipeed Lichee Tang Primer)への書き込み手順はこちらを参照してください。
以下に、TD IDEでのコンパイル(論理合成・配置配線)結果をまとめておきます。
なお、新規設計したDISTUSユニットを単体でコンパイルしたところ、100LUT程の回路でした。
ここから先は、超音波距離計の装置を設計して行きましょう。
必要な部品は、まず超音波センサ、VCC=5Vです。気温を知る必要があるので、気温センサとしてDHT11を使います。こちらも5V定格です(下図)。
続いて、測定結果をリアルタイムに表示するため、OLEDディスプレイを使います。こちらの信号線は3.3V定格ですが、Vccには5Vを接続する必要があります。FPGAボードは3.3V定格ですので、適宜レベルシフタを挿入します(下図)。
以下に超音波距離計の回路図を示します。
今回は、上図回路を400タイポイント(普通サイズ)のブレッドボードに構築しました。
測定プログラムを以下にリンクします。
完成プログラム:range_finder.asm
アセンブルに必要なインクルードファイルなどは、こちらからダウンロードしてください。STWSERユニット用のWireライブラリ(マスタ)を使っています。
アセンブルしてFPGAボードに書き込むと、シリアルモニタから以下のコマンドを受け付けています。
シリアルモニタコマンド仕様:
後程、動画をご覧に入れます。この動画では、〜10数[cm]範囲の精密測定している様子をご覧に入れるため、測定間隔を50ms、移動平均を20区間としました。測定間隔を短くした方がOLEDディスプレイへの表示間隔が縮まって、結果をリアルタイムに確認できるからです。
ところが、この設定値では、数mほどの長い距離を測定する時に問題が生じました。
測定間隔の50msで、超音波は約17m進みます(340m/sの場合)。1/2×17m先から反射して戻って来たら十分減衰していて、センサで検知できないだろうと高を括っていたのですが、部屋の中で対面までの約4.5mほどの距離を計測してみたところ、50ms間隔の測定では全く計測値が安定せず、うまく測れませんでした。
一度測定したら、次の測定までに250ms空けるように設定したところ、測定が安定しました。
超音波センサにはTRIG信号のアサート間隔に規定があるので、何らかの予備動作時間か何かに当たっていて安定しないのか、あるいは、閉じた部屋の中だけに、壁や天井、床などで複雑に反射して戻って来た超音波が干渉するなどして、測定が安定しない模様です。
以下定数で微調整が必要かもしれないので、各自調整して使って見てください。
## (20, 50ms) for short distance < 1m
#equ dst_mva_max,20 // dst: count of moving average
#equ dst_msec_itvl,50 // dst: measure interval [ms]
# (10, 250ms) for general purpose
equ dst_mva_max,10 // dst: count of moving average
equ dst_msec_itvl,250 // dst: measure interval [ms]
測定間隔(dst_msec_itvl)と移動平均区間数(dst_mva_max)の積がタイムラグとなりますので、その点にも注意して設定してください。
測定間隔250ms×移動平均10区間=2.5s
異なる障害物に超音波センサを向け直した場合、新しい値が安定して表示されるようになるまでにかかる時間が、およそ2.5sと考えるのが理解しやすいと思います。
本節では、実験で動作を確認して行きます。
こちらのデザインを書き込んだFPGAボードと、超音波距離計を以下表に従って接続します。
FPGAボード | 接続 | 超音波距離計 |
5V | → | Vcc |
3.3V | → | Vdd |
GND | ⇔ | GND |
stws_scl | ⇔ | SCL |
stws_sda | ⇔ | SDA |
port_iop[7] | → | IOP7(TRIG) |
port_iop[6] | ← | IOP6(ECHO) |
port_iop[5] | ⇔ | IOP5(DHT11) |
※FPGAボード(Nihoniumマイコン)のピン配置表はこちらです。
上の接続に加えて、FPGAボードにFTDI等のUSB⇔UART変換モジュールを接続してください。
以下図に実験中の様子を示し、実験を進めます。
実験サンプル:【 】内はシリアルモニタからの送信データ
【dst,1】
OK+ temp=324/10[degC]
OK+ speed=351[m/s]
OK+ distance=132[mm]
OK: dst (1)
距離測定モードをONにしました。最初の測定一回分に関して、シリアルモニタへ結果が送られてきました(↑)。その後は、OLEDディスプレイの方へリアルタイムで表示されます。
〜10数[cm]の近距離を測定した時の様子を動画にしておきました。以下動画でご確認ください。
以下、考察します。
超音波距離計とは全く関係ないのですが、OLEDディスプレイへの日本語表示についても検証しておこうと思います。
追加実験サンプル:【 】内はシリアルモニタからの送信データ
【dst,0】
OK: dst (0)
【prn,0,はじめまして! コンニチハ、世界】
OK: prn
【prn,1,※8×8ドット日本語フォント表示】
OK: prn
プログラム(range_finder.asm)はS-JISコードを受け付けているので、Arduino IDEのシリアルモニタ(UTF-8)ではダメです。Tera Term等S-JISコードを送受信できる通信ソフトウェアを使ってください。
※反unicode派なので、こんなことでunicode⇔S-JIS変換UNISJIユニットを使ったりはしません。ここはS-JISのみ対応で十分。そもそも、日本語フォントFONTJPユニットがS-JIS対応なので、S-JISに無い文字は表示できません。
日本語の16桁×2行表示です(↑)。いかがですか?
表示領域0.91インチと小さなOLEDディスプレイなので、小さくて粗い8×8[ドット]日本語文字は、どうかな?と心配でしたが、何とか使えそうです。
実は、8×8[ドット]フォントを縦方向に×2倍拡大して、8×16[ドット]で表示しています。拡大せずに8×8[ドット]表示すると、上のOLEDディスプレイに16桁×4行表示出来てしまいます。老眼だし、文字が小さすぎると辛いので、止めておきましたが、どうしてもたくさんの文字を表示したい場合には、そういうソリューションもアリです。
シリアルモニタで測定値などを確認することに慣れていたのだけれど、短い間隔で連続して測定したデータをリアルタイムに確認するには向かないのですよね。OLEDディスプレイを使うと、今回の応用例の様にリアルタイムで情報を確認できるし、何より接続が4端子とお手軽なのでGoodです。