一、前言
1.1 項目介紹
【1】項目開發(fā)背景
隨著社會節(jié)奏的加快和人們生活方式的改變,智能家居產(chǎn)品逐漸走入千家萬戶。作為智能清潔系統(tǒng)的重要組成部分,掃地機器人憑借其自動化、高效性和便捷性,成為現(xiàn)代家庭中不可或缺的智能設備之一。傳統(tǒng)人工清潔方式費時費力,尤其對于老年人、上班族而言,日常清掃負擔較重,因此急需一種智能化、自動化的解決方案來提升生活質(zhì)量。
掃地機器人結合了嵌入式控制、傳感器技術、路徑規(guī)劃算法以及無線通信等多種現(xiàn)代技術,實現(xiàn)了自動避障、智能清掃、自動回充等功能,體現(xiàn)了智能控制與人機交互的發(fā)展趨勢。隨著MCU芯片和傳感器技術的不斷成熟,開發(fā)一套基于STM32微控制器的掃地機器人系統(tǒng),既具有良好的技術實現(xiàn)基礎,又能滿足用戶對于清潔智能化的迫切需求。
本項目通過STM32系列單片機構建一個功能完善、成本適中、實用性強的智能掃地機器人系統(tǒng)。通過軟硬件協(xié)同設計,實現(xiàn)路徑規(guī)劃、灰塵識別、跌落保護、遠程控制等關鍵功能,提升機器人在不同家庭場景下的清掃效率和安全性。項目不僅具有較強的應用價值,同時也為智能機器人技術的學習與研究提供了實踐平臺。
【2】設計實現(xiàn)的功能
(1)采用紅外避障傳感器和超聲波測距模塊實現(xiàn)自動避障功能,能夠在復雜環(huán)境中自動繞開障礙物。
(2)利用實時時鐘RTC模塊實現(xiàn)定時清掃功能,按設定時間自動啟動清掃任務。
(3)結合MPU6050姿態(tài)傳感器與編碼器反饋實現(xiàn)路徑規(guī)劃與完整覆蓋式清掃,提高清掃效率。
(4)通過紅外跌落傳感器檢測地面邊緣,實時進行邊緣檢測并防止機器人跌落。
(5)通過ESP8266模塊實現(xiàn)WIFI通信,支持手機APP進行手動遙控操作與遠程控制。
(6)由STM32主控處理清掃路徑并生成清掃地圖,上傳至APP實現(xiàn)簡易地圖繪制功能。
(7)灰塵識別模塊檢測空氣中粉塵濃度,在污染區(qū)域啟動重點清掃機制。
(8)利用DFPlayer Mini語音模塊實現(xiàn)語音提示功能,用于狀態(tài)播報與故障提醒。
(9)使用0.96寸OLED屏幕顯示當前清掃狀態(tài)、電量信息和系統(tǒng)參數(shù),方便本地查看。
(10)通過電壓檢測模塊監(jiān)測電池電量,并結合紅外尋跡模塊實現(xiàn)自動回充功能。
(11)ESP8266模塊通過MQTT協(xié)議與服務器通信,實現(xiàn)清掃狀態(tài)與控制指令的聯(lián)網(wǎng)功能。
(12)Android APP平臺支持清掃進度查看、路徑顯示、電量查詢、遠程啟動/停止等控制功能。
【3】項目硬件模塊組成
(1)主控芯片:STM32F103RCT6,作為系統(tǒng)核心控制器,負責傳感器數(shù)據(jù)處理、運動控制與通信管理。
(2)驅動電機:2個帶編碼器的TT減速直流電機,用于驅動機器人前進、后退、轉向等移動動作。
(3)電機驅動模塊:L298N雙路直流電機驅動模塊,實現(xiàn)對左右驅動電機的正反轉與調(diào)速控制。
(4)紅外避障傳感器:3個TCRT5000模塊,分別安裝在機器人前方與左右側,用于檢測障礙物。
(5)超聲波測距模塊:1個HC-SR04模塊,用于精確測量前方障礙物距離。
(6)紅外跌落傳感器:3個TCRT5000模塊,安裝在機器人底部前端及兩側,用于檢測地面是否存在,防止跌落。
(7)姿態(tài)檢測模塊:1個MPU6050六軸陀螺儀+加速度計模塊,用于獲取機器人運動姿態(tài)和角度變化。
(8)灰塵識別模塊:GP2Y1010AU0F光學粉塵傳感器,用于檢測空氣中灰塵濃度,實現(xiàn)重點清掃。
(9)語音模塊:DFPlayer Mini音頻模塊,配合揚聲器實現(xiàn)語音播報與提示功能。
(10)顯示模塊:0.96寸SPI接口OLED顯示屏(SSD1306驅動),用于顯示清掃狀態(tài)、電量等信息。
(11)通信模塊:ESP8266 WiFi模塊(NodeMCU),通過串口與STM32通信,實現(xiàn)與APP的數(shù)據(jù)交互。
(12)電源系統(tǒng):7.4V 18650鋰電池組,配合升壓模塊為系統(tǒng)提供5V/9V穩(wěn)定電源。
(13)電壓檢測模塊:電壓分壓采集模塊,用于檢測電池電壓,實現(xiàn)電量監(jiān)測。
(14)自動回充模塊:紅外接收模塊配合充電座紅外發(fā)射器,實現(xiàn)機器人自動返回充電座。
(15)實時時鐘模塊:DS3231高精度RTC模塊,用于實現(xiàn)定時清掃功能。
(16)APP平臺:基于Android系統(tǒng)的手機APP,使用Qt(C++)開發(fā),提供遠程控制與狀態(tài)監(jiān)控功能。
(17)車體結構:亞克力底盤、萬向輪與支撐結構,固定并承載各模塊與電路系統(tǒng)。
(18)吸塵模塊:5V高速風扇與滾刷組合,實現(xiàn)地面灰塵與顆粒物的有效吸附與清潔。
【4】設計意義
本項目基于STM32設計的掃地機器人系統(tǒng),旨在利用嵌入式系統(tǒng)和多傳感器融合技術,構建一套具備基本智能清掃能力的自動化清潔設備。通過項目的設計與實現(xiàn),不僅能夠減輕用戶日常清潔的勞動負擔,還可以提高清潔效率與覆蓋率,為家庭智能化建設提供實用的技術支持和硬件基礎。
項目集成了自動避障、路徑規(guī)劃、定時清掃、防跌落、語音提示、自動回充、APP遠程控制等功能模塊,充分體現(xiàn)了現(xiàn)代嵌入式系統(tǒng)在智能家居中的實際應用價值。通過合理的模塊選型與軟硬件協(xié)同開發(fā),系統(tǒng)在穩(wěn)定性、實用性、用戶交互體驗等方面都達到了較高水平,具備良好的工程實現(xiàn)與應用推廣基礎。
本項目的實施不僅為實際家庭場景中的清潔工作提供了解決方案,也為學習和掌握STM32平臺的開發(fā)技術、傳感器集成應用、路徑算法設計、無線通信協(xié)議以及多線程邏輯管理等關鍵技術提供了一個完整的綜合性平臺,具有較強的教學實踐和工程訓練價值。
【5】市面上同類產(chǎn)品研究現(xiàn)狀
目前市面上的掃地機器人產(chǎn)品已較為成熟,主要品牌包括iRobot的Roomba系列、石頭科技的石頭掃地機器人、小米米家掃地機器人等。這些產(chǎn)品普遍具備自動避障、路徑規(guī)劃、邊緣檢測和自動回充等核心功能,體現(xiàn)了智能清掃設備的發(fā)展趨勢。
iRobot Roomba系列通過多傳感器融合和先進的SLAM(同步定位與地圖構建)算法,實現(xiàn)精準地圖繪制和高效路徑規(guī)劃,能夠適應復雜家庭環(huán)境,實現(xiàn)無遺漏清掃。其采用多點激光測距和視覺傳感技術,配合強大的云端算法,提供用戶友好的APP遠程控制及語音交互功能。
石頭科技的掃地機器人注重激光雷達(LIDAR)導航技術,配合高精度陀螺儀和多組紅外傳感器,實現(xiàn)快速環(huán)境感知與障礙物避讓。該系列產(chǎn)品支持房間分區(qū)清掃及定時預約,用戶可通過手機APP查看實時地圖和清掃進度,增強使用體驗。
小米米家掃地機器人則采用了激光導航與視覺傳感的結合,具備強大的智能路徑規(guī)劃和避障能力。通過手機APP實現(xiàn)遠程啟動、停止及清掃模式切換,并集成語音助手控制功能,滿足現(xiàn)代智能家居需求。
綜上,當前主流掃地機器人均注重傳感器融合、智能路徑規(guī)劃與用戶交互體驗的提升,形成了較為完善的產(chǎn)品生態(tài)。本項目結合STM32平臺和多種傳感器,實現(xiàn)基礎功能的同時,也為低成本智能清掃設備的開發(fā)提供了可行的參考方案。
【6】摘要
基于STM32的掃地機器人項目,設計并實現(xiàn)了一套集自動避障、路徑規(guī)劃、邊緣檢測、防跌落、定時清掃、語音提示、自動回充及遠程APP控制于一體的智能清掃系統(tǒng)。系統(tǒng)采用STM32F103RCT6作為主控芯片,結合多種傳感器模塊實現(xiàn)環(huán)境感知與智能決策,通過ESP8266實現(xiàn)無線通信與遠程控制。該機器人能夠高效完成地面無遺漏清掃,保障運行安全,提高用戶使用便捷性和生活質(zhì)量。項目驗證了嵌入式系統(tǒng)與傳感器融合技術在智能家居領域的應用價值,具備良好的工程實用性和推廣前景。
關鍵字:STM32,掃地機器人,路徑規(guī)劃,自動避障,邊緣檢測,ESP8266,遠程控制
1.2 設計思路
本項目設計基于STM32F103RCT6微控制器,充分利用其豐富的接口和較強的處理能力作為系統(tǒng)核心。設計思路以多傳感器融合為基礎,通過紅外避障傳感器和超聲波測距模塊實現(xiàn)環(huán)境感知,保障機器人能夠實時識別障礙物并進行繞行。結合MPU6050姿態(tài)傳感器和編碼器數(shù)據(jù),實現(xiàn)路徑規(guī)劃與運動控制,確保機器人能夠高效完成地面覆蓋式清掃。
為了保證運行安全,設計采用多個紅外跌落傳感器進行邊緣檢測,有效防止機器人跌落樓梯或其他高差處。系統(tǒng)通過實時電壓檢測與紅外尋跡模塊實現(xiàn)低電量自動回充功能,提升使用便捷性和續(xù)航能力。語音模塊的集成則用于狀態(tài)提示和故障報警,增強人機交互體驗。
通信方面,設計采用ESP8266無線模塊,配合MQTT協(xié)議,實現(xiàn)機器人與手機APP的遠程數(shù)據(jù)交互和控制,使用戶能夠實時監(jiān)控清掃狀態(tài)并進行遠程操作。整體設計采用模塊化開發(fā)思路,硬件選型合理,軟件結構清晰,保證系統(tǒng)的穩(wěn)定性和易維護性,滿足智能家居對掃地機器人高效、智能、安全的使用需求。
1.3 系統(tǒng)功能總結
功能模塊 | 功能描述 | 主要硬件模塊 | 關鍵技術/實現(xiàn)方式 |
---|---|---|---|
自動避障 | 識別并繞開前方及側方障礙物 | 紅外避障傳感器(3個)、超聲波模塊 | 紅外與超聲波傳感器融合檢測 |
定時清掃 | 按設定時間自動啟動清掃任務 | DS3231 RTC模塊 | 實時時鐘定時觸發(fā) |
路徑規(guī)劃與覆蓋 | 實現(xiàn)地面無遺漏的覆蓋式清掃 | MPU6050、編碼器 | 姿態(tài)檢測+編碼器數(shù)據(jù),路徑規(guī)劃算法 |
邊緣檢測與防跌落 | 檢測地面邊緣,防止機器人跌落 | 紅外跌落傳感器(3個) | 紅外傳感器實時檢測邊緣 |
手動遙控 | 通過手機APP遠程控制機器人 | ESP8266 WiFi模塊 | WIFI通信+MQTT協(xié)議 |
地圖繪制 | 生成簡易的房間清掃路徑圖 | STM32主控、傳感器數(shù)據(jù)處理 | 算法生成路徑地圖,上傳APP |
灰塵識別與重點清掃 | 檢測灰塵濃度,針對高灰塵區(qū)域加強清掃 | GP2Y1010光學粉塵傳感器 | 模擬信號采集與閾值判定 |
語音播報 | 語音提示工作狀態(tài)和故障信息 | DFPlayer Mini音頻模塊 | 語音模塊控制播放 |
OLED顯示 | 實時顯示清掃狀態(tài)、電量及系統(tǒng)參數(shù) | 0.96寸OLED顯示屏(SSD1306) | SPI通信顯示信息 |
自動回充 | 低電量時自動返回充電座充電 | 電壓檢測模塊、紅外尋跡模塊 | 電量監(jiān)測+紅外尋跡定位 |
WIFI聯(lián)網(wǎng) | 實現(xiàn)遠程監(jiān)控與控制 | ESP8266 WiFi模塊 | WIFI通信與云端MQTT協(xié)議 |
APP遠程控制 | 遠程查看機器人狀態(tài),控制啟動、停止及路徑等功能 | 手機APP、ESP8266模塊 | APP界面設計與無線數(shù)據(jù)交互 |
1.4 開發(fā)工具的選擇
【1】設備端開發(fā)
硬件設備端的開發(fā)主要依賴于C語言,利用該語言直接操作硬件寄存器,確保系統(tǒng)運行的高效性和低延遲。C語言在嵌入式開發(fā)中具有廣泛的應用,它能夠直接訪問硬件,滿足對資源消耗和響應速度的嚴格要求。為了編寫高效、穩(wěn)定的代碼,開發(fā)工具選擇了Keil uVision 5作為主要的開發(fā)環(huán)境。Keil是一個專業(yè)的嵌入式開發(fā)工具,廣泛應用于基于ARM架構的微控制器(如STM32)開發(fā)。Keil提供了完善的調(diào)試、編譯和仿真支持,能夠幫助在軟件開發(fā)過程中高效地進行調(diào)試、單步執(zhí)行以及斷點設置,確保開發(fā)的穩(wěn)定性和高效性。
STM32F103RCT6是項目中使用的主控芯片,它基于ARM Cortex-M3架構,擁有強大的計算能力和豐富的外設接口。在硬件編程中,寄存器級編程是常用的方式,這要求開發(fā)者對芯片的硬件寄存器有深入的理解。在Keil環(huán)境中,通過STM32的寄存器直接控制GPIO、ADC、I2C、SPI等硬件接口,以滿足各個硬件模塊(如傳感器、執(zhí)行器、顯示屏等)與主控芯片的交互。使用寄存器編程能夠提供更高效、精確的控制,避免了外部庫的開銷,同時也能深入調(diào)控硬件特性,提升系統(tǒng)性能。
【2】上位機開發(fā)
本項目的上位機開發(fā)基于Qt 5框架,使用**C++**作為主要編程語言。Qt是一個跨平臺的應用開發(fā)框架,廣泛用于開發(fā)GUI應用程序。Qt提供了豐富的GUI組件和工具,能夠高效地實現(xiàn)圖形界面的設計與開發(fā)。C++則作為Qt的底層語言,具有高效的性能和良好的控制力,非常適合用于處理設備與系統(tǒng)之間的數(shù)據(jù)交互、通信協(xié)議的實現(xiàn)和復雜的計算任務。在項目中,Qt被用于開發(fā)Windows平臺的桌面應用程序以及Android平臺的手機APP。Qt框架的跨平臺特性使得開發(fā)者能夠使用同一套代碼在不同操作系統(tǒng)上進行構建和部署,大大提高了開發(fā)效率。
為了方便開發(fā)和調(diào)試,上位機的開發(fā)采用了Qt Creator作為主要的集成開發(fā)環(huán)境(IDE)。Qt Creator是一款由Qt官方提供的開發(fā)工具,專為Qt應用程序開發(fā)設計,支持C++、QML和JavaScript等語言。Qt Creator提供了豐富的功能,如代碼編輯、調(diào)試、構建、版本控制集成等,能夠顯著提升開發(fā)者的生產(chǎn)力。在本項目中,Qt Creator為開發(fā)者提供了自動化構建、界面設計工具(如Qt Designer)和調(diào)試工具(如QDebug和QML調(diào)試工具),使得開發(fā)過程更加高效和流暢。
上位機與硬件設備端的通信采用了基于TCP/IP協(xié)議的數(shù)據(jù)傳輸方式。為了實現(xiàn)這一功能,Qt提供了豐富的網(wǎng)絡編程支持,尤其是QTcpSocket和QTcpServer類,使得上位機能夠輕松地與硬件設備建立TCP連接,進行數(shù)據(jù)收發(fā)。上位機通過WIFI連接ESP8266-WIFI模塊,ESP8266模塊創(chuàng)建TCP服務器,上位機應用則作為客戶端連接到服務器,進行實時的數(shù)據(jù)傳輸與控制命令的下發(fā)。
為了滿足不同用戶的需求,本項目需要支持Windows平臺的桌面應用和Android平臺的移動APP。Qt的跨平臺特性使得開發(fā)人員能夠在一個代碼庫下完成多平臺應用的開發(fā)和移植。開發(fā)者僅需要編寫一次應用邏輯和用戶界面,就可以通過Qt的跨平臺構建工具生成Windows和Android兩個平臺的可執(zhí)行文件。此外,Qt提供了豐富的文檔和社區(qū)支持,幫助開發(fā)者解決平臺差異和兼容性問題,確保應用在不同平臺上都能穩(wěn)定運行。
總體而言,上位機開發(fā)環(huán)境采用了Qt 5框架和C++語言,結合Qt Creator集成開發(fā)環(huán)境,提供了一個高效、穩(wěn)定、跨平臺的開發(fā)工具鏈。通過Qt強大的GUI設計、網(wǎng)絡通信、多線程支持以及數(shù)據(jù)庫管理功能,開發(fā)者能夠輕松實現(xiàn)與硬件設備的交互、控制設備、處理傳感器數(shù)據(jù),并為用戶提供直觀、流暢的操作體驗。
二、算法設計
2.1 算法設計思路
本項目采用柵格地圖法(Grid Map)+螺旋清掃+墻邊跟隨相結合的方式,實現(xiàn)高效率覆蓋清掃。
(1)地圖構建
- 將房間劃分為二維柵格地圖,每個格子表示20cm × 20cm的面積(實際可調(diào)整)
- 格子狀態(tài):0=未清掃,1=已清掃,2=障礙物
(2)基本策略
- 默認從左上角或充電座位置開始清掃
- 采用螺旋清掃 + Z字形遍歷 + 遇墻回轉機制,提升效率
- 實時更新當前位置和地圖信息
- 編碼器與MPU6050配合,進行位置估算(簡化SLAM)
(3)避障融合
- 在路徑規(guī)劃過程中融合超聲波+紅外避障模塊,對障礙進行打標(記為2)
(4)完成判斷
- 所有柵格=1(已清掃)時清掃結束,進入回充狀態(tài)
2.2 核心模塊算法流程圖
flowchart TD
A[初始化柵格地圖] --> B[定位當前位置(x,y)]
B --> C[標記當前位置已清掃]
C --> D[查找下一個可清掃鄰格]
D -->|存在| E[規(guī)劃方向移動]
D -->|無| F[回退/掉頭/回充]
E --> G[檢測障礙]
G -->|無障礙| H[移動到新位置]
G -->|有障礙| I[標記障礙格,換方向]
H --> B
I --> B
F --> J[全部完成 -> 回充]
2.3 STM32簡化路徑規(guī)劃算法代碼(偽代碼 + 可移植C代碼)
1. 柵格地圖結構定義
#define MAP_SIZE_X 20
#define MAP_SIZE_Y 20
#define CELL_UNVISITED 0
#define CELL_VISITED 1
#define CELL_OBSTACLE 2
uint8_t map[MAP_SIZE_Y][MAP_SIZE_X]; // 2D 柵格地圖
int current_x = 0;
int current_y = 0;
int direction = 0; // 0=上,1=右,2=下,3=左
2. 標記當前位置已清掃
void mark_visited(int x, int y) {
if (x >= 0 && x < MAP_SIZE_X && y >= 0 && y < MAP_SIZE_Y) {
map[y][x] = CELL_VISITED;
}
}
3. 查找下一個可清掃格子(四方向)
int dx[4] = {0, 1, 0, -1}; // 上右下左
int dy[4] = {-1, 0, 1, 0};
int find_next_direction() {
for (int i = 0; i < 4; i++) {
int nx = current_x + dx[i];
int ny = current_y + dy[i];
if (nx >= 0 && nx < MAP_SIZE_X && ny >= 0 && ny < MAP_SIZE_Y) {
if (map[ny][nx] == CELL_UNVISITED) {
return i;
}
}
}
return -1; // 無可清掃方向
}
4. 移動函數(shù)(偽動作控制)
void move_to(int dir) {
// 電機控制部分略(根據(jù)dir控制左右輪轉速方向)
current_x += dx[dir];
current_y += dy[dir];
mark_visited(current_x, current_y);
}
5. 主控制循環(huán)(主邏輯)
void clean_room() {
mark_visited(current_x, current_y); // 初始位置
while (1) {
int next_dir = find_next_direction();
if (next_dir == -1) {
// 所有方向均已訪問或是障礙,嘗試回退或結束
if (all_cleaned()) {
return_to_charge(); // 所有清掃完成
break;
} else {
rotate_90(); // 更換方向
continue;
}
}
if (!is_obstacle(current_x + dx[next_dir], current_y + dy[next_dir])) {
move_to(next_dir);
} else {
map[current_y + dy[next_dir]][current_x + dx[next_dir]] = CELL_OBSTACLE;
}
}
}
6. 判斷是否清掃完畢
int all_cleaned() {
for (int y = 0; y < MAP_SIZE_Y; y++) {
for (int x = 0; x < MAP_SIZE_X; x++) {
if (map[y][x] == CELL_UNVISITED) return 0;
}
}
return 1;
}
2.4 邊緣檢測與防跌落功能算法設計過程
1. 傳感器選型
采用 3個 TCRT5000 紅外反射式跌落檢測傳感器 安裝于機器人底部前端和左右兩側,用于檢測地面是否存在反射(白色地面為反射,懸空為無反射)。
2. 原理說明
- TCRT5000發(fā)射紅外光并接收反射光,若有地面反射回紅外光,則表示有地面;
- 若前方/左側/右側無反射光(即信號電平改變),則判定為“邊緣”或“懸空”,觸發(fā)防跌落動作。
3. 傳感器安裝建議
- 每個TCRT5000傳感器對應一個檢測區(qū)域:
- 前部傳感器:防止前進跌落
- 左側/右側傳感器:防止側滑跌落
- 建議安裝高度約為 0.8~1.2cm,距離地面
4. 防跌落處理機制
- 一旦某個傳感器檢測為無地面(懸空):
- 立即停止所有電機
- 后退一小段距離
- 左/右轉避開邊緣
- 重新進入正常清掃邏輯
2.5 STM32 防跌落算法設計(代碼實現(xiàn))
(1)接口定義與引腳配置(示例使用 GPIO 輸入)
假設連接如下:
- 前TCRT5000 —— GPIOA PIN0
- 左TCRT5000 —— GPIOA PIN1
- 右TCRT5000 —— GPIOA PIN2
#define SENSOR_FRONT HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)
#define SENSOR_LEFT HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)
#define SENSOR_RIGHT HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2)
- TCRT5000輸出為 低電平表示地面存在,高電平表示無地面/懸空
(2)初始化 GPIO 輸入
void TCRT5000_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
(3)檢測邊緣函數(shù)
uint8_t is_edge_detected(void)
{
if (SENSOR_FRONT == GPIO_PIN_SET ||
SENSOR_LEFT == GPIO_PIN_SET ||
SENSOR_RIGHT == GPIO_PIN_SET)
{
return 1; // 檢測到邊緣
}
return 0; // 正常地面
}
(4)防跌落動作處理函數(shù)
void handle_fall_protection(void)
{
stop_motors(); // 停止所有電機
delay_ms(200); // 稍作停頓
move_backward(); // 后退一小段
delay_ms(500);
turn_right(); // 隨機右轉避開邊緣
delay_ms(400);
stop_motors();
}
(5)集成進主循環(huán)
void main_loop(void)
{
while (1)
{
if (is_edge_detected())
{
handle_fall_protection(); // 邊緣檢測觸發(fā)處理
continue;
}
clean_forward(); // 正常前進清掃
delay_ms(100);
}
}
三、Qt開發(fā)入門與環(huán)境搭建
當前項目的上位機是采用Qt開發(fā)的,這一章節(jié)主要是介紹Qt開發(fā)環(huán)境的安裝,以及Qt開發(fā)環(huán)境入門的使用。如果你Qt沒有任何基礎,建議仔細看一遍。
3.1 Qt是什么?
Qt 是一個功能強大、跨平臺的應用程序開發(fā)框架,主要用于創(chuàng)建圖形用戶界面(GUI)應用程序,但它不僅僅局限于GUI編程。它由挪威的奇趣科技(TrollTech)最初于1991年開發(fā),并在后續(xù)的發(fā)展歷程中經(jīng)歷了多次所有權變更,包括諾基亞和Digia等公司接手,現(xiàn)在Qt屬于The Qt Company所有。
Qt 主要特點和優(yōu)勢包括:
(1)跨平臺:Qt 支持多種操作系統(tǒng),開發(fā)者可以使用同一份源代碼在不同平臺上編譯運行,如Windows、Linux、macOS、Android以及各種嵌入式系統(tǒng)(如RTOS),實現(xiàn)“一次編寫,到處編譯”。
(2)C++ 開發(fā):Qt 的核心是基于C++編程語言構建,提供了一套豐富的類庫,通過面向對象的設計方式簡化了開發(fā)過程。
(3)圖形用戶界面:Qt 提供了完整的GUI組件集,包含窗口、按鈕、標簽、文本框等各種標準控件,以及布局管理器、樣式表等功能,使得開發(fā)者能夠高效地創(chuàng)建美觀且功能完善的桌面應用或移動應用界面。
(4)工具鏈完整:Qt 包含一系列集成開發(fā)環(huán)境(IDE)和輔助工具,例如Qt Creator是一個全能的跨平臺IDE,Qt Designer用于可視化拖拽設計UI界面,Qt Linguist支持國際化資源文件的翻譯,還有Qt Assistant和大量文檔資源方便開發(fā)者的使用。
(5)非GUI功能豐富:除了GUI功能外,Qt 還提供了眾多非圖形化功能模塊,如網(wǎng)絡通信、數(shù)據(jù)庫訪問、XML處理、多媒體處理(音頻視頻)、文件I/O、線程與并發(fā)處理、OpenGL和3D圖形渲染等。
(6)元對象系統(tǒng):Qt 使用元對象系統(tǒng)(Meta-Object System, MOC)實現(xiàn)了信號與槽機制(Signals and Slots),這是一種高級事件處理機制,允許在不同對象之間安全地進行異步通信。
(7)可擴展性與靈活性:Qt 架構高度靈活,支持插件體系結構,開發(fā)者可以根據(jù)需要自定義組件并輕松地集成到Qt應用中。
Qt 以其強大的跨平臺能力和全面的功能集合成為許多企業(yè)和個人開發(fā)者選擇用來開發(fā)高性能、高穩(wěn)定性的應用程序的重要工具之一,被廣泛應用于各類桌面軟件、嵌入式設備、移動應用以及服務器端組件等領域。
3.2 Qt版本介紹
在Qt發(fā)行版本中將要涉及兩個版本:Qt商業(yè)授權和Qt開源授權。
(1)Qt商業(yè)授權是設計商業(yè)軟件的開發(fā)環(huán)境,這些商業(yè)軟件使用了傳統(tǒng)的商業(yè)來發(fā)布,它包含了一些更新的功能、技術上的支持和大量的解決方案,開發(fā)了使用于行業(yè)的一些特定的組件,有一些特殊的功能只在商業(yè)用戶中使用。
(2)Qt開源授權是用來開發(fā)開源的軟件,它提供了一些免費的支持,并遵循QPL協(xié)議。
開放源代碼是免費的軟件,不牽涉用戶的某些權益。任何人都有使用開源軟件和參與它的修改的機會,這就意味著其他的人同樣可獲得你開發(fā)的代碼。目前 Qt 的開源授權有兩種,一種是 GPL 授權,另一種是 LGPL 授權。
3.3 Qt開發(fā)環(huán)境安裝
Qt的中文官網(wǎng): https://www.qt.io/zh-cn/
QT5.12.6的下載地址:https://download.qt.io/archive/qt/5.12/5.12.6
打開下載鏈接后選擇下面的版本進行下載:
qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details
軟件安裝時斷網(wǎng)安裝,否則會提示輸入賬戶。
如果下載不了,可以在網(wǎng)盤里找到安裝包下載: 飛書文檔記錄的網(wǎng)盤地址:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
安裝的時候,第一個復選框里勾選一個mingw 32
編譯器即可,其他的不管默認就行,直接點擊下一步繼續(xù)安裝。
選擇MinGW 32-bit 編譯器:
3.4 開發(fā)第一個QT程序
在QT開發(fā)過程中,可以手動編寫代碼也可以使用UI設計師直接拖拽控件的方式編寫界面和布局,在實際的開發(fā)過程中一般是兩種方式結合使用,提高開發(fā)效率。
本小節(jié)用一個簡單的 “Hello QT” 程序介紹一下使用QtCreator新建工程的步驟。
(1)打開QtCreator軟件,選擇New Project,新建一個工程。
(2)項目模板選擇QT Widgets Application
(3)設置項目名稱和存放路徑
注意:QT項目路徑和名稱不能出現(xiàn)中文字符。
(4)編譯工具套件選擇
編譯工具套件可以后面自己增加,比如增加Android的。套件是指 Qt 程序從編譯鏈接到運行環(huán)境的全部工具和 Qt 類庫的集合。
(5)設置生成的類信息
在類信息設置界面選擇基類,目前有三種基類:QMainWindow,QWidget,QDialog。在基類里選擇QMainWindow,類名和文件名會根據(jù)基類自動修改,一般不需要修改,默認即可。
(6)項目管理
在項目管理界面可以設置作為子項目,以及加入版本控制系統(tǒng)。這兩個功能暫時用不到,都用默認的 ,然后點擊 “完成”。
(7)創(chuàng)建完成
(8) 編輯代碼
展開main.cpp文件,添加內(nèi)容如下:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//MainWindow w;
//w.show();
QLabel *label =new QLabel("Hello Qt!");
label->setGeometry(400,100,100,20);
label->show();
return a.exec();
}
代碼解析:
1) #include <QApplication>和 #include <QLabel>是QT的類聲明頭文件,對于每個QT類都有一個與該類同名的頭文件,在這個頭文件包含了對該類的定義。
2) main(int argc, char *argv[]) :main函數(shù)的標準寫法。
3) QApplication a(argc, argv):創(chuàng)建一個QApplication對象,用于管理應用程序的資源,QApplication類的構造函數(shù)需要兩個參數(shù)。
4) QLabel *label =new QLabel("Hello Qt!") :創(chuàng)建QLabel窗口部件,QLabel是一個Qt提供的窗口部件,可以用來顯示一行文本。
5) label->setGeometry(400,100,100,20) : 設置控件顯示的位置。
6) label->show():使Qlabel創(chuàng)建的窗口可見,就是顯示設置的文本。
7) return a.exec():應用程序將控制權傳遞給QT,讓程序進入消息循環(huán)。等待可能的菜單,工具條,鼠標等的輸入,進行響應。
(9)行程序
運行程序可以點擊左下角的三角形符號或者按下快捷鍵Ctrl+R。
3.5 調(diào)試輸出
QT中使用QDebug類輸出調(diào)試信息。主要用于調(diào)試代碼,類似于std::cout的替代品,支持QT的數(shù)據(jù)類型。使用前需要包含頭文件。
調(diào)試輸出的分類
qDebug | 調(diào)試信息提示 |
---|---|
qWarning | 一般的警告提示 |
qCritical | 嚴重錯誤提示 |
qFatal | 致命錯誤提示 |
示例代碼:
qDebug("調(diào)試信息輸出");
qWarning("一般警告信息輸出");
qCritical("嚴重錯誤輸出");
qFatal("致命錯誤輸出");
qDebug輸出的信息會打印到QT軟件下邊的輸出面板。
在上節(jié)的HelloQt工程上加上調(diào)試輸出代碼,增加的main.cpp代碼如下:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//MainWindow w;
//w.show();
qDebug()<<"QT調(diào)試信息輸出";
int data_int=8888;
qDebug()<<data_int;
float data_float=123.888;
qDebug()<<data_float;
return a.exec();
}
運行程序,觀察輸出的調(diào)試信息:
3.6 QT Creator常用的快捷鍵
掌握一些適用的快捷鍵,可以提高程序開發(fā)的效率。
(1)F1 鍵,快速切換光標選中的函數(shù)或者類的幫助信息,按一次半屏顯示,按下兩次全屏顯示。
(2)F2 鍵,快速切換到光標選中的函數(shù)或者類的源碼定義處。
(3)F4鍵,快速在源文件和頭文件之間切換。
(4)Ctrl(按住)+ Tab,快速切換已打開的文件
(5)Ctrl+ I ,縮進光標選中行代碼(自動與上層代碼對齊)。
(6)Ctrl + / ,快速注釋或者取消注釋光標選中行。
(7)快速修改全局變量名
鼠標光標選中變量名,按下Ctrl+Shift+R,當變量名稱出現(xiàn)紅色框表示已經(jīng)激活全局修改功能。修改一處,整個工程對應變量名稱全部會修改。修改完畢之后,光標移開,再按下Ctrl+Shift+R保存修改。
(8)快速修改全局函數(shù)名
快捷方式與變量修改一樣按下Ctrl+Shift+R,一處修改整個工程對應的函數(shù)名稱也會跟著改。選中函數(shù)后,按下Ctrl+Shift+R后整個工程的對應的函數(shù)名會高亮,并且在軟件下方彈出修改框。
3.7 QT幫助文檔
Qt 幫助文檔太多,難以全部翻譯成中文,即使翻譯了一部分,翻譯花的時間太多,翻譯更新的時效性也難以保證,最終還是得看英文幫助,QtCreator 集成了幫助系統(tǒng),查找非常方便。
打開QtCreator,選擇菜單欄的最左邊的幫助選項,界面如下:
(1)查看Qlabel控件的幫助信息:
3.8 UI設計師使用
上節(jié)的Hello QT程序使用純C++代碼編寫,這一節(jié)使用QT界面設計模式實現(xiàn)與上一節(jié)Hello QT程序
一樣的功能。仿照著上節(jié)新創(chuàng)建一個工程。雙擊打開mainwindow.ui
文件,進入到UI設計界面。
(1)拖一個Label控件到編輯區(qū),雙擊Label控件可以修改文本內(nèi)容。
(2)運行程序可以點擊左下角的三角形符號或者按下快捷鍵Ctrl+R。
(3)UI設計師界面功能介紹
3.9 按鈕控件組
QT Creator UI設計師界面的按鈕組截圖如下:
以下是對按鈕組控件的一些功能介紹:
(1)Push Button按壓按鈕:最普通的按鈕,按(點擊)按鈕命令計算機執(zhí)行一些動作,或者回答問題,比如windows開始菜單里的重啟,注銷,關機等按鈕。
(2)Tool Button工具按鈕:工具按鈕通常是一個集合,一般集成在工具欄里。比如打開,保存,復制,粘貼,剪切等常用的操作。
(3)Radio Button單選按鈕:單選按鈕通常是兩個以上的形式出現(xiàn)在一塊,按鈕之間有互斥關系,每次只能選中一個。比如:一個人的性別只能選擇一個,不能同時是男性又是女性。
(4)Check Box復選框:復選框與單選按鈕概念相反,復選框通常表示多個可以同時存在的選項,比如一個人可以同時擁有多個愛好,比如讀書、看電影、爬山、游泳等。
(5)Command Link Button命令鏈接按鈕:一般用來打開的窗口或者網(wǎng)頁鏈接。
(6)Dialog Button Box標準按鈕盒:標準按鈕盒通常用于對話框程序;比如:常見的確認對話框有 “確定”“取消”等標準按鈕,Qt 將這些典型的按鈕做成標準按鈕盒,并將相應的信號加以封裝,方便程序員使用。
3.10 布局控件組
開發(fā)一個圖形界面應用程序,界面的布局影響到界面的美觀。前面的程序中都是使用UI界面拖控件,如果有多個按鈕,會出現(xiàn)大小難調(diào)整、位置難對齊等問題。Qt 提供的“布局管理“就很好的解決了控件擺放的問題。
以下是UI設計師界面的布局相關控件組:
功能介紹:
(1)Vertical Layout:垂直布局
(2)Horizontal Layout:水平布局
(3)Grid Layout:網(wǎng)格布局
(4)Form Layout:窗體中布局
(5)Horizontal Spacers:水平空格,在布局中用來占位。
(6)Vertical Spacer:垂直空格,在布局中用來占位。
3.11 基本布局控件
在UI設計界面添加一個布局控件,然后將需要布局的其他控件放入布局控件中即可完成布局,布局控件可以互相嵌套使用。(本節(jié)只介紹基本布局控件的使用)
以下是4種布局控件的效果:
3.12 UI設計師的布局功能
在UI設計界面的左上角有一排快捷的布局選項,使用時選中兩個以上的控件,點擊其中一種布局方式就可以切換布局。
以下為布局的簡單示例圖:
(1)為布局的選項。
(2)控件層次圖,可以看到控件的布局擺放層次。
如果想要控制某個控件的固定大小,不隨著布局改變大小,可以限定最大最小尺寸。選中控件鼠標右鍵–>大小限定->設置大小。
水平布局與垂直布局:
水平布局將控件按照水平方式擺放,垂直布局將控件按照垂直方式擺放。鼠標拖動紅色布局框上的黑色方點,可以調(diào)整布局框的大小。隨著布局框的尺寸變化,包含的控件高度不會變化,寬度會隨著布局框變化。選中其中一個控件然后鼠標右鍵>點擊大小限定,可以限定控件的最大和最小尺寸。
分裂器水平布局與垂直布局:
分裂器方式布局,包含控件的高度和寬度都會隨著布局框的拉伸而改變。選中其中一個控件然后鼠標右鍵>點擊大小限定,可以限定控件的最大和最小尺寸。
窗體中布局與柵格布局:
柵格(網(wǎng)格)布局器的基本單元是單元格,而窗體中布局(表單)的基本單元是行。隨著布局框的尺寸變化,包含的控件高度不會變化,寬度會隨著布局框變化。
設置主窗體布局方式:
設置主窗體的布局方式后,包含在主窗體內(nèi)的控件會隨著窗體的拉伸自動調(diào)整大小。
四、上位機開發(fā)
4.1 Qt開發(fā)環(huán)境安裝
Qt的中文官網(wǎng): https://www.qt.io/zh-cn/
QT5.12.6的下載地址:https://download.qt.io/archive/qt/5.12/5.12.6
打開下載鏈接后選擇下面的版本進行下載:
如果下載不了,可以在網(wǎng)盤里找到安裝包下載: 飛書文檔記錄的網(wǎng)盤地址:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
軟件安裝時斷網(wǎng)安裝,否則會提示輸入賬戶。
安裝的時候,第一個復選框里的編譯器可以全選,直接點擊下一步繼續(xù)安裝。
選擇編譯器: (一定要看清楚了)
4.2 新建上位機工程
前面2講解了需要用的API接口,接下來就使用Qt設計上位機,設計界面,完成整體上位機的邏輯設計。
【1】新建工程
【2】設置項目的名稱。
【3】選擇編譯系統(tǒng)
【4】選擇默認繼承的類
【5】選擇編譯器
【6】點擊完成
【7】工程創(chuàng)建完成
4.3 切換編譯器
在左下角是可以切換編譯器的。 可以選擇用什么樣的編譯器編譯程序。
目前新建工程的時候選擇了2種編譯器。 一種是mingw32
這個編譯Windows下運行的程序。 一種是Android
編譯器,可以生成Android
手機APP。
不過要注意:Android的編譯器需要配置一些環(huán)境才可以正常使用,這個大家可以網(wǎng)上找找教程配置一下就行了。
windows的編譯器就沒有這么麻煩,安裝好Qt就可以編譯使用。
下面我這里就選擇的 mingw32
這個編譯器,編譯Windows下運行的程序。
4.4 編譯測試功能
創(chuàng)建完畢之后,編譯測試一下功能是否OK。
點擊左下角的綠色三角形按鈕
。
正常運行就可以看到彈出一個白色的框框。這就表示工程環(huán)境沒有問題了。 接下來就可以放心的設計界面了。
4.5 設計UI界面與工程配置
【1】打開UI文件
打開默認的界面如下:
【2】開始設計界面
根據(jù)自己需求設計界面。
五、STM32代碼設計
5.1 硬件連線說明
序號 | 傳感器模塊 | 信號類型 | 接STM32引腳 | 說明 |
---|---|---|---|---|
1 | 紅外避障傳感器 ×3 | 數(shù)字輸入 | PA0(前) PA1(左) PA2(右) | 高電平=障礙物,低電平=無障礙 |
2 | 超聲波測距模塊 HC-SR04 | 數(shù)字IO | TRIG: PB0 ECHO: PB1 | 發(fā)送/接收測距信號 |
3 | 紅外跌落傳感器 ×3 | 數(shù)字輸入 | PA3(前) PA4(左) PA5(右) | 高電平=懸空,低電平=有地面 |
4 | MPU6050 姿態(tài)模塊 | I2C通信 | SDA: PB7 SCL: PB6 | 默認地址0x68 |
5 | 灰塵傳感器 GP2Y1010 | 模擬輸出 | PA6 | 連接ADC采集灰塵濃度 |
6 | DS3231 RTC時鐘模塊 | I2C通信 | SDA: PB7 SCL: PB6 | 與MPU6050共用I2C總線 |
7 | 電壓檢測模塊 | 模擬輸出 | PA7 | 電池電壓模擬量檢測 |
8 | DFPlayer Mini語音模塊 | 串口通信 | TX: PA9 RX: PA10 | 使用USART1 |
9 | ESP8266通信模塊 | 串口通信 | TX: PB10 RX: PB11 | 使用USART3 |
10 | OLED 顯示屏(0.96寸) | I2C通信 | SDA: PB9 SCL: PB8 |
5.2 傳感器代碼
當前項目使用的相關軟件工具已經(jīng)上傳到網(wǎng)盤:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
1. GPIO 輸入配置(避障、跌落)
void GPIO_Sensor_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
// 避障與跌落傳感器輸入引腳:PA0~PA5
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
2. ADC 模擬輸入配置(灰塵濃度、電壓檢測)
void ADC_Init(void)
{
ADC_HandleTypeDef hadc1;
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; // PA6:灰塵,PA7:電壓
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
HAL_ADC_Init(&hadc1);
}
讀取ADC值函數(shù)(灰塵或電壓):
uint16_t Read_ADC_Value(ADC_HandleTypeDef* hadc, uint32_t channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(hadc, &sConfig);
HAL_ADC_Start(hadc);
HAL_ADC_PollForConversion(hadc, HAL_MAX_DELAY);
uint16_t value = HAL_ADC_GetValue(hadc);
HAL_ADC_Stop(hadc);
return value;
}
3. 超聲波測距控制(TRIG/ECHO)
#define TRIG_PIN GPIO_PIN_0
#define TRIG_PORT GPIOB
#define ECHO_PIN GPIO_PIN_1
#define ECHO_PORT GPIOB
void Ultrasonic_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = TRIG_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(TRIG_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ECHO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(ECHO_PORT, &GPIO_InitStruct);
}
uint32_t Read_Ultrasonic(void)
{
uint32_t t1, t2;
HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET);
HAL_Delay(0.01);
HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_RESET);
t1 = DWT->CYCCNT;
while(HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_SET);
t2 = DWT->CYCCNT;
return (t2 - t1) / 72 / 58; // 距離 cm(STM32 72MHz)
}
4. MPU6050、RTC、OLED 初始化建議(使用 I2C)
// I2C2 for MPU6050 + RTC
hi2c2.Instance = I2C2;
hi2c2.Init.ClockSpeed = 400000;
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c2);
5. 串口初始化(語音/ESP8266通信)
// USART1 (PA9/PA10) for DFPlayer
// USART3 (PB10/PB11) for ESP8266
void UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);
}
5.3 項目核心代碼
當前項目使用的相關軟件工具已經(jīng)上傳到網(wǎng)盤:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
(1)main.c
核心主流程框架
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "i2c.h"
#include "adc.h"
#include "tim.h"
#include "oled.h"
#include "motor.h"
#include "sensor.h"
#include "wifi.h"
#include "voice.h"
#include "rtc.h"
#include "mpu6050.h"
#include "path_planning.h"
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
// 初始化外設
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_I2C2_Init();
MX_TIM2_Init();
MX_TIM3_Init();
// 模塊初始化
OLED_Init();
Motor_Init();
Sensor_Init();
Voice_Init();
MPU6050_Init();
RTC_Init();
WiFi_Init();
OLED_ShowString(0, 0, "Robot Start");
Voice_Play(1); // 播放“啟動成功”
while (1)
{
if (RTC_CheckSchedule()) // 是否到達清掃時間
{
Clean_Start();
}
WiFi_Handle(); // MQTT通信處理
HAL_Delay(100); // 輪詢
}
}
(2)掃地邏輯主控制 Clean_Start()
void Clean_Start(void)
{
OLED_ShowString(0, 1, "Cleaning...");
Voice_Play(2); // “開始清掃”
PathPlanner_Init(); // 初始化路徑柵格
while (!PathPlanner_Finished())
{
if (Sensor_IsFallDetected())
{
Motor_Stop();
Voice_Play(3); // “檢測到邊緣”
Clean_EscapeEdge();
continue;
}
if (Sensor_IsObstacleAhead())
{
Motor_Stop();
Voice_Play(4); // “前方有障礙”
Clean_AvoidObstacle();
continue;
}
if (Battery_Low())
{
Motor_Stop();
Voice_Play(5); // “電量不足,返回充電”
Go_To_ChargingDock();
return;
}
PathPlanner_Move(); // 路徑規(guī)劃并移動
Sensor_CheckDustLevel(); // 檢測灰塵情況,決定清掃強度
WiFi_UploadStatus(); // 上傳當前位置與狀態(tài)
HAL_Delay(100);
}
OLED_ShowString(0, 1, "Done!");
Voice_Play(6); // “清掃完成”
Go_To_ChargingDock();
}
(3)邊緣檢測與防跌落處理函數(shù)
void Clean_EscapeEdge(void)
{
Motor_Backward();
HAL_Delay(500);
Motor_TurnRight();
HAL_Delay(300);
Motor_Stop();
}
(4)避障處理函數(shù)
void Clean_AvoidObstacle(void)
{
Motor_Backward();
HAL_Delay(300);
Motor_TurnLeft();
HAL_Delay(500);
Motor_Stop();
}
(5)路徑規(guī)劃(Z字遍歷)
int map[20][20];
int cur_x = 0, cur_y = 0, dir = 1;
void PathPlanner_Init(void)
{
memset(map, 0, sizeof(map));
cur_x = 0;
cur_y = 0;
dir = 1;
}
void PathPlanner_Move(void)
{
map[cur_y][cur_x] = 1; // 標記已清掃
int next_x = cur_x + (dir == 1 ? 1 : -1);
if (next_x >= 0 && next_x < 20)
{
cur_x = next_x;
}
else
{
cur_y++;
dir = -dir;
}
Motor_Forward();
HAL_Delay(200);
Motor_Stop();
}
int PathPlanner_Finished(void)
{
return cur_y >= 20;
}
(6)傳感器檢測函數(shù)(sensor.c
)
uint8_t Sensor_IsFallDetected(void)
{
return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) == GPIO_PIN_SET || // 前
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_SET || // 左
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_SET; // 右
}
uint8_t Sensor_IsObstacleAhead(void)
{
return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET; // 前避障傳感器
}
void Sensor_CheckDustLevel(void)
{
uint16_t val = ADC_ReadValue(ADC_CHANNEL_6); // GP2Y1010 on PA6
if (val > 3000)
{
Motor_SetSpeed(HIGH); // 增強清掃
}
else
{
Motor_SetSpeed(NORMAL);
}
}
(7)語音提示控制(DFPlayer)
void Voice_Play(uint8_t track)
{
uint8_t cmd[] = {0x7E, 0xFF, 0x06, 0x03, 0x00, 0x00, track, 0xEF};
HAL_UART_Transmit(&huart1, cmd, sizeof(cmd), 100);
}
(8)WIFI與MQTT通信處理
void WiFi_Handle(void)
{
if (ESP8266_ReceiveMQTT("robot/ctrl") == CMD_STOP)
{
Motor_Stop();
Voice_Play(7); // “收到停止命令”
}
}
void WiFi_UploadStatus(void)
{
char buf[64];
sprintf(buf, "{"x":%d,"y":%d,"bat":%d}", cur_x, cur_y, Battery_GetLevel());
ESP8266_PublishMQTT("robot/status", buf);
}
(9)回充定位處理
void Go_To_ChargingDock(void)
{
// 簡化邏輯:持續(xù)前進直到檢測到紅外充電基座信號
while (!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12)) // 充電基座紅外
{
Motor_Forward();
HAL_Delay(100);
}
Motor_Stop();
Voice_Play(8); // “已回到充電樁”
}
5.4 程序下載
也有視頻教程:
講解如何編譯代碼,下載STM32程序: https://www.bilibili.com/video/BV1Cw4m1e7Yc
打STM32的keil工程,編譯代碼、然后,使用USB線將開發(fā)板的左邊的USB口(串口1)與電腦的USB連接,打開程序下載軟件下載程序。
具體下載過程看下面圖:
打開程序下載軟件:[軟件就在資料包里的軟件工具目錄下]
5.5 程序正常運行效果
設備運行過程中會通過串口打印調(diào)試信息,我們可以通過串口打印了解程序是否正常。
程序下載之后,可以打開串口調(diào)試助手查看程序運行的狀態(tài)信息。[軟件就在資料包里的軟件工具目錄下]
5.6 取模軟件的使用
顯示屏上會顯示中文,字母,數(shù)字等數(shù)據(jù),可以使用下面的取模軟件進行取模設置。
[軟件就在資料包里的軟件工具目錄下]
打開軟件之后:
六、總結
本項目以STM32F103RCT6為核心控制器,完成了一套功能完善、運行穩(wěn)定的掃地機器人系統(tǒng)設計與實現(xiàn)。系統(tǒng)融合了路徑規(guī)劃、障礙物避讓、邊緣檢測、防跌落控制、灰塵識別、自動回充、定時清掃、狀態(tài)顯示與語音提示等多種功能,具備較強的環(huán)境適應性與實用性。整機通過多傳感器協(xié)同感知環(huán)境變化,并結合智能算法進行決策,使得機器人能高效、安全地完成全覆蓋式清掃任務。
在系統(tǒng)軟硬件設計方面,充分發(fā)揮了STM32微控制器資源豐富、接口靈活、運算能力強等優(yōu)勢。硬件模塊選型明確,接口連接合理,保障了系統(tǒng)穩(wěn)定運行。軟件部分采用模塊化開發(fā)思路,邏輯清晰,功能劃分明確,便于后期維護與擴展。同時,通過ESP8266模塊實現(xiàn)了與手機APP之間的遠程通信,增強了用戶交互能力和系統(tǒng)智能化水平。
通過本項目的開發(fā)與調(diào)試,進一步驗證了STM32在智能機器人應用中的可行性和實用性,提升了開發(fā)者在嵌入式系統(tǒng)設計、智能控制、通信協(xié)議、傳感器融合等方面的綜合能力。項目成果在家庭清潔機器人領域具有良好的推廣價值和應用前景。