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