PICキット マイコン実験シリーズ 「超音波距離計の製作」
PICキット 周辺モジュールの用意
NO-01 14ピンCPU基板(PIC16F18326を装着)
NO-06 8MHZ X’TALモジュール
NO-12 I2C接続LCD表示器、或いはNO-14LCD表示器
NO-26 HC-SR04超音波測距モジュール
以上の4種のモジュールを使用します
もちろん、5V電源や配線コード類も必要です。
NO-01 14ピンCPU基板(PIC16F18326を装着)
NO-06 8MHZ X’TALモジュール
NO-12 I2C接続LCD表示器、或いはNO-14LCD表示器
NO-26 HC-SR04超音波測距モジュール
以上の4種のモジュールを使用します
もちろん、5V電源や配線コード類も必要です。
14ピンPIC16F18326CPUモジュール
今回はXC8にてプログラムを行います。
プログラムが簡単になるので、浮動小数点演算やPrintf等メモリを大量消費する関数を使用します。
よって、16KWメモリの16F18326のご登場です。
アッセンブラならば、16F1823の小メモリでも使用可能ですが。
今回はI/OピンにI2CバスとしてRC0とRC1の2本、
測距モジュールとの接続にRC3-RC5の3本
RA4-RA5の2本はX’TAL発振に使用します。
LCD表示は上段が超音波伝搬時間(us)、下段が距離(cm)
PIC16F18326機能設定
・システムクロックは8MHZクリスタル発振および4XPLLで32MHZ
・I/Oピンはすべてデジタルで、RC0-3は入力、RC4-5は出力設定
・RA0-5は入力設定としときます。
・PMDレジスタでは、MSSP2のみディセーブルにしています
と言う事は他の内蔵モジュールは、ほぼ動作しています
・測距モジュール用にタイマー1をシングルパルスモードで使用しています
プログラム
・MSSP低レベルルーチンはVer0.2bを使用しています。
・LCDドライバルーチンは、AQM1602用Ver1.0を使用しています。
5V用にコントラスト値を設定しています。
・メインプログラム
0.5秒おきに超音波センサ制御関数を呼び出し、伝搬時間を取得、
そして演算およびLCDに表示を行っているだけです。
割込み等は使用していません。
音速は340m/sの固定値で演算しています。
気温やその他の影響に対する補正処理は、一切していません。
メインプログラムが一番単純なのでは?っと、言われそうです・・・
今回はXC8にてプログラムを行います。
プログラムが簡単になるので、浮動小数点演算やPrintf等メモリを大量消費する関数を使用します。
よって、16KWメモリの16F18326のご登場です。
アッセンブラならば、16F1823の小メモリでも使用可能ですが。
今回はI/OピンにI2CバスとしてRC0とRC1の2本、
測距モジュールとの接続にRC3-RC5の3本
RA4-RA5の2本はX’TAL発振に使用します。
LCD表示は上段が超音波伝搬時間(us)、下段が距離(cm)
PIC16F18326機能設定
・システムクロックは8MHZクリスタル発振および4XPLLで32MHZ
・I/Oピンはすべてデジタルで、RC0-3は入力、RC4-5は出力設定
・RA0-5は入力設定としときます。
・PMDレジスタでは、MSSP2のみディセーブルにしています
と言う事は他の内蔵モジュールは、ほぼ動作しています
・測距モジュール用にタイマー1をシングルパルスモードで使用しています
プログラム
・MSSP低レベルルーチンはVer0.2bを使用しています。
・LCDドライバルーチンは、AQM1602用Ver1.0を使用しています。
5V用にコントラスト値を設定しています。
・メインプログラム
0.5秒おきに超音波センサ制御関数を呼び出し、伝搬時間を取得、
そして演算およびLCDに表示を行っているだけです。
割込み等は使用していません。
音速は340m/sの固定値で演算しています。
気温やその他の影響に対する補正処理は、一切していません。
メインプログラムが一番単純なのでは?っと、言われそうです・・・
NO-026 HC-SR04超音波測距モジュール
秋月電子から購入したHC-SR04超音波測距センサを使用しています。
このままでは使いづらいので、小基板にセンサを挿入する形をとっています。
センサモジュール部分は固定されておらず、基板から着脱できます。
詳細はモジュール製作編を参照して下さい。
モジュール基板出力ピン配置
① GND
② VCC 5V
③ ECHO
これをそのままPIC基板のRC3ピンに接続(注1)
④ TRIG
これをそのままPIC基板のRC4ピンに接続
⑤ LED
これをそのままPIC基板のRC5ピンに接続
使用方法
① TRIGピンに10us以上のHパルスを付与
② Hパルス終了後すぐに40KHZの超音波送信
③ 超音波送信終了後すぐにECHOピンがL→Hとなる
④ 反射波を受信するとすぐにECHOピンがH→Lとなる
⑤ このECHOピンのH持続時間が超音波伝搬時間となる
この時間をPICが測定する
(注1)PICのT1Gピン
PIC16F1823等の第一世代のPIC F1シリーズはRC3に設定できません
今回はPPS機能でT1GピンをRC3に移動しています。
16F1823の場合、RA3ピンかRA4ピンとなります。
APFCONレジスタで2者択一です。
秋月電子から購入したHC-SR04超音波測距センサを使用しています。
このままでは使いづらいので、小基板にセンサを挿入する形をとっています。
センサモジュール部分は固定されておらず、基板から着脱できます。
詳細はモジュール製作編を参照して下さい。
モジュール基板出力ピン配置
① GND
② VCC 5V
③ ECHO
これをそのままPIC基板のRC3ピンに接続(注1)
④ TRIG
これをそのままPIC基板のRC4ピンに接続
⑤ LED
これをそのままPIC基板のRC5ピンに接続
使用方法
① TRIGピンに10us以上のHパルスを付与
② Hパルス終了後すぐに40KHZの超音波送信
③ 超音波送信終了後すぐにECHOピンがL→Hとなる
④ 反射波を受信するとすぐにECHOピンがH→Lとなる
⑤ このECHOピンのH持続時間が超音波伝搬時間となる
この時間をPICが測定する
(注1)PICのT1Gピン
PIC16F1823等の第一世代のPIC F1シリーズはRC3に設定できません
今回はPPS機能でT1GピンをRC3に移動しています。
16F1823の場合、RA3ピンかRA4ピンとなります。
APFCONレジスタで2者択一です。
HC-SR04制御関数
呼び出されると、ECHOピンで示される時間を返します。
戻値は32bit符号無し整数で、単位はusです。
パルス幅測定にはTimer1をシングルパルスモードで測定します。
このモードでは16bitのTMR1カウンタは、T1Gゲートオープンの時だけ、指定された入力パルスをカウントします。
センサモジュールのECHOピンは、このT1Gピンと直結します。
TMR1のカウントパルス源としては、インストラクションクロック(FOSC/4)を指定します。
ただ、そのままではパルスが早すぎるので、プリスケーラを使用します。
システムクロック32MHZではFOSC/4=0.125us
よって、プリスケール値は1/8とし、TMR1を1usでカウントさせます。
因みに、FOSCを変更する時は下記の用に変更します。
FOSC=16MHZの時、PS=1/4
FOSC=8MHZの時、PS=1/2
FOSC=4MHZの時、PS=1/1
と、設定します。
設定可能なプリスケール値は以上の4種類です。
ゲート・シングルパルスモードの動作はマニュアル・タイミング表を見て下さい
「Timer1 ゲートシングルパルスモード」表です。
一目で下記の操作理由が判明します。
関数動作概略
① Timer1起動・シングルパルスモード設定
T1CON=0x35
T1GCON=0xD0
② TMR1カウンタをクリア
③ T1GCONレジスタGO/DONEピットをHにする(動作開始)
④ TRIGピンを10us幅以上でH状態とする
⑤ モジュールから超音波が送信され、ECHO=1となる
⑥ 連結されてるT1G=1となり、TMR1はFOSC/4をカウント開始
⑦ T1GCONレジスタGO/DONEビットがLになるまで待機
⑧ モジュールが反射波を受信すると、ECHO=0、T1G=0となる
⑨ TMR1はカウントを停止、GO/DONE=0となる
⑩ TMR1カウンタ値を読み込み
⑪ TMR1とTMR1IFビット合成し、戻し値として返す
問題点
現在の所、測定にTMR1(16bit)を使用しており、最大で65535us、すなわち理論的に片道11m強までの測定で、それ以上の長さになるとTMR1がオーバーフローしてしまいます。
この関数ではオーバーフローフラグを含めてますので、TMR1カウンタを見かけ上17bitに拡張してます。
よって、片道22m程度の理論的測定限界となりました。
しかしながら、実測では16bitのままで十分で、片道11mですら安定して測定できませんでした・・・
アッセンブラ版での初期構想では、TMR1カウンタを24bitに拡張するつもりでした・・・
もちろん没になりましたが。
呼び出されると、ECHOピンで示される時間を返します。
戻値は32bit符号無し整数で、単位はusです。
パルス幅測定にはTimer1をシングルパルスモードで測定します。
このモードでは16bitのTMR1カウンタは、T1Gゲートオープンの時だけ、指定された入力パルスをカウントします。
センサモジュールのECHOピンは、このT1Gピンと直結します。
TMR1のカウントパルス源としては、インストラクションクロック(FOSC/4)を指定します。
ただ、そのままではパルスが早すぎるので、プリスケーラを使用します。
システムクロック32MHZではFOSC/4=0.125us
よって、プリスケール値は1/8とし、TMR1を1usでカウントさせます。
因みに、FOSCを変更する時は下記の用に変更します。
FOSC=16MHZの時、PS=1/4
FOSC=8MHZの時、PS=1/2
FOSC=4MHZの時、PS=1/1
と、設定します。
設定可能なプリスケール値は以上の4種類です。
ゲート・シングルパルスモードの動作はマニュアル・タイミング表を見て下さい
「Timer1 ゲートシングルパルスモード」表です。
一目で下記の操作理由が判明します。
関数動作概略
① Timer1起動・シングルパルスモード設定
T1CON=0x35
T1GCON=0xD0
② TMR1カウンタをクリア
③ T1GCONレジスタGO/DONEピットをHにする(動作開始)
④ TRIGピンを10us幅以上でH状態とする
⑤ モジュールから超音波が送信され、ECHO=1となる
⑥ 連結されてるT1G=1となり、TMR1はFOSC/4をカウント開始
⑦ T1GCONレジスタGO/DONEビットがLになるまで待機
⑧ モジュールが反射波を受信すると、ECHO=0、T1G=0となる
⑨ TMR1はカウントを停止、GO/DONE=0となる
⑩ TMR1カウンタ値を読み込み
⑪ TMR1とTMR1IFビット合成し、戻し値として返す
問題点
現在の所、測定にTMR1(16bit)を使用しており、最大で65535us、すなわち理論的に片道11m強までの測定で、それ以上の長さになるとTMR1がオーバーフローしてしまいます。
この関数ではオーバーフローフラグを含めてますので、TMR1カウンタを見かけ上17bitに拡張してます。
よって、片道22m程度の理論的測定限界となりました。
しかしながら、実測では16bitのままで十分で、片道11mですら安定して測定できませんでした・・・
アッセンブラ版での初期構想では、TMR1カウンタを24bitに拡張するつもりでした・・・
もちろん没になりましたが。
PIC16F18326
XC8用ソースプログラム
16F18326_HCSR.c
MSSP1ライブラリ
MSSP02b.h
MSSP02b.c
I2C LCD AQM1602ライブラリ
AQM1602v1.h
AQM1602v1.c
XC8用ソースプログラム
16F18326_HCSR.c
MSSP1ライブラリ
MSSP02b.h
MSSP02b.c
I2C LCD AQM1602ライブラリ
AQM1602v1.h
AQM1602v1.c
ソースファイル 補足
詳細はソースファイルを見て頂きたく思います。
(1)MSSP・I2Cマスタモード・XC8用ライブラリ Ver0.2b
(2)AQM1602 XC8用ライブラリ Ver1.0
(3)HC-SR04制御関数
外部関数とはせずに、内部展開としています。
呼び出すと、超音波伝搬時間を返します。
これは往復の時間です
詳細はソースファイルを見て頂きたく思います。
(1)MSSP・I2Cマスタモード・XC8用ライブラリ Ver0.2b
(2)AQM1602 XC8用ライブラリ Ver1.0
(3)HC-SR04制御関数
外部関数とはせずに、内部展開としています。
呼び出すと、超音波伝搬時間を返します。
これは往復の時間です
感想
狭い室内で動作させると乱反射するのか、長距離ではイマイチ動作が不安定です
室内に物がいっぱいあると言うのも影響していると思いますが。
100cm以下の短距離では割と安定して測距しますし、広い部屋の壁なら5m程度までは安定していて、メジャーでの測定と距離数値がほぼ合います。
測定間隔を開けてみましたが、さほど変わりませんでした。
それよりセンサの測定している壁に対する角度等を手動で微調整すると、それらしき数値が表示されます。
初期構想では、何回か測定して平均値を算出表示する案もあったのですが、没になりました。
理由は測距値が不安定な時は極端にずれる、例えば6mの距離での測定で、6mと表示されたり6cmだったり12mだったりと、桁違いな数値表示でふらつきます。
「微妙に数値がおかしい」と言うのはほとんど無く、おかしい時はあからさまにおかしかったです。
そういう意味では測定間隔が早いと、真の数値が判別出来ないので、1~2秒間隔が妥協点かなと思いました。
この辺の理由は今の所不明ですが、解決しようとする気力も乏しいです・・・
しかし・・・実用用途が思い浮かびませんけど・・・
その他
諸般の事情により、半年以上PICプログラミングしていませんでした・・・
プログラミング・リハビリのつもりで行ってみました。
年のせいか結構忘れているもので、我ながら呆れてしまいました・・・
特にCプログラミングは身に付いて無いせいか、すぐ忘れます。
実は今回もアッセンブラでプログラムし、動作確認してからXC8用に移植してます。
未だに、いきなりXC8でプログラムすると、デバッグに苦労するからです。
ならば、アッセンブラで肝心の制御関数部分をチャチャっとプログラムしてしまえば、安心してXC8の関数を作成できます。
XC8を使う以前と違うのはXC8への移植をイメージしながらアッセンブラ・ソースを記述するようになった事です。
これにてビルドできない、動作しないのは、ほぼ単純ミスだけ (^^♪
2018年12月 JA0QON
狭い室内で動作させると乱反射するのか、長距離ではイマイチ動作が不安定です
室内に物がいっぱいあると言うのも影響していると思いますが。
100cm以下の短距離では割と安定して測距しますし、広い部屋の壁なら5m程度までは安定していて、メジャーでの測定と距離数値がほぼ合います。
測定間隔を開けてみましたが、さほど変わりませんでした。
それよりセンサの測定している壁に対する角度等を手動で微調整すると、それらしき数値が表示されます。
初期構想では、何回か測定して平均値を算出表示する案もあったのですが、没になりました。
理由は測距値が不安定な時は極端にずれる、例えば6mの距離での測定で、6mと表示されたり6cmだったり12mだったりと、桁違いな数値表示でふらつきます。
「微妙に数値がおかしい」と言うのはほとんど無く、おかしい時はあからさまにおかしかったです。
そういう意味では測定間隔が早いと、真の数値が判別出来ないので、1~2秒間隔が妥協点かなと思いました。
この辺の理由は今の所不明ですが、解決しようとする気力も乏しいです・・・
しかし・・・実用用途が思い浮かびませんけど・・・
その他
諸般の事情により、半年以上PICプログラミングしていませんでした・・・
プログラミング・リハビリのつもりで行ってみました。
年のせいか結構忘れているもので、我ながら呆れてしまいました・・・
特にCプログラミングは身に付いて無いせいか、すぐ忘れます。
実は今回もアッセンブラでプログラムし、動作確認してからXC8用に移植してます。
未だに、いきなりXC8でプログラムすると、デバッグに苦労するからです。
ならば、アッセンブラで肝心の制御関数部分をチャチャっとプログラムしてしまえば、安心してXC8の関数を作成できます。
XC8を使う以前と違うのはXC8への移植をイメージしながらアッセンブラ・ソースを記述するようになった事です。
これにてビルドできない、動作しないのは、ほぼ単純ミスだけ (^^♪
2018年12月 JA0QON
追記があれば、ここに記します