December, 2025 Update:
I am still using an RPi 3A+ with the Edimax BT dongle as my "music machine".
I use 'cmus' for the player software, with 'pipewire' and 'wireplumber'
managing the "backend" duties. 'pipewire' has been *transformative* for
music over Bluetooth. This system "survived" an in-place upgrade from
'bookworm' to 'trixie', and never failed to play reliably. The only hitch was
that the BT speaker failed to automatically connect after reboot. I found
this was due to a bogus drop-in file I had forgotten about.
... in '~/.config/pipewire/pipewire.conf.d'.
After cleaning that up, everything worked as it did before the upgrade.
It's no secret that the Raspberry Pi was designed - first and foremost - to be cheap. In general, I favor that approach; it gives more people an accessible price point, and more people = better support (in general). But as it is with many things, "cheap" is a relative term; "cheap" is not the same price point for everyone. And in making the myriad tradeoffs in the design of a device such as Raspberry Pi, some of us might choose to allocate better resources in some places vs. others.
Uh - this is awkward... all I'm really trying to say here is that in my humble opinion, I feel the tradeoffs made wrt design of the Bluetooth hardware were not especially well-considered. For example: Being an Electrical Engineer by training and trade, using a single antenna for both Bluetooth and WiFi is something I would not have done. To be sure, MIMO antennas are a real thing... but the RPi implementation is not a MIMO antenna! And the antenna is only one of the tradeoffs. Using Broadcomm hardware for Bluetooth was probably inexpensive - but is it any good? It's proprietary hardware & firmware, and so difficult to say definitively - but ask yourself, "How many computers are being manufactured today with Broadcomm BT hardware?"
I add all of the above to my own personal experience with RPi's BT hardware which is: Not So Great! I find that BT audio playback using the RPi BT hardware suffers from:
- random, but too-frequent drop outs that typically necessitate a
rebootto restore audio - occasionally suffers from intermittent interruptions and artifacts (popping, background noise)
I have found that disabling WiFi (via nmcli radio wifi off or similar) reduces these symptoms, but does not eliminate them. And of course disabling WiFi limits what you can do on your RPi!
For me, the solution was to buy a Bluetooth USB "dongle" - specifically I bought a BT-8500 device from Edimax - about $12 from Amazon. I did some investigation, and found that Edimax uses chips made by Realtek. Realtek is a Chinese company, but offsetting that is the fact that their chips seem to be well-supported in Linux.
I plugged the dongle into the lone USB port on my RPi 3A+. This system runs this "Lite" version of the 'bookworm' RPi OS; it also runs pipewire version '0.3.65' (compiled with libpipewire 0.3.65) - installed with apt in the "standard way". The setup and installation of pipewire on this RPi 3A+ is covered here.
There may be alternatives, but the simplest effective solution I found was to set the disable-bt overlay (Raspberry Pi's device tree makes this easy):
a. Open the file /boot/firmware/config.txt in your editor:
$ sudo nano /boot/firmware/config.txt
# -- OR --
$ sudo vim /boot/firmware/config.txtb. Add this one line:
dtoverlay=disable-bt
c. Reboot:
$ sudo reboot
2. Do the bluetoothctl nutroll:
The only thing I've found that makes this process any simpler is to do it as quickly as possible.
a. As a precaution, check rfkill to make sure bluetooth is not being blocked:
$ rfkill list
0: hci0: Bluetooth
Soft blocked: yes # WTF !!
Hard blocked: no
...
$ rfkill unblock bluetooth
$b. Let's verify that Step 1 actually left us with only one controller (it did!) & then give it an alias:
$ bluetoothctl
[bluetooth]# list
Controller 08:BE:AC:2D:99:85 [default]
[bluetooth]# system-alias edimax
Changing edimax succeeded
[bluetooth]# list
Controller 08:BE:AC:2D:99:85 edimax [default]
[bluetooth]#c. We'll need to recapture our BT audio sink (i.e. speaker/headphones). So quickly power on your speaker, press its "pair" button, and then:
[bluetooth]# scan on
Discovery started
[CHG] Controller 08:BE:AC:2D:99:85 Discovering: yes
[NEW] Device B8:F6:53:9B:1A:97 JBL Flip 5
...
==>[bluetooth]# trust B8:F6:53:9B:1A:97
[CHG] Device B8:F6:53:9B:1A:97 Trusted: yes
Changing B8:F6:53:9B:1A:97 trust succeeded
==>[bluetooth]# pair B8:F6:53:9B:1A:97
Attempting to pair with B8:F6:53:9B:1A:97
[CHG] Device B8:F6:53:9B:1A:97 Connected: yes
[CHG] Device B8:F6:53:9B:1A:97 Bonded: yes
[CHG] Device B8:F6:53:9B:1A:97 UUIDs: 00001101-0000-1000-8000-00805f9b34fb
[CHG] Device B8:F6:53:9B:1A:97 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device B8:F6:53:9B:1A:97 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device B8:F6:53:9B:1A:97 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device B8:F6:53:9B:1A:97 ServicesResolved: yes
[CHG] Device B8:F6:53:9B:1A:97 Paired: yes
Pairing successful
[CHG] Device B8:F6:53:9B:1A:97 ServicesResolved: no
[CHG] Device B8:F6:53:9B:1A:97 Connected: no
...
==>[bluetooth]# scan off
Discovery stopped
...
==>[bluetooth]# info B8:F6:53:9B:1A:97
Device B8:F6:53:9B:1A:97 (public)
Name: JBL Flip 5
Alias: JBL Flip 5
Class: 0x00240414
Icon: audio-card
Paired: yes
Bonded: yes
Trusted: yes
Blocked: no
Connected: no
LegacyPairing: no
UUID: Serial Port (00001101-0000-1000-8000-00805f9b34fb)
UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
...
==>[bluetooth]# connect B8:F6:53:9B:1A:97
Attempting to connect to B8:F6:53:9B:1A:97
[CHG] Device B8:F6:53:9B:1A:97 Connected: yes
[NEW] Endpoint /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/sep1
[NEW] Endpoint /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/sep2
[NEW] Transport /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/sep1/fd0
Connection successful
[NEW] Player /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/player0 [default]
[CHG] Device B8:F6:53:9B:1A:97 ServicesResolved: yes
[CHG] Transport /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/sep1/fd0 Volume: 0x003c (60)
[CHG] Transport /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/sep1/fd0 State: active
[CHG] Transport /org/bluez/hci0/dev_B8_F6_53_9B_1A_97/sep1/fd0 Volume: 0x0034 (52)
==>[JBL Flip 5]# quit
$ $ systemctl status bluetooth.service
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; preset: enabled)
Active: active (running) since Mon 2024-07-29 04:00:35 UTC; 3h 6min ago
Docs: man:bluetoothd(8)
Main PID: 604 (bluetoothd)
Status: "Running"
Tasks: 1 (limit: 174)
CPU: 222ms
CGroup: /system.slice/bluetooth.service
└─604 /usr/libexec/bluetooth/bluetoothd
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/aptx_ll_1
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/aptx_ll_0
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/aptx_ll_duplex_1
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/aptx_ll_duplex_0
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/faststream
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/faststream_duplex
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSink/opus_05
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/opus_05
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSink/opus_05_duplex
Jul 29 06:25:10 rpi3a bluetoothd[604]: Endpoint unregistered: sender=:1.34 path=/MediaEndpoint/A2DPSource/opus_05_duplex- July 30, 2024: This all looks good, and in fact it was. I was able to begin playing music immediately. A fairly straightforward hardware upgrade. And how's it working? So far, so good... I'll post any revelations as follow-ups to this recipe.
- Nov 27, 2025: This (RPi 3A+) system was upgraded from 'bookworm' to 'trixie' about a month ago. The Edimax BT dongle has been 100% reliable since then. Out of curiosity, I decided to "revert" to the native/in-built BT hardware: I removed the Edimax dongle, and removed the
dtoverlay=disable-btfrom/boot/firmware/config.txt. The following day, while listening to music, playback suddenly stopped, thecmusapp appeared to "lock up", and I lost control of the RPi (SSH was non-op). I could find no "smoking gun" indmesgorjournalctl. A re-boot resolved it, but I decided to restore the Edimax setup!
