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