FM transmitter

The Raspberry Pi can be used as an FM transmitter. This applies to Raspberry Pi Zero (W) and other.

The only extra hardware required is a cable to act as an antenna that is connected to GPIO 4. To improve it a shielded cable can be used where the shield is connected to GND.

The setup to stream audio is the following:
  1. mplayer plays a file or a stream and sends the audio to the loopback device like it was an output
  2. arecord reads the audio from the loopback device like it was an input
  3. Pi-FM-RDS or fm_transmitter gets the audio piped from arecord and sends it to GPIO 4 for FM audio


Alternative 1, install Pi-FM-RDS, it supports stereo 44100:

sudo apt-get install libsndfile1-dev.
git clone
cd PiFmRds/src
make clean

Check that it works:
sudo ./pi_fm_rds -audio stereo_44100.wav

Alternative 2, Install fm_transmitter, it supports mono 22050:

sudo apt update
sudo apt install make build-essential
git clone
cd fm_transmitter

Check that it works by playing the included WAV file on a frequency:
sudo ./fm_transmitter -f 100.6 acoustic_guitar_duet.wav

Also install mplayer to play streams:
sudo apt install mplayer

Add the following to /etc/mplayer/mplayer.conf to reduce mplayer startup time. It tells it to use ALSA and not Pulseaudio, disable LIRC and prefer IPv4 over IPv6:

Load loop devices to get a virtual device to play through:
modprobe snd-aloop

Or make it load on start by adding the following to /etc/modules:

List loop devices, there should be at least two named card 0 after that the module has loaded:
aplay -l

Begin transmission

Read audio from the loop device and pipe it to Pi-FM-RDS:

arecord -fS16_LE -r 44100 -Dhw:0,1,0 -c 2 - | ./PiFmRds/src/pi_fm_rds -ps DEFAULT -rt Default -freq 100.6 -audio - &

Or the same for fm_transmitter:
arecord -D hw:0,1,0 -c 1 -d 0 -r 22050 -f S16_LE | ./fm_transmitter -f 100.6 - &

  -D, --device=NAME, Select PCM by name, replace the first number (0) with the loop device number if needed.

  -r, --rate=#<Hz>
  Sampling rate in Hertz. The default rate is 8000 Hertz.  If the value specified
  is less than 300, it is taken as the rate in kilohertz.  Valid values are 2000
  through 192000 Hertz.

  -f --format=FORMAT
  Sample format
  Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE
  S24_BE U24_LE U24_BE  S32_LE  S32_BE  U32_LE U32_BE  FLOAT_LE FLOAT_BE
  S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE
  Some of these may not be available on selected hardware
  The available format shortcuts are:
  -f cd (16 bit little endian, 44100, stereo) [-f S16_LE -c2 -r44100]
  -f cdr (16 bit big endian, 44100, stereo) [-f S16_BE -c2 -r44100]
  -f dat (16 bit little endian, 48000, stereo) [-f S16_LE -c2 -r48000]
  If no format is given U8 is used.

  100.6 is the frequency, adjust it to an empty place on the radio where there is only noise.

Play a stream - get one from Internet Radio for instance:
  mplayer http://<stream-url-here> &

The audio can be a bit low by default, adjust loopback device the volume with alsamixer by using the up and down keys:

End transmission

For Pi FM RDS:
killall mplayer
killall arecord
killall pi_fm_rds

fm_transmitter usually exits gracefully with Ctrl+C when it plays files directly.
It is however not the case when it is getting data piped from arecord. Then it does not reset the GPIO pin and weird stuff happens - repeats, silence and so on.

To stop the playback when piping do the following to stop mplayer, fm_transmitter and set the GPIO pin to output instead of GPCLK0 and to also set it to level low:
killall mplayer
killall fm_transmitter
killall arecord
raspi-gpio set 4 op dl


15 cm antenna, good 125m, audible but noisy 200m
150 cm antenna, good 200-350m, audible but noisy 400m

This is a personal note. Last updated: 2023-02-12 01:26:02.







Don't forget to pay my friend a visit too. Joakim