最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

學(xué)生畢業(yè)設(shè)計選題linux+qt嵌入式物聯(lián)網(wǎng)智能出行助手項目基于stm32mp157開發(fā)板

2023-03-16 17:28 作者:華清遠(yuǎn)見研發(fā)中心  | 我要投稿

stm32mp157開發(fā)板FS-MP1A是華清遠(yuǎn)見自主研發(fā)的一款高品質(zhì)、高性價比的Linux+單片機(jī)二合一的嵌入式教學(xué)級開發(fā)板。開發(fā)板搭載ST的STM32MP157高性能微處理器,集成2個Cortex-A7核和1個Cortex-M4 核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實時操作系統(tǒng)。開發(fā)板搭配仿真器、顯示屏、攝像頭、資源擴(kuò)展板等豐富的擴(kuò)展模塊,可拓展物聯(lián)網(wǎng)、人工智能等相關(guān)技術(shù)學(xué)習(xí),還可以拓展豐富的項目實戰(zhàn),非常貼合企業(yè)當(dāng)下開發(fā)需求,是一款嵌入式Linux入門進(jìn)階必備開發(fā)板!

可學(xué)習(xí)技術(shù):嵌入式Linux應(yīng)用/系統(tǒng)/驅(qū)動開發(fā)、ARM裸機(jī)開發(fā)、Qt界面編程、STM32單片機(jī)、FreeRTOS、人工智能機(jī)器視覺等。其中ARM Cortex-A7裸機(jī)開發(fā)課程是華清遠(yuǎn)見獨(dú)有特色課程,可關(guān)注:https://www.bilibili.com/video/BV1Xe4y1i7vm/,持續(xù)更新中。

可實戰(zhàn)項目:14個Linux+Qt綜合項目案例,6個MP1A物聯(lián)網(wǎng)拓展項目

關(guān)注公眾號“華清遠(yuǎn)見在線實驗室”,回復(fù)“mp157項目”,即可領(lǐng)取項目配套文檔及源碼。

Linux+Qt綜合項目案例:華清遠(yuǎn)見stm32mp157開發(fā)板優(yōu)勢特色部分,包括音樂播放器、智慧家庭、智能工業(yè)電表、智能出行助手、智能貓眼、環(huán)境監(jiān)測、智能安防、智能語音識別等10余個項目案例,涉及家居、醫(yī)療、農(nóng)業(yè)多種應(yīng)用方向,在案例中使用了多種物聯(lián)網(wǎng)和嵌入式技術(shù),包括OT開發(fā)、linux應(yīng)用開發(fā)、linux驅(qū)動開發(fā)、物聯(lián)網(wǎng)云端接入、MQTT協(xié)議、json字符串等知識點(diǎn)。

基于Linux+Qt的智能出行助手項目

項目功能簡介:

1、 調(diào)用百度 AI 開發(fā)平臺 API 進(jìn)行語音識別,進(jìn)行語音控制傳感器的聯(lián)動,實現(xiàn)智能語音識別平臺的功能。

2、 調(diào)用天氣生活指數(shù) API,獲取不同城市每天的運(yùn)動指數(shù)、 舒適度指數(shù)、化妝指數(shù)等等。

3、 調(diào)用百度地圖 api,顯示不同城市的地圖。

4、 實現(xiàn)智能鬧鐘,定時提醒。?

開發(fā)平臺:

華清遠(yuǎn)見stm32mp157開發(fā)板豪華套餐(開發(fā)板+仿真器+五寸屏+攝像頭+資源擴(kuò)展板+tf卡+讀卡器)

項目實戰(zhàn):

Qt 開發(fā)環(huán)境搭建

主機(jī)開發(fā)環(huán)境說明

1) 本文檔主要介紹 linux 環(huán)境下的 Qt 程序開發(fā);

2) 主機(jī) Qt 版本為 5.14.1;

主機(jī) Qt 環(huán)境搭建及使用

Qt Creator 安裝

將 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 實驗源碼\工具軟件) 復(fù)制到 ubuntu 主機(jī)中,可以采用共享文件夾的方式也可以使用 tfp方式將文 件存入家目錄下的 Downloads 目錄。我們需要在終端中賦予安裝程序可執(zhí)行的權(quán)限

我們可以使用圖形化的文件管理器來查看

雙擊“qt-creator-opensource-linux-x86_64-4.10.1.run”圖標(biāo)運(yùn)行安裝程序。出現(xiàn)如下界面:

等待程序驗證完成后點(diǎn)擊“Next”

這里我們需要登錄或者注冊一個賬號,如果我們之前已經(jīng)注冊過直接登錄就可以。如果沒有注冊過則需要新注冊有一個賬號后登錄。這里筆者已經(jīng)注冊過賬號,所以直接登錄。 登錄成功后出現(xiàn)如下界面,點(diǎn)擊 Next

這里選擇安裝路徑

可以直接默認(rèn),Next

這路選擇安裝的組件,直接默認(rèn)即可

這里我們需要同意用戶協(xié)議

這個界面告訴我們安裝完成后需要占用的空間。點(diǎn)擊”Install”按鈕后開始安裝。

安裝完成后出現(xiàn)如下界面

點(diǎn)擊“Finish”按鈕后將彈出 Qt Creator 主界面

點(diǎn)擊“Cancel”按鈕后即可正常使用

?

Qt5.14.1 安裝

復(fù)制到 qt-opensource-linux-x64-5.14.1.run(Qt 實驗源碼\工具軟件)到 ubuntu 主機(jī)中,可以采用共享文件夾的方式也可以使用 tfp 方式將文件存入家目錄下的 Downloads 目錄。進(jìn)入所在文件夾,先給執(zhí)行權(quán)限


輸入命令

chmod +x ./qt-opensource-linux-x64-5.14.1.run

安裝在命令行輸入

./qt-opensource-linux-x64-5.14.1.run

會有可視化引導(dǎo)安裝,一直 next 就行了

在選擇安裝組件的時候要是不知道選擇那些就全選了 大概有 4 個 G 左右


下載 gcc g++

sudo apt-get install gcc g++

?

下載 cmake

sudo apt-get install cmake

?

下載鏈接庫

sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev

?

Qt Creator 配置

1)配置 GCC

運(yùn)行 QtCreator 后,依次點(diǎn)擊"Tool"->"Options",出現(xiàn)選項對話框,在左側(cè)點(diǎn)擊"Kits",右 邊選擇"Compilers"標(biāo)簽。 檢查有沒有下圖標(biāo)注的 C++和 C ,般按上面步驟執(zhí)行后都會有

點(diǎn)擊右側(cè)"Add"按鈕,彈出下拉列表后,選擇"GCC"的"C"

填寫信息如下,"Name"為"Auto-GCC","Compiler path"點(diǎn)擊旁邊的"Browse.."按鈕選擇編譯器的路徑,例子中的路徑是 “/usr/bin/gcc”

2)配置 G++

點(diǎn)擊右側(cè)"Add"按鈕,彈出下拉列表后,選擇"GCC"的"C++",下面的文本框填寫"Name" 為"Auto-G++","Compiler path"點(diǎn)擊旁邊的"Browse.."按鈕選擇編譯器的路徑,例子中的路徑是" /usr/bin/g++"。

填寫完成后,點(diǎn)擊"Apply"。

3)配置 qmake

選擇"Qt Versions"標(biāo)簽,如果有下面紅框中的文本,可以跳過下面步驟

如果沒有,在右側(cè)點(diǎn)擊"Add..."

會彈出 qmake 路徑選擇對話框,這里以"/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"為例子。 選擇”qmake”文件后,點(diǎn)擊"Open"按鈕

"Version name"改為" Qt %{Qt:Version} GCC"。然后點(diǎn)擊"Apply"按鈕。

?

4)配置 Kits

點(diǎn)擊左側(cè)"Kits",右側(cè)選擇"Kits"標(biāo)簽。檢查有沒有下圖紅框選中的文本,如果有可以跳過下面步驟

然后沒有,點(diǎn)擊 Add:

在彈出的對話框中"Name"為"Desktop","Device Type"選擇"Desktop"選項, "Sysroot"選擇目標(biāo)設(shè)備的系統(tǒng)目錄,"Compiler"選擇之前配置的名稱"Auto-GCC"和"Auto-G++","Qt version"選擇之前配 置的名稱"Qt 5.14.1GCC",其它默認(rèn)即可,最后點(diǎn)擊"Apply"和"OK"按鈕。?

Qt Creator 新建工程

注意:工程路徑最好不要包含中文、特殊字符、空格等。

我們可以新建一個“qt”文件夾,該文件夾用作我們以后存放源代碼。

打開 Qt Creator,在歡迎頁面點(diǎn)擊 “New”按鈕,來新建一個工程。

在出現(xiàn)的新建項目窗口中,我們選則“Application”->“Qt Widgets Application”,然后點(diǎn)擊右下方“Choose…”按鈕,來創(chuàng)建一個桌面 Qt 應(yīng)用。

我們在這里設(shè)置項目介紹和源碼位置,我們這里創(chuàng)建一個名為“HelloWorld”的示例項目,設(shè)置完成之后點(diǎn)擊 next

直接點(diǎn)擊 next

隨后進(jìn)行細(xì)節(jié)設(shè)置,主要設(shè)置要創(chuàng)建的源碼文件的基本類信息,包括類名等。這里我們可以根據(jù)自己的項目特點(diǎn)進(jìn)行設(shè)置。需要說明的一點(diǎn)就是基類的選擇,這里基類有 QMainWindow、QWidget、QDialog 三種,它們的不同之處如下:

QMainWindow 類提供一個帶有菜單條,工具條和一個狀態(tài)條的主應(yīng)用程序窗口。主窗口通常提供一個大的中央窗口部件,以及周圍菜單,工具條,和一個狀態(tài)欄。QMainWindow 窗口經(jīng)常被繼承,使得封裝中央部件,菜單,工具條,狀態(tài)欄等都變得很容易,當(dāng)用戶點(diǎn)擊它的時候,相應(yīng)的槽就會被調(diào)用;

QWidget 類是所有用戶界面對象的基類,窗口部件是用戶界面的一個基本單元,它從窗口系統(tǒng)接收鼠標(biāo),鍵盤和其他消息,并在屏幕上繪制自己。一個窗口部件可以被他的父窗口或者是其他窗口擋住一部分;

QDialog 類是對話框窗口的基類,對話框窗口主要用于短期任務(wù)和用戶進(jìn)行短期通訊的頂級窗口,QDialog 可以是模態(tài)對話框或者是非模態(tài)對話框。QDialog 支持?jǐn)U展并帶有返回值,他們可以帶有默認(rèn)值;我們在這里選擇 QDialog 類即可,點(diǎn)擊 next 完成類信息設(shè)置。

直接點(diǎn)擊 next 按鈕即可。

然后進(jìn)行工具選擇,該頁面可以選擇我們創(chuàng)建的工程可以使用的工具,選擇想要使用的編譯器模塊,例如下圖 。點(diǎn)擊 next

最后我們設(shè)置匯總信息,如果不需要版本控制等功能,直接點(diǎn)擊完成finish 即可。

隨后我們就進(jìn)入到了主界面,這時候 Qt 已經(jīng)幫我們做好了一些準(zhǔn)備工作,包括創(chuàng)建了一些文件,寫好了一些前置代碼等等。

我們可以點(diǎn)擊左邊 protect 欄,來查看我們的編譯選項。

我們可以在左下角選擇編譯 Debug 版或者 Release 版,即調(diào)試版或發(fā)行版。

左下角綠色剪頭是編譯并運(yùn)行,錘子是僅編譯,我們可以直接點(diǎn)擊綠色小箭頭將我們導(dǎo)入的工程編譯并運(yùn)行起來。

點(diǎn)擊運(yùn)行按鈕后,我們可以看到 HelloWorld 窗口運(yùn)行起來了。

導(dǎo)入工程

我們可以將已存在的 Qt 程序項目直接打開,這里以上一章節(jié)的HelloWorld 程序為例。首先我們確定源碼存在的位置,如 HelloWorld 程序源碼在 /home/linux/qt/helloworld 路徑下

點(diǎn)擊歡迎頁面的“Open” 按鈕可以打開已有的工程

找到我們剛才解壓好的源碼,選擇“helloworld.pro”文件并點(diǎn)擊打開

接下來我們就可以進(jìn)入到代碼編輯界面了。

左上角是項目欄,點(diǎn)擊項目名稱左邊的小箭頭可以展開項目目錄

我們可以點(diǎn)擊左邊項目欄,來查看我們的編譯選項。需注意的是構(gòu)建設(shè)置中的路徑應(yīng)與工程路徑處于同級目錄下。

我們可以在左下角選擇編譯 Debug 版或者 Release 版,即調(diào)試版或發(fā)行版。

左下角綠色剪頭是編譯并運(yùn)行,錘子是僅編譯,我們可以直接點(diǎn)擊綠色小箭頭將我們導(dǎo)入的工程編譯并運(yùn)行起來

點(diǎn)擊運(yùn)行按鈕后,我們可以看到 HelloWorld 窗口運(yùn)行起來了。

文件說明

通過上面兩個章節(jié),我們學(xué)習(xí)到了 Qt 程序的新建與導(dǎo)入的方法,也知道了Qt 會幫我們做一些基礎(chǔ)工作,比如幫我們建立了一些文件,那么這些文件都是干什么用的呢?我們以HelloWorld 程序來說明一下。

以“.pro”為后綴名的文件,為 Qt 的項目管理文件,存儲項目設(shè)置的文件;

“Qt += core gui”表示項目中加入 core gui 模塊。core gui 是 Qt 用于GUI 設(shè)計的類庫模塊,如果創(chuàng)建的是控制臺(console)應(yīng)用程序,就不需要添加 core gui。

Qt 類庫以模塊的形式組織各種功能的類,根據(jù)項目涉及的功能需求,在項目中添加適當(dāng)?shù)念悗炷K支持。例如,如果項目中使用到了涉及數(shù)據(jù)庫操作的類就需要用到 sql(數(shù)據(jù)庫)模塊,在 pro 文件中需要在后面加上 sql:

1 Qt += core gui sql

“greaterThan(QT_MAJOR_VERSION, 4): QT += widgets”,這是個條件執(zhí)行語句,表示當(dāng) Qt 主版本大于 4 時,才加入 widgets 模塊?!癟ARGET = HelloWorld”表示生成的目標(biāo)可執(zhí)行文件的名稱,即編譯后生成的可執(zhí)行文件是 HelloWorld.exe。

“TEMPLATE = app”表示項目使用的模板是 app,是一般的應(yīng)用程序。

后面的 SOURCES、HEADERS、FORMS 記錄了項目中包含的源程序文件、頭文件和窗體文件(.ui 文件)的名稱。這些文件列表是 Qt Creator 自動添加到項目管理文件里面的,用戶不需要手動修改。當(dāng)添加一個文件到項目,或從項目里刪除一個文件時,項目管理文件里的條目會自動修改。

文件夾“Header”中,存放的是所設(shè)計的窗體類的頭文件;

文件夾“Sources”中,存放著源碼文件。main.cpp 是實現(xiàn) main()函數(shù)的程序文件,HelloWorld.cpp 是 widget.h 里定義類的實現(xiàn)文件。C++中,任何窗體或界面組件都是用類封裝的,一個類一般有一個頭文件(.h 文件)和一個源程序文件(.cpp 文件);

文件夾“Forms”中,存放著界面設(shè)計文件,“.ui”文件是一個 XML 格式存儲的窗體上的元件及其布局的文件,雙擊項目文件目錄樹中的文件 ui,會打開一個集成在 Qt Creator 中的 Qt Designer 對窗體進(jìn)行可視化設(shè)計;

UI 設(shè)計器有以下一些功能區(qū)域:

組件面板:窗口左側(cè)是界面設(shè)計組件面板,分為多個組,如 Layouts、Buttons、Display Widgets 等,界面設(shè)計的常見組件都可以在組件面板里找到。

中間主要區(qū)域是待設(shè)計的窗體。如果要將某個組件放置到窗體上時,從組件面板上拖放一個組件到窗體上即可。

Signals 和 Slots 編輯器與 Action 編輯器是位于待設(shè)計窗體下方的兩個編輯器。Signals 和 Slots 編輯器用于可視化地進(jìn)行信號與槽的關(guān)聯(lián),Action 編輯器用于可視化設(shè)計 Action。

布局和界面設(shè)計工具欄:窗口上方的一個工具欄,工具欄上的按鈕主要實現(xiàn)布局和界面設(shè)計。

對象瀏覽器(Object Inspector):窗口右上方是 Object Inspector,用樹狀視圖顯示窗體上各組件之間的布局包含關(guān)系,視圖有兩列,顯示每個組件的對象名稱(ObjectName)和類名稱。

屬性編輯器(Property Editor):窗口右下方是屬性編輯器,是界面設(shè)計時最常用到的編輯器。屬性編輯器顯示某個選中的組件或窗體的各種屬性及其取值,可以在屬性編輯器里修改這些屬性的值。屬性編輯器的內(nèi)容分為兩列,左側(cè)為屬性的名稱,右側(cè)為屬性的值。屬性又分為多個組,實際上表示了類的繼承關(guān)系,位于下方的類屬性組繼承自位于上方的類屬性組;如果我們需要新建資源文件、源碼文件等,可以在項目文件夾出點(diǎn)擊鼠標(biāo)右鍵,選擇 Add New;如果我們有新的文件需要添加,可以在項目文件夾出點(diǎn)擊鼠標(biāo)右鍵,選擇 Add Existing Files。

幫助文檔

Qt 的幫助文檔是伴隨我們學(xué)習(xí) Qt 開發(fā)的好伙伴。在 Qt 開發(fā)過程中,我們會面臨圖形接口使用的問題,它不像 C 語言那樣就那么幾個函數(shù)接口,圖形接口的接口數(shù)量可以用海量來形容,常用的我們可能能記住,其它的就沒有必要去記了,用到什么就去幫助文檔查看用法是比較方便的。我們可以按 F1 按鍵,或通過上方導(dǎo)航欄的“help->contects”來進(jìn)入幫助文檔。

上方的前進(jìn)后退按鈕方便我們查看文檔,如返回到上一步,返回到下一步。

我們可以通過幫助文檔來查看以下幾個部分:類使用的相關(guān)介紹;查看相關(guān)類的使用介紹,我們可以先進(jìn)入到幫助文檔,然后在左上角選擇“Search”。筆者這里以 QWidget 類為例,輸入我們想要查找的類的名字,然后雙擊查找結(jié)果來查看說明。

也可以先將鼠標(biāo)移動到想要查詢的類的位置,如圖所示,將鼠標(biāo)移動至“QWidget”處,然后按“F1”鍵,即可跳轉(zhuǎn)到相應(yīng)的幫助文檔。

我們可以通過再按一次“F1”鍵來全窗口查看幫助文檔,按“Esc”鍵可以退出。

部分常用的成員元素包括以下幾項:

公有成員函數(shù):操作部件屬性的相關(guān)函數(shù);

公有槽函數(shù):Qt 類中已經(jīng)定義好的槽函數(shù),直接可與信號相連接;

信號:軟中斷,如按下按鈕觸發(fā) pressed() 信號等;

?保護(hù)成員函數(shù):通常事件所對應(yīng)的虛函數(shù)放在此處;

事件:常用事件,如操作鼠標(biāo)觸發(fā)的鼠標(biāo)事件;

滾動鼠標(biāo)滾輪,向下即可看到“Qwdget Class”類的相關(guān)說明了。

部分常用的成員元素包括以下幾項:

公有成員函數(shù):操作部件屬性的相關(guān)函數(shù);

公有槽函數(shù):Qt 類中已經(jīng)定義好的槽函數(shù),直接可與信號相連接;

信號:軟中斷,如按下按鈕觸發(fā) pressed() 信號等;

保護(hù)成員函數(shù):通常事件所對應(yīng)的虛函數(shù)放在此處;

事件:常用事件,如操作鼠標(biāo)觸發(fā)的鼠標(biāo)事件;

滾動鼠標(biāo)滾輪,向下即可看到“Qwdget Class”類的相關(guān)說明了。

1) 查看所用的部件的相應(yīng)成員函數(shù)。

我們可以查找到該類所用部件的相應(yīng)成員函數(shù)的使用方法、功能、參數(shù)、返回值等等,我們以“按鈕”控件,即“QPushButton Class”類為例,我們通過索引搜索的方式,來找到這個類

我們可以通過點(diǎn)擊“Public Functions” 來查看“QPushButton”這個類中的成員函數(shù)。

這里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”為例,我們點(diǎn)擊函數(shù)名字可以進(jìn)入到函數(shù)詳情中。我們可以看到相應(yīng)的描述為:以“text”為顯示內(nèi)容,以“parent”為父對象,構(gòu)造一個push 按鈕。“text”“parent”為函數(shù)參數(shù),由于是構(gòu)造函數(shù),所以此函數(shù)沒有返回值。

還有一些函數(shù)是繼承自其它類的,例如“Public Functions”中有 21 個繼承自“QAbstractButton”類的函數(shù),我們點(diǎn)擊“QAbstractButton”即可查看。擊“QAbstractButton”即可查看

同樣我們可以點(diǎn)擊相應(yīng)的函數(shù)進(jìn)入查看詳情。如查看“void setText(const QString &text)”。

2) 查看所用的部件的信號。

我們這里還是以“PushButton”為例,我們點(diǎn)擊“Public Slots”。

可以看到“PushButton”本身有一個“void showMenu()”的信號,并且有很多繼承自其他類的信號。

一般來說我們用的“PushButton”的信號,最多的是用到其繼承自基類“QAbstractButton”中的幾個信號,分別是點(diǎn)擊(按下后抬起)、按壓(單按下)、釋放(單抬起)等

我們可以點(diǎn)擊相應(yīng)信號查看詳情

3) 查看所用的部件的事件(所對應(yīng)的虛函數(shù)如何編寫)。部件常用事件主要在 “QWidget”中聲明,選擇“Events”即可查看相關(guān)說明。

每個事件都對應(yīng)著事件函數(shù)。

點(diǎn)擊事件函數(shù)可查看詳情


語音識別模塊?

錄音

在 pro 文件添加

QT += network

QT += multimedia

在 mainwindow.h 頭文件添加下面定義

void RecorderStart(QString fileName);//開始錄音

void RecorderEnd();//結(jié)束錄音并轉(zhuǎn)換格式

QFile *outFile;//錄音時的變量

QAudioInput *my_audio;//錄音時的變量

QAudioFormat audioFormat;//錄音時的變量

Mainwindow.cpp 錄音函數(shù)實現(xiàn):

void MainWindow::RecorderStart(QString fileName)

{

?QAudioDeviceInfo device = QAudioDeviceInfo::defaultInputDevice();

?if(device.isNull())

?{

?QMessageBox::warning(NULL,"QAudioDeviceInfo","錄音設(shè)備不存

在");

?return;

?}

// 設(shè)置通道數(shù)

?audioFormat.setChannelCount(1);

// 設(shè)置編碼

audioFormat.setCodec("audio/pcm");

// 設(shè)置采樣頻率

?audioFormat.setSampleRate(16000);

// 設(shè)置位深

?audioFormat.setSampleSize(16);

// 判斷設(shè)備是否支持該格式

?if(!device.isFormatSupported(audioFormat)){ //當(dāng)前使用設(shè)備是否支持

?audioFormat = device.nearestFormat(audioFormat); //轉(zhuǎn)換為最接近格

?}

// 創(chuàng)建錄音對象

?my_audio = new QAudioInput(audioFormat,this);

?outFile = new QFile;

?outFile->setFileName(fileName); //語音原始文件

?outFile->open(QIODevice::WriteOnly);

// 開始錄音

?my_audio->start(outFile);

}?

結(jié)束錄音函數(shù)實現(xiàn)

/**********************

* 結(jié)束錄音并轉(zhuǎn)換格式

**********************/

void MainWindow::RecorderEnd()

{

// 結(jié)束錄音

?my_audio->stop();

?outFile->close();

?delete outFile;

outFile =NULL;

?delete my_audio;

?my_audio = NULL;

}

點(diǎn)擊釋放按鈕槽函數(shù)

右鍵按鈕,轉(zhuǎn)到槽,選擇 pressed 和 released 點(diǎn)擊 ok。會在 mainwindow.cpp生成 on_pushButton_video_pressed()和 on_pushButton_video_released()槽函數(shù)。

在兩個槽函數(shù)分別實現(xiàn)如上圖所示

申請百度 AI 開發(fā)平臺語音識別應(yīng)用

語音識別是利用百度的 API 在線識別。所以需要申請項目 ID。

進(jìn)入百度的 API 平臺:https://ai.baidu.com/

在產(chǎn)品服務(wù)下選擇語音識別:

點(diǎn)擊立即使用:

申請賬號點(diǎn)擊登錄:

點(diǎn)擊創(chuàng)建應(yīng)用:

輸入應(yīng)用名稱、應(yīng)用描述,點(diǎn)擊立即創(chuàng)建:

點(diǎn)擊返回應(yīng)用列表:

獲取 AppID、API Key 和 Secret Key

我們記住其中的 API Key 和 Secret Key,下面會用到。

HTTP 請求類實現(xiàn)

我們錄好的音頻文件需要通過 HTTPS 協(xié)議上傳到百度 AI 開發(fā)平臺進(jìn)行語音識別,之后 AI 平臺會返回給我們識別的結(jié)果。

http 類只需要封裝一個方法

bool post_sync(QString url,QMap<QString,QString>header,QByteArray

requestData,QByteArray &replyData);

使用這個方法去 URL 發(fā)送請求會收到 URL 的返回值。

http.h

#ifndef HTTP_H

#define HTTP_H

#include <QObject>

#include <QMap>

#include <QNetworkAccessManager>

#include <QNetworkRequest>

#include <QNetworkReply>

#include <QEventLoop>

#include <QDebug>

class Http : public QObject

{

?Q_OBJECT

public:

?explicit Http(QObject *parent = nullptr);

?bool post_sync(QString url,QMap<QString,QString>header,QByteArray

requestData,QByteArray &replyData);

};

#endif // HTTP_H

http.cpp

這個方法的第一個參數(shù)是 post 方法發(fā)送請求的 URL,第二個參數(shù)是請求的方法頭,第三個參數(shù)是請求的數(shù)據(jù),第四個參數(shù)是返回的數(shù)據(jù)。

這里要說的是必須要設(shè)置 openssl 簽名配置,否則在 ARM 上會報錯。?

bool Http::post_sync(QString url,QMap<QString,QString>header,QByteArray

requestData,QByteArray &replyData)

{

// 發(fā)送請求的對象

?QNetworkAccessManager manager;

// 請求 對象

?QNetworkRequest request;

?request.setUrl(url);

?QMapIterator<QString,QString> it(header);

?while (it.hasNext()) {

?it.next();

?request.setRawHeader(it.key().toLatin1() ,it.value().toLatin1());

?}

//設(shè)置 openssl 簽名配置,否則在 ARM 上會報錯

?QSslConfiguration conf = request.sslConfiguration();

?conf.setPeerVerifyMode(QSslSocket::VerifyNone);

#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))

?conf.setProtocol(QSsl::TlsV1_0);

#else

?conf.setProtocol(QSsl::TlsV1);

#endif

?request.setSslConfiguration(conf);

QNetworkReply *reply = manager.post(request,requestData);

?QEventLoop l;

?//一旦服務(wù)器返回,reply 會發(fā)出信號

?connect(reply,&QNetworkReply::finished,&l,&QEventLoop::quit);

?l.exec();

?if(reply != nullptr && reply->error() == QNetworkReply::NoError)

?{

?replyData = reply->readAll();

?return true;

?}

?else

?{

?qDebug()<<"request error!";

?return false;

?}

}

發(fā)送請求

這里需要向兩個 URL 發(fā)送兩個請求,第一個請求是把我們 4.2.3 創(chuàng)建應(yīng)用得到的 API Key 和 Secret Key 組合成一個 URL 獲取 access_token,第二個請求是把音頻文件發(fā)送請求到語音識別的 URL 才能返回語音識別的結(jié)果。

我們新建一個類 Speech

Speech.h

這里我們把 API Key 和 Secret Key 作為參數(shù)傳到 const QString baiduTokenUrl 里面去。把主機(jī)名和獲取的 access_token 做為參數(shù)傳入 const QString baiduSpeechUrl。

#include <QObject>

#include <QJsonDocument>

#include <QJsonParseError>

#include <QJsonObject>

#include <QJsonValue>

#include <QJsonArray>

#include <QFile>

#include "http.h"

#include <QHostInfo>

// 獲取 Access Token

const QString baiduTokenUrl =

"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=

%1&client_secret=%2&";

const QString client_id = "我們創(chuàng)建應(yīng)用的 API Key";

const QString client_secret = "我們創(chuàng)建應(yīng)用的 Secret Key";

// 語音識別 url

const QString baiduSpeechUrl =

"https://vop.baidu.com/server_api?dev_pid=1537&cuid=%1&token=%2";

class Speech:public QObject

{

?Q_OBJECT

public:

?Speech();

?QString speechIdentify(QString fileName);

private:

?QString getJsonValue(QByteArray ba,QString key);

};

#endif // SPEECH_H

Speech.cpp

QString Speech::speechIdentify(QString fileName)

{

// 獲取 Access Token

?QString tokenUrl =QString(baiduTokenUrl).arg(client_id).arg(client_secret);

Http my_http;

?QMap<QString,QString>header;

?header.insert(QString("Content-Type"),QString("audio/pcm;rate=16000"));

?QByteArray requestData;//請求內(nèi)容

?QByteArray replyData;//url 返回內(nèi)容

?qDebug()<<tokenUrl;

?bool result = my_http.post_sync(tokenUrl,header,requestData,replyData);

?if(result) {

?QString key = "access_token";

?QString accessToken =getJsonValue(replyData,key);

?qDebug()<<accessToken;

?// 語音識別

?QString speechUrl =

QString(baiduSpeechUrl).arg(QHostInfo::localHostName()).arg(accessToken);

?QFile file;

?file.setFileName(fileName);

?file.open(QIODevice::ReadOnly);

?requestData = file.readAll();

?file.close();

?replyData.clear();

// 再次發(fā)起請求

?result = my_http.post_sync(speechUrl,header,requestData,replyData);

?if(result) {

?QString key = "result";

?QString retText =getJsonValue(replyData,key);

?qDebug()<<retText;

?return retText;

?}

else{

?return NULL;

?}

?}

?else {

?return "error";

?}

}

解析返回的數(shù)據(jù)

返回的數(shù)據(jù)是這種 Json 類型的,我們只需要獲取里邊 result 的值就能得到

我們想要的結(jié)果了。

{"err_no":0,"err_msg":"success.","corpus_no":"15984125203285346378","sn":"

481D633F-73BA-726F-49EF-8659ACCC2F3D","result":["北京天氣"]}

QString Speech::getJsonValue(QByteArray ba,QString key)

{

?QJsonParseError parseError;

?QJsonDocument jsondocument =

QJsonDocument::fromJson(ba,&parseError);

?if(parseError.error ==QJsonParseError::NoError)

?{

?if(jsondocument.isObject())

?{

?QJsonObject jsonObject = jsondocument.object();

?if(jsonObject.contains(key)){

?QJsonValue jsonvalue = jsonObject.value(key);

?if(jsonvalue.isString())

?return jsonvalue.toString();

?else if(jsonvalue.isArray()){

?QJsonArray arr = jsonvalue.toArray();

?QJsonValue val =arr.at(0);

return val.toString();

?}

?}

?}

?}

?return "";

}

MainWindow 類調(diào)用函數(shù)

我們在釋放按鈕的槽函數(shù)里添加以下代碼

void MainWindow::on_pushButton_video_released()

{

?ui->pushButton_video->setText("按住說話");

?RecorderEnd();

?Speech my_speech;

?QString text =my_speech.speechIdentify("./1.pcm");

?ui->textEdit->append(text);

?audioCtrl(text);

}

語音控制設(shè)備聯(lián)動

代碼如下

void MainWindow::audioCtrl(QString text)

{

?if(text == "開燈。")

?{

?system("echo 1 >/sys/class/leds/user1/brightness");

?system("echo 1 >/sys/class/leds/user2/brightness");

?system("echo 1 >/sys/class/leds/user3/brightness");

?ui->textEdit_2->setText("燈已打開");

?}

?else if(text == "關(guān)燈。")

?{

?system("echo 0 >/sys/class/leds/user1/brightness");

?system("echo 0 >/sys/class/leds/user2/brightness");

?system("echo 0 >/sys/class/leds/user3/brightness");

?ui->textEdit_2->setText("燈已關(guān)閉");

?}

?else if(text == "報警。")

?{

?int fd;

?struct input_event event;

?struct timeval time;

?fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);

?event.type = EV_SND;

?event.code = SND_TONE;

?event.value = 1000;

?time.tv_sec = 1;

?time.tv_usec = 0;

?event.time = time;

?write(fd, &event, sizeof(struct input_event));

?ui->textEdit_2->setText("蜂鳴器已報警");

?}

else if(text == "關(guān)閉。")

?{

?int fd;

?struct input_event event;

?struct timeval time;

?fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);

?event.type = EV_SND;

?event.code = SND_TONE;

?event.value = 0;

?time.tv_sec = 0;

?time.tv_usec = 0;

?event.time = time;

?write(fd, &event, sizeof(struct input_event));

?ui->textEdit_2->setText("蜂鳴器報警已關(guān)閉");

?}

?else if(text == "關(guān)風(fēng)扇。")

?{

?unsigned char arg;

?Ioctl(EXIT_FAN,&arg);

?ui->textEdit_2->setText("風(fēng)扇已關(guān)閉");

?}

?else if(text == "開風(fēng)扇。")

?{

?unsigned char arg;

?Ioctl(EXIT_FAN,&arg);

?Ioctl(INIT_FAN,&arg);

?Ioctl(FAN_UP,&arg);

?ui->textEdit_2->setText("風(fēng)扇已打開");

?}

else if(text == "溫度。")

?{

?QString tem = temCollect();

?ui->textEdit_2->setText(QString(" 此 時 溫 度

為:").append(tem).append("'C"));

?}

?else if(text == "濕度。")

?{

?QString hum = humCollect();

?ui->textEdit_2->setText(QString(" 此時濕度

為:").append(hum).append("%"));

?}

}

智慧生活模塊

創(chuàng)建 API 應(yīng)用

瀏覽器進(jìn)入 https://dev.qweather.com/;注冊賬號并登陸,點(diǎn)擊進(jìn)入控制臺

進(jìn)入控制臺后,點(diǎn)擊應(yīng)用管理。

點(diǎn)擊創(chuàng)建應(yīng)用,選擇免費(fèi)開發(fā)板

填寫天氣數(shù)據(jù)應(yīng)用名稱后選擇 WebAPI,自定義天氣數(shù)據(jù)應(yīng)用名稱。

完成上述操作后,把 key 復(fù)制下來,后邊代碼需要用到。

?

方法獲取 API JOSN 數(shù)據(jù)

我們將 key 填寫到下面的 URL 里面,使用 get 方法就能從 API 爬蟲下JOSN 數(shù)據(jù)來了

你的 KEY其中請求參數(shù)

Location:需要查詢地區(qū)的 LocationID 或以英文逗號分隔的經(jīng)度,緯度坐標(biāo)(十進(jìn)制),LocationID 可通過城市搜索服務(wù)獲取。例如 location=101010100

Key:用戶認(rèn)證 key,即上面獲取到的 key。

Type:生活指數(shù)的類型 ID,包括洗車指數(shù)、穿衣指數(shù)、釣魚指數(shù)等。可以一次性獲取多個類型的生活指數(shù),多個類型用英文,分割。例如 type=3,5。具體生活指數(shù)的 ID 和等級參考生活指數(shù)常量。各項生活指數(shù)并非適用于所有城市。

所以我們以參數(shù)的形式將城市的 LocationID 填入 URL 就能獲取不同城市的生活指標(biāo)。

具體代碼參考下面:

//get 方法獲取信息

void LifeWidget::sendQuest(QString cityStr)

{

QString key = "您申請的 key";

?QString quest_url =

"https://devapi.qweather.com/v7/indices/1d?type=0&location=%1&key=%2";

?quest_url = quest_url.arg(cityStr).arg(key);

?QNetworkRequest quest;

?quest.setUrl(QUrl(quest_url));

?//設(shè)置 openssl 簽名配置,否則在 ARM 上會報錯

?QSslConfiguration conf = quest.sslConfiguration();

?conf.setPeerVerifyMode(QSslSocket::VerifyNone);

?#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))

?conf.setProtocol(QSsl::TlsV1_0);

?#else

?conf.setProtocol(QSsl::TlsV1);

?#endif

?quest.setSslConfiguration(conf);

?manager->get(quest); /*發(fā)送 get 網(wǎng)絡(luò)請求*/

}

//數(shù)據(jù)接收槽函數(shù)

void LifeWidget::replyFinished(QNetworkReply *reply)

{

?replyall = reply->readAll();

?reply->deleteLater(); //銷毀請求對象

}

void LifeWidget::init_networt_life()

{

?manager = new QNetworkAccessManager(this);

?connect(manager, SIGNAL(finished(QNetworkReply*)), this,

SLOT(replyFinished(QNetworkReply*)));//關(guān)聯(lián)信號和槽

}

解析 JOSN 數(shù)據(jù)

{

?"code": "200",

?"updateTime": "2021-02-06T16:36+08:00",

?"fxLink": "http://hfx.link/2ax2",

?"daily": [

?{

?"date": "2021-02-06",

?"type": "2",

?"name": "洗車指數(shù)",

?"level": "2",

?"category": "較適宜",

?"text": "較適宜洗車,未來一天無雨,風(fēng)力較小,擦洗一新的汽車至少

能保持一天。"

?},

?{

?"date": "2021-02-06",

?"type": "1",

?"name": "運(yùn)動指數(shù)",

?"level": "3",

?"category": "較不宜",

?"text": "天氣較好,但考慮天氣寒冷,推薦您進(jìn)行室內(nèi)運(yùn)動,戶外運(yùn)動

時請注意保暖并做好準(zhǔn)備活動。"

?}

?],

?"refer": {

?"sources": [

?"Weather China"

?],

"license": [

?"commercial license"

?]

?}

}

?

我們通過 get 方法獲取到的 JOSN 數(shù)據(jù)如上所示。只需要解析 key 為 daily的值即可。其中 daily 的值是一個數(shù)組類型的數(shù)據(jù),只需要取出我們需要的即可。

void DetaInfo::setInfo(QString info,int type)

{

?qDebug()<<"setINfo";

?QJsonParseError err;

?QJsonDocument json_recv = QJsonDocument::fromJson(info.toUtf8(),

&err);//解析 json 對象

?if (!json_recv.isNull())

?{

?QJsonObject object = json_recv.object();

?if (object.contains("daily"))

?{

?QJsonValue value = object.value("daily"); // 獲取指定 key 對

應(yīng)的 value

?if (value.isArray())

?{

?QJsonObject today_life = value.toArray().at(type).toObject();

?QString category = today_life.value("category").toString();

?QString text = today_life.value("text").toString();

?ui->label_category->setText(category);

?ui->label_text->setText(text);

?}

?}

?}

}

出行地圖模塊

申請百度地圖 API 秘鑰

進(jìn)入百度地圖官網(wǎng) https://lbsyun.baidu.com/

點(diǎn)擊進(jìn)入控制臺

這里需要登錄百度賬號,掃碼或者輸入用戶名密碼登錄即可。

登錄成功后點(diǎn)擊應(yīng)用管理下的我的應(yīng)用。

點(diǎn)擊創(chuàng)建應(yīng)用

自定義應(yīng)用名稱后,應(yīng)用類型選擇瀏覽器端,在白名單輸入框輸入*

這里就是我們需要的 AK 秘鑰。

map.html

復(fù)制百度地圖 API 源碼。

新建 map.html

將上面 API 的源碼復(fù)制到嗎 map.html

將代碼里面的紅框里的您的秘鑰替換剛才申請的 AK 即可。

map.html 文件添加方法

添加函數(shù),通過 QT 程序傳參來改變地圖路線的起點(diǎn),途經(jīng)點(diǎn),終點(diǎn)。

QT端實現(xiàn)

這里使用了 webkit 模塊,在 pro 文件中添加 QT += webkit webkitwidgets

具體代碼如下

void MainWindow::mapinit()

{

QWebSettings *settings = QWebSettings::globalSettings();

?settings->setAttribute(QWebSettings::PluginsEnabled, true);//允許插件

?settings->setAttribute(QWebSettings::JavascriptEnabled, true);//JavaScript

?settings->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);//

?settings->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);

?settings->setFontFamily(QWebSettings::FixedFont,"幼圓");

?ui->webView->setStyle(new CustomStyle());

?ui->webView->load(QUrl("qrc:/map.html"));

?connect(ui->webView->page()->mainFrame(),

SIGNAL(javaScriptWindowObjectCleared()), this,

SLOT(populateJavaScriptWindowObject()));

}

void MainWindow::populateJavaScriptWindowObject()

{

ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("Myweb

kit", this);

}

void MainWindow::onBtnCallJSClicked()

{

?QString strVal = QString("callfromqt(要傳的參數(shù));"));

?ui->webView->page()->mainFrame()->evaluateJavaScript(strVal);

}

智能鬧鐘模塊

開啟線程,檢測時間

這里設(shè)置了四個鬧鐘,即在線程類里邊設(shè)置了四個全局變量(鬧鐘時間)。當(dāng)前時間戳等于設(shè)置的時間戳后設(shè)置蜂鳴器響起。

void TimeAlarmClock::run()

{

?while (1) {

?QDateTime time = QDateTime::currentDateTime(); //獲取當(dāng)前時間

?uint timeT = time.toTime_t(); //將當(dāng)前時間轉(zhuǎn)為時間戳

// qDebug()<<timeT<<alarm_clocktime1;

?if(alarm_clocktime1==timeT){

?beep_on();

// qDebug()<<"open";

?}else{

?}

?if(alarm_clocktime2==timeT){

?beep_on();

?}else{

?}

?if(alarm_clocktime3==timeT){

?beep_on();

?}else{

?}

?if(alarm_clocktime4==timeT){

?beep_on();

?}else{

?}

?}

}

void TimeAlarmClock::beep_on()

{

?int fd;

?struct input_event event;

?struct timeval time;

?fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);

?event.type = EV_SND;

?event.code = SND_TONE;

?event.value = 1000;

?time.tv_sec = 1;

?time.tv_usec = 0;

?event.time = time;

?write(fd, &event, sizeof(struct input_event));

?close(fd);

}


提交鬧鐘時間

使用 QdateTimeEdit 設(shè)置鬧鐘時間,點(diǎn)擊按鈕后,將鬧鐘時間設(shè)置到線程中的全局變量中

void MainWindow::on_time_btn1_clicked()

{

?if(ui->time_btn1->text()==" "){

?ui->time_btn1->setText("\n");

?timeAlarmClock.alarm_clocktime1 =

ui->dateTimeEdit_1->dateTime().toTime_t();

?}else{

?ui->time_btn1->setText(" ");

?timeAlarmClock.alarm_clocktime1 = 0;

?}

}?

實驗源碼

源碼路徑【11-出行助手\實驗源碼\04-Aivideo】

注意事項

1.在開發(fā)板運(yùn)行時,需要導(dǎo)入中文字庫,否則會因為識別不了中文。

將【11-出行助手\工具軟件\wqy-zenhei-0.9.47-nightlybuild.tar.gz 或wqy-zenhei-0.8.38-1.tar.gz】復(fù)制到 ubuntu 下。并使用 scp 命令將文件拷貝到開發(fā)板的 usr/share/fonts 目錄下,使用 tar 命令解壓后即可

linux@ubuntu:~$ scp wqy-zenhei-0.8.38-1.tar.gz

root@192.168.10.128:/usr/share/fonts/

2.如果使用 mipi 五寸屏運(yùn)行此項目,需要進(jìn)行屏幕旋轉(zhuǎn)以適應(yīng)屏幕,具體步驟如下:

在/etc/profile.d/qt-eglfs.sh 添加環(huán)境變量如下

下面變量的 event0 設(shè)備需要填實際的觸摸屏設(shè)備

這里即填 event0

export QT_QPA_EGLFS_ROTATION=90

export QT_QPA_EGLFS_NO_LIBINPUT=1

export

QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=90

學(xué)生畢業(yè)設(shè)計選題linux+qt嵌入式物聯(lián)網(wǎng)智能出行助手項目基于stm32mp157開發(fā)板的評論 (共 條)

分享到微博請遵守國家法律
托里县| 鄱阳县| 玉环县| 麻江县| 施甸县| 周宁县| 营山县| 桐柏县| 中方县| 祁阳县| 威宁| 黑水县| 门头沟区| 大姚县| 嘉义县| 卢氏县| 阳山县| 平谷区| 龙门县| 潢川县| 满城县| 呼图壁县| 平凉市| 瓦房店市| 普陀区| 乌鲁木齐县| 慈利县| 中超| 安岳县| 泸水县| 大理市| 车险| 武平县| 都匀市| 文山县| 凤庆县| 玉树县| 红原县| 厦门市| 鄂尔多斯市| 迭部县|