"Доброе утро. Сейчас 7 часов утра. Погода на Малибу 35 градусов выше нуля. Ожидаются небольшие осадки. Наибольший прилив ожидается в 10:52". Наверняка те, кто смотрел серию фильмов про "Железного человека" хорошо помнят этот будильник, говорящий голосом Джарвиса (Jarvis). Конечно, мы пока не можем достичь того уровня жизни, которым жил Тони Старк в "Железного человека" – нам этого пока не позволяют технологии. Но вот заменить наш скучный будильник на тот, который был у Тони Старка, мы уже определенно можем.
В данной статье мы рассмотрим создание говорящего будильника на основе платы Raspberry Pi, интерфейс которого оформлен в стиле "Железного человека". Интерфейс для данного будильника мы разработаем сами, в специализированном GUI (графическом интерфейсе пользователя). Мы запрограммируем чтобы будильник при срабатывании говорил нам текущее время и дату, а также небольшой заранее запрограммированный текст.
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- 3.5” TFT LCD (сенсорный TFT ЖК дисплей диагональю 3,5 дюйма) (купить на AliExpress).
- Громкоговоритель (колонка).
- AUX кабель.
- Соединение с сетью интернет.
Подключение 3.5” TFT ЖК дисплея к плате Raspberry Pi мы рассматривали в этой статье.
Установка преобразователя текста в речь на Raspberry Pi
Поскольку в данном проекте мы будем рассматривать создание говорящего будильника, то на плату Raspberry Pi необходимо будет установить программу преобразователя текста в речь (Text To speech (TTS) Engine). Для Raspberry Pi существует огромный выбор таких преобразователей, но в целях упрощения проекта для этой цели мы решили выбрать Espeak Engine. Чтобы установить Espeak на Raspberry Pi выполните следующие две простые команды:
1 2 |
sudo apt-get install espeak sudo apt-get install espeak python-espeak |
Создание графического интерфейса для говорящего будильника
Для данного проекта мы разработаем специальный графический интерфейс пользователя (graphical user interface, GUI) чтобы пользователь мог в удобном виде просматривать текущее время и устанавливать время срабатывания будильника. Для Python существует достаточно много инструментов для разработки графического интерфейса пользователя, но одним из популярных и универсальных является PyQt4 – его мы и выбрали для нашего проекта. Вы можете пропустить этот пункт статьи если он вам не интересен.
Установка PyQt4 с Qt конструктором на компьютер с Windows
Наш графический интерфейс пользователя мы сначала разработаем на компьютере Windows, а затем портируем его на нашу Raspberry Pi – инструмент PyQt4 позволяет это сделать.
Для установки PQt на компьютер с Windows скачайте этот исполнимый exe файл, запустите его установку, во время которой не забудьте выбрать в опциях установку Qt конструктора (Qt designer) поскольку он нам понадобится для нашего проекта.
Установка PyQt на Raspberry Pi/Linux/MAC
Для установки PyQt на компьютер с Linux просто выполните следующую команду в терминале:
1 |
sudo apt-get install python-qt4 |
Разработка GUI с помощью Qt конструктора
Одним из значимых преимуществ инструмента PyQt4 для создания GUI (графического интерфейса пользователя) является то, что он содержит программное обеспечение Qt конструктора (Qt designer software). Это программное обеспечение можно использовать для создания различных кнопок, дисплеев, текстовых полей и других графических элементов просто путем их перетаскивания (dragging) в рабочее поле с панели инструментов. Это очень удобно и экономит очень много времени разработчику. Мы установили Qt конструктор (Qt designer) вместе с Python и PyQt4 на наш компьютер с Windows с помощью exe файла как было описано в предыдущем пункте статьи. После установки Qt конструктора (Qt designer) запустите его на выполнение и вы на экране должны увидеть следующую картину:
В панели слева находятся макеты (layout), разделители (spacers), кнопки и другие графические элементы, которые вы можете перетащить в рабочее поле своего проекта. Вы также можете настроить внешний вид этих элементов с помощью панели, которая находится справа. Мы использовали семисегментный индикатор (7-segment LCD display), кнопку, текстовую строку и объект для установки времени для создания графического интерфейса нашего будильника. Внешний вид получившегося у нас интерфейса показан на следующем рисунке.
Когда ваш GUI в Qt конструкторе будет готов вы можете сохранить его в виде .ui файла. В дальнейшем вы при необходимости можете внести изменения в этот файл не внося при этом изменений в программу. Если вы не хотите проделывать все те операции для создания дизайна говорящего будильника, которые были описаны в данном разделе, вы можете скачать готовый .ui файл для данного проекта. Когда вы будете удовлетворены спроектированным интерфейсом говорящего будильника, вы можете экспортировать его в код программы на python и после этого приступать к написанию основного кода программы.
У библиотеки Qt4 так много возможностей, что их просто невозможно рассмотреть в рамках одной статьи. Более подробно про эту библиотеку вы можете посмотреть в следующем видео - sentdex PyQt4 tutorial series, в котором объясняется как работать с библиотекой PyQt4 и Qt конструктором (на английском языке).
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Почти половина кода программы написана для нас программным обеспечением Qt конструктора. Эта часть кода программы содержит информацию о типе, стиле, размерах и позициях графических объектов интерфейса будильника на экране ЖК дисплея. Теперь все, что нам осталось сделать – это задать логику функционирования для этих объектов.
Семисегментный индикатор (7-segment display) используется для отображения текущего времени. Объект установки времени (set-time object) используется для установки времени срабатывания будильника – чтобы его установить необходимо нажать кнопку “set alarm”. Текстовая строка внизу экрана показывает время, на которое установлен будильник, и другую полезную информацию. Кроме этого, будильник должен произносить часть текстовой информации голосом.
Первым делом нам в программе необходимо подключить (импортировать) необходимые библиотеки. Для нашей программы будет необходима библиотека PyQt4 для проектирования графического интерфейса пользователя (GUI) и библиотека espeak текста в речь (голосовую информацию). Также нам понадобится пакет strftime для считывания текущего времени с Raspberry Pi.
1 2 3 |
from PyQt4 import QtCore, QtGui #PyQt4 is used for designing the GUI from espeak import espeak #text to speech sonversion from time import strftime # To get time from Raspberry pi |
Далее у нас в программе присутствует несколько фрагментов кода, которые были сформированы Qt конструктором (Qt designer). Эти фрагменты кода состоят из позиций и размеров виджетов (визуальных элементов), которые мы поместили на экран нашего будильника. Мы немного подредактировали эти фрагменты кода чтобы назначить цели виджетам. На семисегментном индикаторе мы будем отображать текущее время с помощью метода strftime, который обеспечит нас информацией о текущем времени, считанным с платы Raspberry Pi.
1 2 3 4 5 |
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")) #get time from Pi and display it self.gridLayout.addWidget(self.Time_LCD, 1, 0, 1, 3) |
Также мы имеем в составе разработанного интерфейса будильника кнопку. При нажатии этой кнопки будет производиться установка времени срабатывания будильника. Для этого мы использовали метод под названием button_pressed. Всегда, когда будет нажиматься кнопка, будет вызываться на выполнение функция button_pressed.
1 2 3 4 5 |
self.pushButton = QtGui.QPushButton(self.centralwidget) self.pushButton.setObjectName(_fromUtf8("pushButton")) self.pushButton.clicked.connect(self.button_pressed) #when button pressed call the button pressed function self.gridLayout.addWidget(self.pushButton, 2, 1, 1, 1) MainWindow.setCentralWidget(self.centralwidget) |
Внутри функции button_pressed мы будем считывать значения часов и минут с виджета установки времени. Эта информация будет в форме строки, поэтому для получения значений часов и минут нам будет необходимо извлечь эту информацию из строки. Извлеченные значения часов и минут мы будем хранить в переменных alarm_h и alarm_m соответственно. Как только мы получили эти значения часов и минут мы можем сравнивать их со значениями текущего времени (часов и минут).
И, наконец, после установки времени срабатывания будильника, мы будем отображать текст на экране с помощью строковой переменной, значение которой будет присваиваться текстовой метке (label text).
1 2 3 4 5 6 7 8 9 10 |
def button_pressed(self): #when set alarm button is pressed print("Button Pressed") alarm_time = str(self.Set_Time.time()) self.alarm_h = int(alarm_time[19:21]) #value of hour is sotred in index value 19 and 20 self.alarm_m = int (alarm_time[23:25]) #value of minute is sotred in index value 23 and 24 message = "Alarm is set at " + str(self.alarm_h) + " hours " + str(self.alarm_m) + " minutes" self.label.setText(_translate("MainWindow", message, None)) #display the message on GUI screen espeak.synth (message) #speak the message through audio jack |
Также мы будем транслировать с помощью функции espeak.synth голосовое сообщение о том, что время срабатывания будильника было установлено.
1 |
espeak.synth (message) #speak the message through audio jack |
Также в программе нам будет необходима функция, которая будет сравнивать текущее время со временем установки будильника и при их совпадении голосом уведомлять пользователя об этом. Соответственно, в коде этой функции будут сравниваться значения переменных current_h и alarm_h и переменных current_m и alarm_m. При их совпадении с помощью голосового сообщения будет воспроизводиться текстовое сообщение, хранящееся в переменной message1. Вы можете самостоятельно при необходимости отредактировать текст, хранящийся в переменной message1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def Time(self): #Function to compare current time with set time 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): #if the both time match print("ALARM ON!!!!!") message1 = " The time is " + str(self.alarm_h) + " : " + str(self.alarm_m) + " on " + strftime("%A") message = "Sir, Good morning.. This is your wake up Alarm." + message1 self.label.setText(_translate("MainWindow",message1, None)) #display the message on GUI screen espeak.synth (message) #speak the message through audio jack time.sleep(1) |
Сборка аппаратной части проекта
Аппаратная часть проекта для нашего говорящего будильника в стиле "Железного человека" достаточно проста. Нам всего лишь необходимо подключить сенсорный 3.5” TFT ЖК дисплей к плате Raspberry Pi. После этого вы можете использовать стилус для навигации по Raspberry Pi OS. Для воспроизведения голоса в проекте вам понадобится громкоговоритель (колонка), подключенный через AUX кабель (именно через него транслируется звук в программе). После сборки у нас получилась следующая конструкция проекта:
Тестирование работы проекта
После того как аппаратная часть проекта будет готова убедитесь в том, что вы установили библиотеки PyQt4 и Espeak на свою плату Raspberry Pi. Запустите программу проекта (приведена в конце статьи) на выполнение. В результате работы программы на экране дисплея появится окно GUI (графического интерфейса пользователя) как показано на следующем рисунке.
В нем будет отображаться текущее время. Также присутствует кнопка для установки времени срабатывания будильника. Используйте стилус чтобы нажать на эту кнопку и установить время для будильника. Когда время срабатывания будильника будет установлено, вы услышите голосовое сообщение, извещающее вас об этом.
Теперь, когда текущее время будет равно времени срабатывания будильника (то есть будильник должен сработать), вы услышите голосовое сообщение, извещающее вас о текущем дне и времени. Сигнал будильника будет повторен 4 раза перед тем как изменится значение минут в текущем времени. Более подробно всю работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Вы можете модернизировать этот проект по своему желанию, например, можете добавить кнопку останова сигнала будильника. Также вы можете изменить текст сообщения, которое произносится голосом при срабатывании будильника.
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# Speaking alarm clock using Raspberry Pi #Connect 3.5" LCD and speaker though AUX and run the program with PyQt4 and espeak packages # Program by: B.Aswinth Raj # Website: circuitdigest.com # # GUI code was created using Qt Designer import sys import time from PyQt4 import QtCore, QtGui #библиотека PyQt4 используется для проектирования GUI from espeak import espeak # text to speech conversion (библиотека для преобразования текста в речь) from time import strftime # библиотека для получения текущего времени с Raspberry pi #Code from Qt Designer (код, созданный Qt конструктором) 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) #End of code from Qt Designer def retranslateUi(self, MainWindow): # обновляем окно GUI print("Dispay Re-translated") MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.label.setText(_translate("MainWindow", "Alarm curretly Turned off", 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 = " The time is " + str(self.alarm_h) + " : " + str(self.alarm_m) + " on " + strftime("%A") message = "Sir, Good morning.. This is your wake up Alarm." + message1 self.label.setText(_translate("MainWindow",message1, None)) #отображаем сообщение на экране GUI espeak.synth (message) # воспроизводим голосовое сообщение через audio jack time.sleep(1) def button_pressed(self): # when set alarm button is pressed (когда кнопка установки времени срабатывания будильника нажата) print("Button Pressed") alarm_time = str(self.Set_Time.time()) self.alarm_h = int(alarm_time[19:21]) #value of hour is sotred in index value 19 and 20 (значение часа хранится в массиве в элементах с индексами 19 и 20) self.alarm_m = int (alarm_time[23:25]) #value of minute is sotred in index value 23 and 24 message = "Alarm is set at " + str(self.alarm_h) + " hours " + str(self.alarm_m) + " minutes" self.label.setText(_translate("MainWindow", message, None)) # отображаем сообщение на экране GUI screen espeak.synth (message) # воспроизводим голосовое сообщение через audio jack if __name__ == "__main__": # main function (основная функция программы) app = QtGui.QApplication(sys.argv) MainWindow = QtGui.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_()) |