There were no cheap micro SD cards in a nearby big box store specializing
in everything for the office, but there was a small pile of inexpensive
Bluetooth speakers in the clearance bin. Bluetooth devices are something I
know very little about except for a brief use of a cheap keyboard which I
threw away when the V key disappeared rather quickly. The speaker packaging
talked of the "premium aluminum (or aluminium if you prefer) body", the
"33 ft wireless range" (33 is an odd number, corresponds to 10 metres I
suppose), the "3 hours of playtime" (not likely!). But most intriguing was
the "built in microphone for call answering". Could I transform it into
something like the Amazon Dot or the Google Home mini when used in
combination with a Raspberry Pi 3 which has built in Bluetooth? The price was
right for experimentation: $10 CDN + $1.50 recycling fee + 15% sales tax.
Testing with an Android tablet confirmed that the speaker could
stream audio and that the microphone could be used, although the
quality was definitely inferior to that of the tablet. And it turned out
that the microphone could only be accessed using an application found on
Play Store.
The device, named AUDIO POD was sold under the
XTREME SOUND label, but I have since realised that
there are many variation on the theme sold under various labels. It also
turns out that for the same price I could have obtained an upgraded model
from the typical Chinese seller... oh well.
Before going ahead with the grand scheme, I had to learn the basics
of using Bluetooth with a Raspberry Pi 3. Here is a description of my
first steps in this arcane world.
Table of Content
- Starting All Over... Again
- Bluetooth on Raspbian Stretch
- Connecting Bluetooth Devices
- Connecting Bluetooth Devices with PIN Code
- Playing Sound Through a Bluetooth Speaker
- Controling the Playback Volume of a Bluetooth Speaker
- Using Multiple Speakers
- Caveat (added May 12, 2018)
This first section is about setting up Raspbian (stretch) on a Raspberry
Pi 3 (RPi3 for short) for headless operation. It can probably be
skipped by most users of the RPi3. It is a bit terse and assumes you
know how to locate a newly connected computer on the local area network.
This should work with any Raspberry Pi.
When this was initially written, the most recent Rasbpian
image available from the Raspberry Foundation was
Raspbian Stretch Lite
Minimal image based on Debian Stretch
Version: November 2017
Release date: 2017-11-29
Kernel version: 4.9.
Since then newer images have been released, the latest being
Raspbian Stretch Lite
Minimal image based on Debian Stretch
Version: April 2018
Release date: 2018-04-19
Kernel version: 4.14.
The
RASPBIAN download page at the Raspberry Pi Foundation
always contains the newest image. I have gone through all the steps described
here with all versions of Stretch since the November 2017 version, and there
were no substantial differences. The pairing of a Bluetooth speaker worked
just as described below. I have done this with a Raspberry Pi 3 B. A reader
from the the Occitanie Region in France has confirmed that it does work with
the newest version of Stretch running on the latest Raspberry Pi 3 version
B+.
Older versions of Rasbian Lite going back to November 2015 are available here if for some reason you want to install
one of them instead of the newest version.
May 12, 2018
I downloaded that image and burned it to a 8GB SD card using Etcher as
per the instructions at raspberrypi.org
. I suggest
that before doing this you uncheck the Auto-unmount on success
option in the programs Settings
. If this is not done, it will be
necessary to remove and reinsert the SD card in the desktop SD card reader to
perform the next step.
In order to configure the RPi3 without monitor and keyboard, I created
an empty file called ssh
in the card's boot partition.
michel@hp:~$ sudo touch /media/michel/boot/ssh
michel@hp:~$ ls /media/michel/boot/ssh
/media/michel/boot/ssh
Then I unmounted the two partitions on the SD card, inserted the latter
in the RPi3 SD card reader, connected an Ethernet cable to the board and
powered it up. If all goes well, the red and green LED will flash on and off.
I think the RPi3 is expanding its file system so give it some time to perform
that one time task. Wait until the green LED no longer flashes and the red
LED is mostly on. It is time to open an SSH session. Use the usual means to
find the IP address of the RPi3. In my case, it was simple, because I had
recently connected the RPi3 to the network, so its IP address lease was still
in effect. However this meant that the security key had to be changed. Its no
big deal, just follow the instructions if that happens.
michel@hp:~$ ssh pi@192.168.0.138
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:ZI+DfebhaxZeK+yy1cHkCmKoup0eNPALps0q60VF/Lw.
Please contact your system administrator.
Add correct host key in /home/michel/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/michel/.ssh/known_hosts:36
remove with:
ssh-keygen -f "/home/michel/.ssh/known_hosts" -R "192.168.0.138"
ECDSA host key for 192.168.0.138 has changed and you have requested strict checking.
Host key verification failed.
michel@hp:~$ ssh-keygen -f "/home/michel/.ssh/known_hosts" -R "192.168.0.138"
# Host 192.168.0.138 found: line 36
/home/michel/.ssh/known_hosts updated.
Original contents retained as /home/michel/.ssh/known_hosts.old
michel@hp:~$ ssh pi@192.168.0.138
The authenticity of host '192.168.0.138 (192.168.0.138)' can't be established.
ECDSA key fingerprint is SHA256:ZI+DfebhaxZeK+yy1cHkCmKoup0eNPALps0q60VF/Lw.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.0.138' (ECDSA) to the list of known hosts.
pi@192.168.0.138's password: raspberry not echoed to screen
Linux raspberrypi 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l
...
SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.
We are in! First thing first, I used raspi-config
to
change the configuration to suit my situation. The most important changes
at this time are setting the password and enabling SSH.
pi@raspberrypi:~ $ sudo raspi-config
- Change password for the current user mandatory
- Configure network settings
- N1 Hostname on the network to rpi3
- N2 Provide Wi-fi credentials (network name and password)
- Boot Options - did nothing
- Localisation Options
- I1 Change Locale to add fr_CA
- I2 Change Timezone - to America/Moncton
- Interfacing Options
- P2 SSH - enabled mandatory
- P5 I2C - enabled
- Overclock - did nothing
- Advanced Options
- A3 Memory Split - minimum 16 MB for the GPU
I rebooted as asked and then updated and upgrade the system.
Connection to 192.168.0.138 closed by remote host.
Connection to 192.168.0.138 closed.
michel@hp:~$ ssh pi@192.168.0.138
pi@192.168.0.138's password:
Linux rpi3 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l
...
pi@rpi3:~ $ sudo apt-get update && sudo apt-get upgrade
...
The following packages will be upgraded:
curl libcurl3 libcurl3-gnutls raspi-config
4 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 760 kB of archives.
After this operation, 2,048 B of additional disk space will be used.
Do you want to continue? [Y/n] y
That was something new... a few days ago, there was no update to
raspi-config
. Hope that having used it before the
update will not have an impact.
The RaspberryPi.org documentation about Bluetooth in its new
Raspbian image (stretch) mentions a change of approach.
Bluetooth audio [in Stretch]
In Jessie, we used PulseAudio to provide support for audio over Bluetooth,
but integrating this with the ALSA architecture used for other audio sources
was clumsy. For Stretch, we are using the bluez-alsa package to make
Bluetooth audio work with ALSA itself. PulseAudio is therefore no longer
installed by default, and the volume plugin on the taskbar will no longer
start and stop PulseAudio. From a user point of view, everything should still
work exactly as before – the only change is that if you still wish to use
PulseAudio for some other reason, you will need to install it yourself.
I take this to mean that older posts about Bluetooth and PulseAudio may
not be that useful. Looking at the boot log for Bluetooth related entries,
the situation looks good.
pi@rpi3:~ $ dmesg | grep -i blue
[ 9.302588] Bluetooth: Core ver 2.22
[ 9.302670] Bluetooth: HCI device and connection manager initialized
[ 9.302688] Bluetooth: HCI socket layer initialized
[ 9.302700] Bluetooth: L2CAP socket layer initialized
[ 9.302729] Bluetooth: SCO socket layer initialized
[ 9.313265] Bluetooth: HCI UART driver ver 2.3
[ 9.313278] Bluetooth: HCI UART protocol H4 registered
[ 9.313284] Bluetooth: HCI UART protocol Three-wire (H5) registered
[ 9.313465] Bluetooth: HCI UART protocol Broadcom registered
[ 9.542892] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[ 9.542902] Bluetooth: BNEP filters: protocol multicast
[ 9.542920] Bluetooth: BNEP socket layer initialized
That reminded me that the UART is connected to the Bluetooth
chip on the Raspberry Pi 3.
pi@rpi3:~ $ sudo systemctl status bluetooth*
● bluetooth.target - Bluetooth
Loaded: loaded (/lib/systemd/system/bluetooth.target; static; vendor preset: enabled)
Active: active since Mon 2017-12-04 14:50:56 AST; 45min ago
Docs: man:systemd.special(7)
Dec 04 14:50:56 rpi3 systemd[1]: Reached target Bluetooth.
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2017-12-04 14:50:56 AST; 45min ago
Docs: man:bluetoothd(8)
Main PID: 457 (bluetoothd)
Status: "Running"
CGroup: /system.slice/bluetooth.service
└─457 /usr/lib/bluetooth/bluetoothd
Dec 04 14:50:56 rpi3 systemd[1]: Starting Bluetooth service...
Dec 04 14:50:56 rpi3 bluetoothd[457]: Bluetooth daemon 5.43
Dec 04 14:50:56 rpi3 systemd[1]: Started Bluetooth service.
Dec 04 14:50:56 rpi3 bluetoothd[457]: Starting SDP server
Dec 04 14:50:56 rpi3 bluetoothd[457]: Bluetooth management interface 1.14 initialized
Dec 04 14:50:56 rpi3 bluetoothd[457]: Failed to obtain handles for "Service Changed" characteristic
Dec 04 14:50:56 rpi3 bluetoothd[457]: Sap driver initialization failed.
Dec 04 14:50:56 rpi3 bluetoothd[457]: sap-server: Operation not permitted (1)
Apparently this is not as bad as it looks. The SIM Access Profile (SAP)
would have allowed the RPi3 to access a SIM card of a Bluetooth enabled phone.
This is far from something of interest to me at this point. In a lengthy
exchange on the Rasbperry Pi forum, entitled Raspbian Stretch Bluetooth is Broken there is a way to get rid of the error message by stopping the attempt
to load the SAP server: add the --noplugin=sap
option when starting
the Bluetooth deamon. Since I am paranoid I made a back up of the
of bluetooth.service
file before doing that.
pi@rpi3:~ $ sudo cp /lib/systemd/system/bluetooth.service /lib/systemd/system/bluetooth.service-org
pi@rpi3:~ $ sudo sed -i 's|^ExecStart=/usr/lib/bluetooth/bluetoothd$|ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap|' /lib/systemd/system/bluetooth.service
pi@rpi3:~
As explained in an exchange on Bluetooth does not work with Raspbian Stretch
and Raspberry Pi 3 there is also a problem of permissions. The user
(pi) needs to be a member of the bluetooth
group to have
access to the service over DBus
.
pi@rpi3:~ $ sudo adduser pi bluetooth
Adding user `pi' to group `bluetooth' ...
Adding user pi to group bluetooth
Done.
pi@rpi3:~ $ sudo reboot
Connection to 192.168.0.138 closed by remote host.
Connection to 192.168.0.138 closed.
I then rebooted and, as expected, the two SAP related errors have
disappeared. However the Failed to obtain handles for "Service Changed"
characteristic
is still there. On the other hand things it was possible
to "pair" with the Bluetooth speaker. I turned the speaker on and waited until
I heard "Bluetooth mote" (or "moat"; that is what I hear, instead of the
expected "mode") and then started the interactive utility
bluetoothctl
to connect.
pi@rpi3:~ $ bluetoothctl
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[bluetooth]# agent on not needed! there is a default agent
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller B8:27:EB:55:FC:57 Discovering: yes
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[bluetooth]# pair 30:21:3E:31:C6:2B
Attempting to pair with 30:21:3E:31:C6:2B
[CHG] Device 30:21:3E:31:C6:2B Connected: yes
[CHG] Device 30:21:3E:31:C6:2B UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:3E:31:C6:2B UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:3E:31:C6:2B UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:3E:31:C6:2B UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:3E:31:C6:2B UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:3E:31:C6:2B ServicesResolved: yes
[CHG] Device 30:21:3E:31:C6:2B Paired: yes
Pairing successful
[CHG] Device 30:21:3E:31:C6:2B ServicesResolved: no
[CHG] Device 30:21:3E:31:C6:2B Connected: no
[bluetooth]# connect 30:21:3E:31:C6:2B
Attempting to connect to 30:21:3E:31:C6:2B
Failed to connect: org.bluez.Error.Failed
[bluetooth]# exit or quit
Agent unregistered
[DEL] Controller B8:27:EB:55:FC:57 rpi3 [default]
pi@rpi3:~ $
This is definitely an improvement, but the connection did fail.
Incidentally, the agent
invoked is the module that
performs the pairing with the device. As for the Universally Unique
IDentifiers, (UUIDs
), they correspond to capabilities of
the speaker. More on that in a latter post.
Further reading of the forum exchange gave another piece of the solution. Load a bit of software:
the blueALSA proxy
. I checked, it was indeed missing so I
installed it.
pi@rpi3:~ $ sudo apt policy bluealsa
bluealsa:
Installed: (none)
Candidate: 0.6 (0.7) with Stretch 2018-03-13
Version table:
0.6 500
500 http://archive.raspberrypi.org/debian stretch/main armhf Packages
pi@rpi3:~ $ sudo apt install bluealsa
...
Do you want to continue? [Y/n] y
...
Setting up bluealsa (0.6) ... (0.7) with Stretch 2018-03-13 of course
Created symlink /etc/systemd/system/graphical.target.wants/bluealsa.service → /lib/systemd/system/bluealsa.service.
This will load the service immediately, there is no need to
restart anything except for bluetoothctl
to try to connect
once again. It turned out the speaker was still paired, so all I had to
do was to connect to it.
pi@rpi3:~ $ bluetoothctl
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[bluetooth]# paired-devices
Device 30:21:3E:31:C6:2B AUDIOPOD2
[bluetooth]# connect 30:21:3E:31:C6:2B
Attempting to connect to 30:21:3E:31:C6:2B
[CHG] Device 30:21:3E:31:C6:2B Connected: yes
Connection successful Speaker: "ding dong"
[CHG] Device 30:21:3E:31:C6:2B ServicesResolved: yes
The speaker made a ding dong type of noise to indicate that it was
connected. This is progress. Note that it was not necessary to register an
agent
since the speaker had already been paired. Time to move on
to the problem of reconnecting the speaker without going through this pairing
rigamarole.
Thankfully, it is not necessary to go through the interactive procedure
described above to connect a Bluetooth device, once it has been paired. If a
paired device is "trusted" by a controller, such as the Raspberry Pi 3, then
connection will be done automatically whenever the device is near a
controller that trusts it.
As far as I known, a device such as a speaker can be connected to only
one controller at a time. That was something to remember as I connected
the Bluetooth speakers with both my desktop computer and the RPi3 nearby.
I had to make sure that I disabled the Bluetooth adapter
on the desktop when connecting the speaker to the RPi3.
Trusting a paired device is a simple procedure.
pi@rpi3:~ $ bluetoothctl
[AUDIOPOD2]# trust 30:21:3E:31:C6:2B
[CHG] Device 30:21:3E:31:C6:2B Trusted: yes
Changing 30:21:3E:31:C6:2B trust succeeded
[AUDIOPOD2]# quit
To test, I rebooted the RPi3 and turned off the speaker at the same time.
Once the Raspberry Pi completed its boot routine, I turned on the
speaker and was pleased to hear it make its ding dong connected noise
after a few seconds.
For the sheer pleasure of it, I used the D-Bus introspection tool
busctl
to monitor the status of the speaker as I turned it
off and then back on again.
pi@rpi3:~ $ busctl tree org.bluez
└─/org
└─/org/bluez
└─/org/bluez/hci0
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B/fd0
turned the speaker off, and waited a few seconds
pi@rpi3:~ $ busctl tree org.bluez
└─/org
└─/org/bluez
└─/org/bluez/hci0
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B
turned the speaker on, and waited a few seconds until it signalled
a connection
pi@rpi3:~ $ busctl tree org.bluez
└─/org
└─/org/bluez
└─/org/bluez/hci0
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B/fd1
It does appear that it is necessary to power cycle the speaker when
the RPi3 is rebooted. Here is what we have after rebooting and turning
the speaker on and off.
pi@rpi3:~ $ busctl tree org.bluez
└─/org
└─/org/bluez
└─/org/bluez/hci0
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B
└─/org/bluez/hci0/dev_30_21_3E_31_C6_2B/fd0
pi@rpi3:~ $ sudo systemctl status bluet*
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2017-12-04 18:07:55 AST; 3min 7s ago
Docs: man:bluetoothd(8)
Main PID: 441 (bluetoothd)
Status: "Running"
CGroup: /system.slice/bluetooth.service
└─441 /usr/lib/bluetooth/bluetoothd --noplugin=sap
Dec 04 18:07:54 rpi3 systemd[1]: Starting Bluetooth service...
Dec 04 18:07:55 rpi3 bluetoothd[441]: Bluetooth daemon 5.43
Dec 04 18:07:55 rpi3 systemd[1]: Started Bluetooth service.
Dec 04 18:07:55 rpi3 bluetoothd[441]: Starting SDP server
Dec 04 18:07:55 rpi3 bluetoothd[441]: Excluding (cli) sap
Dec 04 18:07:55 rpi3 bluetoothd[441]: Bluetooth management interface 1.14 initialized
Dec 04 18:07:55 rpi3 bluetoothd[441]: Failed to obtain handles for "Service Changed" characteristic
Dec 04 18:07:55 rpi3 bluetoothd[441]: Endpoint registered: sender=:1.4 path=/A2DP/SBC/Source/1
Dec 04 18:07:55 rpi3 bluetoothd[441]: Endpoint registered: sender=:1.4 path=/A2DP/SBC/Sink/1
Dec 04 18:10:35 rpi3 bluetoothd[441]: Endpoint registered: sender=:1.4 path=/A2DP/SBC/Source/2
● bluetooth.target - Bluetooth
Loaded: loaded (/lib/systemd/system/bluetooth.target; static; vendor preset: enabled)
Active: active since Mon 2017-12-04 18:07:55 AST; 3min 7s ago
Docs: man:systemd.special(7)
Dec 04 18:07:55 rpi3 systemd[1]: Reached target Bluetooth.
If automatic connection is not desired, then "untrust" the device.
pi@rpi3:~ $ bluetoothctl
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[AUDIOPOD2]# untrust 30:21:3E:31:C6:2B
Changing 30:21:3E:31:C6:2B untrust succeeded
[AUDIOPOD2]# quit
[DEL] Controller B8:27:EB:55:FC:57 rpi3 [default]
pi@rpi3:~ $
The speaker remained paired, and it is possible to connect to it with
a single command.
pi@rpi3:~ $ bluetoothctl connect 30:21:3E:31:C6:2B
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[bluetooth]# connect 30:21:3E:31:C6:2B
Attempting to connect to 30:21:3E:31:C6:2B
[DEL] Controller B8:27:EB:55:FC:57 rpi3 [default]
[bluetooth]#
(bluetoothctl:1006): GLib-CRITICAL **: Source ID 25 was not found when attempting to remove it
pi@rpi3:~ $
Disconnecting is just as simple.
pi@rpi3:~ $ bluetoothctl disconnect 30:21:3E:31:C6:2B
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[AUDIOPOD2]# disconnect 30:21:3E:31:C6:2B
Attempting to disconnect from 330:21:3E:31:C6:2B
[DEL] Controller B8:27:EB:55:FC:57 rpi3 [default]
[AUDIOPOD2]#
(bluetoothctl:1118): GLib-CRITICAL **: Source ID 26 was not found when attempting to remove it
pi@rpi3:~ $
If quieter commands are required, send the output and the standard error
file to null.
pi@rpi3:~ $ bluetoothctl connect 30:21:3E:31:C6:2B >/dev/null 2>&1
Then you can rely on the sound emanating from the speaker for a confirmation.
Finally to "unpair" a device, that is to remove its MAC address from the
controller's database of paired devices use the remove <device_mac>
command (of course <device_mac>
is replaced with the
device MAC address such as 30:21:3E:31:C6:2B) in bluetoothctl
. Should
you want to connect the device in the future, it will have to be paired
again.
Most Bluetooth keyboards and perhaps other Bluetooth devices have a
slightly more complicated pairing procedure. There is an extra step, an
exchange of a PIN number.
To try this out, I borrowed the Adesso keyboard
that my spouse sometime uses with her IPad. I turned
the keyboard on, and then pressed the Bluetooth pairing button. On this
particular keyboard, it is marked <«.»> in the centre above the keys. A
Bluetooth LED then starts to flash signaling the start of the discovery
phase. It is time to pair and connect.
pi@rpi3:~ $ bluetoothctl
[bluetooth]# scan on
Failed to start discovery: org.bluez.Error.InProgress No problem, that means scan was on
[CHG] Device DC:2C:26:21:7B:F6 LegacyPairing: no
[CHG] Device DC:2C:26:21:7B:F6 Name: Adesso Bluetooth 3.0 Keyboard
[CHG] Device DC:2C:26:21:7B:F6 Alias: Adesso Bluetooth 3.0 Keyboard
[bluetooth]# agent on
Agent registered
[bluetooth]# pair DC:2C:26:21:7B:F6
Attempting to pair with DC:2C:26:21:7B:F6
[CHG] Device DC:2C:26:21:7B:F6 Connected: yes
[agent] PIN code: 114412
Enter the PIN code and press the Return key on the Bluetooth keyboard.
[CHG] Device DC:2C:26:21:7B:F6 Modalias: usb:v0A5Cp8502d011B
[CHG] Device DC:2C:26:21:7B:F6 UUIDs: 00001000-0000-1000-8000-00805f9b34fb
[CHG] Device DC:2C:26:21:7B:F6 UUIDs: 00001124-0000-1000-8000-00805f9b34fb
[CHG] Device DC:2C:26:21:7B:F6 UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: yes
[CHG] Device DC:2C:26:21:7B:F6 Paired: yes
Pairing successful
The Blueetooth LED on the keyboard will now stop flashing
[CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: no
[CHG] Device DC:2C:26:21:7B:F6 Connected: no
[CHG] Device 30:21:17:4A:29:DC RSSI: -56
[bluetooth]#
The PIN code changes at each pairing. There is no simple way to test that
the keyboard works without connecting a monitor to the RPi. I am too lazy to
do that, but I trust it would have worked.
If the Raspberry Pi ends up in the living room and if the keyboard does
not work with the IPad because it connected with the RPi there will be two
consequences. First it will take a long time to figure out what is going on.
Second there will be hell to pay. I thought it best to remove the keyboard
from the list of paired devices.
pi@rpi3:~ $ bluetoothctl
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[NEW] Device DC:2C:26:21:7B:F6 Adesso Bluetooth 3.0 Keyboard
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[bluetooth]# remove DC:2C:26:21:7B:F6
[DEL] Device DC:2C:26:21:7B:F6 Adesso Bluetooth 3.0 Keyboard
Device has been removed
[bluetooth]# exit
[DEL] Controller B8:27:EB:55:FC:57 rpi3 [default]
Now its time to try to make a sound come out of the speaker.
Luckily, a recent discussion on the Raspberry forum entitled Bluetooth audio on stretch can get us there.
At this point a WAV
(signed 16 or 32 bit PCM encoded) file is
needed on the RPi3. I used Audacity to export a
MP3
piece of music to both 16 and 32 bit formats. And
the Bluetooth speaker must be connected.
pi@rpi3:~ $ aplay -D bluealsa:HCI=hci0,DEV=30:21:3E:31:C6:2B,PROFILE=a2dp sound-off-S16.wav
Playing WAVE 'sound-off-S16.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
That worked. There is only one Bluetooth device on the Raspberry Pi 3 as can be seen
from the hciconfig
command.
pi@rpi3:~ $ hciconfig -a
hci0: Type: Primary Bus: UART
BD Address: B8:27:EB:55:FC:57 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:39147 acl:289 sco:0 events:4003 errors:0
TX bytes:4556466 acl:7349 sco:0 commands:199 errors:0
Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH SNIFF
Link mode: SLAVE ACCEPT
Name: 'rpi3'
Class: 0x6c0000
Service Classes: Rendering, Capturing, Audio, Telephony
Device Class: Miscellaneous,
HCI Version: 4.1 (0x7) Revision: 0x145
LMP Version: 4.1 (0x7) Subversion: 0x2209
Manufacturer: Broadcom Corporation (15)
So we can simplify the command a little bit by not indicating which
Bluetooth device to use. Similarly, the a2dp
profile seems
to be the default and does not need to be specified.
pi@rpi3:~ $ aplay -D bluealsa:DEV=30:21:3E:31:C6:2B sound-off-S16.wav
Playing WAVE 'sound-off-S16.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
Instead of identifying the playback device in detail in the
aplay
command, a default configuration file, can be created. It
would be better to save an already existing /home/pi/.asoundrc
file before overwriting it.
pi@rpi3:~/somedir$ cd $home
pi@rpi3:~ $ ls -a .asoundrc
.asoundrc the file exists, otherwise ls shows nothing
pi@rpi3:~ $ mv .asoundrc _asoundrc.bak skip this if there is no .asoundrc file
pi@rpi3:~ $ nano .asoundrc
pcm.!default {
type plug
slave.pcm {
type bluealsa
device "30:21:3E:31:C6:2B"
profile "a2dp"
}
}
The filename is all that will need to be specified to play it.
pi@rpi3:~ $ aplay sound-off-S16.wav
Playing WAVE 'sound-off-S16.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
If there was a previously existing .asoundrc
configuration
file, and if it was sound (pun intended), then it would be best to combine
it with the new one. There is an example of a configuration file with three
output devices in section 7 below.
Steve Hawtin of
White Turret
Ltd pointed out, in a very kind fashion, that I had forgotten to give the
name of the configuration file, and, by extension, that I had omitted the
advice on saving a pre-existing file. Thank you for that pointer.
January 19, 2018
The music is played at full volume, which can be loud by my standards,
but would be merely a whisper for others. It is possible to control the
volume, as the music is played, by using AlsaMixer
in a second terminal.
pi@rpi3:~ $ alsamixer -D bluealsa
Press on F3 to view the Playback
devices. Use the left and right cursor keys to select the
AUDIOPOD2 - A2DP
device. Then use the up and down
cursor keys to adjust the volume of the output as the WAV
file is played in another terminal as explained in the previous section.
Alternatively, the volume can be set before playing the music with
the command line.
pi@rpi3:~ $ amixer -D bluealsa sset "AUDIOPOD2 - A2DP" 50%
Simple mixer control 'AUDIOPOD2 - A2DP',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 127
Mono:
Front Left: Playback 64 [50%] [on]
Front Right: Playback 64 [50%] [on]
Append a "+" or "-" to move the volume up or down. For example
to set the volume to 30% of full volume when it is already at
50%, request a diminution of 20% as follows.
pi@rpi3:~ $ amixer -D bluealsa sset "AUDIOPOD2 - A2DP" 20%-
Simple mixer control 'AUDIOPOD2 - A2DP',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 127
Mono:
Front Left: Playback 38 [30%] [on]
Front Right: Playback 38 [30%] [on]
Thus 20%- is not a reduction of 20% of the current
volume because that would have brought the volume to 40% of the maximum
(20% of 50% is 10% and 50% - 10% give 40%.
I used the raspi-config
utility to enable the analogue
output through the 3.5 mm jack. I then connected a typical pair of powered
computer speakers to the RPi3. And while at it, I added a second Bluetooth
speaker which is just as easy as adding the first. Pair it and connect to it
with bluetoothctl
.
pi@rpi3:~ $ bluetoothctl
[NEW] Controller B8:27:EB:55:FC:57 rpi3 [default]
[NEW] Device 30:21:3E:31:C6:2B AUDIOPOD2
[AUDIOPOD2]# agent on
Agent registered
[AUDIOPOD2]# default-agent
Default agent request successful
[AUDIOPOD2]# scan on
Discovery started
[CHG] Controller B8:27:EB:55:FC:57 Discovering: yes
[NEW] Device 30:21:17:4A:29:DC AUDIOPOD2
[AUDIOPOD2]# devices
Device 30:21:3E:31:C6:2B AUDIOPOD2
Device 30:21:17:4A:29:DC AUDIOPOD2
[AUDIOPOD2]# pair 30:21:17:4A:29:DC
Attempting to pair with 30:21:17:4A:29:DC
[CHG] Device 30:21:17:4A:29:DC Connected: yes
[CHG] Device 30:21:17:4A:29:DC UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:17:4A:29:DC UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:17:4A:29:DC UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:17:4A:29:DC UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:17:4A:29:DC UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 30:21:17:4A:29:DC ServicesResolved: yes
[CHG] Device 30:21:17:4A:29:DC Paired: yes
Pairing successful
[CHG] Device 30:21:17:4A:29:DC ServicesResolved: no
[CHG] Device 30:21:17:4A:29:DC Connected: no
[AUDIOPOD2]# connect 30:21:17:4A:29:DC
Attempting to connect to 30:21:17:4A:29:DC
[CHG] Device 30:21:17:4A:29:DC Connected: yes
Connection successful
[CHG] Device 30:21:17:4A:29:DC ServicesResolved: yes
[AUDIOPOD2]# scan off
[CHG] Device 30:21:17:4A:29:DC RSSI is nil
Discovery stopped
[CHG] Controller B8:27:EB:55:FC:57 Discovering: no
[AUDIOPOD2]# exit
Agent unregistered
[DEL] Controller B8:27:EB:55:FC:57 rpi3 [default]
Modify the sound configuration file
pcm.!default plug:jack
pcm.!jack {
type plug
slave {
pcm "hw:0,0"
}
}
pcm.!pod1 {
type plug
slave.pcm {
device "30:21:17:4A:29:DC"
type bluealsa
profile "a2dp"
}
}
pcm.!pod2 {
type plug
slave.pcm {
type bluealsa
device "30:21:3E:31:C6:2B"
profile "a2dp"
}
}
Now a sound file can be played through the built in 3.5mm analogue
output.
pi@rpi3:~ $ aplay -D jack sound-off-S16.wav
or
pi@rpi3:~ $ aplay -D default sound-off-S16.wav
or simply
pi@rpi3:~ $ aplay sound-off-S16.wav
To hear the sound through one of the Bluetooth speakers, which of course
needs to be connected, use the command.
pi@rpi3:~ $ aplay -D pod1 sound-off-S16.wav
or
pi@rpi3:~ $ aplay -D pod2 sound-off-S16.wav
It remains possible to set the volume. In alsamixer
both speaker will be visible. On the command line, the name of the
device is now different.
pi@rpi3:~ $ amixer -D bluealsa sset "AUDIOPOD2 #2 - A2DP" 30%
But what about playing the same sound file through both speakers
simultaneously? I tried following advice from
Eliot Eshelman without success. I keep on getting
xrun
errors - which means buffer overruns or underruns.
For the fun of it, I tried playing different wav files simultaneously
from different terminals. There is no problem in running the analogue audio
and one of the Bluetooth speaker at the same time. But running both Bluetooth
speakers does not work at all well, there is a lot of stuttering.
Added: May 12, 2018
When I tried to run Music On Console (MOC) on the
Raspberry Pi using Bluetooth speakers, I ran into difficulties. It turns out
that the culprit was the .asoundrc
configuration file.
The solution that I found (see Music on Console, ALSA, and Bluetooth on Raspbian Stretch)
was to use a bare bones configuration file:
defaults.bluealsa.interface "hci0"
defaults.bluealsa.device "30:21:3E:31:C6:2B"
defaults.bluealsa.profile "a2dp"
Then aplay
, alsamixer
and amixer
work with the Bluetooth speaker if the -D bluealsa
option is included in the command line. When no device is specified,
the sound is output to the 3.5 mm jack (or HDMI connector).
That "solution" will not be very useful if different Bluetooth speakers
will be connected at different times. For those
that find themselves in that situation, I suggest looking at the script
memeplex
presented at the end of the Unable to find
definition 'defaults.bluealsa.interface' issue that
he raised on the bluez-alsa github site. My
reading of the script is that it creates a new .asoundrc
configuration file on the run, setting the bluealsa.device
value (the Bluetooth speaker MAC address) from bluetoothctl
.