FM-RDS transmitter using the Raspberry Pi

This program generates an FM modulation, with RDS (Radio Data System) data generated in real time. It can include monophonic or stereophonic audio.

It is based on the FM transmitter created by Oliver Mattos and Oskar Weigl, and later adapted to using DMA by Richard Hirst.

 Christophe Jacquet adapted it and added the RDS data generator and modulator.

The transmitter uses the Raspberry Pi's PWM generator to produce VHF signals.

It is compatible with both the Raspberry Pi 1 (the original one) and the Raspberry Pi 2 and 3.

PiFmRds has been developed for experimentation only. It is not a media center, it is not intended to broadcast music to your stereo system. See the legal warning.

How to use it?

Pi-FM-RDS, depends on the sndfile library. To install this library on Debian-like distributions, for instance Raspbian, run sudo apt-get install libsndfile1-dev.

Pi-FM-RDS also depends on the Linux rpi-mailbox driver, so you need a recent Linux kernel. The Raspbian releases from August 2015 have this.

Important. The binaries compiled for the Raspberry Pi 1 are not compatible with the Raspberry Pi 2/3, and conversely. Always re-compile when switching models, so do not skip the make clean step in the instructions below!

Clone the source repository and run make in the src directory:

git clone

cd PiFmRds/src

make clean


Then you can just run:

sudo ./pi_fm_rds

This will generate an FM transmission on 107.9 MHz, with default station name (PS), radiotext (RT) and PI-code, without audio. The radiofrequency signal is emitted on GPIO 4 (pin 7 on header P1).

You can add monophonic or stereophonic audio by referencing an audio file as follows:

sudo ./pi_fm_rds -audio sound.wav

To test stereophonic audio, you can try the file stereo_44100.wav provided.

The more general syntax for running Pi-FM-RDS is as follows:

pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code] [-ps ps_text] [-rt rt_text]

All arguments are optional:

-freq specifies the carrier frequency (in MHz). Example: -freq 107.9.

-audio specifies an audio file to play as audio. The sample rate does not matter: Pi-FM-RDS will resample and filter it. If a stereo file is provided, Pi-FM-RDS will produce an FM-Stereo signal. Example: -audio sound.wav. The supported formats depend on libsndfile. This includes WAV and Ogg/Vorbis (among others) but not MP3. Specify - as the file name to read audio data on standard input (useful for piping audio into Pi-FM-RDS, see below).

-pi specifies the PI-code of the RDS broadcast. 4 hexadecimal digits. Example: -pi FFFF.

-ps specifies the station name (Program Service name, PS) of the RDS broadcast. Limit: 8 characters. Example: -ps RASP-PI.

-rt specifies the radiotext (RT) to be transmitted. Limit: 64 characters. Example: -rt 'Hello, world!'.

-ctl specifies a named pipe (FIFO) to use as a control channel to change PS and RT at run-time (see below).

-ppm specifies your Raspberry Pi's oscillator error in parts per million (ppm), see below.

By default the PS changes back and forth between Pi-FmRds and a sequence number, starting at 00000000. The PS changes around one time per second.

Clock calibration (only if experiencing difficulties)

The RDS standards states that the error for the 57 kHz subcarrier must be less than ± 6 Hz, i.e. less than 105 ppm (parts per million). The Raspberry Pi's oscillator error may be above this figure. That is where the -ppm parameter comes into play: you specify your Pi's error and Pi-FM-RDS adjusts the clock dividers accordingly.

In practice, I found that Pi-FM-RDS works okay even without using the -ppm parameter. I suppose the receivers are more tolerant than stated in the RDS spec.

One way to measure the ppm error is to play the pulses.wav file: it will play a pulse for precisely 1 second, then play a 1-second silence, and so on. Record the audio output from a radio with a good audio card. Say you sample at 44.1 kHz. Measure 10 intervals. Using Audacity for example determine the number of samples of these 10 intervals: in the absence of clock error, it should be 441,000 samples. With my Pi, I found 441,132 samples. Therefore, my ppm error is (441132-441000)/441000 * 1e6 = 299 ppm, assuming that my sampling device (audio card) has no clock error...

Piping audio into Pi-FM-RDS

If you use the argument -audio -, Pi-FM-RDS reads audio data on standard input. This allows you to pipe the output of a program into Pi-FM-RDS. For instance, this can be used to read MP3 files using Sox:

sox -t mp3 -t wav -  | sudo ./pi_fm_rds -audio -

Or to pipe the AUX input of a sound card into Pi-FM-RDS:

sudo arecord -fS16_LE -r 44100 -Dplughw:1,0 -c 2 -  | sudo ./pi_fm_rds -audio -

Changing PS, RT and TA at run-time

You can control PS, RT and TA (Traffic Announcement flag) at run-time using a named pipe (FIFO). For this run Pi-FM-RDS with the -ctl argument.


mkfifo rds_ctl

sudo ./pi_fm_rds -ctl rds_ctl

Then you can send “commands” to change PS, RT and TA:

cat >rds_ctl

PS MyText

RT A text to be sent as radiotext


PS OtherTxt



Every line must start with either PS, RT or TA, followed by one space character, and the desired value. Any other line format is silently ignored. TA ON switches the Traffic Announcement flag to on, any other value switches it to off.

Warning and Disclaimer

PiFmRds is an experimental program, designed only for experimentation. It is in no way intended to become a personal media center or a tool to operate a radio station, or even broadcast sound to one's own stereo system.

In most countries, transmitting radio waves without a state-issued licence specific to the transmission modalities (frequency, power, bandwidth, etc.) is illegal.

Therefore, always connect a shielded transmission line from the RaspberryPi directly to a radio receiver, so as not to emit radio waves. Never use an antenna.

Even if you are a licensed amateur radio operator, using PiFmRds to transmit radio waves on ham frequencies without any filtering between the RaspberryPi and an antenna is most probably illegal because the square-wave carrier is very rich in harmonics, so the bandwidth requirements are likely not met.

I could not be held liable for any misuse of your own Raspberry Pi. Any experiment is made under your own responsibility.


Pi-FM-RDS was successfully tested with all my RDS-able devices, namely:

a Sony ICF-C20RDS alarm clock from 1995,

a Sangean PR-D1 portable receiver from 1998, and an ATS-305 from 1999,

a Samsung Galaxy S2 mobile phone from 2011,

a Philips MBD7020 hifi system from 2012,

a Silicon Labs USBFMRADIO-RD USB stick, employing an Si4701 chip, and using my RDS Surveyor program,

a “PCear Fm Radio”, a Chinese clone of the above, again using RDS Surveyor.

Reception works perfectly with all the devices above. RDS Surveyor reports no group errors.

CPU Usage

CPU usage is as follows:

without audio: 9%

with mono audio: 33%

with stereo audio: 40%

CPU usage increases dramatically when adding audio because the program has to upsample the (unspecified) sample rate of the input audio file to 228 kHz, its internal operating sample rate. Doing so, it has to apply an FIR filter, which is costly.


The RDS data generator lies in the rds.c file.

The RDS data generator generates cyclically four 0A groups (for transmitting PS), and one 2A group (for transmitting RT). In addition, every minute, it inserts a 4A group (for transmitting CT, clock time). get_rds_group generates one group, and uses crc for computing the CRC.

To get samples of RDS data, call get_rds_samples. It calls get_rds_group, differentially encodes the signal and generates a shaped biphase symbol. Successive biphase symbols overlap: the samples are added so that the result is equivalent to applying the shaping filter (a root-raised-cosine (RRC) filter specified in the RDS standard) to a sequence of Manchester-encoded pulses.

The shaped biphase symbol is generated once and for all by a Python program called that uses Pydemod, one of my other software radio projects. This Python program generates an array called waveform_biphase that results from the application of the RRC filter to a positive-negative impulse pair. Note that the output of, two files named waveforms.c and waveforms.h, are included in the Git repository, so you don't need to run the Python script yourself to compile Pi-FM-RDS.

Internally, the program samples all signals at 228 kHz, four times the RDS subcarrier's 57 kHz.

The FM multiplex signal (baseband signal) is generated by fm_mpx.c. This file handles the upsampling of the input audio file to 228 kHz, and the generation of the multiplex: unmodulated left+right signal (limited to 15 kHz), possibly the stereo pilot at 19 kHz, possibly the left-right signal, amplitude-modulated on 38 kHz (suppressed carrier) and RDS signal from rds.c. Upsampling is performed using a zero-order hold followed by an FIR low-pass filter of order 60. The filter is a sampled sinc windowed by a Hamming window. The filter coefficients are generated at startup so that the filter cuts frequencies above the minimum of:

the Nyquist frequency of the input audio file (half the sample rate) to avoid aliasing,

15 kHz, the bandpass of the left+right and left-right channels, as per the FM broadcasting standards.

The samples are played by pi_fm_rds.c that is adapted from Richard Hirst's PiFmDma. The program was changed to support a sample rate of precisely 228 kHz.


EN 50067, Specification of the radio data system (RDS) for VHF/FM sound broadcasting in the frequency range 87.5 to 108.0 MHz


2015-09-05: support for the Raspberry Pi 2

2014-11-01: support for toggling the Traffic Announcement (TA) flag at run-time

2014-10-19: bugfix (cleanly stop the DMA engine when the specified file does not exist, or it's not possible to read from stdin)

2014-08-04: bugfix (ppm now uses floats)

2014-06-22: generate CT (clock time) signals, bugfixes

2014-05-04: possibility to change PS and RT at run-time

2014-04-28: support piping audio file data to Pi-FM-RDS' standard input

2014-04-14: new release that supports any sample rate for the audio input, and that can generate a proper FM-Stereo signal if a stereophonic input file is provided

2014-04-06: initial release, which only supported 228 kHz monophonic audio input files

© Christophe Jacquet (F8FTK), 2014-2015. Released under the GNU GPL v3.

Outil de traduction gratuite de site Internet



Transmetteur FM-RDS utilisant le Raspberry Pi

Ce programme génère une modulation FM, avec des données RDS (Radio Data System) générées en temps réel. Il peut inclure un audio monophonique ou stéréophonique.

Il est basé sur l'émetteur FM créé par Oliver Mattos et Oskar Weigl, puis adapté à l'utilisation de DMA par Richard Hirst.

Christophe Jacquet l'a adapté et a ajouté le générateur de données RDS et le modulateur.

L'émetteur utilise le générateur PWM de Raspberry Pi pour produire des signaux VHF.

Il est compatible avec le Raspberry Pi 1 (l'original) et le Raspberry Pi 2 et 3.

PiFmRds a été développé uniquement pour l'expérimentation. Ce n'est pas un centre de médias, il n'est pas destiné à diffuser de la musique sur votre système stéréo. Voir l'avertissement légal.

Comment l'utiliser?

Pi-FM-RDS, dépend de la bibliothèque sndfile. Pour installer cette bibliothèque sur les distributions de type Debian, par exemple Raspbian, exécutez sudo apt-get install libsndfile1-dev.

Pi-FM-RDS dépend également du pilote Linux rpi-mailbox, donc vous avez besoin d'un noyau Linux actuel. Les versions de Raspbian depuis août 2015 ont ceci.

Important. Les binaires compilés pour le Raspberry Pi 1 ne sont pas compatibles avec le Raspberry Pi 2/3 et inversement. Toujours re-compiler lors de la commutation des modèles, alors ne pas sauter la bonne étape dans les instructions ci-dessous!

Cloner le référentiel source et exécuter make dans le répertoire src:

Git clone

Cd PiFmRds / src

Rendre propre


Ensuite, vous pouvez exécuter:

Sudo ./pi_fm_rds

Cela générera une transmission FM sur 107,9 MHz, avec le nom de station par défaut (PS), le radiotextre (RT) et le code PI, sans audio. Le signal radiofréquence est émis sur GPIO 4 (broche 7 sur l'en-tête P1).

Vous pouvez ajouter un audio monophonique ou stéréophonique en référençant un fichier audio comme suit:

Sudo ./pi_fm_rds -audio sound.wav

Pour tester l'audio stéréophonique, vous pouvez essayer le fichier stereo_44100.wav fourni.

La syntaxe plus générale pour l'exécution de Pi-FM-RDS est la suivante:

Pi_fm_rds [-freq freq] [-fichier audio] [-ppm ppm_error] [-pi pi_code] [-ps ps_text] [-rt rt_text]

Tous les arguments sont facultatifs:

-freq spécifie la fréquence porteuse (en MHz). Exemple: -freq 107.9.

-audio spécifie un fichier audio à lire comme audio. Le taux d'échantillonnage n'a pas d'importance: Pi-FM-RDS va le rééchantillonner et le filtrer. Si un fichier stéréo est fourni, Pi-FM-RDS produira un signal FM-Stereo. Exemple: -audio sound.wav. Les formats supportés dépendent de libsndfile. Cela comprend WAV et Ogg / Vorbis (entre autres) mais pas MP3. Spécifiez - comme le nom du fichier pour lire les données audio sur l'entrée standard (utile pour la transmission audio en Pi-FM-RDS, voir ci-dessous).

-pi spécifie le code PI de la diffusion RDS. 4 chiffres hexadécimaux. Exemple: -pi FFFF.

-ps spécifie le nom de la station (Nom du service du programme, PS) de la diffusion RDS. Limite: 8 caractères. Exemple: -ps RASP-PI.

-rt spécifie le radiotextre (RT) à transmettre. Limite: 64 caractères. Exemple: -rt 'Bonjour, monde!'.

-ctl spécifie un pipe nommé (FIFO) à utiliser comme canal de contrôle pour changer PS et RT au moment de l'exécution (voir ci-dessous).

-ppm spécifie l'erreur de l'oscillateur de votre frappe de framboise en parties par million (ppm), voir ci-dessous.

Par défaut, le PS évolue entre Pi-FmRds et un numéro de séquence, à partir de 00000000. Le PS change autour d'une fois par seconde.

Étalonnage de l'horloge (uniquement en cas de difficultés)

Les normes RDS indiquent que l'erreur pour la sous-porteuse de 57 kHz doit être inférieure à ± 6 Hz, soit moins de 105 ppm (parties par million). L'erreur de l'oscillateur de Raspberry Pi peut être supérieure à cette figure. C'est là que le paramètre -ppm entre en jeu: vous spécifiez l'erreur de votre Pi et Pi-FM-RDS ajuste les diviseurs d'horloge en conséquence.

En pratique, j'ai trouvé que Pi-FM-RDS fonctionne bien, même sans utiliser le paramètre -ppm. Je suppose que les récepteurs sont plus tolérants que ceux indiqués dans la spécification RDS.

Une façon de mesurer l'erreur en ppm est de lire le fichier pulses.wav: il jouera une impulsion pour une précision précise de 1 seconde, puis un silence de 1 seconde, et ainsi de suite. Enregistrez la sortie audio d'une radio avec une bonne carte audio. Disons que vous échantillons à 44,1 kHz. Mesurez 10 intervalles. En utilisant Audacity par exemple, déterminer le nombre d'échantillons de ces 10 intervalles: en l'absence d'erreur d'horloge, il devrait s'agir de 441 000 échantillons. Avec mon Pi, j'ai trouvé 441 132 échantillons. Par conséquent, mon erreur de ppm est (441132-441000) / 441000 * 1e6 = 299 ppm, en supposant que mon périphérique d'échantillonnage (carte audio) n'a pas d'erreur d'horloge ...

Piping audio dans Pi-FM-RDS

Si vous utilisez l'argument -audio -, Pi-FM-RDS lit les données audio sur l'entrée standard. Cela vous permet de canaliser la sortie d'un programme en Pi-FM-RDS. Par exemple, cela peut être utilisé pour lire des fichiers MP3 en utilisant Sox:

Sox -t mp3 -t wav - | Sudo ./pi_fm_rds -audio -

Ou pour canaliser l'entrée AUX d'une carte son en Pi-FM-RDS:

Sudo arecord -fS16_LE -r 44100 -Dplughw: 1,0 -c 2 - | Sudo ./pi_fm_rds -audio -

Modification de PS, RT et TA en temps d'exécution

Vous pouvez contrôler PS, RT et TA (Traffic Announcement flag) au moment de l'exécution en utilisant un pipe nommé (FIFO). Pour cette exécution, Pi-FM-RDS avec l'argument -ctl.


Mkfifo rds_ctl

Sudo ./pi_fm_rds -ctl rds_ctl

Ensuite, vous pouvez envoyer des "commandes" pour changer PS, RT et TA:

Chat> rds_ctl

PS MyText

RT Un texte à envoyer en radiotext


PS AutreTxt



Chaque ligne doit commencer avec PS, RT ou TA, suivi d'un caractère d'espace et de la valeur souhaitée. Tout autre format de ligne est silencieusement ignoré. TA ON permet d'allumer le drapeau Traffic Announcement, toute autre valeur l'éteint.

Avertissement et avertissement

PiFmRds est un programme expérimental conçu uniquement pour l'expérimentation. Il ne s'agit en aucun cas de devenir un centre de médias personnel ou un outil pour exploiter une station de radio, ni même diffuser du son sur son propre système stéréo.

Dans la plupart des pays, la transmission d'ondes radio sans permis délivré par l'État spécifiquement aux modalités de transmission (fréquence, puissance, bande passante, etc.) est illégale.

Par conséquent, connectez toujours une ligne de transmission blindée du RaspberryPi directement à un récepteur radio afin de ne pas émettre des ondes radio. Ne jamais utiliser une antenne.

Même si vous êtes un opérateur de radio amateur autorisé, l'utilisation de PiFmRds pour transmettre des ondes radio sur les fréquences de jambon sans filtrage entre RaspberryPi et une antenne est probablement illégale car le support à ondes carrées est très riche en harmoniques, donc les exigences de bande passante sont probables pas rencontré.

Je ne pouvais être tenu pour responsable de toute mauvaise utilisation de votre propre Raspberry Pi. Toute expérience est faite sous votre propre responsabilité.


Pi-FM-RDS a été testé avec succès avec tous mes appareils RDS, à savoir:

Un réveil ICF-C20RDS de Sony depuis 1995,

Un récepteur portable Sangean PR-D1 de 1998 et un ATS-305 de 1999,

Un téléphone mobile Samsung Galaxy S2 à partir de 2011,

Un système hifi Philips MBD7020 à partir de 2012,

Une clé USB USB de Silicon Labs USBFMRADIO-RD, utilisant une puce Si4701 et utilisant mon programme RDS Surveyor,

Une "PCear Fm Radio", un clone chinois de ce qui précède, à nouveau en utilisant RDS Surveyor.

La réception fonctionne parfaitement avec tous les appareils ci-dessus. RDS Surveyor ne signale aucune erreur de groupe.

L'utilisation du processeur

L'utilisation du processeur est la suivante:

Sans audio: 9%

Avec audio mono: 33%

Avec audio stéréo: 40%

L'utilisation du processeur augmente de façon spectaculaire lors de l'ajout d'audio, car le programme doit subir un échantillonnage de la fréquence d'échantillonnage (non spécifiée) du fichier audio d'entrée à 228 kHz, son taux d'échantillonnage d'exploitation interne. Dans ce cas, il faut appliquer un filtre FIR, ce qui est coûteux.


Le générateur de données RDS réside dans le fichier rds.c.

Le générateur de données RDS génère cycliquement quatre groupes 0A (pour la transmission de PS) et un groupe 2A (pour transmettre RT). De plus, chaque minute, il insère un groupe 4A (pour transmettre le CT, l'heure de l'horloge). Get_rds_group génère un groupe et utilise crc pour calculer le CRC.

Pour obtenir des échantillons de données RDS, appelez get_rds_samples. Il appelle get_rds_group, codifie différentiellement le signal et génère un symbole biphase en forme. Les symboles biphase successifs se chevauchent: les échantillons sont ajoutés de sorte que le résultat équivaut à l'application du filtre de mise en forme (un filtre RRC (RRC) spécifié dans la norme RDS) à une séquence d'impulsions codées par Manchester.

Le symbole en forme de biphase est généré une fois pour toutes par un programme Python appelé qui utilise Pydemod, l'un de mes autres projets de radio de logiciel. Ce programme Python génère un réseau appelé waveform_biphase qui résulte de l'application du filtre RRC à une paire impulsion positive négative. Notez que la sortie de, deux fichiers appelés waveforms.c et waveforms.h, sont inclus dans le référentiel Git, de sorte que vous ne devez pas exécuter le script Python vous-même pour compiler Pi-FM-RDS.

En interne, le programme échantillonne tous les signaux à 228 kHz, quatre fois le 57 kHz de la sous-porteuse RDS.

Le signal multiplex FM (signal bande de base) est généré par fm_mpx.c. Ce fichier gère le dépassement du fichier audio d'entrée à 228 kHz et la génération du multiplex: signal non modifié de gauche + droite (limité à 15 kHz), éventuellement le pilote stéréo à 19 kHz, éventuellement le signal gauche-droit, l'amplitude- Modulé sur 38 kHz (support supprimé) et signal RDS de rds.c. L'amorçage est effectué à l'aide d'une prise de commande nulle suivie d'un filtre passe-bas FIR d'ordre 60. Le filtre est une fenêtre échantillonnée illustrée par une fenêtre Hamming. Les coefficients de filtrage sont générés au démarrage de sorte que le filtre coupe les fréquences au-dessus du minimum de:

La fréquence Nyquist du fichier audio d'entrée (la moitié du taux d'échantillonnage) pour éviter l'aliasing,

15 kHz, le passage de bande des canaux gauche + droit et gauche-droit selon les normes de diffusion FM.

Les échantillons sont joués par pi_fm_rds.c qui est adapté de PiFmDma de Richard Hirst. Le programme a été modifié pour supporter un taux d'échantillonnage précis de 228 kHz.

Les références

EN 50067, Spécification du système de données radio (RDS) pour la diffusion de sons VHF / FM dans la gamme de fréquences 87,5 à 108,0 MHz


2015-09-05: soutien pour le Raspberry Pi 2

2014-11-01: prise en charge de l'affichage de l'indicateur de trafic (TA) au moment de l'exécution

2014-10-19: bugfix (arrête le moteur DMA lorsque le fichier spécifié n'existe pas, ou il n'est pas possible de le lire sur stdin)

2014-08-04: bugfix (ppm utilise maintenant des flotteurs)

2014-06-22: générer des signaux CT (horloge), des corrections d'erreurs

2014-05-04: possibilité de changer PS et RT au moment de l'exécution

2014-04-28: prend en charge les données du fichier audio par canalisation à l'entrée standard de Pi-FM-RDS

2014-04-14: nouvelle version prenant en charge toute fréquence d'échantillonnage pour l'entrée audio, et qui peut générer un signal FM-stéréo approprié si un fichier d'entrée stéréophonique est fourni

2014-04-06: version initiale, qui ne prend en charge que les fichiers d'entrée audio monophoniques de 228 kHz

© Christophe Jacquet (F8FTK), 2014-2015. Sortie sous GNU GPL v3.