一、前言
1.1 項(xiàng)目開發(fā)背景
在現(xiàn)代電子技術(shù)的快速發(fā)展中,各種智能設(shè)備的精確度和便捷性不斷提升,電子水平儀作為一種常見的測量工具,廣泛應(yīng)用于建筑、家居安裝、機(jī)械制造等領(lǐng)域。傳統(tǒng)的水平儀通常依賴機(jī)械原理,如氣泡管或機(jī)械刻度盤,雖然簡單直觀,但在一些精度要求較高的場合,傳統(tǒng)工具往往難以滿足需求。因此,電子水平儀應(yīng)運(yùn)而生,憑借其數(shù)字化顯示和高精度測量,逐漸取代了傳統(tǒng)水平儀,成為更加智能化的測量工具。
本項(xiàng)目基于STM32F103C8T6單片機(jī)設(shè)計(jì)一款電子水平儀。STM32F103C8T6作為一種性能強(qiáng)大的微控制器,具有較高的計(jì)算能力和豐富的外設(shè)接口,能夠滿足項(xiàng)目對實(shí)時(shí)數(shù)據(jù)處理和顯示控制的需求。該單片機(jī)將與MPU6050傳感器相結(jié)合,利用其內(nèi)置的加速度計(jì)和陀螺儀,實(shí)現(xiàn)設(shè)備的傾斜角度測量。MPU6050傳感器能夠高精度地檢測設(shè)備在三個(gè)軸向上的加速度信息,從而計(jì)算出設(shè)備在左右方向(X軸)和前后方向(Y軸)的傾斜角度。
為了更直觀地展示測量結(jié)果,本項(xiàng)目選用了一款高分辨率的OLED顯示屏。該顯示屏可以清晰地呈現(xiàn)實(shí)時(shí)的角度數(shù)據(jù),并且提供了足夠的分辨率來實(shí)現(xiàn)可視化的圖形展示。通過中心點(diǎn)圓圈和滾動(dòng)小球的設(shè)計(jì),用戶可以輕松識別設(shè)備當(dāng)前的水平狀態(tài)。這種可視化的反饋方式不僅更加直觀,而且提升了用戶體驗(yàn),特別適用于需要頻繁調(diào)整水平狀態(tài)的場景。
隨著智能化技術(shù)的普及,越來越多的傳統(tǒng)工具開始向數(shù)字化、智能化方向發(fā)展。電子水平儀作為數(shù)字工具的一種,其精度、穩(wěn)定性和用戶友好性成為了設(shè)計(jì)的核心目標(biāo)。項(xiàng)目通過結(jié)合MPU6050傳感器的高精度檢測與STM32F103C8T6單片機(jī)的強(qiáng)大處理能力,提供了一種新型的、可視化的電子水平儀設(shè)計(jì)方案。這種方案不僅滿足了基礎(chǔ)的角度測量功能,還通過創(chuàng)新的顯示方式,使得用戶能夠更加高效和精準(zhǔn)地進(jìn)行水平調(diào)整和測量。
核心的部件:
1.2 設(shè)計(jì)實(shí)現(xiàn)的功能
基于STM32設(shè)計(jì)一款電子水平儀
功能要求:
1. 本地一個(gè)SPI協(xié)議接口的OLED顯示屏,展示當(dāng)前 設(shè)備左右方向的傾斜角度,設(shè)備前后方向的傾斜角度。
2. 能夠通過一個(gè)中心點(diǎn)圓圈+一個(gè)滾動(dòng)的小球展示可視化展示當(dāng)前的水平狀態(tài)。
3. 支持按鍵校準(zhǔn),校準(zhǔn)水平儀的參數(shù)
硬件要求:
1. 單片機(jī)采用STM32F103C8T6
2. 水平狀態(tài)監(jiān)測采用MPU6050
3. 顯示屏采用高分辨率的OLED顯示屏
4. 供電采用可充電鋰電池供電,方便便攜式攜帶
5. 一個(gè)按鈕,進(jìn)行復(fù)位參數(shù)校準(zhǔn)。
(1) 傾斜角度測量
通過 MPU6050 傳感器,實(shí)時(shí)測量設(shè)備在 X 軸(左右方向)和 Y 軸(前后方向)的傾斜角度。系統(tǒng)能夠精準(zhǔn)地計(jì)算設(shè)備相對于水平的角度,并將其顯示在 OLED 屏幕上,提供清晰的數(shù)值反饋,幫助用戶了解設(shè)備當(dāng)前的水平狀態(tài)。
(2) 實(shí)時(shí)水平狀態(tài)可視化顯示
在 OLED 顯示屏上,采用圖形化方式展示設(shè)備的水平狀態(tài)。通過中心圓圈和滾動(dòng)的小球,用戶可以直觀地看到設(shè)備的水平偏差。小球會(huì)根據(jù)設(shè)備的傾斜方向和角度實(shí)時(shí)滾動(dòng),偏離水平時(shí)會(huì)向?qū)?yīng)方向移動(dòng),水平時(shí)則停留在圓圈中心,增強(qiáng)用戶體驗(yàn)。
(3) 數(shù)據(jù)濾波與角度計(jì)算
在數(shù)據(jù)處理方面,設(shè)計(jì)了合適的濾波算法,如卡爾曼濾波或簡單平均濾波,用于去除傳感器數(shù)據(jù)中的噪聲和提高計(jì)算的準(zhǔn)確性。通過這些算法,系統(tǒng)能夠更加穩(wěn)定和精準(zhǔn)地輸出設(shè)備的傾斜角度。
(4) 校準(zhǔn)功能
系統(tǒng)提供校準(zhǔn)功能,用戶可以通過按下按鈕來重置設(shè)備的零點(diǎn),校準(zhǔn)設(shè)備的水平狀態(tài)。當(dāng)按下按鈕時(shí),設(shè)備的當(dāng)前角度被重置為零,確保在每次使用時(shí)都能從準(zhǔn)確的水平狀態(tài)開始。此功能特別適用于設(shè)備多次使用后的精度校正,保證每次測量的精度和可靠性。
(5) OLED 顯示角度數(shù)值
在 OLED 屏幕上,實(shí)時(shí)顯示設(shè)備的具體傾斜角度,分別顯示 X 軸(左右方向)和 Y 軸(前后方向)的傾斜角度數(shù)值。通過直觀的數(shù)字顯示,用戶可以準(zhǔn)確了解當(dāng)前設(shè)備的水平狀態(tài),并在需要時(shí)進(jìn)行調(diào)整。
(6) 便攜性與充電功能
該電子水平儀設(shè)計(jì)為便攜式設(shè)備,配備了可充電鋰電池,用戶可以在不依賴外部電源的情況下,長時(shí)間使用設(shè)備。通過電池管理模塊,支持 USB 充電接口,方便充電并延長使用時(shí)間。電池的可充電特性使得設(shè)備在戶外、工地等環(huán)境下更加便捷。
(7) 低功耗設(shè)計(jì)
為了提高設(shè)備的使用時(shí)長,設(shè)計(jì)中采用了低功耗模式。STM32F103C8T6 單片機(jī)與 MPU6050 傳感器均支持低功耗操作,系統(tǒng)在不進(jìn)行操作時(shí)可以進(jìn)入低功耗待機(jī)狀態(tài),減少能耗,延長電池使用時(shí)間。
(8) 用戶友好界面
通過簡潔直觀的 OLED 顯示屏界面,用戶可以輕松獲取設(shè)備的實(shí)時(shí)傾斜角度和水平狀態(tài)。顯示內(nèi)容清晰、易于閱讀,設(shè)計(jì)了視覺化的反饋方式,使得設(shè)備使用者能夠快速理解設(shè)備的水平偏差并進(jìn)行相應(yīng)調(diào)整。
1.3 項(xiàng)目硬件模塊組成
(1) STM32F103C8T6 單片機(jī)
STM32F103C8T6 是本項(xiàng)目的核心控制單元,負(fù)責(zé)數(shù)據(jù)處理、控制顯示屏和執(zhí)行用戶輸入的操作。該單片機(jī)具備多種外設(shè)接口,如 I2C 和 GPIO,能夠與 MPU6050 傳感器和 OLED 顯示屏進(jìn)行通信。此外,它具有較強(qiáng)的運(yùn)算能力,能夠進(jìn)行角度計(jì)算、校準(zhǔn)功能以及實(shí)時(shí)顯示更新。
(2) MPU6050 傳感器
MPU6050 是集成了 3 軸加速度計(jì)和 3 軸陀螺儀的傳感器,用于檢測設(shè)備在 X 軸(左右方向)和 Y 軸(前后方向)的加速度,進(jìn)而計(jì)算出設(shè)備的傾斜角度。通過 I2C 協(xié)議將數(shù)據(jù)傳輸給 STM32F103C8T6 單片機(jī),用于后續(xù)角度計(jì)算和顯示。
(3) OLED 顯示屏
OLED 顯示屏用于顯示設(shè)備的傾斜角度和水平狀態(tài)。高分辨率的 OLED 顯示屏能清晰地呈現(xiàn)數(shù)值角度和可視化圖形(如中心圓圈和滾動(dòng)小球)。通過 I2C 連接 STM32F103C8T6 單片機(jī),實(shí)時(shí)顯示 X、Y 軸的傾斜角度以及水平狀態(tài)的圖形反饋。
(4) 可充電鋰電池
可充電鋰電池提供電子水平儀系統(tǒng)所需的電力,支持便攜式使用。它通常提供 3.7V 的電壓,滿足 STM32F103C8T6、MPU6050 傳感器和 OLED 顯示屏的工作需求。電池可以通過充電電路進(jìn)行充電,以便用戶在外出時(shí)使用。
(5) 電池充電管理模塊
為了方便充電,配備電池充電管理模塊(TP4056)用于給可充電鋰電池充電。該模塊能夠通過 Micro-USB 或其他充電接口連接電源,并在充電時(shí)提供電池保護(hù),防止過充或過放。
(6) 按鍵模塊
一個(gè)按鍵用于用戶與電子水平儀的交互,具體功能包括校準(zhǔn)或復(fù)位。按鍵可以觸發(fā) STM32F103C8T6 的GPIO引腳,在長按時(shí)啟動(dòng)水平儀的參數(shù)校準(zhǔn)功能,重新設(shè)置設(shè)備的零點(diǎn),確保在不同使用環(huán)境下仍能獲得準(zhǔn)確的測量結(jié)果。
1.4 設(shè)計(jì)思路
本項(xiàng)目的設(shè)計(jì)思路主要是通過結(jié)合硬件和軟件的緊密配合,開發(fā)一款精準(zhǔn)且便于攜帶的電子水平儀。該電子水平儀通過 STM32F103C8T6 單片機(jī)作為核心處理單元,利用 MPU6050 傳感器獲取設(shè)備的加速度數(shù)據(jù),實(shí)時(shí)計(jì)算設(shè)備的傾斜角度,并通過高分辨率的 OLED 顯示屏直觀地呈現(xiàn)出來。設(shè)計(jì)的關(guān)鍵在于如何準(zhǔn)確捕捉設(shè)備的水平狀態(tài)并通過用戶友好的方式展示出來,同時(shí)確保系統(tǒng)的便攜性和易操作性。
系統(tǒng)的核心是 STM32F103C8T6 單片機(jī),作為高性能的微控制器,它具有多種外設(shè)接口和足夠的運(yùn)算能力,能夠進(jìn)行實(shí)時(shí)數(shù)據(jù)處理。通過 I2C 協(xié)議,單片機(jī)與 MPU6050 傳感器進(jìn)行通信,獲取加速度計(jì)和陀螺儀數(shù)據(jù)。這些數(shù)據(jù)將用于計(jì)算設(shè)備的傾斜角度,并進(jìn)一步進(jìn)行校準(zhǔn)和調(diào)整,確保在任何情況下都能提供精準(zhǔn)的水平測量。
在傳感器數(shù)據(jù)處理方面,設(shè)計(jì)的關(guān)鍵是如何精確地計(jì)算設(shè)備的角度。MPU6050 傳感器提供了 X、Y 和 Z 軸的加速度數(shù)據(jù),我們將使用這些數(shù)據(jù)計(jì)算設(shè)備相對于水平面(X軸和Y軸的傾斜角度)的變化。為了減少噪聲和提高測量精度,設(shè)計(jì)時(shí)引入了數(shù)據(jù)濾波算法,以保證角度計(jì)算的穩(wěn)定性和準(zhǔn)確性。
OLED 顯示屏作為用戶與設(shè)備交互的界面,提供了豐富的顯示功能。設(shè)計(jì)中通過實(shí)時(shí)顯示當(dāng)前設(shè)備的左右方向(X軸)和前后方向(Y軸)的傾斜角度,用戶可以清晰地了解設(shè)備的水平狀態(tài)。此外,為了增加可視化的體驗(yàn),我們設(shè)計(jì)了一個(gè)中心點(diǎn)圓圈,并通過小球的滾動(dòng)來展示設(shè)備的傾斜程度。當(dāng)設(shè)備完全水平時(shí),小球?qū)⑼A粼谥行膱A圈內(nèi),偏離水平時(shí),小球會(huì)向?qū)?yīng)的方向移動(dòng)。這樣直觀的顯示方式讓用戶能在瞬間理解設(shè)備的水平情況。
為了確保設(shè)備能夠適應(yīng)不同的環(huán)境和使用場景,本設(shè)計(jì)還加入了校準(zhǔn)功能。通過設(shè)置一個(gè)按鍵,用戶可以在需要時(shí)對設(shè)備進(jìn)行參數(shù)復(fù)位和重新校準(zhǔn)。當(dāng)按下按鈕時(shí),STM32 單片機(jī)會(huì)清除當(dāng)前的角度偏差,并重置為零點(diǎn),確保在多次使用過程中系統(tǒng)依然保持高精度。
便攜性是本項(xiàng)目的另一個(gè)重要設(shè)計(jì)方向。采用可充電鋰電池為電源,配備電池管理模塊,以支持系統(tǒng)在無外部電源的情況下長時(shí)間工作。電池的充電功能使得用戶可以在野外或移動(dòng)環(huán)境中隨時(shí)使用,并且通過 USB 充電接口方便充電,解決了傳統(tǒng)水平儀無法持續(xù)工作的問題。
通過這些硬件和軟件的結(jié)合,整個(gè)電子水平儀系統(tǒng)實(shí)現(xiàn)了精確、直觀和便捷的功能。系統(tǒng)設(shè)計(jì)不僅具備高精度的水平測量功能,還通過簡潔的用戶界面和便攜設(shè)計(jì)使得用戶能夠在各種環(huán)境下使用,提供了一個(gè)全新的測量工具,取代了傳統(tǒng)的機(jī)械水平儀。
1.5 系統(tǒng)功能總結(jié)
功能編號 | 功能描述 | 實(shí)現(xiàn)方式 |
---|---|---|
(1) | 傾斜角度測量 | 通過 MPU6050 傳感器測量 X 軸和 Y 軸的傾斜角度,并進(jìn)行計(jì)算顯示。 |
(2) | 實(shí)時(shí)水平狀態(tài)可視化顯示 | 在 OLED 屏幕上展示中心點(diǎn)圓圈及滾動(dòng)小球,直觀展示設(shè)備的水平狀態(tài)。 |
(3) | 數(shù)據(jù)濾波與角度計(jì)算 | 使用卡爾曼濾波或簡單平均濾波去除噪聲,計(jì)算設(shè)備的精確傾斜角度。 |
(4) | 校準(zhǔn)功能 | 通過按鍵觸發(fā)校準(zhǔn),重置設(shè)備角度為零,確保每次使用時(shí)從準(zhǔn)確零點(diǎn)開始。 |
(5) | OLED 顯示角度數(shù)值 | 在 OLED 屏幕上實(shí)時(shí)顯示設(shè)備的 X 軸和 Y 軸傾斜角度的數(shù)值。 |
(6) | 便攜性與充電功能 | 配備可充電鋰電池,支持 USB 充電,適合便攜式使用,解決外部電源依賴問題。 |
(7) | 低功耗設(shè)計(jì) | 系統(tǒng)支持低功耗模式,確保設(shè)備在待機(jī)時(shí)減少能耗,延長使用時(shí)間。 |
(8) | 用戶友好界面 | OLED 顯示屏提供清晰直觀的角度數(shù)值和圖形化的反饋,簡化操作和交互。 |
1.6 開發(fā)工具的選擇
開發(fā)工具選擇Keil,keil是一家世界領(lǐng)先的嵌入式微控制器軟件開發(fā)商,在2015年,keil被ARM公司收購。因?yàn)楫?dāng)前芯片選擇的是STM32F103系列,STMF103是屬于ARM公司的芯片構(gòu)架、Cortex-M3內(nèi)核系列的芯片,所以使用Kile來開發(fā)STM32是有先天優(yōu)勢的,而keil在各大高校使用的也非常多,很多教科書里都是以keil來教學(xué),開發(fā)51單片機(jī)、STM32單片機(jī)等等。
1.7 MPU6050模塊介紹
MPU6050 是一款由 Invensense 公司生產(chǎn)的六軸傳感器模塊,它結(jié)合了三軸加速度計(jì)和三軸陀螺儀,廣泛應(yīng)用于運(yùn)動(dòng)追蹤、姿態(tài)檢測、電子穩(wěn)定、虛擬現(xiàn)實(shí)等領(lǐng)域。MPU6050 采用 MEMS(微機(jī)電系統(tǒng))技術(shù),能夠提供高精度的角度和加速度數(shù)據(jù),適用于需要實(shí)時(shí)動(dòng)態(tài)感知的應(yīng)用。
該傳感器模塊內(nèi)置了一個(gè)三軸加速度計(jì)和一個(gè)三軸陀螺儀。三軸加速度計(jì)能夠測量物體在 X、Y 和 Z 軸上的加速度變化,單位為“g”(地球重力加速度),可以感知物體的靜態(tài)或動(dòng)態(tài)加速度變化。三軸陀螺儀則用于測量物體在三個(gè)軸上的角速度,單位通常為“度/秒”(°/s),可提供物體旋轉(zhuǎn)的速率信息。通過這些數(shù)據(jù),MPU6050 可以檢測物體的運(yùn)動(dòng)、旋轉(zhuǎn)以及傾斜角度,并為其他系統(tǒng)提供準(zhǔn)確的傳感信息。
MPU6050 的最大特點(diǎn)之一是它內(nèi)置了一個(gè)數(shù)字運(yùn)動(dòng)處理單元(DMP,Digital Motion Processor),它能夠?qū)铀俣扔?jì)和陀螺儀的數(shù)據(jù)進(jìn)行實(shí)時(shí)處理,從而減輕主處理器的計(jì)算負(fù)擔(dān)。DMP 還可以進(jìn)行傳感器數(shù)據(jù)的濾波、姿態(tài)估算和融合處理,這使得 MPU6050 在傳感器輸出的穩(wěn)定性和準(zhǔn)確性上具有顯著優(yōu)勢。此外,DMP 支持直接輸出已經(jīng)處理和融合的運(yùn)動(dòng)數(shù)據(jù),減少了主控單元的數(shù)據(jù)處理量,從而提升了整體系統(tǒng)的性能。
MPU6050 模塊支持 I2C 通信協(xié)議,具有兩線串行總線接口,便于與主控單元(如 STM32F103C8T6、Arduino 等)進(jìn)行數(shù)據(jù)傳輸。其通信速率最高可達(dá) 400 kHz,因此可以在需要高頻率數(shù)據(jù)采集的應(yīng)用中提供實(shí)時(shí)數(shù)據(jù)反饋。通過該接口,開發(fā)者能夠讀取加速度計(jì)和陀螺儀的數(shù)據(jù),還能夠配置模塊的工作模式、靈敏度等參數(shù),以滿足特定應(yīng)用需求。
在實(shí)際應(yīng)用中,MPU6050 具有較高的靈敏度和較低的功耗,適合用于移動(dòng)設(shè)備、機(jī)器人、無人機(jī)、車載系統(tǒng)等對體積、功耗有要求的場景。其內(nèi)置的低通濾波器和數(shù)字處理單元,使得它能夠有效地抑制噪聲,提高測量數(shù)據(jù)的穩(wěn)定性,尤其在動(dòng)態(tài)環(huán)境下,能夠準(zhǔn)確地感知物體的運(yùn)動(dòng)狀態(tài)和姿態(tài)變化。
此外,MPU6050 還具有一些自檢功能,可以通過內(nèi)部自檢機(jī)制判斷傳感器是否正常工作。模塊中還有內(nèi)置溫度傳感器,用于補(bǔ)償溫度對加速度計(jì)和陀螺儀的影響,確保測量精度不會(huì)受到環(huán)境溫度變化的影響。
MPU6050 以其小巧的體積、高精度的傳感能力、內(nèi)置數(shù)字運(yùn)動(dòng)處理單元(DMP)以及低功耗特點(diǎn),成為許多運(yùn)動(dòng)監(jiān)測和姿態(tài)檢測系統(tǒng)中不可或缺的核心傳感器。它不僅能夠提供高質(zhì)量的數(shù)據(jù),還能減少對主控制單元的計(jì)算壓力,使得整體系統(tǒng)更加高效、穩(wěn)定。
二、代碼設(shè)計(jì)
模塊代碼可以去網(wǎng)盤下載學(xué)習(xí):https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
2.1 工作原理
在電子水平儀中,MPU6050 傳感器的主要作用是通過測量加速度和角速度來計(jì)算設(shè)備的傾斜角度。它集成了三軸加速度計(jì)和三軸陀螺儀,這兩者協(xié)同工作,實(shí)現(xiàn)對設(shè)備在各個(gè)方向上的姿態(tài)和運(yùn)動(dòng)的監(jiān)測。
MPU6050 在水平儀中的工作原理如下:
MPU6050 內(nèi)部的三軸加速度計(jì)可以測量設(shè)備在三個(gè)方向(X、Y、Z軸)上的加速度。加速度計(jì)的基本工作原理是根據(jù)物體受到的力(如重力)產(chǎn)生的加速度來推算設(shè)備的運(yùn)動(dòng)狀態(tài)。在一個(gè)理想的水平狀態(tài)下,重力僅作用于Z軸(即垂直方向)。因此,設(shè)備的傾斜會(huì)導(dǎo)致加速度的分布發(fā)生變化,從而改變X軸和Y軸的加速度值。
當(dāng)設(shè)備傾斜時(shí),重力的作用方向?qū)⒉辉偻耆赶?Z 軸,而是分布到 X 和 Y 軸上,產(chǎn)生一定的加速度。這些加速度值可以用來計(jì)算設(shè)備的傾斜角度。通過對 X 和 Y 軸加速度值的計(jì)算,可以推算出設(shè)備的俯仰角度(pitch)和滾轉(zhuǎn)角度(roll)。例如,通過以下公式,可以計(jì)算出設(shè)備的俯仰角(pitch)和滾轉(zhuǎn)角(roll):
- 俯仰角(Pitch) :
[ text{pitch} = arctanleft(frac{accelX}{sqrt{accelY^2 + accelZ^2}}right) ] - 滾轉(zhuǎn)角(Roll) :
[ text{roll} = arctanleft(frac{-accelY}{sqrt{accelX^2 + accelZ^2}}right) ]
通過這些計(jì)算,可以獲取設(shè)備的實(shí)時(shí)傾斜角度。
陀螺儀工作原理
MPU6050 內(nèi)部的三軸陀螺儀可以測量設(shè)備的旋轉(zhuǎn)速率,也就是角速度。陀螺儀通過檢測設(shè)備在各個(gè)軸上的旋轉(zhuǎn)速率(單位:度/秒或 rad/s)來捕捉設(shè)備的動(dòng)態(tài)變化。與加速度計(jì)不同,陀螺儀主要檢測旋轉(zhuǎn)的角速度,能反映設(shè)備在實(shí)時(shí)運(yùn)動(dòng)中的變化。
在水平儀中,陀螺儀的工作原理通常用于跟蹤設(shè)備的快速變化。例如,當(dāng)設(shè)備發(fā)生快速旋轉(zhuǎn)或傾斜時(shí),陀螺儀的角速度數(shù)據(jù)可以幫助補(bǔ)充加速度計(jì)測量的數(shù)據(jù),增強(qiáng)系統(tǒng)對動(dòng)態(tài)變化的響應(yīng)能力。特別是在靜態(tài)情況下,加速度計(jì)能夠提供較為穩(wěn)定的角度測量,而在快速運(yùn)動(dòng)或旋轉(zhuǎn)時(shí),陀螺儀可以提供更快的反應(yīng)數(shù)據(jù)。
數(shù)據(jù)融合與姿態(tài)計(jì)算
雖然加速度計(jì)和陀螺儀都能提供關(guān)于設(shè)備傾斜的不同信息,但它們各自存在局限性。加速度計(jì)受到重力和運(yùn)動(dòng)加速度的影響,可能會(huì)產(chǎn)生一定的噪聲;而陀螺儀在長時(shí)間使用中可能會(huì)受到漂移的影響。因此,在水平儀中,通常會(huì)采用 傳感器融合算法 ,如互補(bǔ)濾波或 卡爾曼濾波 ,來結(jié)合加速度計(jì)和陀螺儀的數(shù)據(jù),從而提高系統(tǒng)的精度和穩(wěn)定性。
- 互補(bǔ)濾波 : 這種方法結(jié)合了加速度計(jì)和陀螺儀的優(yōu)勢,通過加速度計(jì)提供的穩(wěn)定低頻信息和陀螺儀提供的高頻旋轉(zhuǎn)信息,實(shí)現(xiàn)一個(gè)平衡的結(jié)果。
- 卡爾曼濾波 :卡爾曼濾波是一種更復(fù)雜的算法,它能夠基于信號的不確定性,計(jì)算出加速度計(jì)和陀螺儀數(shù)據(jù)的最優(yōu)融合,提供更為精確和穩(wěn)定的角度計(jì)算。
在水平儀中,結(jié)合加速度計(jì)和陀螺儀的數(shù)據(jù)后,可以獲得非常精確的設(shè)備俯仰和滾轉(zhuǎn)角度,從而在 OLED 屏幕上顯示出設(shè)備的水平狀態(tài),直觀地向用戶反饋設(shè)備是否處于水平狀態(tài)。
工作流程總結(jié)
- 加速度計(jì) :用于檢測設(shè)備在 X、Y 和 Z 軸上的加速度,并通過計(jì)算設(shè)備的俯仰角和滾轉(zhuǎn)角來推算其在水平面上的傾斜角度。
- 陀螺儀 :用于檢測設(shè)備在各個(gè)軸上的旋轉(zhuǎn)速率,幫助系統(tǒng)在快速運(yùn)動(dòng)和變化時(shí)實(shí)時(shí)更新角度信息。
- 數(shù)據(jù)融合 :結(jié)合加速度計(jì)和陀螺儀的輸出數(shù)據(jù),通過傳感器融合算法(如互補(bǔ)濾波或卡爾曼濾波),獲取更為準(zhǔn)確的設(shè)備角度數(shù)據(jù)。
- 角度計(jì)算 :根據(jù)加速度計(jì)和陀螺儀數(shù)據(jù)計(jì)算出設(shè)備的俯仰角和滾轉(zhuǎn)角,從而實(shí)時(shí)監(jiān)控和顯示設(shè)備的傾斜狀態(tài),向用戶反饋設(shè)備是否處于水平狀態(tài)。
2.2 MPU6050的驅(qū)動(dòng)代碼
#include "mpu6050.h"
#include "sys.h"
#include "delay.h"
#include < stdio.h >
/*--------------------------------------------------------------------IIC協(xié)議底層模擬時(shí)序--------------------------------------------------------------------------------*/
/*
函數(shù)功能:MPU IIC 延時(shí)函數(shù)
*/
void MPU6050_IIC_Delay(void)
{
DelayUs(2);
}
/*
函數(shù)功能: 初始化IIC
*/
void MPU6050_IIC_Init(void)
{
RCC- >APB2ENR|=1< 3; //先使能外設(shè)IO PORTB時(shí)鐘
GPIOB- >CRL&=0X00FFFFFF; //PB6/7 推挽輸出
GPIOB- >CRL|=0X33000000;
GPIOB- >ODR|=3< 6; //PB6,7 輸出高
}
/*
函數(shù)功能: 產(chǎn)生IIC起始信號
*/
void MPU6050_IIC_Start(void)
{
MPU6050_SDA_OUT(); //sda線輸出
MPU6050_IIC_SDA=1;
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SDA=0;//START:when CLK is high,DATA change form high to low
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;//鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)
}
/*
函數(shù)功能: 產(chǎn)生IIC停止信號
*/
void MPU6050_IIC_Stop(void)
{
MPU6050_SDA_OUT();//sda線輸出
MPU6050_IIC_SCL=0;
MPU6050_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
MPU6050_IIC_SDA=1;//發(fā)送I2C總線結(jié)束信號
MPU6050_IIC_Delay();
}
/*
函數(shù)功能: 等待應(yīng)答信號到來
返 回 值:1,接收應(yīng)答失敗
0,接收應(yīng)答成功
*/
u8 MPU6050_IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
MPU6050_SDA_IN(); //SDA設(shè)置為輸入
MPU6050_IIC_SDA=1;MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;MPU6050_IIC_Delay();
while(MPU6050_READ_SDA)
{
ucErrTime++;
if(ucErrTime >250)
{
MPU6050_IIC_Stop();
return 1;
}
}
MPU6050_IIC_SCL=0;//時(shí)鐘輸出0
return 0;
}
/*
函數(shù)功能:產(chǎn)生ACK應(yīng)答
*/
void MPU6050_IIC_Ack(void)
{
MPU6050_IIC_SCL=0;
MPU6050_SDA_OUT();
MPU6050_IIC_SDA=0;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;
}
/*
函數(shù)功能:不產(chǎn)生ACK應(yīng)答
*/
void MPU6050_IIC_NAck(void)
{
MPU6050_IIC_SCL=0;
MPU6050_SDA_OUT();
MPU6050_IIC_SDA=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;
}
/*
函數(shù)功能:IIC發(fā)送一個(gè)字節(jié)
返回從機(jī)有無應(yīng)答
1,有應(yīng)答
0,無應(yīng)答
*/
void MPU6050_IIC_Send_Byte(u8 txd)
{
u8 t;
MPU6050_SDA_OUT();
MPU6050_IIC_SCL=0;//拉低時(shí)鐘開始數(shù)據(jù)傳輸
for(t=0;t< 8;t++)
{
MPU6050_IIC_SDA=(txd&0x80) >>7;
txd< <=1;
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;
MPU6050_IIC_Delay();
}
}
/*
函數(shù)功能:讀1個(gè)字節(jié),ack=1時(shí),發(fā)送ACK,ack=0,發(fā)送nACK
*/
u8 MPU6050_IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
MPU6050_SDA_IN();//SDA設(shè)置為輸入
for(i=0;i< 8;i++ )
{
MPU6050_IIC_SCL=0;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
receive< <=1;
if(MPU6050_READ_SDA)receive++;
MPU6050_IIC_Delay();
}
if(!ack)
MPU6050_IIC_NAck();//發(fā)送nACK
else
MPU6050_IIC_Ack(); //發(fā)送ACK
return receive;
}
/*--------------------------------------------------------------------MPU6050底層驅(qū)動(dòng)代碼--------------------------------------------------------------------------------*/
/*
函數(shù)功能:初始化MPU6050
返 回 值:0,成功
其他,錯(cuò)誤代碼
*/
u8 MPU6050_Init(void)
{
u8 res;
MPU6050_IIC_Init();//初始化IIC總線
MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //復(fù)位MPU6050
DelayMs(100);
MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //喚醒MPU6050
MPU6050_Set_Gyro_Fsr(3); //陀螺儀傳感器,±2000dps
MPU6050_Set_Accel_Fsr(0); //加速度傳感器,±2g
MPU6050_Set_Rate(50); //設(shè)置采樣率50Hz
MPU6050_Write_Byte(MPU_INT_EN_REG,0X00); //關(guān)閉所有中斷
MPU6050_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式關(guān)閉
MPU6050_Write_Byte(MPU_FIFO_EN_REG,0X00); //關(guān)閉FIFO
MPU6050_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引腳低電平有效
res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);
if(res==MPU6050_ADDR)//器件ID正確
{
MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //設(shè)置CLKSEL,PLL X軸為參考
MPU6050_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度與陀螺儀都工作
MPU6050_Set_Rate(50); //設(shè)置采樣率為50Hz
}else return 1;
return 0;
}
/*
設(shè)置MPU6050陀螺儀傳感器滿量程范圍
fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
返回值:0,設(shè)置成功
其他,設(shè)置失敗
*/
u8 MPU6050_Set_Gyro_Fsr(u8 fsr)
{
return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,fsr< 3);//設(shè)置陀螺儀滿量程范圍
}
/*
函數(shù)功能:設(shè)置MPU6050加速度傳感器滿量程范圍
函數(shù)功能:fsr:0,±2g;1,±4g;2,±8g;3,±16g
返 回 值:0,設(shè)置成功
其他,設(shè)置失敗
*/
u8 MPU6050_Set_Accel_Fsr(u8 fsr)
{
return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,fsr< 3);//設(shè)置加速度傳感器滿量程范圍
}
/*
函數(shù)功能:設(shè)置MPU6050的數(shù)字低通濾波器
函數(shù)參數(shù):lpf:數(shù)字低通濾波頻率(Hz)
返 回 值:0,設(shè)置成功
其他,設(shè)置失敗
*/
u8 MPU6050_Set_LPF(u16 lpf)
{
u8 data=0;
if(lpf >=188)data=1;
else if(lpf >=98)data=2;
else if(lpf >=42)data=3;
else if(lpf >=20)data=4;
else if(lpf >=10)data=5;
else data=6;
return MPU6050_Write_Byte(MPU_CFG_REG,data);//設(shè)置數(shù)字低通濾波器
}
/*
函數(shù)功能:設(shè)置MPU6050的采樣率(假定Fs=1KHz)
函數(shù)參數(shù):rate:4~1000(Hz)
返 回 值:0,設(shè)置成功
其他,設(shè)置失敗
*/
u8 MPU6050_Set_Rate(u16 rate)
{
u8 data;
if(rate >1000)rate=1000;
if(rate< 4)rate=4;
data=1000/rate-1;
data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,data); //設(shè)置數(shù)字低通濾波器
return MPU6050_Set_LPF(rate/2); //自動(dòng)設(shè)置LPF為采樣率的一半
}
/*
函數(shù)功能:得到溫度值
返 回 值:返回值:溫度值(擴(kuò)大了100倍)
*/
short MPU6050_Get_Temperature(void)
{
u8 buf[2];
short raw;
float temp;
MPU6050_Read_Len(MPU6050_ADDR,MPU_TEMP_OUTH_REG,2,buf);
raw=((u16)buf[0]< 8)|buf[1];
temp=36.53+((double)raw)/340;
return temp*100;;
}
/*
函數(shù)功能:得到陀螺儀值(原始值)
函數(shù)參數(shù):gx,gy,gz:陀螺儀x,y,z軸的原始讀數(shù)(帶符號)
返 回 值:0,成功,其他,錯(cuò)誤代碼
*/
u8 MPU6050_Get_Gyroscope(short *gx,short *gy,short *gz)
{
u8 buf[6],res;
res=MPU6050_Read_Len(MPU6050_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
if(res==0)
{
*gx=((u16)buf[0]< 8)|buf[1];
*gy=((u16)buf[2]< 8)|buf[3];
*gz=((u16)buf[4]< 8)|buf[5];
}
return res;;
}
/*
函數(shù)功能:得到加速度值(原始值)
函數(shù)參數(shù):gx,gy,gz:陀螺儀x,y,z軸的原始讀數(shù)(帶符號)
返 回 值:0,成功,其他,錯(cuò)誤代碼
*/
u8 MPU6050_Get_Accelerometer(short *ax,short *ay,short *az)
{
u8 buf[6],res;
res=MPU6050_Read_Len(MPU6050_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
if(res==0)
{
*ax=((u16)buf[0]< 8)|buf[1];
*ay=((u16)buf[2]< 8)|buf[3];
*az=((u16)buf[4]< 8)|buf[5];
}
return res;;
}
/*
函數(shù)功能:IIC連續(xù)寫
函數(shù)參數(shù):
addr:器件地址
reg:寄存器地址
len:寫入長度
buf:數(shù)據(jù)區(qū)
返 回 值:0,成功,其他,錯(cuò)誤代碼
*/
u8 MPU6050_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
u8 i;
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((addr< 1)|0);//發(fā)送器件地址+寫命令
if(MPU6050_IIC_Wait_Ack()) //等待應(yīng)答
{
MPU6050_IIC_Stop();
printf("等待應(yīng)答失敗rn");
return 1;
}
MPU6050_IIC_Send_Byte(reg); //寫寄存器地址
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
for(i=0;i< len;i++)
{
MPU6050_IIC_Send_Byte(buf[i]); //發(fā)送數(shù)據(jù)
if(MPU6050_IIC_Wait_Ack()) //等待ACK
{
MPU6050_IIC_Stop();
printf("等待ACK失敗rn");
return 1;
}
}
MPU6050_IIC_Stop();
return 0;
}
/*
函數(shù)功能:IIC連續(xù)寫
函數(shù)參數(shù):
IIC連續(xù)讀
addr:器件地址
reg:要讀取的寄存器地址
len:要讀取的長度
buf:讀取到的數(shù)據(jù)存儲(chǔ)區(qū)
返 回 值:0,成功,其他,錯(cuò)誤代碼
*/
u8 MPU6050_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((addr< 1)|0);//發(fā)送器件地址+寫命令
if(MPU6050_IIC_Wait_Ack()) //等待應(yīng)答
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Send_Byte(reg); //寫寄存器地址
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((addr< 1)|1);//發(fā)送器件地址+讀命令
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
while(len)
{
if(len==1)*buf=MPU6050_IIC_Read_Byte(0);//讀數(shù)據(jù),發(fā)送nACK
else *buf=MPU6050_IIC_Read_Byte(1); //讀數(shù)據(jù),發(fā)送ACK
len--;
buf++;
}
MPU6050_IIC_Stop(); //產(chǎn)生一個(gè)停止條件
return 0;
}
/*
函數(shù)功能:IIC寫一個(gè)字節(jié)
函數(shù)參數(shù):
reg:寄存器地址
data:數(shù)據(jù)
返 回 值:0,成功,其他,錯(cuò)誤代碼
*/
u8 MPU6050_Write_Byte(u8 reg,u8 data)
{
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((MPU6050_ADDR< 1)|0);//發(fā)送器件地址+寫命令
if(MPU6050_IIC_Wait_Ack()) //等待應(yīng)答
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Send_Byte(reg); //寫寄存器地址
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
MPU6050_IIC_Send_Byte(data);//發(fā)送數(shù)據(jù)
if(MPU6050_IIC_Wait_Ack()) //等待ACK
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Stop();
return 0;
}
/*
函數(shù)功能:IIC讀一個(gè)字節(jié)
函數(shù)參數(shù):
reg:寄存器地址
data:數(shù)據(jù)
返 回 值:返回值:讀到的數(shù)據(jù)
*/
u8 MPU6050_Read_Byte(u8 reg)
{
u8 res;
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((MPU6050_ADDR< 1)|0);//發(fā)送器件地址+寫命令
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
MPU6050_IIC_Send_Byte(reg); //寫寄存器地址
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((MPU6050_ADDR< 1)|1);//發(fā)送器件地址+讀命令
MPU6050_IIC_Wait_Ack(); //等待應(yīng)答
res=MPU6050_IIC_Read_Byte(0);//讀取數(shù)據(jù),發(fā)送nACK
MPU6050_IIC_Stop(); //產(chǎn)生一個(gè)停止條件
return res;
}
2.3 整體代碼框架
初始化硬件、讀取傳感器數(shù)據(jù)、計(jì)算傾斜角度并通過 OLED 顯示屏顯示結(jié)果。
#include "stm32f10x.h"
#include "mpu6050.h"
#include "oled.h"
#include "math.h"
// 常量定義
#define ALPHA 0.98 // 互補(bǔ)濾波的權(quán)重系數(shù)
#define DEG_TO_RAD(x) ((x) * 3.14159265358979 / 180.0)
// 全局變量定義
float pitch = 0.0f; // 俯仰角
float roll = 0.0f; // 滾轉(zhuǎn)角
float pitch_prev = 0.0f; // 上一周期俯仰角
float roll_prev = 0.0f; // 上一周期滾轉(zhuǎn)角
float gyroX = 0.0f, gyroY = 0.0f, gyroZ = 0.0f; // 陀螺儀數(shù)據(jù)
float accelX = 0.0f, accelY = 0.0f, accelZ = 0.0f; // 加速度計(jì)數(shù)據(jù)
float gyroXrate = 0.0f, gyroYrate = 0.0f, gyroZrate = 0.0f; // 角速度
void delay_ms(uint32_t ms);
void MPU6050_Init(void);
void ReadMPU6050(void);
void UpdateAngles(void);
void Display(void);
int main(void)
{
// 初始化硬件
SystemInit(); // 初始化系統(tǒng)時(shí)鐘
MPU6050_Init(); // 初始化MPU6050
OLED_Init(); // 初始化OLED顯示屏
while (1)
{
// 讀取MPU6050傳感器數(shù)據(jù)
ReadMPU6050();
// 更新角度數(shù)據(jù)
UpdateAngles();
// 顯示結(jié)果到OLED屏幕
Display();
}
}
// 延時(shí)函數(shù)
void delay_ms(uint32_t ms)
{
uint32_t i;
for(i = 0; i < ms * 1000; i++)
{
__NOP();
}
}
// 初始化MPU6050傳感器
void MPU6050_Init(void)
{
// 假設(shè)已經(jīng)實(shí)現(xiàn)了 I2C 初始化和MPU6050的配置
MPU6050_InitI2C(); // I2C初始化
MPU6050_Config(); // 配置MPU6050
}
// 讀取MPU6050傳感器數(shù)據(jù)
void ReadMPU6050(void)
{
// 從MPU6050讀取加速度和陀螺儀數(shù)據(jù)
accelX = (float)MPU6050_ReadAccelX(); // 讀取X軸加速度數(shù)據(jù)
accelY = (float)MPU6050_ReadAccelY(); // 讀取Y軸加速度數(shù)據(jù)
accelZ = (float)MPU6050_ReadAccelZ(); // 讀取Z軸加速度數(shù)據(jù)
gyroX = (float)MPU6050_ReadGyroX(); // 讀取X軸陀螺儀數(shù)據(jù)
gyroY = (float)MPU6050_ReadGyroY(); // 讀取Y軸陀螺儀數(shù)據(jù)
gyroZ = (float)MPU6050_ReadGyroZ(); // 讀取Z軸陀螺儀數(shù)據(jù)
// 將陀螺儀的角速度轉(zhuǎn)換為角度變化
gyroXrate = gyroX * DEG_TO_RAD(1.0f); // 角速度轉(zhuǎn)化為角度
gyroYrate = gyroY * DEG_TO_RAD(1.0f);
gyroZrate = gyroZ * DEG_TO_RAD(1.0f);
}
// 更新俯仰角和滾轉(zhuǎn)角
void UpdateAngles(void)
{
// 加速度計(jì)計(jì)算角度(靜態(tài))
float accel_pitch = atan2f(accelX, sqrtf(accelY * accelY + accelZ * accelZ)) * 180.0f / M_PI;
float accel_roll = atan2f(accelY, sqrtf(accelX * accelX + accelZ * accelZ)) * 180.0f / M_PI;
// 陀螺儀計(jì)算角度(動(dòng)態(tài))
pitch += gyroXrate * 0.01f; // 0.01f為采樣時(shí)間間隔
roll += gyroYrate * 0.01f;
// 互補(bǔ)濾波(數(shù)據(jù)融合)
pitch = ALPHA * (pitch_prev + gyroXrate * 0.01f) + (1 - ALPHA) * accel_pitch;
roll = ALPHA * (roll_prev + gyroYrate * 0.01f) + (1 - ALPHA) * accel_roll;
// 更新上一周期角度
pitch_prev = pitch;
roll_prev = roll;
}
// 顯示數(shù)據(jù)到OLED屏幕
void Display(void)
{
// 清屏
OLED_Clear();
// 顯示俯仰角(pitch)和滾轉(zhuǎn)角(roll)
OLED_ShowString(0, 0, "Pitch: ");
OLED_ShowFloat(60, 0, pitch, 2); // 顯示俯仰角,保留2位小數(shù)
OLED_ShowString(0, 2, "Roll: ");
OLED_ShowFloat(60, 2, roll, 2); // 顯示滾轉(zhuǎn)角,保留2位小數(shù)
// 顯示中心圓圈與小球可視化(此部分需根據(jù)具體顯示庫實(shí)現(xiàn))
OLED_DrawCircle(64, 32, 30); // 圓心 (64, 32),半徑 30
int ball_x = (int)(64 + 30 * sin(DEG_TO_RAD(roll)));
int ball_y = (int)(32 + 30 * sin(DEG_TO_RAD(pitch)));
OLED_DrawCircle(ball_x, ball_y, 3); // 小球,半徑3
}
- 硬件初始化 :
MPU6050_Init()
:初始化 MPU6050 傳感器。OLED_Init()
:初始化 OLED 顯示屏。
- MPU6050 數(shù)據(jù)讀取 :
ReadMPU6050()
從 MPU6050 讀取加速度計(jì)和陀螺儀數(shù)據(jù)。- 數(shù)據(jù)讀取后,轉(zhuǎn)換為設(shè)備的角速度和加速度,并存儲(chǔ)為
gyroXrate
、gyroYrate
、gyroZrate
和accelX
、accelY
、accelZ
。
- 數(shù)據(jù)融合與角度計(jì)算 :
UpdateAngles()
使用互補(bǔ)濾波算法融合加速度計(jì)和陀螺儀數(shù)據(jù),更新設(shè)備的俯仰角(pitch)和滾轉(zhuǎn)角(roll)。- 計(jì)算的俯仰角和滾轉(zhuǎn)角實(shí)時(shí)更新并用于后續(xù)顯示。
- 顯示結(jié)果 :
Display()
函數(shù)清空 OLED 屏幕并顯示俯仰角和滾轉(zhuǎn)角。它還顯示了一個(gè)可視化效果,其中包括一個(gè)圓圈和一個(gè)根據(jù)角度變化的小球。- 顯示函數(shù)
OLED_ShowFloat()
和OLED_DrawCircle()
用于顯示浮動(dòng)數(shù)字和繪制圓形。
三、總結(jié)
本項(xiàng)目設(shè)計(jì)并實(shí)現(xiàn)了一款基于 STM32F103C8T6 單片機(jī)的電子水平儀,采用 MPU6050 傳感器進(jìn)行姿態(tài)檢測,并通過 OLED 顯示屏實(shí)時(shí)展示設(shè)備的俯仰角和滾轉(zhuǎn)角。通過應(yīng)用互補(bǔ)濾波算法,項(xiàng)目有效地融合了加速度計(jì)和陀螺儀的數(shù)據(jù),提供了高效、實(shí)時(shí)且精確的角度估算,滿足了設(shè)備在動(dòng)態(tài)和靜態(tài)環(huán)境下的姿態(tài)檢測需求。
本系統(tǒng)設(shè)計(jì)具有高度的可擴(kuò)展性,可以根據(jù)不同的應(yīng)用場景進(jìn)一步優(yōu)化濾波算法、增加功能如按鍵校準(zhǔn)、低功耗優(yōu)化等。該電子水平儀不僅在電子設(shè)備的水平測量中具有廣泛應(yīng)用,還可以作為嵌入式系統(tǒng)設(shè)計(jì)中的經(jīng)典實(shí)踐,展示了如何結(jié)合傳感器數(shù)據(jù)融合、實(shí)時(shí)顯示和用戶交互。
審核編輯 黃宇
-
單片機(jī)
+關(guān)注
關(guān)注
6039文章
44579瀏覽量
636452 -
STM32F103C8T6
+關(guān)注
關(guān)注
108文章
161瀏覽量
83704
發(fā)布評論請先 登錄
相關(guān)推薦
評論