以前にも超音波人体検出ユニットV1を製作しましたが、今回は、人体に特化せずに、超音波を反射する物体までの距離を測るユニットを製作しました。
<仕様>
センサーには、日本セラミック社製の超音波センサ(送信:T40-16、受信:R40-16)を使用します。
【超音波センサの仕様】
【全体の流れ】
//********************************************************************** /* <超音波距離計> */ //********************************************************************** #define LED PORTA.F7 #define CLEAR PORTA.F4 //********************************************************************** void interrupt() { if (PIR2.CMIF == 1) { PIE2.CMIE = 0; PIR2.CMIF = 0; // T1CON.TMR1ON = 0; CLEAR = 1; } } //********************************************************************** void Pwm_Change_DutyEx(unsigned int duty_ratio) { CCPR1L = duty_ratio >> 2; CCP1CON.F6 = duty_ratio & 0b00000001; CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; } //********************************************************************** unsigned int measurement() { static unsigned int dat; //TIMER1の設定 TMR1H = 0; TMR1L = 0; PIR1.TMR1IF = 0; T1CON.TMR1ON = 1; //40kHz送信 CLEAR = 1; Pwm_Start(); Delay_us(200); Pwm_Stop(); Delay_us(200); CLEAR = 0; //割り込みの設定 PIR2.CMIF = 0; PIE2.CMIE = 1; // while ((T1CON.TMR1ON == 1) && (PIR1.TMR1IF == 0)) ; if (PIR1.TMR1IF == 1) { PIE2.CMIE = 0; return (-1); } // dat = TMR1H << 8; dat |= TMR1L; // return (dat); } //********************************************************************** void main() { //変数の設定 static short cnt; static double dat; static long tmp; static char buf[10]; //ポート関連の設定 TRISA = 0b00101100; TRISB = 0b00000000; OSCCON = 0b01110000; // クロックを8Mhzに設定する。 ANSEL = 0b00000000; // A/D変換は使用しない。 //TIMER1の設定 T1CON.TMR1CS = 0; T1CON.T1CKPS0 = 0; T1CON.T1CKPS1 = 0; T1CON.TMR1ON = 0; TMR1H = 0; TMR1L = 0; PIE1.TMR1IE = 0; PIR1.TMR1IF = 0; //LCDの設定 Lcd_Custom_Config(&PORTB, 7, 6, 5, 4, &PORTB, 3, 2, 1); Lcd_Custom_Cmd(LCD_CURSOR_OFF); Lcd_Custom_Cmd(LCD_CLEAR); // for (cnt = 0; cnt < 16; cnt++) { Lcd_Custom_Chr(1, cnt + 1, 0xFF); Delay_ms(50); } for (cnt = 0; cnt < 16; cnt++) { Lcd_Custom_Chr(2, cnt + 1, 0xFF); Delay_ms(50); } Lcd_Custom_Cmd(LCD_CLEAR); //PWMの設定(40kHz) Pwm_Init(40000); Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Stop(); //コンパレータ用の基準電圧の設定 CVRCON.CVREN = 1; CVRCON.CVR3 = 1; CVRCON.CVR2 = 0; CVRCON.CVR1 = 0; CVRCON.CVR0 = 0; CVRCON.CVRR = 1; //コンパレータの設定 CMCON.CM2 = 0; CMCON.CM1 = 1; CMCON.CM0 = 0; CMCON.CIS = 1; // 割り込み関連の設定 INTCON.PEIE = 1; INTCON.GIE = 1; // while (1) { //測定 dat = 0.0; for (cnt = 0; cnt < 100; cnt++) { tmp = measurement(); if (tmp != -1) { dat += tmp; } else { cnt--; } } dat /= 100.0; //測定値の表示(換算前) WordToStr(dat, buf); Lcd_Custom_Out(2, 1, buf); //測定値の表示(換算後) dat = (dat / 2.0) * 0.0000005 * 330.0; WordToStr(dat * 100.0, buf); // m -> cm Lcd_Custom_Out(1, 1, buf); Lcd_Custom_Out(1, 6, "cm"); // LED = 1; Delay_ms(100); LED = 0; } } //**********************************************************************
超音波センサー部です。
今回は、整流回路のリセット機能を搭載したので、特に送受のセンサーの間隔を広げる必要はありません。

左側:センサー部です。
右側:LM386(2個)、ダイオード倍電圧整流、トランジスタ、LED、PICです。

リセット信号(40kHz/200usec含む)と反射波(倍電圧整流後)の波形です。(1msec/div)
撮影のために、リセット回路はオープン状態にしています。
左上:反射物までの距離<約30cm:1msec>
右上:反射物までの距離<約60cm:2msec>
左下:反射物までの距離<約170cm:5.5msec>


リセット回路を接続したときの波形です。
約1.8Vでコンパレータが働いています。そして割り込み処理の中で、リセット回路をONにしているので、反射波(倍電圧整流後)の波形が1.8Vを超えると、0Vにリセットされています。
椅子の上に置いて、天井までの距離を測定してみました。→172cm

8cmの高さのタッパーの上に置いて、天井までの距離を測定してみました。→164cm(172cm-8cm))

如何ですか?
思った以上に精度は高いようですね!
※アンプ部の増幅率を上げる(40000倍)と、更に距離を伸ばすことが出来ます。