手把手教你做一個天貓精靈(二)

語言: CN / TW / HK

上一章講到如何使用fubuki-iot製作一個簡單的電腦版的天貓精靈,這次需要把它運行在硬件上。考慮到硬件環境比較複雜,我最終選擇了相對簡單的樹莓派(Ubuntu 22.04 LTS 64bit)。同時,配合麥克風、揚聲器等元件可以滿足基本的語音輸入和輸出功能。

硬件準備

  • 樹莓派(Raspberry Pi 3/4/zero w均可,但是要能聯網)
  • 揚聲器、麥克風(最好是免驅動的)
  • 開關、麪包板、杜邦線、充電線等

硬件環境搭建

樹莓派

我用的是Raspberry Pi Zero 2w,但是發現USB接口不夠又添加了擴展版。如圖所示:

樹莓派

提醒:如果第一次使用需要刷系統。最新的刷系統方式是通過 Raspberry Pi Imager 刷的,可以在官網下載這個軟件,然後選擇對應的Linux系統,並配置賬户、WIFI等信息,最後寫到SD卡中。然後將SD卡插入樹莓派,連上電源就可以運行了。

啟動樹莓派後先通過SSH登陸樹莓派,然後下載 fubuki-iot包和RPI.GPIO包。如果沒有pip需要先安裝對應版本的pip。

fubuki-iot安裝

fubuki-iot這個包是默認包含pyaudio包的,而pyaudio是需要C++擴展包安裝的,所以要安裝對應的api:

shell sudo apt-get update sudo apt-get install build-essential

這個軟件包括arm-linux-gnueabihf-gcc這個C++編譯器,在Linux環境下開發經常要用到。此外,我們還要下載對應的Python接口和Audio接口以供C++調用:

shell sudo apt-get install python3-dev sudo apt install portaudio19-dev python3-pyaudio

最後安裝fubuki-iot應該可以能正常安裝了:

pip install fubuki-iot

RPI.GPIO安裝

這個包也需要底層依賴的支持,只需要安裝Linux的GPIO支持即可:

shell sudo apt-get install rpi.gpio pip install RPI.GPIO

其實,樹莓派的GPIO還支持I2C和SPI協議,它們可以通過極少的引腳數完成元件設備之間的通信。此外,樹莓派也支持UART串口通信,這大大加速了元件之間的交流速率。但是這些內容我們目前還接觸不到,只需要最原始的GPIO對引腳操作即可。

樹莓派引腳圖

按鈕

在上一章中,我們通過鍵盤喚醒智能終端的,在樹莓派中,我們可以結合其GPIO能力,通過按鈕喚醒它。根據上圖,我們選擇一個GPIO引腳作為輸入,如果為高電平則表示喚醒,可以如圖所示接入:

接入

接入-事務

通過開關直接和電源和GPIO4相連,這樣當開關閉合的時候就可以給樹莓派一個高電平觸發喚醒功能了。但是這樣接會導致開關斷開的時候引腳是高阻態,因此最好是按照下面方法接入:

接入2

這樣,閉合開關後相當於把電阻短路了,這樣是高電平。而斷開狀態引腳則直接和GND相連,所以是低電平。

提醒:在數字信號領域中有“上拉電阻”和“下拉電阻”的概念,具體可以查找相關資料。

麥克風、揚聲器和電源

由於使用的是免驅動的麥克風和揚聲器,所以直接通過USB接口和揚聲器接口接到樹莓派上即可。但是仍有可能遇到依賴缺失的問題,比如ALSA報錯,這時候需要安裝alsa-utils,具體可點擊這裏

樹莓派的供電是為人詬病的地方,其所有版本的電壓不能超過 5V ,而電流則是在條件允許的情況下越大越好。我採用的是原配的充電器,即5V-2000mA。剛開始會有點供電不足的情況但後來有點緩解,而使用移動電源(3.6V-10000mA)則有明顯的異味。同時,用原配電源也不宜太長。

連接圖

程序開發

上一章我們用fubuki-iot創建了一個語義模型,並實現了提醒事項的功能,這次我們要創建一個錄音設備,從而實現通過GPIO喚醒終端。

首先,我們在原有的mods目錄下創建一個文件,命名為gpio.py,並在入口文件app.py中加入一行引入這個文件:

```python from iot import Terminal Terminal.load_models('mods.timer') Terminal.load_models('mods.gpio')

if name == 'main': Terminal.run() ```

然後,在gpio.py中創建一個類,讓它繼承Recorder代表錄音機,並實現兩個方法。其中awake方法調用GPIO輪詢檢查GPIO4的電平狀態,如果是高電平則返回True代表喚醒。而record函數則仍然使用內置的AudioClient,具體如下調用:

```python import RPi.GPIO as GPIO import time as tm

from iot import Recorder, RecorderFactory from iot.integration.audio import AudioClient from iot.utils import get_slash from iot.context import Context

@RecorderFactory.set class RaspberryRecorder(Recorder):

def awake(self) -> bool:
    print("按下按鈕喚醒終端")
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(7, GPIO.IN)
    while True:
        if GPIO.input(7):
            GPIO.cleanup()
            return True

def record(self, time: int) -> str:
    data = AudioClient.record(time=time)
    local_time = tm.strftime('%Y-%m-%d_%H-%M-%S', tm.localtime())
    path = f'{Context.config["RESOURCE_PATH"]}{get_slash()}wav{get_slash()}{local_time}.wav'
    AudioClient.save(data=data, path=path)
    return path

```

最後,我們再修改一下配置文件,添加一行如下:

DEVICE_REC=RaspberryRecorder

注意:dotenv包在我的Linux環境下有點問題,有時找不到.env文件,但是把它移到項目根目錄的外層。即/home/pi/目錄下就可以找到了。

最後,我們運行程序。就可以通過按鈕實現對終端的喚醒,並使用提醒事項的功能。

同樣,樹莓派的環境下仍可以使用PocketSphinx的語音喚醒功能,也需要下載相關的依賴,具體點擊這裏

在這一章中,我們把項目移植到了樹莓派中,但是受硬件限制所以需要安裝很多依賴,可能每個人遇到的問題都不一樣。下一章我們要實現智能終端操作硬件的功能。