文書の表示以前のリビジョンバックリンクPDF の出力全て展開する/折り畳むODT 出力文書の先頭へ この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。 ====== 超音波人体検出ユニットV1 ====== ===== 概要 ===== 以前に人体(焦電型赤外線)検出ユニットを作成しましたが、今回は超音波を利用した人体検出ユニットを作成してみました。 ===== 動作原理 ===== 超音波を利用した人体検出や距離計は良く見かけますが、結構複雑な回路構成なので作成にあたっては、少し躊躇してしまいます。 そこで、何とかもっと簡単に出来ないものかと考えてみました。 今回は、基本動作の確認もあり、30cm前方の物体(人体)を検出し、LEDを点灯させることのみにしました。 <超音波センサー> 日本セラミック社の送信用(T40-16)、受信用(R40-16)を使用しました。 【特徴】 空中用超音波センサは、振動子として圧電セラミックを用い、超音波を発生、それを空中に放射あるいは逆に空中からの超音波信号を検知するセンサで、物体の存在判別や物体までの距離の測定等広い分野において利用できます。 <送信部分> PICには、PWM(Pulse Width Modulation)モジュールを内蔵しているものがありますのでこれを利用します。 回路図を見てもお分かりのようにとても簡単です。コンデンサ1本でセンサーに接続するだけです。 40KHzの信号を2msec出力する例です。 <code c> Pwm_Init(40000);// 40kHz Pwm_Change_DutyEx((PR2 * 4) / 2);// デューティ比50% Pwm_Start();// 開始 Delay_ms(2);// 2msecスリープ Pwm_Stop();// 終了 </code> <受信部分> これもまた簡単で、低電圧オーディオ・パワーアンプのLM386を利用します。動作電圧も4V~12Vと手頃ですし、利得も20倍~200倍の設定が可能なので、今回のユニットには丁度良いと考えました。 通常は、この後に検波回路や、コンパレータ(比較)回路を通してから、PICに接続するのですが、今回は省略し、ソフトウエアで処理しました。 <処理の流れ> - 40KHzの超音波を2msecの間出力します。 - その後、2msecの間スリープします。(距離に換算すると約30cm) - 反射波を測定します。10回測定し、その内の最大値を反射波とみなします。(タイプA/検波回路不要) - 反射波を測定します。50回測定し、その平均値を反射波とみなします。(タイプB/検波回路必要)\\ ※最大値版よりも平均値版の方が安定性には優れています。好みで判断してください。 - 測定値を表示します。 - 測定値をバー表示します。 - オフセット値を表示します。 - 測定値を(オフセット値+250mV)と比較し、測定値が大きければ人体を検出したとみなして、LEDを1秒間点灯します。 - SWが押されていればオフセット値を再セットします。(デフォルトでは、2.5V) - 1.に戻ります。 ===== 回路図 ===== {{:imgpaste:202004:htmikan-20200429-174251.png}} <データシートに記載してある参考「受信回路」> {{:imgpaste:202004:htmikan-20200429-174310.png}} <データシートに記載してある参考「送信回路」> {{:imgpaste:202004:htmikan-20200429-174313.png}} ===== ソースコード ===== タイプA/検波回路不要/最大値版 <code c UltraSound2a.c> //********************************************************************** /* <超音波人体検出ユニット> */ //********************************************************************** #define LED PORTA.F2 #define SW PORTA.F3 //********************************************************************** unsigned int measurement() { unsigned int ad, max; unsigned char cnt; // max = 0; for (cnt = 0; cnt < 10; cnt++) { ad = Adc_Read(1); max = max < ad ? ad : max; } return (max); } //********************************************************************** void Pwm_Change_DutyEx(unsigned int duty_ratio) { CCPR1L = duty_ratio >> 2; CCP1CON.F6 = duty_ratio & 0b00000001; CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; } //********************************************************************** void main() { unsigned int ad, ave, offset; unsigned char buf[10], cnt, tmp; // OSCCON = 0b01110000; // クロックは8Mhz CMCON = 0b00000111; // コンパレータは使用しない。 ANSEL = 0b00000010; // AD1を使用する。 TRISA = 0b00111010; TRISB = 0b00001110; // Lcd_Custom_Config(&PORTB, 4, 5, 6, 7, &PORTA, 0, 7, 6); Lcd_Custom_Cmd(LCD_CURSOR_OFF); Lcd_Custom_Out(1, 1, "UltraSoundV2 "); Lcd_Custom_Out(2, 1, " JF3SFB 2007.12"); Delay_ms(1000); Lcd_Custom_Cmd(LCD_CLEAR); // Pwm_Init(40000); // 40kHz Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Stop(); // LED = 0; offset = 512; // 1024÷2 // while (1) { // 40KHzの超音波を2msec間出力する。 Pwm_Start(); Delay_ms(2); Pwm_Stop(); Delay_ms(2); // 反射波を測定する。 ad = measurement(); // 測定値を表示する。 WordToStr(ad, buf); Lcd_Custom_Out(1, 1, buf); // 測定値をバー表示する。 tmp = ad / 57; for (cnt = 0; cnt < 16; cnt++) { if (tmp > cnt) Lcd_Custom_Chr(2, cnt + 1, 0xFF); else Lcd_Custom_Chr(2, cnt + 1, ' '); } // 測定値をオフセット値と比較し、検出していればLEDを1秒点灯する。 WordToStr(offset, buf); Lcd_Custom_Out(1, 9, buf); if (ad > (offset + 100)) { LED = 1; Delay_ms(1000); LED = 0; } // SWが押されていればオフセット値をセットする。 if (SW == 0) { offset = ad; } } } //********************************************************************** </code> タイプB/検波回路必要/平均値版 <code c UltraSound2b.c> //********************************************************************** /* <超音波人体検出ユニット> */ //********************************************************************** #define LED PORTA.F2 #define SW PORTA.F3 //********************************************************************** unsigned int measurement() { unsigned int ad; unsigned char cnt; // ad = 0; for (cnt = 0; cnt < 50; cnt++) { ad += Adc_Read(1); } return (ad / 50); } //********************************************************************** void Pwm_Change_DutyEx(unsigned int duty_ratio) { CCPR1L = duty_ratio >> 2; CCP1CON.F6 = duty_ratio & 0b00000001; CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; } //********************************************************************** void main() { unsigned int ad, ave, offset; unsigned char buf[10], cnt, tmp; // OSCCON = 0b01110000; // クロックは8Mhz CMCON = 0b00000111; // コンパレータは使用しない。 ANSEL = 0b00000010; // AD1を使用する。 TRISA = 0b00111010; TRISB = 0b00001110; // Lcd_Custom_Config(&PORTB, 4, 5, 6, 7, &PORTA, 0, 7, 6); Lcd_Custom_Cmd(LCD_CURSOR_OFF); Lcd_Custom_Out(1, 1, "UltraSoundV2 "); Lcd_Custom_Out(2, 1, " JF3SFB 2007.12"); Delay_ms(1000); Lcd_Custom_Cmd(LCD_CLEAR); // Pwm_Init(40000); // 40kHz Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Stop(); // LED = 0; offset = 512; // 1024÷2 // while (1) { // 40KHzの超音波を2msec間出力する。 Pwm_Start(); Delay_ms(2); Pwm_Stop(); Delay_ms(2); // 反射波を測定する。 ad = measurement(); // 測定値を表示する。 WordToStr(ad, buf); Lcd_Custom_Out(1, 1, buf); // 測定値をバー表示する。 tmp = ad / 57; for (cnt = 0; cnt < 16; cnt++) { if (tmp > cnt) Lcd_Custom_Chr(2, cnt + 1, 0xFF); else Lcd_Custom_Chr(2, cnt + 1, ' '); } // 測定値をオフセット値と比較し、検出していればLEDを1秒点灯する。 WordToStr(offset, buf); Lcd_Custom_Out(1, 9, buf); if (ad > (offset + 50)) { LED = 1; Delay_ms(1000); LED = 0; } // SWが押されていればオフセット値をセットする。 if (SW == 0) { offset = ad; } } } //********************************************************************** </code> ===== 動作確認 ===== いつものようにブレッドボード上で確認しました。 超音波センサー(送信&受信)は、小さな基板に固定し、ブレッドボードに差込めるようにしてあります。 左から、【超音波センサー】【PIC】【LCD】の順です。 {{:imgpaste:202004:htmikan-20200429-174516.png?500}} 超音波センサー部分を拡大した所です。(左側が受信、右側が送信) {{:imgpaste:202004:htmikan-20200429-174527.png}}{{:imgpaste:202004:htmikan-20200429-174532.png}} PICとLCDの接続部分です。 LCDの1行目の左の数値は現在値、右はオフセット値です。 2行目は現在値をバー表示したものです。 {{:imgpaste:202004:htmikan-20200429-174541.png?500}} 上の波形は、送信波形です。2msec送信していますが、その後少し減衰しながら残存しています。 下の波形は、受信波形です。反射が無いので殆ど変化がありません。 {{:imgpaste:202004:htmikan-20200429-174556.png?500}} 超音波センサーの手前(約30cm)に物を翳してみた所です。 2msec後の受信波形では、約2V以上の変化があります。 {{:imgpaste:202004:htmikan-20200429-174609.png?500}} この時に人体を検出したと判断し、LEDを1秒間点灯させます。 {{:imgpaste:202004:htmikan-20200429-174621.png?500}} 如何ですか? とても簡単な回路ですが、当初の目的は達成できました。 これを応用して物体(人体)との距離を測定できるように改善強化していきたく考えております。^_^ <callout type="warning" title="著作権表示 copyright notice"> このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。[[elechobby:picdic:picdic|詳細]] This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.[[elechobby:picdic:picdic|Details]] </callout> elechobby/picdic/pic16f88/61.txt 最終更新: 2025/10/17 14:29by 127.0.0.1