系列目錄
點擊查看目錄
- STM32 HAL庫快速實戰【一】《32點燈》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【三】《pwm控制舵機》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【四】《串口簡單使用》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【五】《控制串口電機》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【六】《藍牙控制》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【七】《機械臂控制》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【八】《聲音傳感器的使用》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
- STM32 HAL庫快速實戰【九】《超聲波傳感器的使用以及自由避障》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 博客園 (cnblogs.com)
模塊介紹
引腳 | 作用 |
---|---|
VCC | 電源,3.3-5V |
Trig (Trigger) | 觸發超聲波脈沖 |
Echo | 回聲當接收到反射信號時,引腳產生一個脈沖。脈沖的長度與檢測發射信號所需的時間成正比。 |
GND | 接地 |
(1)超聲波測距原理
1)超聲波測距原理是在超聲波發射裝置發出超聲波,它的根據是接收器接到超聲波時的時間差,與雷達測距原理相似。 超聲波發射器向某一方向發射超聲波,在發射時刻的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即返回來,超聲波接收器收到反射波就立即停止計時。(超聲波在空氣中的傳播速度為340m/s,根據計時器記錄的時間t,就可以計算出發射點距障礙物的距離(s),即:s=340t/200)
(2)HC-SR04超聲波測距模塊工作原理
1)采用IO觸發測距,給至少10us的高電平信號。
2)模塊自動發送8個40KHz的方波,自動檢測是否有信號返回。
3)有信號返回,通過IO輸出一高電平,高電平持續時間就是超聲波從發射到返回的時間聲波從發射到返回的時間
————————————————
版權聲明:本文為CSDN博主「精神小火君」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43853307/article/details/104065508
接線
Trig接到SA5上即PA4上
Echo接到SD5即PA6上
CubeMX配置
復制上一節工程,新增兩個GPIO,PA4設置為推挽輸出,初始高電平,標簽Trig
PA6設置為輸入,浮空模式,標簽Echo
點擊查看配置圖片


編寫超聲波代碼
由於驅動模塊涉及到多次翻轉電平,為了省事,我們可以define一下GPIO輸入輸出代碼。
打開sensor.h,將WritePin定義為Trig(),這樣可以直接Trig(1)進行輸出高電平。將ReadPin定義為Echo()
#define Trig(x) HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,(GPIO_PinState)x)
#define Echo() HAL_GPIO_ReadPin(Echo_GPIO_Port,Echo_Pin)
然后打開sensor.c編寫超聲波模塊驅動代碼。
hcsr04的驅動思路為:
1.Trig引腳輸出一個周期為20us的方波
2.等待Echo引腳從高拉低
3.開啟定時器,等待Echo從低拉高
4.計算定時時間,算出距離。
輸出方波很簡單,
Trig(1);
csb_Delay_Us(20);
Trig(0);
即可。
這里涉及個問題,即STM32HAL里面的延時是ms,沒有us。參考51延時,我們可以用兩個for循環進行延時。
void csb_Delay_Us(uint16_t time) //延時函數
{
uint16_t i,j;
for(i=0;i<time;i++)
for(j=0;j<9;j++);
}
然后用while(Echo() == 0);
來等待電平變換。
前面驅動arm時我們已經開啟了三個基本定時器用於輸出PWM,這里我們可以直接拿來用於計數。
在.c頂部引入"tim.h"。
__HAL_TIM_SetCounter(&htim2,0);
將定時器2計數值歸零,
然后用while(Echo() == 1);
來等待Echo從低拉高。完畢后csb_t =__HAL_TIM_GetCounter(&htim2);
來獲取計時時間。注意我們定時器分頻72,因此時間分辨率為1us,即距離為340/2m/s=0.017cm/us(聲波來回時間)
進行下單位換算csb_t = csb_t*0.017;
,獲取距離的代碼就完成了。
完整如下:
點擊查看代碼
/**
* @brief :采集超聲波數據
* @param :None
* @retval 采集的數據
**/
uint16_t get_csb_value(void) {
uint16_t csb_t;
Trig(1);
csb_Delay_Us(20);
Trig(0);
while(Echo() == 0); //等待接收口高電平輸出
__HAL_TIM_SetCounter(&htim2,0);
while(Echo() == 1);
csb_t =__HAL_TIM_GetCounter(&htim2);//獲取時間,分辨率為1US
//340m/s = 0.017cm/us
if(csb_t < 20000) {
csb_t = csb_t*0.017;
return csb_t;
}
return 0;
}
一般由於震動等干擾,獲取一次值正確的概率很低。我們可以獲取多次數據,然后取中間值。
代碼如下:
點擊查看代碼
/**
* @brief :對於給定元素長度數組,從小到大進行排序
* @param :數組地址,元素個數
* @retval None
**/
void selection_sort(int *a, int len) {
int i,j,mi,t;
for(i=0;i<len-1;i++) {
mi = i;
for(j=i+1;j<len;j++) {
if(a[mi] > a[j]) {
mi = j;
}
}
if(mi != i) {
t = a[mi];
a[mi] = a[i];
a[i] = t;
}
}
}
/**
* @brief :處理超聲波采集到的數據,取采集到的中間值
* @param :數組地址,元素個數
* @retval 處理后的超聲波數據
**/
int get_adc_csb_middle() {
uint8_t i;
static int ad_value[5] = {0}, myvalue;
for(i=0;i<5;i++)ad_value[i] = get_csb_value();
selection_sort(ad_value, 5);
myvalue = ad_value[2];
return myvalue;
}
自由避障設計
得到超聲波返回的數據后,我們可以根據機器人前方障礙物的距離來設計路徑規划。一個比較 智障 簡單的方案就是,有障礙物就右轉。
點擊查看代碼
/**
* @brief : 根據超聲波返回的數據執行自動避障功能。
* @param :數組地址,元素個數
* @retval 處理后的超聲波數據
**/
void hcsr_task(void)
{
static uint32_t systick_ms_bak = 0;
uint8_t cmd_return[100];
int speed = 500, adc_csb;
int millis=HAL_GetTick();//獲取系統時間
if(millis - systick_ms_bak > 20) {
systick_ms_bak = HAL_GetTick();
adc_csb = get_adc_csb_middle();//獲取a0的ad值,計算出距離
sprintf((char *)cmd_return, "adc_csb = %d\r\n", adc_csb);
usart_send_str(&huart3,cmd_return);
if(adc_csb < 30) {//距離低於20cm就右轉
motor_set(speed+500, -speed-500);
HAL_Delay(500);
}else if(adc_csb>80){
motor_set(1000, 1000);
}else{
motor_set(speed,speed);
}
}
}
然后在.h中聲明該函數,即可在其他地方引用。
點擊查看代碼
#include "stdint.h"
#define sound_vol HAL_GPIO_ReadPin(sound_GPIO_Port,sound_Pin)
#define Trig(x) HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,(GPIO_PinState)x)
#define Echo() HAL_GPIO_ReadPin(Echo_GPIO_Port,Echo_Pin)
void sound_task(void);
void hcsr_task(void);
uint16_t get_csb_value(void);
例如在主函數中,接收到H字符開啟自動避障功能。
case 'H':while(1){hcsr_task();};break;
工程源碼
國內用戶請使用gitee克隆或是使用代理訪問Github
https://github.com/USTHzhanglu/stm32-hal/tree/main/hcsr-04