今回は超音波距離センサです。超音波距離センサは超音波を利用して距離を計測することができる距離センサです。センサから超音波を出力し、跳ね返ってくるまでの時間を計測し距離を求めます。
以前作成した7セグメントディスプレイシステムにシリアル通信を使用して距離を送り表示します。表示する距離の単位はセンチメートルとします。
回路図およびプログラムに関する各種詳細は、以下の記事を参考にしてください。
1.今回使用するPICについて
今回使用するPICは「PIC12F1822」です。
2.回路
2.1 電子回路図
2.2 電子回路の写真
2.3 回路説明
2.3.1 使用するパーツ一覧
パーツ名 | 説明 | 使用数 |
---|---|---|
PIC12F1822 | PIC本体 | 1 |
超音波距離センサ(HC-SR04) | 超音波距離センサ(amazon:HC-SR04 ) | 1 |
2.3.2 PICの配線
PICのピン | 接続 | 補足 |
---|---|---|
VDD | 電源 | 5[V] |
RA0 | シリアル通信(TxD:送信) | 7セグメントディスプレイへデータ転送 |
RA1 | -未使用- | |
RA2 | -未使用- | |
RA3 | -未使用- | |
RA4 | 超音波距離センサ(HC-SR04) | Echo Pulse Output(PICは入力) |
RA5 | 超音波距離センサ(HC-SR04) | Trigger Pulse Input(PICは出力) |
VSS | グランド |
3.プログラム
プログラムの基本的な部分は以下の記事を参考にしてください。
3.1 プログラムの注意点(エラー処理)
今回作成するプログラムでは、エラー処理を行っていません。必要に応じてエラー処理を追加するようにしてください。以下のタイムアウト処理が必要だと思います。
- 超音波距離センサに対して指示を出力後の無応答(Trigをオン後、Echoがハイにならない)
- 超音波距離センサからの無応答(Echoがハイからローにならない)
ただし、タイムアウト時間を短くし過ぎると測定ができなくなるので、よく検討する必要があります。対象とする測定距離から応答時間を計算し、タイムアウト時間を求めてください。
3.2 超音波距離センサ「HC-SR04」の不具合
今回使用している超音波距離センサにおいて、出荷ロットにより不具合が発生することがあるようです。症状は、測定対象物が近すぎるか遠すぎるとEchoからの出力がハイに固定されてしまうようです。問題が発生した場合、1度電源を切るしかないようです。
不具合があるままだと使いにくいので、対策をしました。詳しくは以下の記事を参照してください。
超音波距離センサ(改)不具合対応
3.3 距離の計算方法
超音波距離センサから出力された超音波が、測定対象物に当たり跳ね返ってくるまでの時間を計測し、距離を計算します。
距離 = 速度 × 時間
超音波を利用した距離測定方法については以下のサイトが参考になると思います。
3.3.1 速度
超音波の速度は大気中では約340[m/s]です、気温や湿度、気圧により伝播速度が変わるので、正確な距離を求めたい場合、それらの情報を計算に加える必要があります。今回はそれほど精度を求めていないので、速度は340[m/s]として計算します。
3.3.2 時間
超音波距離センサを使用して求めることができる時間は、センサが超音波を出力し、測定対象物に当たり反射して戻ってくるまでの時間です。なので、センサから対象物までの実質の時間は、取得した時間の半分になります。(往復の時間なので半分にする)
3.3.3 距離
以上の情報から、距離を求めるには以下の式を使用します。
距離 = 340 × (往復の時間 ÷ 2)
3.4 超音波距離センサ(HC-SR04)の制御
超音波距離センサ(HC-SR04)を使う手順は以下の通りです。
- PICが、超音波距離センサのTrigにハイの信号を10[μs]出力する
- 超音波距離センサは内部で、距離測定の準備を行う(PICへは特に何もない)
- PICは、超音波距離センサのEchoから出力されるハイ信号を受信する
Echoからハイが出力されている時間 = 「3.3.2 時間」で説明した往復の時間
超音波距離センサのEchoからハイが出力されている時間を取得することができれば、対象までの往復時間がわかるので、距離を求めることができます。
3.5 PICのタイマ1のゲート機能
今回はタイマ1のゲート機能を使用します。ゲート機能を使用することで、超音波距離センサのEchoと接続しているRA4の入力がハイになっている間だけタイマを動作させることができます。RA4がハイになっている時間は「3.4 超音波距離センサ(HC-SR04)の制御」で説明した対象物までの往復の時間になります。
3.6 プログラムの説明
プログラムを見ながら以下の説明を見てください。ソースコードは次の節にあるので、そちらを参照してください。
3.6.1 グローバル変数の宣言
#define _XTAL_FREQ 32000000 #define TX_UART_SIZE 3 #define SONIC_TRIG RA5 #define SONIC_ECHO RA4 #define IO_OFF 0 #define IO_ON 1 volatile unsigned char uart_tx_msg[TX_UART_SIZE] = {0}; volatile unsigned char uart_tx_cnt = 0;
定数の宣言およびグローバル変数の宣言。グローバル変数は7セグメントディスプレイへのシリアル通信でのデータ転送用です。
3.6.2 シリアル通信用の割り込み処理
void interrupt isr_ctrl( void ) { if( TXIF ) { if( uart_tx_cnt < TX_UART_SIZE ) { TXREG = uart_tx_msg[ uart_tx_cnt ]; uart_tx_cnt++; } else { TXIE = 0; } if( uart_tx_cnt >= TX_UART_SIZE ) { uart_tx_cnt = 0; TXIE = 0; } TXIF = 0; } }
シリアル通信でのデータ転送処理です。
3.6.3 PICの初期設定
long echo_time; long dist; short work1,work2,work3; OSCCON = 0b01110000 ; // 内部クロック8MHz ANSELA = 0b00000000 ; // デジタルI/Oに割当てる TRISA = 0b00011000 ; // RA3,4を入力にし、他は出力に割当てる PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) T1CON = 0b00110000 ; // FOSC/4を選択 分周比1/8 T1GCON = 0b11010000 ; // ゲート有効、Hiでカウント、単一パルス、T1Gピン TXSTA = 0x24; // 送信情報設定:非同期モード 8ビット・ノンパリティ RCSTA = 0x90; // 受信情報設定 BAUDCON = 0x08; // 16bit SPBRG = 0x40; // ボーレートを9600(高速モード)に設定 SPBRGH = 0x03; RXDTSEL = 0; TXCKSEL = 0; TMR1ON = 1; // タイマー1開始 TXIE = 0; TXIF = 0; PEIE = 1; GIE = 1;
各種初期設定です。周波数、ポート設定、シリアル通信設定などを行っています。
タイマ1のゲート機能の設定を行っています。T1GCONの設定は以下の通りです。
T1GCON = 0b11010000;
bit | 設定値 | 内容 |
---|---|---|
bit7 | 1 | ゲート機能を有効にする |
bit6 | 1 | ハイの時にカウントする |
bit5 | 0 | |
bit4 | 1 | シングルパルスモードを有効にする |
bit3 | 0 | |
bit2 | 0 | |
bit0~1 | 00 | Timer1ゲートピン |
3.6.4 カウンタの初期化
// タイマ1のカウンタ準備 TMR1 = 0; // カウンタの初期化 T1GGO = 1; // 単一パルスを使用する
タイマ1の初期化
3.6.5 超音波距離センサの開始処理
// トリガ送信 SONIC_TRIG = IO_ON; __delay_us( 10 ); SONIC_TRIG = IO_OFF;
超音波距離センサに対して距離測定の開始を指示。「3.4 超音波距離センサ(HC-SR04)の制御」を確認してください。
3.6.6 超音波距離センサからの開始信号待ち
// エコー信号のON待ち while( SONIC_ECHO == IO_OFF ) { // 処理なし }
超音波距離センサのEchoからハイ信号が来るのを待つ。超音波距離センサはすぐに測定を開始しないため、信号がハイになるのを待つ必要があります。
3.6.7 超音波距離センサ計測中
// エコー信号のOFF待ち while( SONIC_ECHO == IO_ON ) { // 処理なし }
超音波距離センサのEchoから出力されるハイ信号が終了するまで待ちます。
3.6.8 超音波距離センサからの値から距離を計算
// 超音波の往復時間を取得 echo_time = TMR1; // 往復時間から片道の時間にする echo_time /= 2; // パルス時間から距離(cm)に変更 dist = echo_time * 34 / 1000;
タイマ1の時間(往復の時間)を取得し、距離を計算します。今回は7セグメントディスプレイに出力する都合上、単位をセンチメートル([cm])に変換しています。
PICやタイマの設定により取得できる時間は変わるので、必要に応じて計算方法を変更してください。
3.6.9 7セグメントディスプレイ表示用の処理
if( dist < 400 ) { // 位で分割 work1 = dist % 10; dist /= 10; work2 = dist % 10; dist /= 10; work3 = dist; // 送信データ構築 uart_tx_msg[0] = 0x00; // 少数点位置の設定 uart_tx_msg[1] = 0x0f & work3; uart_tx_msg[2] = (work2 << 4) | work1; } else { // 送信データ構築 uart_tx_msg[0] = 0x00; // 少数点位置の設定 uart_tx_msg[1] = 0x04; uart_tx_msg[2] = 0x00; } uart_tx_cnt = 0; TXIE = 1; // 送信開始
7セグメントディスプレイに出力するためのデータを作成しています。
今回使用している超音波距離センサ(HC-SR04)は最大測定距離が4[m]です。なので、4[m]を超えた場合は4[m]としています。
3.7 ソースコード
プログラムの全文を掲載します。
<注意>
ファイル名は必要に応じて変更し利用してください。
本サイトの注意事項を確認してください。
ソースコードや回路図などを使用する場合、上記注意とともに、自己責任でお願いします。
4.動作確認
起動すると7セグメントディスプレイに対象物までの距離を表示します。
<更新履歴>
日付 | 内容 |
2015年8月10日 | 新規作成 |
2015年11月5日 | 超音波距離センサの不具合対策へのリンク追加 |
2016年10月7日 | フォーマット変更(内容の変更はなし) |