游乐游手机版
首页/AI热点日报/热点详情

从零开始用树莓派制作Jarvis主题口语闹钟教程

类型:热点整理2026-07-06
“早上好。现在是早上7:00,马里布天气72度,云层散落。冲浪条件一般,浪高到腰到肩。涨潮时间为上午10:52。”每次在电影《钢铁侠》里听到贾维斯报时,总让人心头一震。相信不少人跟我一样,幻想过托尼·斯塔克那种精致的生活——可惜的是,微型方舟反应堆和像JARVIS一样聪明的AI还没普及。不过,用树莓

“早上好。现在是早上7:00,马里布天气72度,云层散落。冲浪条件一般,浪高到腰到肩。涨潮时间为上午10:52。”每次在电影《钢铁侠》里听到贾维斯报时,总让人心头一震。相信不少人跟我一样,幻想过托尼·斯塔克那种精致的生活——可惜的是,微型方舟反应堆和像JARVIS一样聪明的AI还没普及。不过,用树莓派做一个类似贾维斯的闹钟,倒是能拯救一下我们每天无聊的起床铃声。这个项目做完,你会得到一个非常基础的GUI界面,用来设置闹钟,闹钟响起时,它会通过语音告诉你当前时间和日期。听起来够酷吧?那就动手吧。

所需材料

  • 树莓派
  • 3.5英寸TFT液晶屏
  • 扬声器
  • AUX线缆
  • 网络连接

先决条件

假设你的树莓派已经刷好了操作系统,并且能连上互联网——如果还没搞定,先参考树莓派入门教程把基础搭好。这里用的是Raspbian Jessie系统,树莓派3代。

另外,你需要能通过终端或别的应用访问树莓派,用来写Python程序、跑命令。还有一点,最好提前了解怎么把3.5英寸TFT LCD接到树莓派上,因为本项目要用到它。

为树莓派安装TTS引擎(Espeak)

我们要做一个会说话的闹钟,所以得让树莓派能开口。文本转语音(TTS)引擎很多,但为了简单,这里选了Espeak。在终端里跑下面这两条命令就行:

sudo apt-get install espeak
sudo apt-get install espeak python-espeak

为树莓派说话闹钟创建GUI

这个项目需要一个能显示当前时间、设置闹钟的图形界面。Python的GUI库不少,最流行也最通用的要算PyQt4——我们就用它来开发。下面几个小节会介绍怎么用PyQt4设计自己的GUI,当然,如果你急着看代码,可以直接跳到“说话闹钟程序”那一节。

在Windows上使用Qt Designer安装PyQt4

设计GUI时,通常先在笔记本(Windows/Linux)上写程序,再移植到树莓派上。PyQt4的移植性很好,大多数开发者都这么干,毕竟在笔记本上开发比直接在树莓派上敲代码快多了。

如果你的Windows机器上已经装好了Python和PyQt包,可以跳过这一段。还没装的话,下载对应的exe文件,安装时记得勾选Qt Designer软件,因为我们要用它来设计界面。

在Pi/Linux/MAC上安装PyQt

在Linux系统上安装PyQt很简单,终端里跑这一句:

sudo apt-get install python-qt4

使用Qt Designer设计GUI

PyQt4的一大亮点就是Qt Designer——这个软件可以让你用拖拽的方式把按钮、显示屏、文本框摆到窗口上,省去了手动输入坐标和尺寸的麻烦。安装好Qt Designer后打开它,你会看到这样的界面:

左侧是布局、间隔、按钮等各种组件,直接拖到窗口上就能用。右侧面板可以自定义对象的属性。这里用了一个7段LCD显示屏、一个按钮、一个时间编辑框(Set Time)来构建闹钟的UI。调整好位置和大小后,窗口大概是这个样子:

设计好GUI后,把它保存为.ui文件。以后想修改,打开这个文件就行,不用在代码里上下翻找。如果你需要调整,也可以下载说话闹钟的.ui文件作为参考。满意后,把.ui文件导出为Python代码,接下来就可以开始真正的编程了。

Qt Designer生成的文件已经包含了界面上的所有对象信息(类型、样式、大小、位置)。我们要做的,就是给这些对象赋予功能和逻辑。关于PyQt4的更多用法,可以参考相关教程系列,这里就不展开了。

用于树莓派说话闹钟的Python程序

完整的Python代码在页面最后给出,可以直接在树莓派上运行。下面把程序拆成小片段来讲,方便理解。

程序中,7段LCD用于显示当前时间;时间编辑框用来选择闹铃时间;按下“Set Alarm”按钮就设置闹铃;底部的文本行会显示设置的时间和其他信息。除此之外,闹钟设置和触发时都要播放语音。

我们需要导入三个包:PyQt4做GUI,espeak做语音,time库里的strftime用来获取当前时间。代码如下:

from PyQt4 import QtCore, QtGui
from espeak import espeak
from time import strftime

接着是从Qt Designer导出的代码块,它定义了所有小部件的位置和尺寸。我们稍微编辑了一下,给每个小部件指定了用途。首先,在7段LCD上显示当前时间:

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"))
self.gridLayout.addWidget(self.Time_LCD, 1, 0, 1, 3)

再来看按钮部分:当“Set Alarm”按钮被按下时,会触发一个叫button_pressed的函数:

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)

button_pressed函数的实现如下:从时间编辑框里读取小时和分钟的值(字符串格式),然后提取出整数并存储到alarm_h和alarm_m变量中。接着把设置时间显示在标签上,同时通过espeak读出语音提示:

def button_pressed(self):
    print("Button Pressed")
    alarm_time = str(self.Set_Time.time())
    self.alarm_h = int(alarm_time[19:21])  # 小时存在索引19、20
    self.alarm_m = int(alarm_time[23:25])  # 分钟存在索引23、24
    message = "闹钟设置在 " + str(self.alarm_h) + " hours " + str(self.alarm_m) + " minutes"
    self.label.setText(_translate("MainWindow", message, None))
    espeak.synth(message)

最后,还需要一个比较函数,不断将当前时间与设定时间对比,一旦匹配就触发语音通知。这个函数叫Time,每秒执行一次(由QTimer驱动)。它读出当前小时和分钟,与alarm_h、alarm_m比较,同时判断秒数是否为15的倍数(避免重复触发)。匹配时,用语音播报时间和日期:

def Time(self):
    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):
        print("ALARM ON!!!!!")
        message1 = "时间是 " + str(self.alarm_h) + " : " + str(self.alarm_m) + " on " + strftime("%A")
        message = "先生,早上好……这是您的起床闹钟。" + message1
        self.label.setText(_translate("MainWindow", message1, None))
        espeak.synth(message)
        time.sleep(1)

树莓派闹钟的硬件设置

硬件部分非常简单:树莓派连接3.5英寸TFT LCD屏幕(可参考LCD接口教程),再通过AUX线把便携式扬声器接到Pi的音频口。一切就绪后,启动程序,效果如下:

基于Pi的说话闹钟的工作原理

硬件连好,确保树莓派上已经安装了PyQt4和Espeak。然后把下面的完整Python代码粘贴到IDLE中运行,就会弹出GUI窗口:

窗口显示当前时间,还有一个时间编辑框用来设置闹铃。用触控笔设定时间,按下“Set Alarm”按钮,树莓派会发出语音告诉你闹钟已设置。接着只需等待当前时间与设定时间匹配——匹配时,语音会报出时间和日期。在分钟值变化之前,闹钟会重复四次(每隔15秒播报一次)。完整的工作演示可以看下面的视频链接(此处省略)。

# 使用树莓派说话闹钟
# 通过AUX连接3.5英寸LCD和扬声器,并使用PyQt4和espeak包运行程序

import sys
import time
from PyQt4 import QtCore, QtGui
from espeak import espeak
from time import strftime

# Qt Designer生成的代码
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _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)

class 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"))
        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)

    def retranslateUi(self, MainWindow):
        print("Display Re-translated")
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.label.setText(_translate("MainWindow", "闹钟当前已关闭", None))
        self.pushButton.setText(_translate("MainWindow", "Set Alarm", None))

    def Time(self):
        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):
            print("ALARM ON!!!!!")
            message1 = "时间是 " + str(self.alarm_h) + " : " + str(self.alarm_m) + " on " + strftime("%A")
            message = "先生,早上好……这是您的起床闹钟。" + message1
            self.label.setText(_translate("MainWindow", message1, None))
            espeak.synth(message)
            time.sleep(1)

    def button_pressed(self):
        print("Button Pressed")
        alarm_time = str(self.Set_Time.time())
        self.alarm_h = int(alarm_time[19:21])
        self.alarm_m = int(alarm_time[23:25])
        message = "闹钟设置在 " + str(self.alarm_h) + " hours " + str(self.alarm_m) + " minutes"
        self.label.setText(_translate("MainWindow", message, None))
        espeak.synth(message)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
来源:https://m.elecfans.com/article/1870320.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。