Raspberry Pi 是一款手掌大小的計算機,具有內(nèi)置藍牙、Wi-Fi、以太網(wǎng)端口、攝像頭端口等,使其最適合基于 IoT 的嵌入式應(yīng)用程序的微控制器。它還用于制作多種服務(wù)器,如打印服務(wù)器、媒體服務(wù)器、Web 服務(wù)器等。今天我們將學(xué)習(xí)樹莓派如何將具有 3.5 毫米插孔的普通揚聲器轉(zhuǎn)換為無線藍牙揚聲器。
在這篇文章中,我們將通過融合 A2DP、Linux 和音頻編解碼器的強大功能來構(gòu)建基于 Raspberry Pi 的藍牙揚聲器,以將數(shù)據(jù)包從音頻源無線傳輸?shù)揭纛l接收器。為此,我們將破解一點 Linux 系統(tǒng)并用 bash 和 python 編寫一段代碼,然后我們就可以開展業(yè)務(wù)了。
A2DP
A2DP 是Advanced Audio Distribution Profile的首字母縮寫。這是幾乎所有支持藍牙的設(shè)備中都存在的協(xié)議。它為從一個設(shè)備到另一個設(shè)備的聲音數(shù)據(jù)傳輸鋪平了道路,前提是它們都通過藍牙相互連接。A2dp 使用無損壓縮算法在傳輸前壓縮音頻數(shù)據(jù)包以減少延遲,但由于這種壓縮導(dǎo)致的損失幾乎無法被人耳感知。
為無頭設(shè)置準備 Raspberry Pi
要將 Raspberry Pi 轉(zhuǎn)換為無線揚聲器,首先將 OS(Raspbian Stretch)安裝到 Raspberry PI SD 卡中,如果您是 Raspberry Pi 新手,請按照本文開始使用 Raspberry Pi。
我們大多數(shù)人都擁有 Raspberry Pi 和筆記本電腦,但沒有顯示器。但是為了通過 SSH 連接到 Raspberry Pi,我們希望將其連接到與我們的計算機連接的同一網(wǎng)絡(luò)中。我們需要連接到 Pi 的顯示器,通過它我們可以選擇 Wi-Fi 并連接?
其實我們沒有。Raspberry Pi 可以通過向名為wpa_supplicant.conf的文件添加條目來連接到 Wi-Fi
為此,請將 SD 卡連接到計算機并打開文件rootfs/etc/wpa_supplicant/wpa_supplicant.conf并將以下條目添加到其中。不要忘記以管理員(root)權(quán)限打開文件。
網(wǎng)絡(luò)={
?
ssid="wifi_ssid" psk="wifi_passkey" key_mgmt=WPA-PSK }
?
條目應(yīng)與此類似。
上面的條目應(yīng)該讓我們連接到 Wi-Fi,但這還不足以在 Raspberry Pi 和計算機之間創(chuàng)建和維護 SSH 連接。默認情況下 SSH 在 Raspberry Pi 中是禁用的,因此要啟用它,請在引導(dǎo)目錄中創(chuàng)建一個名為ssh的空文件。
現(xiàn)在 Raspberry Pi 在技術(shù)上可以遠程訪問。將樹莓派連接到電源。現(xiàn)在 pi 會自動連接到 Wi-Fi,但需要它的 IP 地址才能通過 SSH 連接到它。有多種方法可以找出相同的。我使用nmap命令
nmap -sn [網(wǎng)關(guān)ip地址]/24
該命令將為我們提供網(wǎng)絡(luò)中連接的所有設(shè)備的 IP 地址。例如,
其中之一是樹莓派的。現(xiàn)在我們知道了 pi 的 IP 地址讓我們連接到它
ssh pi@pi_ip_address
在 Raspberry Pi 中安裝的先決條件
藍Z
BlueZ 是 Raspbian 發(fā)行版附帶的默認應(yīng)用程序。它用于訪問系統(tǒng)的藍牙控件。如果您的 pi 中沒有它,也可以安裝它,原因只有您可能知道。
下面的命令獲取安裝在我們的 pi 中的藍牙接口應(yīng)用程序。
apt-get 安裝 bluez
脈沖音頻
Pulse Audio 是一種將計算機數(shù)據(jù)字節(jié)轉(zhuǎn)換為人類感知的應(yīng)用程序。它也被稱為音樂播放器。A2DP 協(xié)議在 PulseAudio 應(yīng)用程序插件中可用。因此,讓我們使用以下命令安裝所有與脈沖音頻相關(guān)的應(yīng)用程序:
apt-get 安裝 pulseaudio-*.
將藍牙設(shè)備與 Raspberry Pi 配對
使用命令打開 BlueZ 應(yīng)用程序
藍牙控制
藍牙代理是在兩個啟用藍牙的設(shè)備之間進行通信并初始化它們之間的連接的代理。有不同類型的藍牙代理。我們將使用NoInputNoOutput代理,因為它讓我們無需用戶干預(yù)即可連接。因此,讓我們通過運行以下命令來初始化代理。
代理 NoInputNoOutput
您應(yīng)該得到消息“代理注冊”作為響應(yīng)?,F(xiàn)在我們已經(jīng)注冊了我們的代理,讓我們將其設(shè)為默認代理。
默認代理
響應(yīng)應(yīng)該是“默認代理請求成功”
現(xiàn)在讓我們讓我們的設(shè)備可被發(fā)現(xiàn)
可在
其響應(yīng)應(yīng)為“成功更改可發(fā)現(xiàn)”
現(xiàn)在嘗試將您的手機或計算機連接到樹莓派
應(yīng)用程序會提示我們授權(quán)服務(wù),我們不需要這樣做。相反,我們將只信任設(shè)備并連接它。信任設(shè)備非常重要,因為當(dāng)受信任的設(shè)備嘗試與 pi 連接時,它允許相同的操作而無需用戶干預(yù)。
trust [設(shè)備mac地址]
connect [設(shè)備mac地址]
完成所有這些操作后,您的終端應(yīng)該與此類似。
耶!我們的手機通過藍牙與 Raspberry Pi 連接。但這足夠了嗎?顯然不,我們希望我們的聲音數(shù)據(jù)包從手機傳輸?shù)?pi,然后從 pi 傳輸?shù)竭B接到 pi 音頻端口的揚聲器。
讓我們通過運行以下命令確保我們的手機在PulseAudio應(yīng)用程序的音頻源中列出:
契約清單簡短
它將列出所有加載的聲音模塊、音頻接收器和音頻源
對照序列號 30 查看值。Bluez_source表示通過藍牙的 BlueZ 應(yīng)用程序的音頻源。交叉檢查bluez_source 和 a2dp_source 之間的設(shè)備 MAC 地址以及您在 BlueZ 應(yīng)用程序中的地址。在我的情況下,它是bluez_source.3C_28_6D_FD_65_3D.a2dp_source,它與 BlueZ 應(yīng)用程序中的相同。現(xiàn)在,如果您從連接到 pi 的設(shè)備播放歌曲,它應(yīng)該被路由到連接到樹莓派音頻端口的揚聲器。
尤里卡!我們已經(jīng)成功打造了一款藍牙音箱。我們已經(jīng)路由了聲音,但這還不是全部。我們無法手動完成上述所有步驟,因此讓我們使用expect 腳本和接口 pi 與一個開關(guān)來自動化它們,按下該開關(guān)時,將 Pi 與 devices 配對。
涼爽的?現(xiàn)在讓我們開始談?wù)隆?/p>
使用 Python 腳本自動化藍牙配對過程
Expect 腳本類似于 bash 腳本,但是是自動化的。它在終端中查找給定的單詞,當(dāng)相同的單詞到達時,它根據(jù)腳本發(fā)送命令。讓我們自動化配對過程。創(chuàng)建一個名為pair_bluetooth_device.expect的文件
?
設(shè)置超時 30 生成藍牙ctl 預(yù)計 ”# ” 發(fā)送“代理關(guān)閉\r” 期待“?gistered” 發(fā)送“\r” 預(yù)計 ”# ” 發(fā)送“代理 NoInputNoOutput\r” 期待“代理注冊” 發(fā)送“\r” 預(yù)計 ”# ” 發(fā)送“默認代理\r” 期望“默認代理請求成功” 發(fā)送“\r” 預(yù)計 ”# ” 發(fā)送“可發(fā)現(xiàn)于\r” 期待“授權(quán)” 發(fā)送“是\r” 發(fā)送“退出\r”
?
復(fù)制代碼并將其粘貼到文件中。它只是自動執(zhí)行,我們在將手機與樹莓派配對時執(zhí)行的操作。它只是讓設(shè)備連接但不信任它。要信任設(shè)備,我們需要它的 mac 地址。所以我們將把這個expect腳本的輸出打印到一個可以獲取mac地址的日志文件中。
?
grep -Pom 1 "(?<=Device ).*(?= Connected)"
?
上面的命令打印出字符串“Device”和“Connected”之間的值。在我們的例子中(Device 3C:28:6D:FD:65:3D Connected: no)它是設(shè)備的 MAC 地址。
讓我們編寫一個期望腳本,它將 mac 地址作為第一個參數(shù)并信任并連接到該設(shè)備。
創(chuàng)建一個名為trust_and_connect.expect的文件
?
設(shè)置超時 30 spawn bluetoothctl expect "#" send "agent off\r" expect "?egistered" send "\r" 期望“#” 發(fā)送“代理在\r” 期望“代理注冊” 發(fā)送“\r” 期望“#” 發(fā)送“默認代理\r” 期望“默認代理請求成功” 發(fā)送“\r” 期望“#” 發(fā)送“信任[lindex $argv 0]\r” 期望“變化” 發(fā)送“連接 [lindex $argv 0]\r” 期望“連接成功” 發(fā)送“退出\r”
?
將上面的代碼復(fù)制到該文件中。它自動完成信任和連接部分。
現(xiàn)在讓我們將所有這些都放在一個 Python 腳本文件中,以便整個配對過程可以自動化。
讓我們創(chuàng)建一個文件pair_and_trust_bluetooth_device.sh
?
cd $(dirname $0) echo "Pairing..." expect pair_bluetooth_device.expect > expect_script.log chmod 777 expect_script.log sleep 2 echo "信任和連接.." device_mac_address=$(cat expect_script.log | grep -Pom 1 "(?<=Device ).*(?= Connected)") echo mac address is $device_mac_address if [[ ! -z $device_mac_address ]] ; 然后 期望 trust_and_connect.expect $device_mac_address else echo "No device connected" fi rm expect_script.log
?
所以bash腳本,
調(diào)用一個期望腳本(其輸出將被打印到一個名為 expect_script.log 的文件中),其中,
啟動NoInputNoOutput代理
使其成為默認代理
打開 pi 的可發(fā)現(xiàn)性
等待某人連接并在有人連接或超時時退出
睡眠 2 秒
獲取設(shè)備mac地址的expect_script.log文件
如果 mac_address 為空,則信任并連接設(shè)備
刪除殘留文件expect_script.log
使用按鈕觸發(fā)藍牙配對腳本
現(xiàn)在我們有了自動化配對過程的腳本。但是這個腳本必須在用戶需要的時候方便地運行。因此,讓我們將此腳本與一個物理按鈕掛鉤,以便每次按下按鈕時都會調(diào)用此腳本。中斷是嵌入式編程的重要組成部分之一。對于初學(xué)者來說,當(dāng)感知到中斷時,會執(zhí)行程序的常規(guī)例程并運行一個預(yù)定義的 ISR,稱為中斷服務(wù)例程。
因此,讓我們將按鈕連接到 gpio 引腳 11 并為其分配 ISR。在 ISR 內(nèi)部,我們將調(diào)用腳本。
讓我們創(chuàng)建一個名為?Bluetooth-speaker-main.py的 python 文件,并將下面的代碼添加到其中。我已經(jīng)在程序中添加了注釋,所以如果你使用這個代碼,你仍然有它們
?
#import 需要的包 import subprocess import RPi.GPIO as gpio import time import os import logging pair_pin=11 #獲取運行python腳本的文件目錄 fileDirectory = os.path.dirname(os.path.realpath(__file__)) #設(shè)置日志文件位置和python腳本位置一樣 logFile=fileDirectory+"/bluetoothSpeaker.log" logging.basicConfig(filename=logFile, filemode='w', format='%(name)s - %(levelname)s - %(message)s', level=logging.INFO) def pairNewDevice(channel): #ISR for pin 11 print("Waiting to pair") logging.info("Waiting to pair") output = subprocess.call(["/bin/bash",fileDirectory+"/pair_and_trust_bluetooth_device.sh" , ">>", 文件目錄+"/bluetoothSpeaker.log"]) gpio.setmode(gpio.BOARD) gpio.setup(pair_pin, gpio.IN, pull_up_down=gpio.PUD_UP) try: #將pair_pin設(shè)置為檢測下降沿的中斷引腳,當(dāng)檢測到下降沿時,調(diào)用pairNewDevice函數(shù) gpio.add_event_detect(pair_pin, gpio.FALLING, callback=pairNewDevice,bouncetime=1000) print("Bluetooth program has started") logging.info("Bluetooth program has started") while True: time.sleep (5) 除了 KeyboardInterrupt: gpio.cleanup()
?
電路原理圖
下面是連接一個按鈕與樹莓派的 GPIO11 以觸發(fā)藍牙配對過程以通過藍牙傳輸音頻的電路圖。
設(shè)置 Cron 作業(yè)以在啟動時啟動藍牙揚聲器 Python 程序
現(xiàn)在最后讓我們設(shè)置一個 cron 作業(yè),它將在每次 pi 啟動時啟動這個 python 程序。
crontab -e
選擇您喜歡的編輯器并在文件末尾添加以下行
@reboot python3 /home/pi/blueooth-speaker/Bluetooth-speaker-main.py
這將在每次 pi 啟動時調(diào)用我們的 python 程序。
就是這樣。鷹已著陸。你已經(jīng)制作了一個無頭樹莓派藍牙音箱。
重新啟動您的 Pi,配對您的手機并流式傳輸音頻。:)
評論
查看更多