Introduction: Raspberry Pi Wireless Bluetooth Audio FM Radio Transmitter

Picture of Raspberry Pi Wireless Bluetooth Audio FM Radio Transmitter

Use your raspberry pi to wirelessly stream music directly from your phone to your radio! Fantastic to get music to your car stereo.

This instructable draws on information from two other instructables, and fills in the gaps to make them work together. All of the steps to complete your Wireless Bluetooth Audio FM Radio Transmitter will be listed here, but more (specific) information about each piece can be found in these instructables:

Also many thanks to the Imperial College Robotics Society, for the pifm software.

Step 1: The Prerequisites

The parts (to make it work):

  1. Raspberry Pi with power supply (any model, but A+ or B+ are recommended)
  2. At least 2GB micro SD card with Raspian on it
    • You'll need to burn the image to the SD card
    • For windows, use a handy utility such as Win32DiskImager
    • For mac, there's instructions here
  3. Bluetooth A2DP dongle (something like this)
  4. Antenna
    • Just a length of wire will do (30cm - 75cm), attached to GPIO 4

The extra parts (needed only to complete the installation)

  1. Ethernet cable (and internet access)
  2. USB keyboard (or ssh)
  3. HDMI display and cable (or ssh)

Before you plug the SD card into your pi, plug it into your computer. Open up the drive, and find the config.txt file. Uncomment the following lines. This will allow us to force audio to be played through the HDMI output, rather than the stereo jack, which is necessary for the pi to stream music from bluetooth to the fm transmitter (without which you'd just get a loud, screechy noise on both the audio jack and on your radio).

hdmi_force_hotplug=1
hdmi_drive=2

Step 2: The Software

Plug the SD card (with OS image) into your pi, plug in the USB keyboard, the ethernet cable, connect it to the display, and power it up.

If it asks for login credentials, the default username is pi and the default password is raspberry.

Proceed with downloading the necessary software by executing the following commands:

sudo apt-get upgrade
sudo apt-get install bluez pulseaudio-module-bluetooth python-gobject python-gobject-2 bluez-tools sudo apt-get install sox libsox-fmt-all cd /home/pi; mkdir fm; cd fm wget http://www.icrobotics.co.uk/wiki/images/c/c3/Pifm.tar.gz

tar -zxvf Pifm.tar.gz

Step 3: The Configuration

Make the following modifications

Add our user pi to the Pulse audio group

sudo usermod –a –G lp pi

Audio configuration settings

sudo nano /etc/bluetooth/audio.conf

Add the following text under

[General]:
Enable=Source,Sink,Media,Socket

Pulse settings

sudo nano /etc/pulse/daemon.conf

Comment this line by adding a semicolon

; speex-float-3

Add these lines

resample-method = trivial
exit-idle-time = -1

Bluetooth configuration

sudo nano /etc/bluetooth/main.conf

Modify these lines to customize your bluetooth device name and class

Name = nameyourbluetoothdevicehere
Class = 0x20041C

Bluetooth configuration of your device

sudo nano /var/lib/bluetooth/<bluetooth mac address>/config

Modify these lines to customize your bluetooth device name and class

(Note, the class may reset on reboot. Don't worry too much about it)

name nameyourbluetoothdevicehere
class 0x20041C

Input rules

sudo nano /etc/udev/rules.d/99-input.rules

Add this line

KERNEL=="input[0-9]*", RUN+="/usr/lib/udev/bluetooth"

Device initialization (auto-login)

sudo nano /etc/inittab

Modify the following line to look like this

(was something like this) 1:2345:respawn:/sbin/getty --noclear 38400 tty1

1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

== OPTIONAL ==

Increase the audio quality of the fm transmitter

sudo nano /home/pi/fm/pifm.c

Find and modify the following lines

QUALITY=15 SQUALITY=20

Then recompile

cd /home/pi/fm; mv pifm pifm_bak;

g++ -O3 -o pifm pifm.c

Step 4: The Scripts

Create the following scripts

sudo nano /usr/lib/udev/bluetooth

Type this all into the empty editor, then save

Note and adjust the radio frequency and volume to your preference 

#!/bin/bash
AUDIOSINK="alsa_output.platform-bcm2835_AUD0.0.analog-stereo"
ACTION=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")
echo "Executing bluetooth script...|$ACTION|" >> /var/log/bluetooth_dev
if [ "$ACTION" = "add" ]
then
  # Turn off BT discover mode before connecting existing BT device to audio
  hciconfig hci0 noscan
  # Turn off BT auto connect if it is still running
  sudo killall bluetooth-auto

  # set the audio output to the hdmi
  amixer cset numid=3 2
  # Set volume level to 100 percent
  amixer set Master 100%
  # Set sink volume to 125%
  pacmd set-sink-volume 0 0x12500

  for dev in $(find /sys/devices/virtual/input/ -name input*)
    do
	if [ -f "$dev/name" ]
	then
	
	  mac=$(cat "$dev/name")
	  # Add this mac address to list of trusted addresses
	  TRUST=$(grep "$mac" /usr/lib/udev/bluetooth-trust)
	  if [ -z "$TRUST" ]
	  then
		echo "Adding $mac to trusted addresses" >> /var/log/bluetooth_dev
		echo $mac >> /usr/lib/udev/bluetooth-trust
	  fi
	  
	  mac_underscore=$(cat "$dev/name" | sed 's/:/_/g')
	  bluez_dev=bluez_source.$mac_underscore
	  
	  # Set source volume to 125%
	  pacmd set-source-volume $bluez_dev 0x12500

	  sleep 1
	  CONFIRM=`sudo -u pi pactl list short | grep $bluez_dev`
	  if [ ! -z "$CONFIRM" ]
	  then
		echo "Setting bluez_source to:  $bluez_dev" >> /var/log/bluetooth_dev
		echo pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
		sudo -u pi pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
		echo "Killing any existing radio connections" >> /var/log/bluetooth_dev
		sudo killall pifm >> /var/log/bluetooth_dev
		echo "Connecting bluetooth output to radio input, playing on 87.7" >> /var/log/bluetooth_dev
		# Using $AUDIOSINK instead of 0 here doesn't seem to work, not sure why
		echo pacat -r -d 0 --latency-msec=50 | sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - gain -l 10 | sudo /home/pi/fm/pifm - 87.9 44100 stereo >> /var/log/bluetooth_dev
		sudo -u pi pacat -r -d 0 --latency-msec=50 | sudo -u pi sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - gain -l 10 | sudo /home/pi/fm/pifm - 87.7 44100 stereo >> /var/log/bluetooth_dev
	  fi
	fi
  done
fi

if [ "$ACTION" = "remove" ]
then
  # Turn on bluetooth discovery if device disconnects
  sudo hciconfig hci0 piscan
  # Turn on bluetooth auto discovery
  sudo /usr/lib/udev/bluetooth-auto &
fi

Finally, grant appropriate permissions to the script
sudo chmod 774 /usr/lib/udev/bluetooth
sudo nano /usr/lib/udev/bluetooth-auto

Type this all into the empty editor, then save


#!/bin/bash
while [ true ]
do
  sleep 1
  echo "Scanning for trusted devices" >> /var/log/bluetooth_dev
  for mac in $(sudo hcitool scan | grep ":" | awk '{print $1}')
  do
	trust=$(grep "$mac" /usr/lib/udev/bluetooth-trust)
	if [ ! -z "$trust" ]
	then
	  _BT_ADAPTER=`dbus-send --system --print-reply --dest=org.bluez / org.bluez.Manager.DefaultAdapter|awk '/object path/ {print $3}'`
	  BT_ADAPTER=${_BT_ADAPTER//\"/}
	  mac_underscore=$(cat "$mac" | sed 's/:/_/g')
	  echo "Connecting to device at: $mac" >> /var/log/bluetooth_dev
	  sudo dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER/dev_$mac_underscore org.bluez.AudioSource.Connect >> /var/log/bluetooth_dev
	  exit 0
	fi
  done
done


Finally, grant appropriate permissions to the script, and create the trust file
sudo chmod 774 /usr/lib/udev/bluetooth-auto
sudo touch /usr/lib/udev/bluetooth-trust
sudo nano /etc/init.d/bluetooth-agent

Type this all into the empty editor, then save

#!/bin/sh
#/etc/init.d/bluetooth-agent
### BEGIN INIT INFO
# Provides: bluetooth-agent
# Required-Start: $remote_fs $syslog bluetooth pulseaudio
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Makes Bluetooth discoverable and connectable to 0000
# Description: Start Bluetooth-Agent at boot time.
### END INIT INFO
USER=root
HOME=/root
export USER HOME
case "$1" in
  start)
	echo "initializing pulseaudio"
	sudo pactl info
	echo "setting bluetooth discoverable"
	sudo hciconfig hci0 piscan
	start-stop-daemon -S -x /usr/bin/bluetooth-agent -c pi -b -- 0000
	echo "bluetooth-agent started pw: 0000"
	sudo /usr/lib/udev/bluetooth-auto &
        echo "bluetooth-auto-discovery started"
        sudo /home/pi/fm/pifm /home/pi/fm/silence 87.7 44100 stereo
	echo "pifm started at 87.7, playing silence"
	;;
  stop)
	echo "Stopping bluetooth-agent"
	start-stop-daemon -K -x /usr/bin/bluetooth-agent
	;;
  *)
	echo "Usage: /etc/init.d/bluetooth-agent {start|stop}"
	exit 1
	;;
  esac
exit 0

Finally, create the silence file, grant appropriate permissions to the script, and add it to the list of programs that run on startup


sudo touch /home/pi/fm/silence
sudo chmod 755 /etc/init.d/bluetooth-agent
sudo update-rc.d bluetooth-agent defaults

Step 5: Enjoy

That's it. Restart your pi - either by just disconnecting and reconnecting the power supply, or by running the command:

sudo reboot

Disconnect the keyboard, display, and ethernet cable. You no longer need these.

You should see the pi as a bluetooth device to which you can connect. After connecting the first time, the pi will add your phone to its list of trusted devices. Each time the pi powers up, it will attempt to automatically connect to nearby trusted devices. Likewise, if you move out of bluetooth range, the pi will attempt to reconnect when you're back in range.

Begin playing music, send it to the pi, and tune your radio to your chosen frequency (default 87.7).

Comments

Tinclon (author)2015-01-26

Update: Turns out pacat adds delay by default. Updated the line in /usr/lib/udev/bluetooth to read as follows:

sudo -u pi pacat -r -d 0 --latency-msec=50 | sudo -u pi sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - gain -l 10 | sudo /home/pi/fm/pifm - 87.7 44100 stereo >> /var/log/bluetooth_dev

I've also added 10dB gain to the line, as I found the volume on the radio was too low. The docs say this may produce some clipping/distortion, but I've yet to really notice any.

RyanK99 (author)2016-05-08

Sorry it's been a while since you posted, but my phone keeps saying "pairing rejected" after inputting the passcode. Any fix?

MorenoR2 (author)RyanK992017-02-08

you could use my custom simple-agent, check out my website's post (comments above)

SebastienThiry (author)2016-05-22

Hello, anyone for update this how to, it doesn't work anymore on Raspbian jessie and Raspberry 2 B+

MorenoR2 (author)SebastienThiry2017-02-08

Check out my comment above :)

MorenoR2 made it! (author)2017-02-08

I had few issues following this guide due to raspbian changes over time, but finally i managed to make my own Stereo + bluetooth fm radio transmitter https://blog.morrolinux.it/raspberry-pi-fm-radio-t...

blackout73 (author)2016-01-24

Have anyone tried this radio application working in Raspberry Pi A+?

JonathanV4 (author)2015-06-26

hi, right after i can't seem to get any audio from my device to stream to pifm

this is the output of the log


Setting bluez_source to: bluez_source.EC_88_92_6C_3B_58

pactl load-module module-loopback source=bluez_source.EC_88_92_6C_3B_58 sink=alsa_output.platform-bcm2835_AUD0.0.analog-stereo rate=44100 adjust_time=0

Killing any existing radio connections

Connecting bluetooth output to radio input, playing on 87.7

exiting

ChristopherE9 (author)JonathanV42015-08-27

Try getting rid of the platform-bcm2835_AUD0. in the script. That worked for me

ChristopherE9 (author)2015-08-24

https://github.com/markondej/fm_transmitter

Can you update using the new program for both RPi 1 and 2?

abnev (author)2015-05-09

Hi Tinclon,

I followed the steps above but i'm unable to get it working correctly. I went through the scripts and found that it's failing in /usr/lib/udev/bluetooth when running the following:

CONFIRM=`sudo -u pi pactl list short | grep $bluez_dev`

Modifying the script to output $bluez_dev I have the following:

/org/bluez/2069/hci0

Attempting to run the pactl line manually, I found that my device isn't listed:

pi@raspberrypi ~ $ sudo -u pi pactl list short | grep /org/bluez/2069/hci0

pi@raspberrypi ~ $

Running 'sudo -u pi pactl list short' I have the following:

0 module-device-restore

1 module-stream-restore

2 module-card-restore

3 module-augment-properties

4 module-alsa-card device_id="0" name="0" card_name="alsa_card.0" namereg_fail=false tsched=yes fixed_latency_range=no ignore_dB=no deferred_volume=yes card_properties="module-udev-detect.discovered=1"

5 module-udev-detect

6 module-bluetooth-discover

7 module-native-protocol-unix

8 module-default-device-restore

9 module-rescue-streams

10 module-always-sink

11 module-intended-roles

12 module-suspend-on-idle

13 module-console-kit

14 module-systemd-login

15 module-position-event-sounds

16 module-role-cork

17 module-filter-heuristics

18 module-filter-apply

19 module-dbus-protocol

20 module-switch-on-port-available

21 module-alsa-sink device_id=0

23 module-cli-protocol-unix

0 alsa_output.0.analog-stereo module-alsa-card.c s16le 2ch 44100Hz SUSPENDED

1 alsa_output.0.analog-stereo.2 module-alsa-sink.c s16le 2ch 44100Hz SUSPENDED

0 alsa_output.0.analog-stereo.monitor module-alsa-card.c s16le 2ch 44100Hz SUSPENDED

1 alsa_output.0.analog-stereo.2.monitor module-alsa-sink.c s16le 2ch 44100Hz SUSPENDED

25 protocol-native.c pactl

0 alsa_card.0 module-alsa-card.c

I backtracked a bit and made sure the device was connected to the PulseAudio server:

udo dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER/dev_$mac_underscore org.bluez.AudioSource.Connect

I tested by running the following:

sudo dbus-send --print-reply --system --dest=org.bluez /org/bluez/2069/hci0/dev_D4_F4_6F_B1_1F_FF org.bluez.AudioSource.Connect

And i get the following:

Error org.bluez.Error.AlreadyConnected: Already Connected

Also, I think you might have an error in your bluetooth-auto script:

mac_underscore=$(cat "$mac" | sed 's/:/_/g')

I changed this to:

mac_underscore=$(echo "$mac" | sed 's/:/_/g')

Any ideas as to where i can go from here?

ZacharyV1 (author)2015-04-15

I looked At the instructable you used to make this and answered my own question. You may need to create the folder /usr/lib/udev to do so, simply type

sudo mkdir /usr/lib/udev

Thats it! good luck!

ZacharyV1 (author)2015-04-14

I got to the start of step 4, I copied and pasted the sudo command at the start for the first script, copied the text for it. All was good until I tried to save it. I got the error [Error writing /usr/lib/udev/bluetooth: No such file or directory ]. what do I do? i have no udev file under lib

Xx_tomcraft_xX (author)2015-04-01

It doesn't work for me :/ Can someone check if the tutorial is up to date ? Because my level for scripting or for the linux environment is not very high :/

Jobo17 (author)2015-03-29

So I got everything working except streaming audio. I can connect to the pi as a speaker and play music to it but the pi isn't routing the music to 87.7 or HDMI and I followed every step carefully and setup config.txt to output on HDMI only.

sam5757 (author)2015-03-25

I followed the instructions carefully for 4 times now. But i cant get it to work, the sound quality is very, very poor. You have to listen very carefully to recognize the song. Has anyone tried this recently? Maybe it's due to an update or something...

motionpotion (author)2015-01-29

I made this but it doesn't work to output sound to hdmi from the bluetooth input device. I can connect my iPhone to the Pi fine via bluetooth. I can output sound via pifmplay if I play the sound (MP3) directly from the SD card using the command sudo sh /home/pi/pifmplay/pifmplay "/home/pi/music" 91.3 and it plays over Pin 4 on the GPIO and I can hear it on my radio. But the bluetooth sound does not output over FM. How can I redirect the bluetooth input to the FM output on pin 4 of the GPIO (HDMI)?

jfreeman81 (author)2014-11-25

I am so glad to have found this; I've been wanting to do this with my rpi for a while now. I've set everything up and I can hear the audio on my radio, but it is very slow and delayed. Any ideas on how to go about fixing it? I'm fairly new to all of this..

Tinclon (author)jfreeman812014-12-02

Glad you are benefitting.

Not sure what you mean by slow, but the audio will definitely be delayed by a few seconds. The pi has a lot of post-processing to to on the bluetooth audio before it can be sent to the fm transmitter (converting from RAW to WAV).

jfreeman81 (author)Tinclon2014-12-02

Sorry, I should have clarified! Slow as in I hear the music at half (estimating) the normal speed. This is probably what is causing a significant amount of the delay, but delay doesn't really bother me.

Tinclon (author)jfreeman812014-12-02

Interesting.

In /usr/lib/udev/bluetooth, there is the following line:

sudo -u pi pacat -r -d 0 | sudo -u pi sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - | sudo /home/pi/fm/pifm - 87.7 44100 stereo >> /var/log/bluetooth_dev

If I change the rate parameter as follows, I get sound at half speed:

sudo -u pi pacat -r -d 0 | sudo -u pi sox -t raw -r 44100 -e signed-integer -b 16 -c 2 - -t wav - | sudo /home/pi/fm/pifm - 87.7 22050 stereo >> /var/log/bluetooth_dev

Perhaps consider changing the input rate to 22050, and leaving the output at 44100 in order to speed up the output in relation to the input:

sudo -u pi pacat -r -d 0 | sudo -u pi sox -t raw -r 22050 -e signed-integer -b 16 -c 2 - -t wav - | sudo /home/pi/fm/pifm - 87.7 44100 stereo >> /var/log/bluetooth_dev

ben.randall.503 (author)Tinclon2015-01-12

I am having this problem as well. It also takes about a minute for the song to change when changed on the phone. Any ideas?

NathanV1 (author)ben.randall.5032015-01-14

The time delay is based on the raw encoding, there isn't much to do about that. However, I still haven't been able to get the music to play at normal speed. I've tried changing every frequency in turn and nothing works correctly.

ben.randall.503 (author)NathanV12015-01-15

Yeah I expect a bit of a delay for conversion. Strangely, I removed the HDMI cable that I had plugged in for a display and found that this made a difference as to how slowed down the music was. But it still didn't fix it. I've changed every freq in turn as well. I did wonder if it was because I was using an original model B and not a B+ but I can't see why that would make a difference. Possibly moving away from PiFM as well because of the harmonic leak it has. I was picking up my broadcast from 87.7 up to 108 :/

Tinclon (author)ben.randall.5032015-01-26

Do you know of another good fm transmitter software for the pi? I'd love to know about it and give it a try.

ben.randall.503 (author)Tinclon2015-01-27

Hi,

Funny you should ask. I am about to look into using FMBerry and an MMR-70 transmitter from an old Sony Ericson FM transmitter. This should give a really good signal as its just a 3.5 jack from the Pi connected to the transmitter. Havent managed to play yet do to other projects!

https://github.com/Manawyrm/FMBerry

NathanV1 (author)Tinclon2014-12-28

was this ever fully resolved? I am having the same issue and making the change that you proposed didn't fix the problem.

JeromeA1 (author)2014-12-26

There is an error in the bluetooth-auto script. Change the 6th line to:

for mac in $(sudo hcitool scan | grep ":" | awk '{print $1}')

Tinclon (author)JeromeA12014-12-31

Good catch. Made the change.

Thanks.

SammyS1 (author)2014-12-02

I dont get step 4, create scripts ??? how and where to put those scripts ???

Tinclon (author)SammyS12014-12-02

I see Instructables messed up all my formatting in the scripts. I just removed it all and republished. The file name and location of each script is shown at the top of said script, in the command to invoke the editor.

For example. The first script is created in the /usr/lib/udev/bluetooth file:

sudo nano /usr/lib/udev/bluetooth

ju5t1n15 (author)2014-11-28

Awesome Idea and nice instruction! I just have the problem, that I can see the Raspberry Pi's Bluetooth stick, but I can't connect to it. And I am sure the stick is Pi compatible. My phone tries to make a connection but after not even a second it stops connecting. Any ideas to solve this problem? If not, I'll just format the SD and try it again.

Thanks

seamster (author)2014-11-21

This is a brilliant idea! Very nicely done.

About This Instructable

34,839views

77favorites

License:

More by Tinclon:Raspberry Pi Wireless Bluetooth Audio FM Radio Transmitter
Add instructable to: