Raspberry Pi Bluetooth Speaker: Difference between revisions

From Alpine Linux
m (→‎Bluetooth: Use more pkg template.)
 
(25 intermediate revisions by 7 users not shown)
Line 7: Line 7:
* A Raspberry Pi
* A Raspberry Pi
* A Bluetooth USB dongle (if your Pi doesn’t have Bluetooth on board)
* A Bluetooth USB dongle (if your Pi doesn’t have Bluetooth on board)
* An active speaker or sound card and passive speaker(s)
* Sound card and speaker(s)
 
=Article Completion=
# Test everything
# Turn every background task into a service
# More investigation on Bluetooth pairing


=Getting the Speaker(s) Working=
=Getting the Speaker(s) Working=
The audio hardware can range from using the Raspberry Pi's on board audio with an external (active) travel speaker to wiring up an amplifier to some high-end passive speakers.
To get the best results, you'll need an dedicated audio add-on board and matching speakers. Higher end passive speakers need a proper amplifier (e.g. HiFiBerry Amp2 or IQaudIO IQaudIO DigiAMP+).


I'm testing this using Raspberry Pi's excellent IQaudio DigiAMP+ board with a pair bookshelf speakers and an old (active) travel speaker using the on board audio. It is possible to test by using headphones instead of active speakers.
I've used the whole range of IQaudio audio boards with different speakers and headphones. I'd also recommend a dedicated USB Bluetooth dongle (don't get the cheapest versions of these). It is possible to test by using the on-board Bluetooth and the on-board audio with headphones but because of dropped packets, the audio quality isn't great.


Once the speaker(s), and possibly amplifier, are wired into the Pi, it's time to install a fresh version of Alpine Linux.  The armv7 version from the [https://alpinelinux.org/downloads/ Downloads] page works on almost all Pis. This Wiki has several articles about installing Alpine on a Raspberry Pi.
Once the speakers and audio card are connected to the Raspberry Pi, it's time to install a fresh version of Alpine Linux.  The armv7 version from the [https://alpinelinux.org/downloads/ Downloads] page works on almost all Pis. This Wiki has several articles about installing Alpine on a Raspberry Pi.


Enable writing to the boot media:
Enable writing to the boot media:
Line 20: Line 25:
   mount /media/mmcblk0p1 -o rw,remount
   mount /media/mmcblk0p1 -o rw,remount


Then either enable the on board sound:
Then, either enable the on board sound:


   echo "dtparam=audio=on" >> /media/mmcblk0p1/usercfg.txt
   echo "dtparam=audio=on" >> /media/mmcblk0p1/usercfg.txt


or your fancier sound card (e.g. IQaudIO):
or your sound card (e.g. IQaudIO):


   echo "dtoverlay=iqaudio-dacplus,unmute_amp" >> /media/mmcblk0p1/usercfg.txt
   echo "dtoverlay=iqaudio-dacplus,unmute_amp" >> /media/mmcblk0p1/usercfg.txt


and then reboot your Pi.
reboot.


Follow [https://wiki.alpinelinux.org/wiki/ALSA these instructions] to enable ALSA. In summary
Follow [[ALSA|these instructions]] to enable ALSA. In summary:
    
    
   apk add alsa-utils alsa-utils-doc alsa-lib alsaconf # the required software for sound
   apk add {{pkg|alsa-utils|arch=a*}} {{pkg|alsa-utils-doc|arch=a*}} {{pkg|alsa-lib|arch=a*}} {{pkg|alsaconf|arch=a*}} # the required software for sound
   aplay -l # should display a List of PLAYBACK Hardware Devices
   aplay -l # should display a List of PLAYBACK Hardware Devices


Line 48: Line 53:
     Subdevice #6: subdevice #6
     Subdevice #6: subdevice #6


Before you play anything from your speakers, I advise you to lower the volume first.
Before you play anything from your speakers, I recommend turnong down the volume.


   amixer
   amixer


displays a list of "simple controls"; for my headphones and the on-board sound, the output is this:
displays a list of "simple controls." For my headphones and the on-board sound, the output looks like this:


   Simple mixer control 'Headphone',0
   Simple mixer control 'Headphone',0
Line 60: Line 65:
     Mono: Playback 0 [96%] [0.00dB] [on]
     Mono: Playback 0 [96%] [0.00dB] [on]


In this case there is only 1 control, 'Headphone', so I issue this command to lower the maximum volume to a comfortable level (50% in my case).
In this case, there is only 1 control, 'Headphone', so I issue this command to lower the maximum volume to a comfortable level. (50%)


   amixer sset Headphone 50%
   amixer sset Headphone 50%


The IQaudIO DAC that I use has a much longer set of controls. I issued this command to set the volume:
The IQaudIO DAC that I use has a much larger set of controls. I issued this command to set the volume:


   amixer sset 'Digital' 50 # quotes may be required if there are spaces in the control name
   amixer sset 'Digital' 50 # quotes may be required if there are spaces in the control name


Note that there can be several interlinked controls, some of which are muted by defualt. ALSA (and other audio software on Linux) is notoriously under-documented, try `man amixer` for more information. Sometimes it is easier to use a more visual control to change the configuration:
Note: there can be several interlinked controls, some of which are muted by defualt. ALSA (and other audio software on Linux) is notoriously under-documented, try `man amixer` for more information. Sometimes it is easier to use a more visual control to change the configuration:


   alsamixer
   alsamixer
Line 76: Line 81:
   speaker-test -t wav -c 2
   speaker-test -t wav -c 2


Then you should hear "Front Left, Front Right" repeating from your chosen speakers. Now it's time to setup Bluetooth. Don't forget to save your changes (lbu commit) before moving on.
Then you should hear "Front Left, Front Right" repeating from your chosen speakers. Now it's time to setup Bluetooth. Don't forget to save your changes (lbu commit).


=Bluetooth=
=Bluetooth=
 
I used [[Raspberry Pi 3 - Setting Up Bluetooth|Raspberry Pi 3 - Setting Up Bluetooth]] as a reference with some slight modifications as I am using a Pi 4.
I used [https://wiki.alpinelinux.org/wiki/Raspberry_Pi_3_-_Setting_Up_Bluetooth Raspberry Pi 3 - Setting Up Bluetooth] as a reference with some slight modifications as I am using a Pi 4.


Raspberry Pi 4
Raspberry Pi 4


   apk add bluez
   apk add {{pkg|bluez|arch=a*}}
   btattach -B /dev/ttyAMA0 -P bcm -S 3000000 &
   btattach -B /dev/ttyAMA0 -P bcm -S 3000000 &
   # btattach -B /dev/ttyAMA0 -P bcm -S 115200 -N & # Pi 3 - not tested by me
   # btattach -B /dev/ttyAMA0 -P bcm -S 115200 -N & # Pi 3 - not tested by me
   rc-service bluetooth start
   rc-service bluetooth start


edit {{Path|/etc/mdev.conf}} and enable bluetooth. This is done by uncommenting the the line and change the <code>btattach</code> to work with Pi 4.


edit ''/etc/mdev.conf'' and enable bluetooth. We're using `sed`, where '''s/#rpi bluetooth/rpi bluetooth/''' means replace '''#rpi bluetooth''' with '''rpi bluetooth'''.
{{cat|/etc/mdev.conf|<nowiki>...
# rpi bluetooth
ttyAMA0 root:tty 660 @btattach -B /dev/ttyAMA0 -P bcm -S 3000000 &
...</nowiki>}}


  sed -i 's/#rpi bluetooth/rpi bluetooth/' /etc/mdev.conf
Changes to {{Path|/etc/bluetooth/main.conf}}
  sed -i 's/#ttyAMA0        root:tty 660 @btattach -B \/dev\/$MDEV -P bcm -S 115200/ttyAMA0        root:tty 660 @btattach -B \/dev\/$MDEV -P bcm -S 3000000/' /etc/mdev.conf


Note: the last command uncomments the ''btattach'' command and changes it to work with the Pi 4.
  Name = Pi-Bluetooth-Speaker  # This is what you'll see when connecting
  Class = 0x41C                # Adding audio playback and recording to this Bluetooth device
  DiscoverableTimeout = 0      # Always discoverable
  AlwaysPairable = true        # Always pairable
  PairableTimeout = 0          # no time limit
  AutoEnable=true              # starts Bluetooth when Linux 'sees' the Bluetooth device at boot


 
Ensure that Bluetooth is started at boot:
  apk add python3 py3-dbus py3-gobject3
 
Ensure that bluetooth is started at boot:


   rc-update add bluetooth
   rc-update add bluetooth


Bluetooth's state, including paired devices, in held in `/var/lib/bluetooth` so you'll need to add this to `lbu` state:
Bluetooth's state, including paired devices, in held in {{Path|/var/lib/bluetooth}} so you'll need to add this to `lbu` state:


   lbu include /var/lib/bluetooth
   lbu include /var/lib/bluetooth
  lbu commit && reboot
Manual device pairing


  bluetoothctl


   lbu commit && reboot
   [bluetooth]# discoverable on
  [agent] Confirm passkey 627133 (yes/no): yes
  [agent] Authorize service 0000110e-0000-1000-8000-00805f9b34fb (yes/no): yes


Changes to /etc/bluetooth/main.conf
Device pairing:


   Name = BlueZ-ALSA-test
   apk add {{pkg|python3|arch=a*}} {{pkg|py3-dbus|arch=a*}} {{pkg|py3-gobject3|arch=a*}}
  Class = 0x41C
  DiscoverableTimeout = 0
  AlwaysPairable = true
  PairableTimeout = 0
  AutoEnable=true


Getting this to work currently involves running the bluez-simple-agent after having edited it to always return sucessful. You'll need to comment out some lines (by adding "#" at the beginning):


Getting this to work currently involves running the bluez-simple-agent after having edited it to always return sucessful. Note the comments below:
  vi /usr/bin/bluez-simple-agent


        def RequestPinCode(self, device):                                     
  #import bluezutils
                print("RequestPinCode (%s)" % (device))                     
                set_trusted(device)                                         
                return #ask("Enter PIN Code: ")


          def RequestConfirmation(self, device, passkey):                    
        def RequestConfirmation(self, device, passkey):
                 print("RequestConfirmation (%s, %06d)" % (device, passkey))  
                 #print("RequestConfirmation (%s, %06d)" % (device, passkey))
                 #confirm = ask("Confirm passkey (yes/no): ")              
                 #confirm = ask("Confirm passkey (yes/no): ")
                 #if (confirm == "yes"):                                    
                 #if (confirm == "yes"):
                 set_trusted(device)                                        
                 set_trusted(device)      
                 return                                                      
                 return      
                 #raise Rejected("Passkey doesn't match")
                 #raise Rejected("Passkey doesn't match")


And then running the revised agent in the background:
And then running the revised agent in the background, and pair your devices:


   bluez-simple-agent &
   bluez-simple-agent &
  lbu include /usr/bin/bluez-simple-agent
  lbu commit


Notes: [https://www.kynetics.com/docs/2018/pairing_agents_bluez/ Pairing Agents in BlueZ stack]
Notes: [https://www.kynetics.com/docs/2018/pairing_agents_bluez/ Pairing Agents in BlueZ stack]
Line 145: Line 155:


=bluez-alsa=
=bluez-alsa=
At the time of writing this article, bluez-alsa is only found in the community repositories, so you need to edit your repository list:


   vi /etc/apk/repositories
   vi /etc/apk/repositories


remove the comment from your community repository, mine is:
remove the "#" from the community repository, mine is:


   http://uk.alpinelinux.org/alpine/v3.14/community
   https://uk.alpinelinux.org/alpine/v3.14/community


This is the final stretch.  We've got bluetooth working and now we want to link bluetooth to the speakers
This is the final stretch.  We've got bluetooth working and now we want to link bluetooth to the speakers


   apk add bluez-alsa
   apk add bluez-alsa bluez-alsa-utils
   bluealsa -p a2dp-source -p a2dp-sink &
   rc-update add bluealsa
  rc-service start bluealsa
   bluealsa-aplay &
   bluealsa-aplay &


=Doing Something Title=
[https://github.com/Arkq/bluez-alsa Bluetooth Audio ALSA Backend]
Write the steps of how to do something in this section.
[https://github.com/Arkq/bluez-alsa/tree/master/doc bluez-alsa doc]
If possible, show an example first, then tell your readers the steps.
[https://manpages.debian.org/unstable/bluez-alsa-utils/bluealsa.8.en.html man bluealsa]
Break this procedure into separate procedures to avoid more than
[https://manpages.debian.org/unstable/bluez-alsa-utils/bluealsa-aplay.1.en.html man bluealsa-aplay]
about 7-9 steps per procedure.
[https://panther.kapsi.fi/posts/2018-11-17_linux_bluetooth_audio Bluetooth audio in Linux: ALSA and LDAC]
 
INSERT GREAT EXAMPLE HERE
 
#Answer the following three questions, at least in your head.
##What do I explain how to do?
##How do I do that?
##What do HOWTO readers already know about doing that?
#Write up a good example. This ensures you can do it.
#Write up the steps to do it.
#Write the background info/prerequisites readers need.
#Write the summary.
#Clean up your work.
#Revise, revise, revise.


=See Also=
=See Also=
Line 184: Line 183:
* Pimoroni's [https://shop.pimoroni.com/products/audio-amp-shim-3w-mono-amp Audio Amp SHIM (3W Mono Amp)] and [https://shop.pimoroni.com/products/mini-speaker-4-3w Mini Speaker 4Ω (3W)]
* Pimoroni's [https://shop.pimoroni.com/products/audio-amp-shim-3w-mono-amp Audio Amp SHIM (3W Mono Amp)] and [https://shop.pimoroni.com/products/mini-speaker-4-3w Mini Speaker 4Ω (3W)]
* The Pi Hut offers this [https://thepihut.com/products/adafruit-i2s-3w-stereo-speaker-bonnet-for-raspberry-pi Adafruit I2S 3W Stereo Speaker Bonnet for Raspberry Pi (Mini Kit)] and the [https://thepihut.com/products/stereo-enclosed-speaker-set-3w-4-ohm Stereo Enclosed Speaker Set - 3W 4 Ohm]
* The Pi Hut offers this [https://thepihut.com/products/adafruit-i2s-3w-stereo-speaker-bonnet-for-raspberry-pi Adafruit I2S 3W Stereo Speaker Bonnet for Raspberry Pi (Mini Kit)] and the [https://thepihut.com/products/stereo-enclosed-speaker-set-3w-4-ohm Stereo Enclosed Speaker Set - 3W 4 Ohm]
[[Category:ARM]]
[[Category:Raspberry]]
[[Category:Sound]]

Latest revision as of 13:22, 10 January 2024

How To Build a Raspberry Pi Bluetooth Speaker

This articles describes how to build a Bluetooth speaker. This article is being actively written. Currently it is full of bugs but will provide some useful pointers.

Before You Start

You’ll need:

  • A Raspberry Pi
  • A Bluetooth USB dongle (if your Pi doesn’t have Bluetooth on board)
  • Sound card and speaker(s)

Article Completion

  1. Test everything
  2. Turn every background task into a service
  3. More investigation on Bluetooth pairing

Getting the Speaker(s) Working

To get the best results, you'll need an dedicated audio add-on board and matching speakers. Higher end passive speakers need a proper amplifier (e.g. HiFiBerry Amp2 or IQaudIO IQaudIO DigiAMP+).

I've used the whole range of IQaudio audio boards with different speakers and headphones. I'd also recommend a dedicated USB Bluetooth dongle (don't get the cheapest versions of these). It is possible to test by using the on-board Bluetooth and the on-board audio with headphones but because of dropped packets, the audio quality isn't great.

Once the speakers and audio card are connected to the Raspberry Pi, it's time to install a fresh version of Alpine Linux. The armv7 version from the Downloads page works on almost all Pis. This Wiki has several articles about installing Alpine on a Raspberry Pi.

Enable writing to the boot media:

 mount /media/mmcblk0p1 -o rw,remount

Then, either enable the on board sound:

 echo "dtparam=audio=on" >> /media/mmcblk0p1/usercfg.txt

or your sound card (e.g. IQaudIO):

 echo "dtoverlay=iqaudio-dacplus,unmute_amp" >> /media/mmcblk0p1/usercfg.txt

reboot.

Follow these instructions to enable ALSA. In summary:

 apk add alsa-utils alsa-utils-doc alsa-lib alsaconf # the required software for sound
 aplay -l # should display a List of PLAYBACK Hardware Devices

In my case my list is:

 **** List of PLAYBACK Hardware Devices ****
 card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
   Subdevices: 8/8
   Subdevice #0: subdevice #0
   Subdevice #1: subdevice #1
   Subdevice #2: subdevice #2
   Subdevice #3: subdevice #3
   Subdevice #4: subdevice #4
   Subdevice #5: subdevice #5
   Subdevice #6: subdevice #6

Before you play anything from your speakers, I recommend turnong down the volume.

 amixer

displays a list of "simple controls." For my headphones and the on-board sound, the output looks like this:

 Simple mixer control 'Headphone',0
   Capabilities: pvolume pvolume-joined pswitch pswitch-joined
   Playback channels: Mono
   Limits: Playback -10239 - 400
   Mono: Playback 0 [96%] [0.00dB] [on]

In this case, there is only 1 control, 'Headphone', so I issue this command to lower the maximum volume to a comfortable level. (50%)

 amixer sset Headphone 50%

The IQaudIO DAC that I use has a much larger set of controls. I issued this command to set the volume:

 amixer sset 'Digital' 50 # quotes may be required if there are spaces in the control name

Note: there can be several interlinked controls, some of which are muted by defualt. ALSA (and other audio software on Linux) is notoriously under-documented, try `man amixer` for more information. Sometimes it is easier to use a more visual control to change the configuration:

 alsamixer

Finally, if you issue this command:

 speaker-test -t wav -c 2

Then you should hear "Front Left, Front Right" repeating from your chosen speakers. Now it's time to setup Bluetooth. Don't forget to save your changes (lbu commit).

Bluetooth

I used Raspberry Pi 3 - Setting Up Bluetooth as a reference with some slight modifications as I am using a Pi 4.

Raspberry Pi 4

 apk add bluez
 btattach -B /dev/ttyAMA0 -P bcm -S 3000000 &
 # btattach -B /dev/ttyAMA0 -P bcm -S 115200 -N & # Pi 3 - not tested by me
 rc-service bluetooth start

edit /etc/mdev.conf and enable bluetooth. This is done by uncommenting the the line and change the btattach to work with Pi 4.

Contents of /etc/mdev.conf

... # rpi bluetooth ttyAMA0 root:tty 660 @btattach -B /dev/ttyAMA0 -P bcm -S 3000000 & ...

Changes to /etc/bluetooth/main.conf

 Name = Pi-Bluetooth-Speaker   # This is what you'll see when connecting 
 Class = 0x41C                 # Adding audio playback and recording to this Bluetooth device
 DiscoverableTimeout = 0       # Always discoverable
 AlwaysPairable = true         # Always pairable
 PairableTimeout = 0           # no time limit
 AutoEnable=true               # starts Bluetooth when Linux 'sees' the Bluetooth device at boot

Ensure that Bluetooth is started at boot:

 rc-update add bluetooth

Bluetooth's state, including paired devices, in held in /var/lib/bluetooth so you'll need to add this to `lbu` state:

 lbu include /var/lib/bluetooth
 lbu commit && reboot

Manual device pairing

 bluetoothctl
 [bluetooth]# discoverable on
 [agent] Confirm passkey 627133 (yes/no): yes
 [agent] Authorize service 0000110e-0000-1000-8000-00805f9b34fb (yes/no): yes

Device pairing:

 apk add python3 py3-dbus py3-gobject3

Getting this to work currently involves running the bluez-simple-agent after having edited it to always return sucessful. You'll need to comment out some lines (by adding "#" at the beginning):

 vi /usr/bin/bluez-simple-agent
 #import bluezutils
       def RequestConfirmation(self, device, passkey):
               #print("RequestConfirmation (%s, %06d)" % (device, passkey))
               #confirm = ask("Confirm passkey (yes/no): ")
               #if (confirm == "yes"):
               set_trusted(device)        
               return        
               #raise Rejected("Passkey doesn't match")

And then running the revised agent in the background, and pair your devices:

 bluez-simple-agent &
 lbu include /usr/bin/bluez-simple-agent
 lbu commit

Notes: Pairing Agents in BlueZ stack Since Bluez 5.48, iPhones require pairing when connecting on a BLE GAP peripheral, why? Headless A2DP Audio Streaming on Raspbian Stretch

bluez-alsa

At the time of writing this article, bluez-alsa is only found in the community repositories, so you need to edit your repository list:

 vi /etc/apk/repositories

remove the "#" from the community repository, mine is:

 https://uk.alpinelinux.org/alpine/v3.14/community

This is the final stretch. We've got bluetooth working and now we want to link bluetooth to the speakers

 apk add bluez-alsa bluez-alsa-utils
 rc-update add bluealsa
 rc-service start bluealsa
 bluealsa-aplay &

Bluetooth Audio ALSA Backend bluez-alsa doc man bluealsa man bluealsa-aplay Bluetooth audio in Linux: ALSA and LDAC

See Also

Raspberry Pi's blog on How to play sound and make noise with your Raspberry P

There are lots of speaker and amplifier options: