生活随笔
收集整理的這篇文章主要介紹了
基于STM32F103HAL库的声音定位系统
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這是一道學校出的電賽題目,要求在100*100cm的平面上實現定位實現聲音定位。由于一米太大了,我們就做了40cm的,下面的講解我按照40厘米的寫。用到的處理器是stm32f103c8t6接下來分享一下調試心得。
硬件部分需要制作發聲裝置和接收裝置,詳細可以參考這個文章.
需要知道的是,揚聲器發出的聲音經過接收裝置,得到的是一個方波信號,所以單片機需要根據這些方波求出距離
解題思路
一.直線
既然我們說,接收模塊得到的是方波信號,那么單片機肯定可以檢測到方波的下降沿和上升沿,在直線上,聲源距離接收模塊越近,聲音先到達,就先接收到下降沿,相反,聲源距離接收模塊遠,就后接受到下降沿,這樣我們可以得到時間差。接下來就是小學數學了(手動狗頭),根據兩個時間可以算出距離。
用C語言描述就是這樣
傳入參數:兩個下降沿分別到兩個接收器之間的時間差
傳出參數:距離
float Find_Line(float ltime
)
{float S
=0,timeall
=0,timefst
=0;timeall
=0.0012; timefst
=(timeall
+ltime
)/2;S
=0.4*(timefst
/timeall
);return S
;
}
二.平面
在平面上,就需要三個接收模塊,這樣就能得出兩個時間差。
像下面這幅圖
用C語言描述是這樣,得到的arv1和arv2就是坐標值,
整個函數就是解方程的思路,用窮舉法求出合適的值,我在后面又對得到的值做了求平均處理。
void Find_Square(float ctime1
,float ctime2
)
{int count
,i
=0;for(x
=0.0; x
<=40.0; x
++){for(y
=0.0; y
<=40.0;y
++){if(fabs(sqrt(x
*x
+(y
-40)*(y
-40))-sqrt(x
*x
+y
*y
)-34000*ctime1
)<3 && fabs(sqrt(x
*x
+y
*y
)-sqrt((40-x
)*(40-x
)+y
*y
)-34000*ctime2
)<3) { a
[i
]=x
;b
[i
]=y
;i
++;count
=i
;printf("x=%.2f y=%.2f count=%d\n",x
,y
,count
);} else{printf("方程無解");}}}
for(int i
=0; i
< count
; i
++){sum1
=sum1
+a
[i
];sum2
=sum2
+b
[i
];arv1
=sum1
/count
;arv2
=sum2
/count
;printf("a[i]=%.2f b[i]=%.2f count=%d %f\n",a
[i
],b
[i
],count
,sum1
);}printf("arv1=%.2f arv2=%.2f\n",arv1
,arv2
);sum1
=0;sum2
=0;
}
二.單片機獲取時間
其實解題思路不難,難點就在于獲取到準確的時間,我使用的獲取方法是外部中斷,當單片機的一個IO口檢測到下降沿,定時器開始計時,另一個IO口檢測到下降沿停止計時,這樣就得到時間差
1.cubemx配置
1.外部中斷
2.定時器
由于晶振是72MHZ,而且接收到下降沿的時間在微秒級別,所以將單位時間設置為100us(72000000/72/100=10000hz)(1/10000=100us)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin
)
{if(GPIO_Pin
==GPIO_PIN_0
){if(time1
==0){wosignA
=0;HAL_TIM_Base_Start_IT(&htim2
); }else{wosignA
=time1
+255*time2
;}signA
=1; }if(GPIO_Pin
==GPIO_PIN_1
){if(time1
==0){wosignB
=0;HAL_TIM_Base_Start_IT(&htim2
); }else{wosignB
=time1
+255*time2
;}signB
=1;}if(GPIO_Pin
==GPIO_PIN_11
){if(time1
==0){wosignC
=0;HAL_TIM_Base_Start_IT(&htim2
); }else{wosignC
=time1
+255*time2
;}signC
=1;}}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef
*htim
)
{if (htim
->Instance
== htim2
.Instance
){time1
++; if(time1
==255){time2
++;time1
=0;}}if (htim
->Instance
== htim1
.Instance
){}
}
key
=read_key();if(key
==1) {mode
=1;OLED_Clear();}if(key
==2) {mode
=2;OLED_Clear();}if(key
==3) {mode
=3;OLED_Clear();}if(mode
==1){if(signA
&&signB
){EXTI
->IMR
&= ~(GPIO_PIN_0
);EXTI
->IMR
&= ~(GPIO_PIN_1
);HAL_TIM_Base_Stop_IT(&htim2
);if(wosignA
<wosignB
){t1
=wosignB
;}else {t1
=wosignA
;}if(t1
>11){t1
=11;}s
=Find_Line(fabs((float)(t1
))*100/1000000);printf("%d %d %f %d %d %d %d\n",time1
,time2
,s
,wosignA
,wosignB
,wosignC
,t1
);OLED_ShowFloat(0,0,s
,2,4,16);HAL_Delay(100);EXTI
->IMR
|= GPIO_PIN_0
; EXTI
->IMR
|= GPIO_PIN_1
;signA
=0;signB
=0;time1
=0;time2
=0;}}
if(mode
==2){if(signA
&&signB
&&signC
){EXTI
->IMR
&= ~(GPIO_PIN_0
);EXTI
->IMR
&= ~(GPIO_PIN_1
);EXTI
->IMR
&= ~(GPIO_PIN_11
);HAL_TIM_Base_Stop_IT(&htim2
);if((wosignA
<wosignB
)&&(wosignB
<wosignC
)){t2
=wosignB
;t3
=wosignC
;}if((wosignA
<wosignC
)&&(wosignB
>wosignC
)){t2
=wosignC
;t3
=wosignB
;}if((wosignB
<wosignA
)&&(wosignA
<wosignC
)){t2
=wosignA
;t3
=wosignC
;}if((wosignB
<wosignC
)&&(wosignC
<wosignA
)){t2
=wosignC
;t3
=wosignA
;}if((wosignC
<wosignA
)&&(wosignA
<wosignB
)){t2
=wosignA
;t3
=wosignB
;}if((wosignC
<wosignB
)&&(wosignB
<wosignA
)){t2
=wosignB
;t3
=wosignA
;}if(t2
>11){t2
=11;}if(t3
>11){t3
=11;}
printf("%d %d %f %d %d %d %d %d\n",time1
,time2
,s
,wosignA
,wosignB
,wosignC
,t2
,t3
);Find_Square((float)t2
/10000,(float)t3
/10000);OLED_ShowFloat(0,0,arv1
,2,4,16);OLED_ShowFloat(0,2,arv2
,2,4,16);EXTI
->IMR
|= GPIO_PIN_0
; EXTI
->IMR
|= GPIO_PIN_1
;EXTI
->IMR
|= GPIO_PIN_11
;signA
=0;signB
=0;signC
=0;time1
=0;time2
=0;}}if(mode
==3){goto MENU
;}}
可以用自己的按鍵,設置標志位做兩個模式,完成持續監測。
成品的誤差稍微有些大,不乏溫度,濕度,以及硬件誤差,和單片機檢測誤差,沒有濾波等等,總的來說,大體方向是對的,我們的作品還能進一步完善。
在調試的時候,單片機PB10引腳接收不到方波信號,拆了板子打電表,查不出問題,結果換了個引腳,好了,,,,,
總結
以上是生活随笔為你收集整理的基于STM32F103HAL库的声音定位系统的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。