“早上好。現(xiàn)在是早上 7:00 馬里布的天氣是 72 度,云層散落。沖浪條件公平,腰部到肩的高線。漲潮時(shí)間為上午 10:52”。每次在電影鋼鐵俠中聽到賈維斯的這個(gè)聲音,都會(huì)讓我脊背發(fā)涼。我敢肯定,就像我一樣,很多人都?jí)粝脒^(guò)像托尼·斯塔克一樣精致的生活。但遺憾的是,我們還沒(méi)有在微型 Arc 反應(yīng)堆或像 JARVIS 一樣聰明的 AI 方面取得進(jìn)步。但是可以用類似于 Jarvis 使用 Raspberry Pi 的鬧鐘來(lái)代替我們無(wú)聊的早晨鬧鐘。在這個(gè)項(xiàng)目結(jié)束時(shí),我們將創(chuàng)建一個(gè)非常基本的 GUI,我們可以使用它來(lái)設(shè)置鬧鐘,當(dāng)鬧鐘響起時(shí),我們將通過(guò)一些預(yù)定義的文本告訴我們當(dāng)前時(shí)間和日期。聽起來(lái)很酷吧??!所以讓我們建立一個(gè)。
所需材料
3.5” TFT液晶屏
揚(yáng)聲器
輔助電纜
先決條件
假設(shè)您的 Raspberry Pi 已刷入操作系統(tǒng)并能夠連接到 Internet。如果沒(méi)有,請(qǐng) 在繼續(xù)之前遵循Raspberry Pi 入門教程。這里我們使用 Rasbian Jessie 安裝 Raspberry Pi 3。
還假設(shè)您可以通過(guò)終端窗口或其他應(yīng)用程序訪問(wèn)您的 pi,您可以使用這些應(yīng)用程序編寫和執(zhí)行 python 程序并使用終端窗口。
您可能還想了解如何將 3.5 英寸 TFT LCD 與 Raspberry Pi 連接,因?yàn)槲覀儗⒃诖隧?xiàng)目中使用它。
為 Raspberry Pi 安裝 TTS 引擎 (Espeak)
正如項(xiàng)目標(biāo)題所述,我們將構(gòu)建一個(gè)說(shuō)話時(shí)鐘。為了讓您的 Pi 說(shuō)話,我們需要一個(gè)文本到語(yǔ)音 (TTS) 引擎。有很多選項(xiàng)可供選擇,但為了簡(jiǎn)單起見(jiàn),我選擇了Espeak Engine。要在您的 Pi 上安裝 Espeak,只需在終端上運(yùn)行以下命令
sudo apt-get install espeak
sudo apt-get install espeak python-espeak
為 Raspberry Pi 口語(yǔ)鬧鐘創(chuàng)建 GUI
對(duì)于這個(gè)項(xiàng)目,我們需要開發(fā)一個(gè)代表鬧鐘的 GUI,以便用戶可以查看當(dāng)前時(shí)間并設(shè)置鬧鐘。使用 Python 開發(fā) GUI有很多選擇,但最流行和通用的一個(gè)是PyQt4,所以我們將使用它來(lái)開發(fā)我們的 GUI。在下面的幾個(gè)標(biāo)題中,我們討論了如何使用 PyQt4 設(shè)計(jì)自己的 GUI,但如果您不感興趣,可以直接跳到“語(yǔ)音鬧鐘程序”標(biāo)題。
在 Windows 機(jī)器上使用 Qt 設(shè)計(jì)器安裝 PyQt4
由于我們正在設(shè)計(jì)一個(gè) GUI,我們將首先在我們的筆記本電腦(windows/Linux)上開始我們的編程,然后將這個(gè) python 腳本移植到我們的 Pi 上。由于 PyQt4 具有非常好的可移植性,大多數(shù)開發(fā)人員都會(huì)這樣做,因?yàn)樵诠P記本電腦上進(jìn)行開發(fā)既簡(jiǎn)單又快捷,而實(shí)際上在 Raspberry Pi 上進(jìn)行。
我已經(jīng)在我的 windows 機(jī)器上安裝了 python 和 PQt 包;如果您對(duì)此不感興趣,您可以跳過(guò)此步驟在您的樹莓派上開發(fā)您的 GUI。要在 Windows 上安裝 PQt,請(qǐng)下載此 exe 文件,并在安裝過(guò)程中確保您已檢查 Qt 設(shè)計(jì)器軟件,因?yàn)槲覀儗⒃谖覀兊捻?xiàng)目中使用它。
在 Pi/Linux/MAC 機(jī)器上安裝 PyQt
要在 Linux 機(jī)器上安裝 PyQt,只需在命令終端上運(yùn)行以下行
sudo apt-get install python-qt4
使用 Qt Designer 設(shè)計(jì) GUI
使用 PyQt4 進(jìn)行 GUI 設(shè)計(jì)的一個(gè)顯著優(yōu)勢(shì)是它具有Qt 設(shè)計(jì)器軟件。該軟件可用于創(chuàng)建按鈕、顯示、文本和其他圖形,只需將東西拖到屏幕上并將它們放置在需要的地方。這為我們節(jié)省了大量時(shí)間,因?yàn)槲覀儾槐厥謩?dòng)輸入屏幕上對(duì)象的大小和位置。我已經(jīng)使用上面段落中討論的 exe 文件在我的 Windows 筆記本電腦上安裝了 Qt 設(shè)計(jì)器以及 Python 和 PyQt4。安裝后打開你的 Qt Designer,你會(huì)得到這個(gè)屏幕。
在左側(cè),您可以找到布局、間隔、按鈕和其他項(xiàng)目,您只需將其拖到窗口中即可使用。您還可以使用右側(cè)的窗口根據(jù)需要自定義對(duì)象。我使用了一個(gè)7 段 LCD 顯示屏、一個(gè)按鈕、一個(gè)文本行和設(shè)置時(shí)間對(duì)象來(lái)為我們的鬧鐘創(chuàng)建 UI。使用布局將所有對(duì)象放置在所需的位置和大小后,我的窗口如下所示
準(zhǔn)備好 GUI 后,您可以將設(shè)計(jì)保存為.ui文件。以后,當(dāng)您希望對(duì) GUI 進(jìn)行更改時(shí),您只需打開此文件并進(jìn)行更改,而無(wú)需在程序中上下滾動(dòng)。如果您希望對(duì)此設(shè)計(jì)進(jìn)行任何更改,可以下載口語(yǔ)時(shí)鐘的.ui 文件。一旦您對(duì) GUI 設(shè)計(jì)感到滿意,您可以將其導(dǎo)出為 Python 代碼,您可以從那里開始您的 Python 編程。
我知道這里有很多事情會(huì)讓您不知所措,但是不可能在一個(gè)教程中解釋如何使用 Qt4 庫(kù)。您可以參考sentdex PyQt4 教程系列,了解如何使用 PyQt4 和 Qt 設(shè)計(jì)器軟件。
用于樹莓派口語(yǔ)鬧鐘的 Python 程序
此項(xiàng)目的完整 python 代碼在本頁(yè)末尾給出。您可以直接在您的 Raspberry pi 上運(yùn)行它以獲取輸出,但下面我將程序解釋為小片段,以便您了解該程序的工作原理。
Qt 設(shè)計(jì)器軟件已經(jīng)為我們編寫了幾乎一半的代碼,然后該代碼包含有關(guān)我們屏幕頂部對(duì)象的類型、樣式、大小和位置的信息。現(xiàn)在我們要做的就是為這些對(duì)象提供用途和功能。
7 段顯示器用于顯示當(dāng)前時(shí)間。設(shè)置時(shí)間對(duì)象用于選擇鬧鈴時(shí)間,點(diǎn)擊“設(shè)置鬧鈴”按鈕設(shè)置鬧鈴時(shí)間。底部的文本行顯示設(shè)置警報(bào)的時(shí)間和其他有用信息。除此之外,我們還必須在設(shè)置和觸發(fā)警報(bào)時(shí)播放語(yǔ)音??警報(bào)。
對(duì)于我們的程序,我們需要PyQt4來(lái)設(shè)計(jì) GUI 和espeak?來(lái)播放語(yǔ)音警報(bào)和時(shí)間包strftime來(lái)從 Pi 讀取當(dāng)前時(shí)間。所以我們使用下面的代碼行導(dǎo)入所有三個(gè)包。
?
from PyQt4 import QtCore, QtGui #PyQt4 用于設(shè)計(jì) GUI from espeak import espeak #text to Speech Sonversion from time import strftime # To get time from Raspberry pi
?
接下來(lái)我們有一個(gè)從 Qt 設(shè)計(jì)器獲得的代碼塊,這些代碼將包含我們放置在屏幕上的小部件的位置和大小。我們對(duì)代碼進(jìn)行了一些編輯,以便為小部件指定用途。首先,在 7 段 LCD 小部件上,我們必須顯示當(dāng)前時(shí)間,這可以通過(guò)使用strftime方法來(lái)完成,該方法將為我們提供在 Pi 上運(yùn)行的當(dāng)前時(shí)間。然后我們可以在 LCD 上顯示這個(gè)時(shí)間,如下所示。
?
self.Time_LCD = QtGui.QLCDNumber(self.centralwidget) self.Time_LCD.setObjectName(_fromUtf8("Time_LCD")) self.Time_LCD.setDigitCount(8) self.Time_LCD.display(strftime("%H"+":"+ "%M"+":"+"%S")) #從 Pi 獲取時(shí)間并顯示 self.gridLayout.addWidget(self.Time_LCD, 1, 0, 1, 3)
?
接下來(lái)我們有一個(gè)按鈕按下按鈕,當(dāng)按下這個(gè)按鈕時(shí),我們必須設(shè)置警報(bào)。所以我們使用了一種叫做button_pressed的方法。每當(dāng)按下此按鈕時(shí),都會(huì)調(diào)用函數(shù)button_pressed 。
?
self.pushButton = QtGui.QPushButton(self.centralwidget) self.pushButton.setObjectName(_fromUtf8("pushButton")) self.pushButton.clicked.connect(self.button_pressed) #當(dāng)按鈕按下時(shí)調(diào)用按鈕按下函數(shù) self.gridLayout。 addWidget(self.pushButton, 2, 1, 1, 1) MainWindow.setCentralWidget(self.centralwidget)
?
button_pressed函數(shù)如下所示。在這里,我們從設(shè)置的時(shí)間小部件中讀取小時(shí)和分鐘的值。此信息將采用字符串形式,因此可以對(duì)其進(jìn)行修剪以獲得小時(shí)和分鐘的值并存儲(chǔ)在變量alarm_h和alarm_m中。一旦我們有了分鐘和小時(shí)的值,我們就可以使用它與當(dāng)前的分鐘和小時(shí)進(jìn)行比較。
最后,在讀取設(shè)置的時(shí)間后,我們還使用字符串變量消息顯示文本。此消息將顯示為標(biāo)簽文本。
?
def button_pressed(self): #當(dāng)設(shè)置鬧鐘按鈕被按下時(shí) print("Button Pressed") alarm_time = str(self.Set_Time.time()) self.alarm_h = int(alarm_time[19:21]) #小時(shí)值為存儲(chǔ)在索引值 19 和 20 self.alarm_m = int (alarm_time[23:25]) #分鐘值存儲(chǔ)在索引值 23 和 24 message = "警報(bào)設(shè)置在 " + str(self.alarm_h) + " hours " + str(self.alarm_m) + " minutes" self.label.setText(_translate("MainWindow", message, None)) #顯示GUI 屏幕上 的消息 espeak.synth (message) #通過(guò)音頻插孔說(shuō)出消息
?
我們還通過(guò)使用espeak方法發(fā)出語(yǔ)音警報(bào),說(shuō)明警報(bào)已設(shè)置為某某時(shí)間。此方法只是說(shuō)出通過(guò)音頻插孔傳遞給它的任何文本。這里讀出了變量message中的字符串
?
espeak .synth (message) #通過(guò)音頻插孔說(shuō)出消息
?
最后,我們還需要一種方法,將當(dāng)前時(shí)間與設(shè)定時(shí)間進(jìn)行比較,當(dāng)兩者匹配時(shí),它必須通過(guò)語(yǔ)音通知用戶。為此,我們的代碼中有時(shí)間函數(shù),它將 current_h 與 alarm_h 和 current_m 與 alarm_m 進(jìn)行比較。當(dāng)兩者都匹配時(shí),它會(huì)通過(guò)說(shuō)出存儲(chǔ)在變量 message1 中的文本來(lái)觸發(fā)警報(bào)。如果你想讓時(shí)鐘說(shuō)別的東西,你可以自定義變量 message1;現(xiàn)在它會(huì)祝你早安以及當(dāng)前的時(shí)間和日期。
?
def Time(self): #比較當(dāng)前時(shí)間和設(shè)置時(shí)間 的函數(shù) self.Time_LCD.display(strftime("%H"+":"+"%M"+":"+"%S")) self.current_h = int (strftime("%H")) self.current_m = int (strftime("%M")) if (self.current_h == self.alarm_h) and (self.current_m == self.alarm_m) and ((int(strftime("%S"))%15) == 0): #如果兩個(gè)時(shí)間都匹配 print ("ALARM ON!!!!!") message1 = " 時(shí)間是 " + str(self.alarm_h) + " : " + str(self.alarm_m) + " on " + strftime("%A") message = “先生,早上好……這是您的起床鬧鐘。” + 消息1 self.label.setText(_translate("MainWindow",message1, None)) #在GUI屏幕上顯示 消息 espeak.synth (message) #通過(guò)音頻插孔朗讀消息 time.sleep (1)
?
Raspberry Pi 鬧鐘的硬件設(shè)置
該項(xiàng)目的硬件設(shè)置非常簡(jiǎn)單。我們的 PI 僅使用3.5 英寸 TFT LCD 屏幕。要設(shè)置顯示器,您可以按照接口 Pi 與 3.5 英寸 LCD 教程進(jìn)行操作。一旦你的接口完成,你應(yīng)該能夠使用手寫筆并瀏覽樹莓派的操作系統(tǒng)。為了播放您需要揚(yáng)聲器的聲音,我通過(guò) AUX 電纜將便攜式揚(yáng)聲器連接到 pi。一切設(shè)置好并啟動(dòng)程序后,我的設(shè)置如下所示。
基于 Pi 的口語(yǔ)鬧鐘的工作原理
如上所示準(zhǔn)備硬件,然后確保您已在 Pi 上安裝 PyQt4 和 Espeak。然后使用下面給出的python代碼,只需將其粘貼到python IDLE中并運(yùn)行程序。它將啟動(dòng) GUI 窗口,如下所示
它顯示當(dāng)前時(shí)間,還提供一個(gè)文本框來(lái)設(shè)置鬧鐘。使用觸控筆設(shè)置鬧鐘時(shí)間并按下設(shè)置鬧鐘按鈕。這將為您提供一條語(yǔ)音消息,說(shuō)明已設(shè)置警報(bào)?,F(xiàn)在只需等待 7 段顯示屏上顯示的當(dāng)前時(shí)間等于警報(bào)時(shí)間。當(dāng)它等于觸發(fā)警報(bào)時(shí),這將再次提供帶有當(dāng)前時(shí)間和日期的語(yǔ)音消息。在分鐘值更改之前,此警報(bào)將重復(fù)四次。該項(xiàng)目的完整工作可以在下面給出的視頻鏈接中找到。
# 使用 Raspberry Pi 說(shuō)話鬧鐘
#通過(guò) AUX 連接 3.5" LCD 和揚(yáng)聲器,并使用 PyQt4 和 espeak 包運(yùn)行程序
# 程序作者:B.Aswinth Raj?
# 網(wǎng)站: circuitdigest.com?
#?
# GUI 代碼是使用 Qt Designer 創(chuàng)建的?
導(dǎo)入系統(tǒng)
導(dǎo)入時(shí)間
from PyQt4 import QtCore, QtGui #PyQt4 用于設(shè)計(jì) GUI?
from espeak import espeak #text to Speech Sonversion?
from time import strftime # To get time from Raspberry pi
#Qt Designer 中的代碼
try:?
? ? _fromUtf8 = QtCore.QString.fromUtf8?
except AttributeError:?
? ? def _fromUtf8(s):?
? ? ? ? return s
嘗試:
? ? _encoding = QtGui.QApplication.UnicodeUTF8?
? ? def _translate(context, text, disambig):?
? ? ? ? return QtGui.QApplication.translate(context, text, disambig, _encoding)?
except AttributeError:?
? ? def _translate(context, text, disambig):?
? ? ? ? return QtGui. QApplication.translate(context, text, disambig)
類 Ui_MainWindow(object):?
? ? def setupUi(self, MainWindow):
? ? ? ? self.alarm_h = 0?
? ? ? ? self.alarm_m = 0?
? ? ? ? MainWindow.setObjectName(_fromUtf8("MainWindow"))?
? ? ? ? MainWindow.resize(676, 439)?
? ? ? ? self.centralwidget = QtGui.QWidget(MainWindow)?
? ? ? ? self.centralwidget.setObjectName(_fromUtf8("centralwidget" ))?
? ? ? ? self.gridLayout = QtGui.QGridLayout(self.centralwidget)?
? ? ? ? self.gridLayout.setObjectName(_fromUtf8("gridLayout"))?
? ? ? ? self.label = QtGui.QLabel(self.centralwidget)?
? ? ? ? font = QtGui.QFont()?
? ? ? ? font.setPointSize( 14)?
? ? ? ? self.label.setFont(font)?
? ? ? ? self.label.setObjectName(_fromUtf8("label"))?
? ? ? ? self.gridLayout.addWidget(self.label, 3, 0, 1, 1)
? ? ? ? self.Time_LCD = QtGui.QLCDNumber(self.centralwidget)?
? ? ? ? self.Time_LCD.setObjectName(_fromUtf8("Time_LCD"))?
? ? ? ? self.Time_LCD.setDigitCount(8)?
? ? ? ? self.Time_LCD.display(strftime("%H"+":"+ "%M"+":"+"%S")) #從 Pi 獲取時(shí)間并顯示?
? ? ? ? self.gridLayout.addWidget(self.Time_LCD, 1, 0, 1, 3)
? ? ? ? self.timer = QtCore.QTimer(MainWindow)?
? ? ? ? self.timer.timeout.connect(self.Time)?
? ? ? ? self.timer.start(1000)?
? ? ? ? current_time = QtCore.QTime()?
? ? ? ? self.Set_Time = QtGui.QTimeEdit(self.centralwidget)?
? ? ? ? self .Set_Time.setObjectName(_fromUtf8("Set_Time"))?
? ? ? ? self.Set_Time.setTime(current_time.currentTime())?
? ? ? ? self.gridLayout.addWidget(self.Set_Time, 2, 0, 1, 1)
? ? ? ? self.pushButton = QtGui.QPushButton(self.centralwidget)?
? ? ? ? self.pushButton.setObjectName(_fromUtf8("pushButton"))?
? ? ? ? self.pushButton.clicked.connect(self.button_pressed)?
? ? ? ? self.gridLayout.addWidget(self.pushButton, 2, 1 , 1, 1)?
? ? ? ? MainWindow.setCentralWidget(self.centralwidget)?
? ? ? ? self.menubar = QtGui.QMenuBar(MainWindow)?
? ? ? ? self.menubar.setGeometry(QtCore.QRect(0, 0, 676, 21))?
? ? ? ? self.menubar.setObjectName(_fromUtf8( "menubar"))?
? ? ? ? MainWindow.setMenuBar(self.menubar)?
? ? ? ? self.statusbar = QtGui.QStatusBar(MainWindow)?
? ? ? ? self.statusbar.setObjectName(_fromUtf8("statusbar"))?
? ? ? ? MainWindow.setStatusBar(self.statusbar)
? ? ? ? self.retranslateUi(MainWindow)?
? ? ? ? QtCore.QMetaObject.connectSlotsByName(MainWindow)
#Qt Designer 代碼結(jié)束
? ? def retranslateUi(self, MainWindow): #更新GUI窗口?
? ? ? ? print("Dispay Re-translated")?
? ? ? ? MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))?
? ? ? ? self.label.setText(_translate("MainWindow" , "警報(bào)當(dāng)前已關(guān)閉", None))?
? ? ? ? self.pushButton.setText(_translate("MainWindow", "Set Alarm", None))
? ? def Time(self): #比較當(dāng)前時(shí)間和設(shè)置時(shí)間?
? ? ? ? 的函數(shù) self.Time_LCD.display(strftime("%H"+":"+"%M"+":"+"%S"))?
? ? ? ? self.current_h = int (strftime("%H"))?
? ? ? ? self.current_m = int (strftime("%M"))
? ? ? ? if (self.current_h == self.alarm_h) and (self.current_m == self.alarm_m) and ((int(strftime("%S"))%15) == 0): #如果兩個(gè)時(shí)間都匹配?
? ? ? ? ? ? print ("ALARM ON!!!!!")?
? ? ? ? ? ? message1 = " 時(shí)間是 " + str(self.alarm_h) + " : " + str(self.alarm_m) + " on " + strftime("%A")?
? ? ? ? ? ? message = “先生,早上好……這是您的起床鬧鐘。” + message1?
? ? ? ? ? ? self.label.setText(_translate("MainWindow",message1, None)) #在GUI屏幕上顯示??
? ? ? ? ? ? 消息 espeak.synth (message) #通過(guò)音頻插孔朗讀消息 time.sleep??
? ? ? ? ? ? (1)
? ? def button_pressed(self): #當(dāng)設(shè)置鬧鐘按鈕被按下時(shí)?
? ? ? ? print("Button Pressed")?
? ? ? ? alarm_time = str(self.Set_Time.time())?
? ? ? ? self.alarm_h = int(alarm_time[19:21]) #小時(shí)值為存儲(chǔ)在索引值 19 和 20?
? ? ? ? self.alarm_m = int (alarm_time[23:25]) #分鐘值存儲(chǔ)在索引值 23 和 24
? ? ? ? message = "警報(bào)設(shè)置在 " + str(self.alarm_h) + " hours " + str(self.alarm_m) + " minutes"?
? ? ? ? self.label.setText(_translate("MainWindow", message, None)) #顯示GUI 屏幕上??
? ? ? ? 的消息 espeak.synth (message) #通過(guò)音頻插孔說(shuō)出消息?
if __name__ == "__main__": #main function??
? ? app = QtGui.QApplication(sys.argv)?
? ? MainWindow = QtGui.QMainWindow()?
? ? ui = Ui_MainWindow()?
? ? ui.setupUi(MainWindow)?
? ? MainWindow.show()?
? ? sys.exit(app.執(zhí)行_())
評(píng)論
查看更多