md
Baby Bluetooth Steps on Raspberry Pi 3 - Raspbian (Stretch)
December 4, 2017
Updated: May 14, 2018
-- Music on Console, ALSA, and Bluetooth on Raspbian Stretch->
Bluetooth Audio with Rasbian Stretch on the Raspberry Pi 3->

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.

Since writing this paper and the follow-up post on using MOC on the Raspberry Pi with a Bluetooth speaker, I have learned a bit more about Bluetooth. At first I patched this post, but I have now taken a second attempt at the subject. Before applying what is proposed here, it would be a good idea to read Bluetooth Audio with Rasbian Stretch on the Raspberry Pi 3.
May 14, 2018

Table of Contents

  1. Starting All Over... Again
  2. Bluetooth on Raspbian Stretch
  3. Connecting Bluetooth Devices
  4. Connecting Bluetooth Devices with PIN Code
  5. Playing Sound Through a Bluetooth Speaker
  6. Controling the Playback Volume of a Bluetooth Speaker
  7. Using a second Bluetooth Speaker
  8. Caveat (added May 12, 2018)

  1. Starting All Over... Again
  2. 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
    1. Change password for the current user mandatory
    2. Configure network settings
      • N1 Hostname on the network to rpi3
      • N2 Provide Wi-fi credentials (network name and password)
    3. Boot Options - did nothing
    4. Localisation Options
      • I1 Change Locale to add fr_CA
      • I2 Change Timezone - to America/Moncton
    5. Interfacing Options
      • P2 SSH - enabled mandatory
      • P5 I2C - enabled
    6. Overclock - did nothing
    7. 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.

  3. Bluetooth on Stretch
  4. 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.

  5. Connecting Bluetooth Devices
  6. 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:~ $ echo -e "connect 30:21:3E:31:C6:2B" | bluetoothctl [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:~ $ echo -e "disconnect 30:21:3E:31:C6:2B" | bluetoothctl [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:~ $ echo -e "connect 30:21:3E:31:C6:2B" | bluetoothctl > /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.

  7. Connecting Bluetooth Devices with PIN Code
  8. 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]

  9. Playing Sound Through a Bluetooth Speaker
  10. 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

  11. Controlling the Playback Volume of a Bluetooth Speaker
  12. 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%.

  13. Using Multiple Speakers
  14. 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.

  15. Caveat
  16. 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.

-- Music on Console, ALSA, and Bluetooth on Raspbian Stretch->
Bluetooth Audio with Rasbian Stretch on the Raspberry Pi 3->