0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32單片機(jī)+MPU6050設(shè)計(jì)一個(gè)電子水平儀

DS小龍哥-嵌入式技術(shù) ? 來源:DS小龍哥-嵌入式技術(shù) ? 作者:DS小龍哥-嵌入式技 ? 2025-01-09 11:14 ? 次閱讀

一、前言

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)整和測量。

image-20241115162559398

核心的部件:

image-20241115162319901

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ī)等等。

image-20221210225339928

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é)

  1. 加速度計(jì) :用于檢測設(shè)備在 X、Y 和 Z 軸上的加速度,并通過計(jì)算設(shè)備的俯仰角和滾轉(zhuǎn)角來推算其在水平面上的傾斜角度。
  2. 陀螺儀 :用于檢測設(shè)備在各個(gè)軸上的旋轉(zhuǎn)速率,幫助系統(tǒng)在快速運(yùn)動(dòng)和變化時(shí)實(shí)時(shí)更新角度信息。
  3. 數(shù)據(jù)融合 :結(jié)合加速度計(jì)和陀螺儀的輸出數(shù)據(jù),通過傳感器融合算法(如互補(bǔ)濾波或卡爾曼濾波),獲取更為準(zhǔn)確的設(shè)備角度數(shù)據(jù)。
  4. 角度計(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
}
  1. 硬件初始化
    • MPU6050_Init():初始化 MPU6050 傳感器。
    • OLED_Init():初始化 OLED 顯示屏。
  2. MPU6050 數(shù)據(jù)讀取
    • ReadMPU6050() 從 MPU6050 讀取加速度計(jì)和陀螺儀數(shù)據(jù)。
    • 數(shù)據(jù)讀取后,轉(zhuǎn)換為設(shè)備的角速度和加速度,并存儲(chǔ)為 gyroXrate、gyroYrate、gyroZrateaccelX、accelY、accelZ
  3. 數(shù)據(jù)融合與角度計(jì)算
    • UpdateAngles() 使用互補(bǔ)濾波算法融合加速度計(jì)和陀螺儀數(shù)據(jù),更新設(shè)備的俯仰角(pitch)和滾轉(zhuǎn)角(roll)。
    • 計(jì)算的俯仰角和滾轉(zhuǎn)角實(shí)時(shí)更新并用于后續(xù)顯示。
  4. 顯示結(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í)顯示和用戶交互。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6039

    文章

    44579

    瀏覽量

    636452
  • STM32F103C8T6
    +關(guān)注

    關(guān)注

    108

    文章

    161

    瀏覽量

    83704
收藏 人收藏

    評論

    相關(guān)推薦

    基于STM32單片機(jī)+MPU6050傳感器做的載人平衡車

    基于STM32單片機(jī)+MPU6050傳感器做的載人平衡車
    發(fā)表于 01-20 15:54 ?236次下載

    三陀螺mpu6050測試程序

    MPU6050 用51單片機(jī)串口測試程序,通過1602顯示數(shù)據(jù)
    發(fā)表于 04-28 14:57 ?33次下載

    mpu6050測試程序

     InvenSense公司的三軸陀螺MPU6050測試程序。IIC接口,51單片機(jī)驅(qū)動(dòng),LCD1602同步顯示。
    發(fā)表于 11-07 14:01 ?6135次閱讀
    <b class='flag-5'>mpu6050</b>測試程序

    mpu6050怎么與單片機(jī)連接

    本文開始介紹了mpu6050的定義和mpu6050的感測范圍,其次闡述了mpu6050特征,最后介紹了mpu6050單片機(jī)的連接方法。
    發(fā)表于 03-09 08:42 ?2.7w次閱讀

    mpu6050單片機(jī)串口連接通訊實(shí)驗(yàn)資料下載

    mpu6050單片機(jī)串口連接通訊實(shí)驗(yàn)資料下載
    發(fā)表于 04-23 09:11 ?15次下載
    <b class='flag-5'>mpu6050</b>與<b class='flag-5'>單片機(jī)</b>串口連接通訊實(shí)驗(yàn)資料下載

    使用MSP430單片機(jī)應(yīng)用MPU6050陀螺的程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用MSP430單片機(jī)應(yīng)用MPU6050陀螺的程序免費(fèi)下載。
    發(fā)表于 07-24 16:03 ?70次下載

    如何使用STM32單片機(jī)的硬件I2C讀取MPU6050的數(shù)據(jù)資料和程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是如何使用STM32單片機(jī)的硬件I2C讀取MPU6050的數(shù)據(jù)資料和程序免費(fèi)下載。
    發(fā)表于 07-25 17:31 ?0次下載
    如何使用<b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b>的硬件I2C讀取<b class='flag-5'>MPU6050</b>的數(shù)據(jù)資料和程序免費(fèi)下載

    使用STM32單片機(jī)讀取MPU6050傳感器數(shù)據(jù)的程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用STM32單片機(jī)讀取MPU6050傳感器數(shù)據(jù)的程序免費(fèi)下載。
    發(fā)表于 07-26 17:35 ?61次下載
    使用<b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b>讀取<b class='flag-5'>MPU6050</b>傳感器數(shù)據(jù)的程序免費(fèi)下載

    MPU6050單片機(jī)通訊的C語言源碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是MPU6050單片機(jī)通訊的C語言源碼免費(fèi)下載。
    發(fā)表于 09-09 17:15 ?34次下載
    <b class='flag-5'>MPU6050</b>與<b class='flag-5'>單片機(jī)</b>通訊的C語言源碼免費(fèi)下載

    MPU6050簡介

    MPU6050簡介什么是MPU6050MPU6050的特點(diǎn)MPU6050框圖MPU6050初始化MPU6050—DMP使用介紹
    發(fā)表于 12-06 11:51 ?76次下載
    <b class='flag-5'>MPU6050</b>簡介

    MPU6050常見問題的分析與處理

    # MPU6050常見問題的分析與處理本文主要針對STM32使用MPU6050過程中產(chǎn)生的問題進(jìn)行分析和處理,部分內(nèi)容也適用于其他單片機(jī)。本文基于M
    發(fā)表于 12-06 12:21 ?43次下載
    <b class='flag-5'>MPU6050</b>常見問題的分析與處理

    STM32獲取MPU6050數(shù)據(jù)

    STM32獲取MPU6050數(shù)據(jù)
    發(fā)表于 12-06 13:06 ?55次下載
    <b class='flag-5'>STM32</b>獲取<b class='flag-5'>MPU6050</b>數(shù)據(jù)

    STM32讀取MPU6050陀螺芯片數(shù)據(jù)核心程序

    MPU6050芯片數(shù)據(jù)的。想要讀取MPU6050芯片,其實(shí)就是通過IIC去操作讀取寄存器。大致過程就是STM32MPU6050先建立好IIC通訊。再去初始化
    發(fā)表于 12-06 14:06 ?12次下載
    <b class='flag-5'>STM32</b>讀取<b class='flag-5'>MPU6050</b>陀螺<b class='flag-5'>儀</b>芯片數(shù)據(jù)核心程序

    STM32F407ZE開發(fā)板MPU6050陀螺的應(yīng)用

    STM32F407ZE開發(fā)板MPU6050陀螺的應(yīng)用
    發(fā)表于 12-06 14:36 ?11次下載
    <b class='flag-5'>STM32</b>F407ZE開發(fā)板<b class='flag-5'>MPU6050</b>陀螺<b class='flag-5'>儀</b>的應(yīng)用

    STM32 MPU6050 平衡車

    STM32 MPU6050 平衡車
    發(fā)表于 12-06 14:51 ?63次下載
    <b class='flag-5'>STM32</b> <b class='flag-5'>MPU6050</b> 平衡車