超聲測距

来源:https://www.cnblogs.com/vinccc/archive/2018/01/20/8318586.html
-Advertisement-
Play Games

超聲測距模塊 HC-SR04P。工作電壓3-5V,有效距離2-400cm,解析度1mm。註意型號末尾的“P”:有另一個外觀、介面、工作方式一樣的型號 HC-SR04,但工作電壓為5V。我這個模塊 PCB正面印刷的是HC-SR04,反面印刷 HC-SR04P: 有4個引腳,VCC/GND供電,TRIG ...


超聲測距模塊 HC-SR04P。工作電壓3-5V,有效距離2-400cm,解析度1mm。註意型號末尾的“P”:有另一個外觀、介面、工作方式一樣的型號 HC-SR04,但工作電壓為5V。我這個模塊 PCB正面印刷的是HC-SR04,反面印刷 HC-SR04P:

有4個引腳,VCC/GND供電,TRIG觸發測距,ECHO接收測量結果。向TRIG給一個10us以上(規格書建議40-50us)的正脈衝觸發信號,模塊開始工作,發射超聲波並接收回聲。從發射到接收到回聲的時間,以迴響電平的形式從ECHO輸出;電平持續時間等於聲波往返模塊到障礙物的時間:

 溫下,聲音在空氣中的傳播速度約343m/s = 3.43mm/10us = .8575mm/2.5us。初步想法是,啟動一個Timer作為時間基,計數頻率 2.5us = 400kHz,以滿足10us觸發信號延時和1mm測量解析度的需求。介面方式,觸發信號用GPIO output,迴響信號用GPIO外部中斷。如下圖,迴響信號接PC7(Arduino相容Pin D9),其EXTI line編號為7:

使用基本Timer TIM6,時鐘源為PCLK1 x 2=72MHz。設PSC=179,得計數頻率 CK_CNT = 72MHz / (1+179) = 400kHz。設 ARR = 63999,則 UEV 頻率為 400kHz /(1+63999) = 6.25Hz = 160ms。

計時及有關工具函數實現如下。全局變數 _App_timestamp 記錄時間戳,在TIM6 UEV 中斷回調函數中更新,因此其精度為160ms。獲取當前時間戳時,將_App_timestamp 與 TIM6 CNT寄存器值相加,可達到 2.5us 精度:

typedef struct {
    uint32_t milli;
    uint16_t micro;
} _App_Timestamp;

volatile _App_Timestamp _App_timestamp = { 0, 0 };

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (&htim6 == htim) {
        _App_timestamp.milli += 160; // 160 ms/tick
    }
}

#define _App_GetDuration(from, to)  (           \
        1000 * ((to).milli - (from).milli)    \
        + (to).micro - (from).micro           \
        )

void _App_GetTimestamp(_App_Timestamp *ts) {
    *ts = _App_timestamp;
    uint32_t micro = 5 * htim6.Instance->CNT / 2;
    ts->milli += (micro / 1000);
    ts->micro += (micro % 1000);
}

void _App_DelayMicro(uint32_t micro) {
    _App_Timestamp t1, t2;
    _App_GetTimestamp(&t1);
    for (;;) {
        _App_GetTimestamp(&t2);
        if (_App_GetDuration(t1, t2) >= micro) {
            break;
        }
    }
}

ECHO Pin啟用外部中斷,在中斷回調函數內記錄上升沿和下降沿的時間戳:

typedef struct {
    uint8_t state;
    uint32_t duration; // in us
    _App_Timestamp _risingTs;
} _App_Measure;

volatile _App_Measure _App_measure = { 0 };

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (D9_ECHO_Pin == GPIO_Pin) {
        if (GPIO_PIN_SET == HAL_GPIO_ReadPin(D9_ECHO_GPIO_Port, D9_ECHO_Pin)) {
            // Rising edge
            _App_Timestamp now;
            _App_GetTimestamp(&now);
            _App_measure._risingTs = now;
            _App_measure.state = 0;
        } else {
            // Falling edge
            _App_Timestamp now;
            _App_GetTimestamp(&now);
            _App_measure.duration = _App_GetDuration(_App_measure._risingTs,
                    now);
            _App_measure.state = 1;
        }
    }
}

 

主迴圈如下。首先發送TRIG脈衝,時間設為20us。距離的計算註意將聲波往返距離除以 2 才是到障礙物的距離:

void App_Loop() {

    _App_Trig(20);

    HAL_Delay(500);

    if (_App_measure.state) {
        uint32_t dur = _App_measure.duration;
        uint32_t dist = (uint32_t) (.343f * dur / 2);

        if (dist > 25 && dist < 5000) {
            char msg[80];
            sprintf(msg, "%d mm\n", (int) dist);
            HAL_UART_Transmit(&huart2, (uint8_t *) msg, strlen(msg),
            HAL_MAX_DELAY);
        }
    }
}

void _App_Trig(uint32_t micro) {
    HAL_GPIO_WritePin(D8_TRIG_GPIO_Port, D8_TRIG_Pin, GPIO_PIN_SET);
    _App_DelayMicro(micro);
    HAL_GPIO_WritePin(D8_TRIG_GPIO_Port, D8_TRIG_Pin, GPIO_PIN_RESET);
}

測得的距離從串口 USART2 輸出,單位為mm:

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文地址:https://www.cnblogs.com/pipi-changing/p/5697481.html 找了下Cron的資料,這篇作者寫的比較清晰,轉載記錄一下,方便後面使用的時候在google 1. cron表達式格式: {秒數} {分鐘} {小時} {日期} {月份} {星期} {年... ...
  • 昨天,在做一個NPOI讀取的小demo的時候,使用OpenFileDialog打開文件,最開始的寫法,直接在按鈕點擊事件中寫,會報錯,代碼如下: 或者直接 這兩種,無論哪種寫法,在代碼執行的時候,會報錯,具體報錯為: 這種情況,在網上查詢,是說線程問題,就是線程衝突了,不知道該執行哪一個,具體說法如 ...
  • 本篇文章更適合具有一定開發經驗,一定功底,且對底層代碼有所研究的朋友!!! 本篇文章主要採用理論和代碼實例相結合方式來論述委托和事件,涉及到一些邊界技術,如軟體架構的OCP原則(開-閉原則), 軟體架構解耦,設計模式(Sender-Order)和事件驅動模型,有一定難度和深度,不適合初級者。 第一部 ...
  • 這篇文章介紹了 NEST 中是如何實現 Elasticsearch 中的時間段的 ...
  • RGB顏色感測器。感測器晶元不知道是TCS230,或是TCS3200。二者pinout及電氣性能一樣。左邊的模塊有8個引腳,LED常亮。S0, S1 預設上拉為高電平,/OE下拉低電平。S2, S3, OUT 三個引腳供單片機介面。如下: 照片中右邊的模塊有10個引腳,原理與8pin相同,只是多了一 ...
  • centos install vsftpd with SSL support ...
  • 是一款跨windows/linux/MAC OS平臺的文件同步工具,不僅支持本地對本地同步,也支持通過SSH、RSH和Socket等網路協議進行同步。更棒的是, 支持雙向同步操作,你既可以從A同步到B,也可以從B同步到A,這些都不需要額外的設定。 是一個 Linux 內核特性,它監控文件系統,並且及 ...
  • CM3 的堆棧分為兩個:主堆棧和進程堆棧。 那麼,這兩個棧分別在什麼情況下使用呢? 這時,我們看一下CM3的控制寄存器(CONTROL):控制寄存器用於定義特權級別,還用於選擇當前使用哪個堆棧指針。 CONTROL[1] 在 Cortex‐M3 的 handler 模式中, CONTROL[1]總是 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...