构建一个基于Raspberry Pi的蓝牙扬声器

构建一个基于Raspberry Pi的蓝牙扬声器,第1张

  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
}

 

  条目应与此类似。

构建一个基于Raspberry Pi的蓝牙扬声器,pYYBAGMPGcSAfXf5AABeA9FmcW8589.png,第2张

  上面的条目应该让我们连接到 Wi-Fi,但这还不足以在 Raspberry Pi 和计算机之间创建和维护 SSH 连接。默认情况下 SSH 在 Raspberry Pi 中是禁用的,因此要启用它,请在引导目录中创建一个名为ssh的空文件。

  现在 Raspberry Pi 在技术上可以远程访问。将树莓派连接到电源。现在 pi 会自动连接到 Wi-Fi,但需要它的 IP 地址才能通过 SSH 连接到它。有多种方法可以找出相同的。我使用nmap命令

  nmap -sn [网关ip地址]/24

  该命令将为我们提供网络中连接的所有设备的 IP 地址。例如,

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGbyAAvraAACJNfSness185.png,第3张

  其中之一是树莓派的。现在我们知道了 pi 的 IP 地址让我们连接到它

  ssh pi@pi_ip_address

构建一个基于Raspberry Pi的蓝牙扬声器,pYYBAGMPGbiAKo69AACzBqi_d7o271.png,第4张

  在 Raspberry Pi 中安装的先决条件

  蓝Z

  BlueZ 是 Raspbian 发行版附带的默认应用程序。它用于访问系统的蓝牙控件。如果您的 pi 中没有它,也可以安装它,原因只有您可能知道。

  下面的命令获取安装在我们的 pi 中的蓝牙接口应用程序。

  apt-get 安装 bluez

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGbSAVEGFAAELqtKkQaw629.png,第5张

  脉冲音频

  Pulse Audio 是一种将计算机数据字节转换为人类感知的应用程序。它也被称为音乐播放器。A2DP 协议在 PulseAudio 应用程序插件中可用。因此,让我们使用以下命令安装所有与脉冲音频相关的应用程序:

  apt-get 安装 pulseaudio-*.

构建一个基于Raspberry Pi的蓝牙扬声器,pYYBAGMPGa6AIWZFAAEPgK_Znfo790.png,第6张

  将蓝牙设备与 Raspberry Pi 配对

  使用命令打开 BlueZ 应用程序

  蓝牙控制

  蓝牙代理是在两个启用蓝牙的设备之间进行通信并初始化它们之间的连接的代理。有不同类型的蓝牙代理。我们将使用NoInputNoOutput代理,因为它让我们无需用户干预即可连接。因此,让我们通过运行以下命令来初始化代理。

  代理 NoInputNoOutput

  您应该得到消息“代理注册”作为响应。现在我们已经注册了我们的代理,让我们将其设为默认代理。

  默认代理

  响应应该是“默认代理请求成功”

  现在让我们让我们的设备可被发现

  可在

  其响应应为“成功更改可发现”

  现在尝试将您的手机或计算机连接到树莓派

  应用程序会提示我们授权服务,我们不需要这样做。相反,我们将只信任设备并连接它。信任设备非常重要,因为当受信任的设备尝试与 pi 连接时,它允许相同的 *** 作而无需用户干预。

  trust [设备mac地址]

  connect [设备mac地址]

  完成所有这些 *** 作后,您的终端应该与此类似。

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGamABMj7AAPyfuo4ZKw068.png,第7张

  耶!我们的手机通过蓝牙与 Raspberry Pi 连接。但这足够了吗?显然不,我们希望我们的声音数据包从手机传输到 pi,然后从 pi 传输到连接到 pi 音频端口的扬声器。

  让我们通过运行以下命令确保我们的手机在PulseAudio应用程序的音频源中列出:

  契约清单简短

  它将列出所有加载的声音模块、音频接收器和音频源

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGaWAdhA2AAMqZoqqimk932.png,第8张

  对照序列号 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 以触发蓝牙配对过程以通过蓝牙传输音频的电路图。

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGZqAbOC1AAId4hCzMbU234.png,第9张

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGZaARZZxAAW-mHGKcrE582.png,第10张

  设置 Cron 作业以在启动时启动蓝牙扬声器 Python 程序

  现在最后让我们设置一个 cron 作业,它将在每次 pi 启动时启动这个 python 程序。

  crontab -e

  选择您喜欢的编辑器并在文件末尾添加以下行

  @reboot python3 /home/pi/blueooth-speaker/Bluetooth-speaker-main.py

构建一个基于Raspberry Pi的蓝牙扬声器,pYYBAGMPGZOAZcZZAADNDRNuE-A301.png,第11张

  这将在每次 pi 启动时调用我们的 python 程序。

  就是这样。鹰已着陆。你已经制作了一个无头树莓派蓝牙音箱。

  重新启动您的 Pi,配对您的手机并流式传输音频。:)

构建一个基于Raspberry Pi的蓝牙扬声器,poYBAGMPGY6ALTscAATZy6xp4qc919.png,第12张

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/dianzi/2999612.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-26
下一篇 2022-09-26

发表评论

登录后才能评论

评论列表(0条)

保存