zurück zum Artikel

Radiosender bauen mit Raspi, Arduino oder ESP32

Daniel Bachfeld
Ein altes Radio, davor ein Raspberry Pi und ein Arduino mit Antennendrähten.

Mit Arduino, Pi und Co. lassen sich mit Leichtigkeit Funksignale erzeugen, die jedes Radio empfangen kann. Wir erklären, worauf Sie achten müssen.

Anlässlich des 100. Jubiläums des Radios haben wir diesen Artikel aus unserem Fundus geholt.

Vor mehr als 100 Jahren war es noch eine hohe Kunst, hochfrequente Schwingungen zu erzeugen und Energie per Antenne durch den Äther (nein, nicht wirklich) zu Empfängern zu schicken. Auch heute noch ist der Aufbau hochfrequenter analoger Schaltungen für viele Einsteiger eher abschreckend. Doch mit den Fähigkeiten moderner Mikrocontroller kann man auch hochfrequente Signale erzeugen und mit Musikdaten modulieren, die ein herkömmliches Radio empfangen und wiedergeben kann. Nützlich kann dies beispielsweise sein, um Opas nur mittelwellentauglichen, aber optisch bestechenden Empfänger wieder Musik spielen zu lassen – ohne Eingriffe in sein Innenleben.

10 Jahre Raspi: Projekte und Hintergrund

Das funktioniert in den meisten Fällen sogar ohne zusätzliche externe Bauelemente, ein Draht als Antenne an einem Mikrocontrollerausgang genügt. Allein durch geschickte Programmierung der Taktgeneratoren, Timer, Counter und Interrupts lässt sich ein kleiner Rundfunksender realisieren. Wir zeigen vier Beispiele, wie leicht man das nachbauen kann. Ein paar Grundlagen und etwas Historie vorab können zum Verständnis der Technik und der Projekte sicherlich nicht schaden.

Kurzinfo
  • Grundlagen Funktechnik
  • Amplituden- und Frequenzmodulation verstehen
  • Eigene Sender bauen

Checkliste

  • Zeitaufwand: eine Stunde
  • Kosten: etwa 6 bis 40 Euro
  • Programmieren: C/C++
  • Elektronik: kleiner Schaltungsaufbau

Material

  • Raspberry Pi 3B+
  • ESP32
  • Adafruit Feather Express
  • Arduino Uno/Nano
  • Breadboard
  • Jumper
  • Draht für Antenne
  • 2 Widerstände 47 Kiloohm
  • 1 Elko 1µF

Radiowellen sind elektromagnetische Wellen, die sich von einem Sender ausbreiten. Anfangs erzeugte man sie durch Hochspannungsgeneratoren [11], die genügend Spannung lieferten, um zwischen zwei voneinander entfernten Elektroden einen Funkenüberschlag zu erzeugen. Daher rührt auch der Name Funktechnik, weil tatsächlich früher die Funken flogen. Je nach Dimensionierung des Generators (Kondensatoren und Spulen bilden einen Schwingkreis) erzeugte der Funken im Schwingkreis eine abklingende elektromagnetische Schwingung auf einer bestimmten Frequenz, die über eine Antenne abgestrahlt wurde.

Mit einem entfernten, aber passend abgestimmten, zweiten Schwingkreis konnte man die Welle empfangen und in eine Spannung umwandeln. Mit diesen sogenannten Knallfunkensendern ließen sich jedoch nur wenig Informationen übertragen: an oder aus oder länger an. Sie ahnen es schon: am Anfang war damit nur Morsetelegrafie möglich.

Im Laufe der Jahre entwickelte man Sender, die kontinuierlich und ohne Funkenüberschlagstrecken auf einer gewünschten Frequenz schwingen konnten (Oszillator). Nach heutigen Maßstäben sind die damals erreichten Frequenzen von 100kHz vergleichsweise gering. Die zu dieser Frequenz (Hz) gehörende Wellenlänge liegt bei 3000 Metern, weshalb man auch von Langwelle (LW) spricht. Auf Radios ist das der unterste Frequenzbereich. Ein Vorteil der Langwelle ist die große Reichweite, sodass mit einem einzigen Sender große Flächen mit einem stabilen Signal versorgt werden können.

Später etablierten sich auch Mittelwellensender, deren Frequenz zwischen 526,5kHz und 1606,5kHz lag, die aber nicht mehr so weitreichend sind. Die Signale von Kurzwellensendern (bis 30MHz) werden in höheren Schichten der Atmosphäre, genau genommen der Ionosphäre, und dem Boden reflektiert und können auf diese um den Erdball wandern. Allerdings schwanken beispielsweise aufgrund von Sonneneinstrahlung die Ausbreitungsbedingungen sehr stark.

Experimentieren verboten?

Im Bereich der Langwelle (30kHz bis 300kHz) und Mittelwelle (526,5kHz bis 1606,5kHz) ist es nicht erlaubt, zu senden. Selbst Funkamateure benötigen dafür eine Erlaubnis. Warum zeigen wir die Anleitungen trotzdem? Weil es sinnvoll ist, Wissen über Funktechnik an unsere Leser weiterzugeben. Stellen Sie sich vor, aus diversen Gründen bricht die öffentliche Infrastruktur nebst Internet, Mobilfunk und Festnetz zusammen und sie müssen – weil sie vielleicht in der Pampa wohnen – Hilfe holen. Mit Arduino und einer Powerbank gelingt Ihnen vielleicht das Absetzen eines Notrufs. Würde MacGyver nach einer Sendeerlaubnis fragen?

Die hier gezeigten Schaltungen senden mit so geringer Leistung, dass schon in zwei Metern Entfernung mit handelsüblichen Radios kaum Empfang mehr möglich ist. Ihr Nachbar müsste also schon auf dem Sender sitzen, um sich gestört zu fühlen. Anders sieht dies mit dem vorgestellten UKW-Sender aus, dessen Signale bei angeschlossener Antenne schon weiter reichen können.

Problematisch sind die von Mikrocontrollern erzeugten Oberwellen, die mit einem normalen Radio nicht empfangen werden können, aber durchaus andere Frequenzbereiche stören. In Umgebungen mit Infrastrukturen wie Flughäfen, Krankenhäusern, Polizei, Feuerwehr, Häfen und so weiter sollten Sie trotz der geringen Leistung auf LW und MW von dem Testbetrieb absehen. Auf dem Lande dürften Tests unproblematischer sein, es sei denn, Sie wohnen in einer Einflugschneise.

Mehr von Make Mehr von Make [12]

Statt einen Sender einfach nur ein- und auszuschalten, verändert man bei der Amplitudenmodulation (AM) die Amplitude respektive die Auslenkung der Schwingung (auch Trägerfrequenz genannt) nach oben und unten. Möglich wurde dies mit der Erfindung der Elektronenröhre ab 1906. Mit ihr ließen sich stabile Oszillatoren bauen, deren Auslenkung man mit niederfrequenten Signalen – also Sprache und Musik – steuern konnte. Mit einfachen Empfängern, die im Wesentlichen aus einem Schwingkreis bestanden, ließen sich diese Signale empfangen. Um das aufmodulierte Signal hörbar zu machen, benutzte man einen Hüllkurvendemodulator – der Name ist an die das HF-Signal umhüllende Kurve angelehnt.

Schematische Darstellung von Amplitudenmodulation

Amplitudenmodulation: Die Trägerfrequenz (blau) wird mit dem Nutzsignal (rot) moduliert und es ergibt sich das Sendesignal (violett). Die Hüllkurve (grün) wird im Empfänger demoduliert. Weil sich das Nutzsignal bei Sprache ständig ändert, verändert sich die Form des Sendesignals permanent. Ausprobieren kann man das selbst unter https://academo.org/demos/amplitude-modulation/ [13].

Ein Kristall aus Bleiglanz oder Pyrit mit einer aufgesetzten Metallspitze fungierte als Diode zur Gleichrichtung des HF-Signals, um nur die obere Hälfte der Amplituden zu erhalten. Das war notwendig, damit sich die symmetrischen Amplitudenauslenkungen nicht aufheben. Ein Tiefpassfilter beseitigte das HF-Signal, sodass nur noch die Hüllkurve übrig bleibt, das Sprach- oder Musiksignal. Als auf Langwelle noch Radiosendungen ausgestrahlt wurden, konnte man im einfachsten Fall mit billigen batterielosen Detektorempfängern mithören.

Älteres Radio mit Auswahl zwischen AM und FM.

Etwas ältere Radios können noch LW und MW empfangen.

Prinzipbedingt funktionierte die Übertragung bei AM nur in Mono, weil die Hüllkurve nur ein Signal enthält. Herkömmliche Radios sind grundsätzlich so gebaut, dass sie auf Lang- und Mittelwelle immer ein amplitudenmoduliertes Signal erwarten. Auf manchen Radios ist deshalb die Umschaltung zwischen den Empfangsbereichen auch nur noch mit AM/FM beschriftet, statt mit LW/MW/UKW.

Die Übertragung amplitudenmodulierter Signale ist anfällig für Störungen auf dem Ausbreitungsweg, die beispielsweise die Amplitude ungewollt schwanken lassen. Im Empfänger macht sich das anschließend als Lautstärkeschwankungen bemerkbar. Mit fortschreitender Technik war es später möglich, die Senderoszillatoren in ihrer Frequenz zu ändern. Im Rhythmus von Musik und Sprache moduliert man die Frequenz. Je höher die Auslenkung des niederfrequenten Signals, desto höher die Abweichung von der Normalfrequenz. Heutzutage kennt man FM hauptsächlich im Zusammenhang mit Ultrakurzwellensendern (UKW), die man Zuhause und im Auto empfängt.

Schematische Darstellung von Frequenzmodulation.

Bei der Frequenzmodulation steuert ein niederfrequentes Signal (NF) die Frequenz des hochfrequenten Signals (HF).

Frequenzmodulierte Signale (FM) sind weniger störanfällig während der Ausbreitung, allerdings ist ihre Reichweite erheblich geringer. Dafür lassen sich per FM nicht nur Stereosignale übertragen, sondern auch Daten, beispielsweise Senderdaten per RDS und Verkehrsdaten per TMC. Normale Radios erwarten auf dem UKW-Band immer ein FM-Signal.

Prinzipiell könnte man auf LW und MW auch FM-Signale übertragen und auf UKW auch AM-Signale, das ist aber eher ein Übungsfeld für Funkamateure.

Seit einiger Zeit sind alle Langwellen- und Mittelwellensender in Deutschland außer Betrieb, weshalb Radioempfänger auf diesen Frequenzen nur noch vor sich hin rauschen oder nachts Gedudel von ausländischen Sendern hören lassen. Ältere Empfänger, die nur für LW und MW ausgelegt sind und denen das UKW-Band fehlt, sind damit größtenteils nutzlos geworden. Zum Wegschmeißen sind sie vermutlich zu schade, weil entweder schöne Erinnerungen daran hängen oder das Gehäuse einfach zu schick oder retro ist. Mit eigenen AM-Sendern kann man sie aber weiter betreiben, zumindest im heimischen Wohnzimmer, Keller oder der Garage. Aber auch den UKW-Empfängern droht durch DAB+ mittelfristig das Aus.

Im einfachsten Fall kann jeder moderne Mikrocontroller bereits durch das schnelle Schalten eines Ausgangs-Pins zwischen 0 und 3,3 beziehungsweise 5V ein Hochfrequenzsignal erzeugen, das sich über ein längeres Stück Draht abstrahlen lässt. Je schneller der Prozessor getaktet wird, desto höher die erreichbare Frequenz am Pin.

Ein Arduino kann beispielsweise Frequenzen erzeugen, die im Mittelwellenband liegen, ein Raspberry Pi schafft locker Frequenzen im UKW-Bereich. Mit einem einfachen Trägersignal allein lässt sich jedoch noch nicht viel erreichen; was fehlt, ist die Modulation durch Musik.

Schematische Darstellung: Umwandlung in PWM-Signal

Der Wert des sinusförmigen Verlaufs (grün) kann durch den Vergleich mit dem Register OCR2B in Timer2 in ein unten in rosa dargestelltes PWM-Signal umgewandelt werden.

(Bild: CYrilB, Commonswiki, CC BY-SA 3.0)

Bedingt durch den erreichbaren Frequenzbereich erfordert ein Arduino-Sender eine Amplitudenmodulation, ein Pi-Sender muss sein Signal frequenzmodulieren.

Das erste Arduino-Beispiel ist in Bild 1 zu sehen. Es wurde vom Bastler Markus Gritsch veröffentlicht [14] und benötigt im einfachsten Fall nur zwei Widerstände und einen Elko, um beispielsweise den Kopfhörerausgang eines Smartphones an den AD-Wandler-Eingang des Arduino anzuschließen. Eine Antenne – also ein längerer Draht – schließt man an Pin D3 an. Das Radio stellt man auf eine Frequenz zwischen 730 und 740kHz ein.

Schaltplan für den Aufbau mit Arduino und Breadboard.

Bild 1: Je länger die Antenne (Pin 3) am Arduino, desto besser.

Spielt man nun auf dem Smartphone Musik beispielsweise von Spotify oder anderen Diensten ab, so kann man sie im Radio hören – allerdings meist nur in eher schlechter Qualität. Als Proof-of-Concept und Grundlage für Verbesserungen reicht es aber allemal.

Für erste Tests legt man die Antenne sehr nah an das Radio. Später kann man probieren, welche Entfernungen sich überbrücken lassen. Grundsätzlich gilt: Je länger die Antenne, desto besser.

Die Software für den Arduino nutzt Funktionen des auf dem Board arbeitenden ATmega328, die die Arduino-IDE [15] eher vor den Augen von Einsteigern versteckt. Konkret bedeutet das, dass der Takt des internen, fest eingestellten Taktgenerators (16MHz) über Frequenzteilung reduziert wird und einen Timer respektive Zähler (Counter) antreibt.

Im Prinzip ist das ein Register (genau heißt es TCNT für Timer/Counter Register), das von 0 bis 255 zählt und mit jedem Takt seinen Inhalt um 1 erhöht. Nach 255 fängt es wieder bei 0 an. Das Timer-Register lässt sich auslesen und sein Inhalt mit zwei weiteren Registern vergleichen, den sogenannten Output-Compare-Registern (OCR). Sofern TCNT und das jeweilige OCR gleich sind, kann eine interne Logik unterschiedliche Ereignisse anstoßen, beispielsweise einen Ausgangs-Pin OCn ändern.

Im Bild 2 ist nun zu sehen, dass zwei OCR-Register mit unterschiedlichen Werten PWM-Signale erzeugen können. Mit OCRnA (das n steht für Timer 0, 1 oder 2) lässt sich die Frequenz des PWM-Signals festlegen (hier 734kHz), während sich am Ausgang OCnB mit dem Wert in Register OCRnB das Tastverhältnis einstellen lässt. Unterschiedliche Tastverhältnisse resultieren in unterschiedlichen effektiven Spannungen am PWM-Ausgang. Mit OCRnB lässt sich also das Ausgangssignal amplitudenmodulieren. Und OCRn wiederum wird über das am Analog-Digital-Wandler anliegende Musiksignal bestimmt.

Schema: Arbeitsweise der Timer- und Compare-Register

Bild 2: Die Register OCR bestimmen, wann die OC-Pins des Arduino geschaltet werden.

Der Code ist in Listing 1 zu sehen, der ohne Studium des ATmega-Datenblatts und Kenntnisse der internen Register leider für Einsteiger nicht zu verstehen ist. Zum Ausprobieren müssen Sie den Sketch [16] nur in die Arduino-IDE laden, übersetzen und hochladen. Zum Verständnis nur so viel: In der Funktion loop werden die Timer Control Register für Timer 2 gesetzt, die Funktion setup() liest den AD-Wandler-Wert in einer Endlosschleife ein, skaliert ihn und schreibt ihn in das Register OCR2B, welches das Tastverhältnis bestimmt. Unterschiedliche Werte führen zu unterschiedlichen Tastverhältnissen, was zu unterschiedlich hohen Spannungen der Trägerfrequenz führt.

#define INPUT_PIN  0 // ADC-Eingang
#define TIMER_PIN  3 // PWM Ausgang, OC2B (PD3)
#define DEBUG_PIN  2 // 
#define LED_PIN   13 // 

#define SHIFT_BY   3 // 2 ... 7 Abschw�chung 
#define TIMER_TOP 20 // Faktor Tr�gerfrequenz
#define A_MAX TIMER_TOP / 4

void setup() {
    pinMode( DEBUG_PIN, OUTPUT );
    pinMode( TIMER_PIN, OUTPUT );
    pinMode( LED_PIN, OUTPUT );

    // ADC Vorteiler (0b100)
    ADCSRA = ( ADCSRA | _BV( ADPS2 ) ) & ~( _BV( ADPS1 ) | _BV( ADPS0 ) );

    // FAST PWM ohne Teiler
    TCCR2A = 0b10100011; // COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
    TCCR2B = 0b00001001; // FOC2A FOC2B - - WGM22 CS22 CS21 CS20

    // 16E6 / ( OCR2A + 1 ) = 762 kHz @ TIMER_TOP = 20
    OCR2A = TIMER_TOP; //   = 727 kHz @ TIMER_TOP = 21
    OCR2B = TIMER_TOP / 2; // Amplitude der TF bei 50% Tastverh�ltnis
}

void loop() {
    // 34 kHz Sampling-Frequenz 
    digitalWrite( DEBUG_PIN, HIGH );
    int8_t value = ( analogRead( INPUT_PIN ) >> SHIFT_BY ) -
                   ( 1 << ( 9 - SHIFT_BY ) );
    digitalWrite( DEBUG_PIN, LOW );

    // clipping
    if ( value < -A_MAX ) {
        value = -A_MAX;
        digitalWrite( LED_PIN, HIGH );
    } else if ( value > A_MAX ) {
        value = A_MAX;
        digitalWrite( LED_PIN, HIGH );
    } else {
        digitalWrite( LED_PIN, LOW );
    }

    OCR2B = A_MAX + value;
}

Zwar kommt aus dem Arduino ein PWM mit Rechtecksignalen in verschiedenen Tastverhältnissen heraus, letztlich resultiert dies aber in einem amplitudenmodulierten Trägersignal.

Ein moderner ESP32 ist dank seiner hohen Taktfrequenz von bis zu 240MHz in der Lage, die Sinus-Trägerwelle über seinen integrierten Digital-Analog-Converter (DAC) selbst zu erzeugen. Dazu gibt man beispielsweise 16, 32 oder 64 Werte an den DAC aus, die einem Sinus-Signal mit Abstufungen nahekommen (Bild 3).

Sinuskurve mit stufenförmigen Zacken auf einem Oszilloskop-Bildschirm.

Bild 3: Mit einem Digital-Analog-Converter lassen sich Sinuskurven aus diskreten Werten erzeugen.

Matthias Balwierz, auf YouTube auch als bitluni bekannt, hat einen AM-Sender [17] auf Basis des ESP32 und seinem DAC programmiert. Ein Auszug des Programms ist in Listing 2 zu sehen. Jede Halbwelle besteht aus 8 festen Werten, die einen kontinuierlichen Sinus erzeugen. Aus einem Array mit zuvor digitalisierten Audio-Samples (samples[]) liest eine Schleife die Werte und multipliziert damit die Sinus-Werte der Trägerfrequenz. Die Multiplikation entspricht einer Modulation. Weil die Trägerfrequenz um einiges höher als das NF-Signal ist, muss man immer mehrere Sinus-Werte mit ein und demselben Sample multiplizieren. Das Sinussignal der Trägerfrequenz liegt bei 835kHz.

short buff[1024];
//sine represented in 16 values. at 13MHz sampling rate the resulting carrier is at around 835KHz
int sintab[] = {0, 48, 90, 117, 127, 117, 90, 48, 0, -48, -90, -117, -127, -117, -90, -48};

unsigned long long pos = 0;         
unsigned int posLow = sampleCount;  
unsigned long long posInc = ((unsigned long long)sampleRate < 32) / 835000;  

void loop() 
{
  //reset sample position when button is down
  if(!digitalRead(BUTTON_PIN))
    pos = posLow = 0;

  //fill the sound buffer
  for(int i = 0; i < 1024; i+=16)
  {
    if(posLow >= sampleCount) posLow = sampleCount - 1;
    //taking current sample
    int s = samples[posLow] + 128;
    
    for(int j = 0; j < 16; j += 4)
    {
      buff[i + j + 1] = (sintab[j + 0] * s + 0x8000);
      buff[i + j + 0] = (sintab[j + 1] * s + 0x8000);
      buff[i + j + 3] = (sintab[j + 2] * s + 0x8000);
      buff[i + j + 2] = (sintab[j + 3] * s + 0x8000);
    }
    if(posLow < sampleCount - 1)
    {
      pos += posInc;
      posLow = pos > 32;
    }
  }
  i2s_write_bytes(i2s_num, (char*)buff, sizeof(buff), portMAX_DELAY);
}

Bitluni hat in seinem auf Github frei verfügbaren Code [18] bereits Samples in der C-Header-Datei samples.h bereitgestellt, die beim Übersetzen des Codes in der Arduino-IDE in das ausführbare Programm eingebunden werden. Darüber hinaus lassen sich mit eigenen Ergänzungen im Code über den A/D-Wandler des ESP32 Signale aus beliebigen Quellen digitalisieren und über den DAC senden.

Verbinden Sie den ESP über die USB-Buchse mit dem PC, um das Programm aufzuspielen. Mit der Arduino-IDE geht das ganz einfach, wenn Sie vorab über den Boardverwalter der Entwicklungsumgebung Ihr ESP-Modul eingerichtet haben. Bei unseren kostenlosen Hintergrundartikeln zeigen wir Ihnen [19], wie einfach das funktioniert.

Das Demoprogramm für einen FM-Sender besteht aus nur zwei Dateien, die Sie aus Github herunterladen können [20]: AMTransmitterI2S.ino und sample.h. Bitluni bietet unter Github ein Online-Konvertierungstool zum Download, mit dem Sie eigene Daten für die Datei samples.h erstellen können.

Ist das übersetzte, ausführbare Programm auf den ESP32 geladen, genügt an Pin D25 ein längerer Draht (Bild 4) – D25 ist der Ausgang des 1. DAC-Kanals. Bringen Sie die Antenne in die unmittelbare Nähe des Radios und suchen Sie im MW-Bereich von 835kHz nach dem Signal, bis Sie den Text „High Five …“ hören. Sollte das Signal brummen, liegt das vermutlich an Ihrem Netzteil für den ESP oder anderen Kabeln in der Nähe. Probieren Sie dann ein anderes Netzteil aus oder versorgen Sie den Aufbau über den PC oder eine Batterie. Die Signalstärke und damit die Reichweite lassen sich steigern, wenn Sie einen etwa zwei Meter langen Draht als Antenne nutzen und das bisher offene Ende mit Masse verbinden, um den Spuleneffekt zu verbessern.

Schaltbild: ESP32 mit einem Draht als Antenne.

Bild 4: Software und Draht genügen: der ESP32 als AM-Sender.

Noch einfacher und flexibler lassen sich Prüfsender mit der AM-Radio-Bibliothek von Adafruit [21] bauen. Allerdings funktioniert dies nur mit Adafruit-Boards mit ARM-Prozessoren des Typs ATSAMD21, beispielsweise dem Feather M0 Express und dem Circuit Playground Express.

Die Bibliothek lässt sich in die Arduino-IDE über den Bibliotheks-Manager als ZIP-Datei [22] importieren und bringt zwei Beispiele mit. Eins davon enthält das Gebrüll von Godzilla in Form vorgefertigter Samples in einer Header-Datei. Der eigentliche Sketch ist in Listing 3 zu sehen. Gleich am Anfang setzt radio.begin(540000); die Trägerfrequenz. Die Methode play() liest die unter dem Pointer *data liegenden Samples ein und variiert mit dem Wert per radio.write() die Amplitude der Trägerfrequenz.

#include <Adafruit_AMRadio.h>
#include "zilla.h" // Audio data is in a table in this file

Adafruit_AMRadio radio;

void setup() {
  radio.begin(540000);
}

// Plays back audio stored in PROGMEM array
void play(const uint8_t *data, uint32_t len, uint16_t sampleRate,
  boolean tenBit) {

  uint32_t i;
  uint32_t r2 = sampleRate / 2;
  uint32_t startTime = micros();

  if(tenBit) { // 10-bit audio samples?
    uint8_t loIdx = 4;
    uint32_t idx = 0;
    uint16_t hiBits;
    for(i=0; i<len; i++) {
      if(++loIdx >= 4) {
        hiBits = (uint16_t)pgm_read_byte(&data[idx++]);
        loIdx  = 0;
      }
      hiBits <= 2; 
      radio.write((hiBits & 0x300) | pgm_read_byte(&data[idx++]));
      while(((micros()-startTime+50)/100) < ((i*10000UL+r2)/sampleRate));
    }
  } else { // 8-bit audio samples
    for(i=0; i<len; i++) {
      radio.write((pgm_read_byte(&data[i]) * 257) > 6);
      while(((micros()-startTime+50)/100) < ((i*10000UL+r2)/sampleRate));
    }
  }
  radio.write(512);
}

void loop() {
  play(zillaAudioData, zillaSamples, zillaSampleRate, false);
  delay(250);
}

Um den Sketch übersetzen zu können, benötigt man zusätzlich die Bibliothek ZeroDMA [23] sowie die Unterstützung für die Adafruit-Boards in der Arduino-IDE [24]. Die Integration der Boards funktioniert wie bei den ESP-Boards (siehe oben) mit dem Unterschied, dass die URL für den Board Manager unter Einstellungen eine andere ist: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json [25].

Ist das erledigt, kann man über den Board Manager „Adafruit SAMD Boards“ installieren und schließlich unter Werkzeuge das richtige Ziel-Board festlegen. Für einen ersten Test genügt es, unter Beispiele/AMRadio das Beispiel zilla auszuwählen, zu übersetzen und auf das Board zu laden. Die Antenne schließt man beispielsweise beim Feather M0 Express an Pin A0 an (Bild 5), an dem der DAC angeschlossen ist.

Platine mit Antennendraht.

Bild 5: Der DAC des SAMD-Prozessors liegt an Pin A0, an den man einen längeren Draht anschließen muss.

Unter 540kHz ist im Radio der Schrei Godzillas in gar nicht mal so schlechter Qualität zu hören. Das ist umso erstaunlicher, weil der DAC des Prozessors mit dem Sketch nicht nur am Anschlag arbeitet, sondern eigentlich weit darüber. Die Zeit, um einen diskreten Wert akkurat an seinen analogen Ausgang zu legen, erlaubt laut Hersteller nur Sample-Frequenzen von 350 kilo samples per second (ksps). Der Sketch respektive die Bibliothek wartet aber nicht so lange, sondern schiebt einfach schneller Werte in die Register. Das scheint gut zu funktionieren, wie man hören kann.

Mit seiner hohen Taktrate kann der Raspberry Pi schnell genug arbeiten, um auch im UKW-Bereich Signale zu erzeugen und zu frequenzmodulieren. Die beiden Hacker Oliver Mattos and Oskar Weigl haben bereits 2013 das PiFM-Projekt ins Leben gerufen [26], das dies für Anwender auf sehr einfache und komfortable Art erledigt. Die in C geschriebene Software steht als Archiv zum freien Download zur Verfügung. Das Archiv enthält neben dem Quellcode auch ein bereits für den Pi übersetztes Binary und zwei Sounddateien für erste Tests.

Im Kern macht sich die Software einen der vier internen Taktgeneratoren (PLL, Phase Locked Loop A bis D) und Frequenzteiler des Broadcom-Chips zunutze. PLLD läuft mit 500MHz und kann mit den Teilern weitere Frequenzen zwischen 1 und 250MHz erzeugen. Das erzeugte Signal wird praktischerweise gleich auf dem Pin 7 (GPIO4, GPCLK0, ) ausgegeben. Indem man den internen Teiler variiert, kann man die Trägerfrequenz variieren. Die Software verändert den Teiler entsprechend den Werten in den Soundsamples, womit ein FM-Signal an Pin 7 zu messen ist (Bild 6).

Raspberry Pi mit Antennendraht.

Bild 6: Ein langer Draht am Pin 7 der GPIO-Leiste des Pi soll Reichweiten bis über 100 Meter ermöglichen.

Was sich so einfach anhört, ist im Kern dann aber doch erheblich komplizierter als bei AM, insbesondere weil PiFM auch in Stereo senden kann und dazu softwaretechnisch einige Hürden zusätzlich zu nehmen sind. Wer mehr wissen will, liest sich auf Wikipedia die Erklärung zum Pilotton-Multiplexverfahren durch. Aufgrund der Komplexität der Software verzichten wir hier auf das komplette Listing.

Die Software ist einfach zu bedienen, hat in unseren Tests aber nur mit dem Pi Zero, Pi 1 und dem Pi 2B+ (V1.2) ein empfangbares Signal produziert. Beim Pi 2B (V1.1) und einem Pi 3B+ blieb der Empfänger stumm beziehungsweise dudelte die eigentlich auf dieser Frequenz empfangbare Station.

Nach dem Auspacken des Archivs (am zuverlässigsten über den Archivmanager des Pi) wechselt man in das Zielverzeichnis und startet – zunächst ohne Antenne – den Befehl sudo ./pifm sound.wav 100. Stellt man nun ein UKW-Radio in die Nähe und auf 100MHz ein, sollte man den Imperial March von Star Wars hören. Je nach Radio muss man teilweise sehr nah an den Pi heranrücken, Stromversorgungs- und andere Kabel können den Empfang stören.

Praktischerweise kann man unter Linux Ausgaben von einem Programm auf ein anderes umleiten (Piping), sodass man auch andere Sound-Schnipsel per UKW senden kann. Eine eigene MP3-Datei sendet man etwa mit

ffmpeg -i input.mp3 -f s16le -ar 22.05k -ac 1 – | sudo ./pifm -

den Strich am Ende nicht vergessen, input.mp3 passt man entsprechend an), mit einem USB-Mikrofon kann man mit

arecord -d0 -c2 -f S16_LE -r 22050 -twav -D copy | sudo ./pifm -

live senden. Weitere Details sind auf der Projektseite von PiFM zu finden [27].

Zwar erlaubt die Bundesnetzagentur seit 2006 den Betrieb von Mini-UKW-Sendern, aber diese dürfen nicht mehr als 50nW abstrahlen (max. effektive Strahlungsleistung). Damit lässt sich üblicherweise ein Umkreis von rund 10 Metern abdecken. Der Raspi dürfte aber auch ohne Antenne die zulässige Sendeleistung überschreiten. Weil der Pi für seine Trägerfrequenz statt eines Sinussignals ein Rechtecksignal erzeugt, entstehen neben der eigentlichen Sendefrequenz weitere (harmonische) Oberwellen, also Vielfache der Trägerwelle. Die können in Frequenzbereichen stören, die andere Dienste nutzen. Mit einem Bandpass ließen sich solche Störungen aber leicht ausfiltern.

Das gewollte UKW-Senden in Bereichen oberhalb von 108MHz sollte man gar nicht erst probieren. Dort liegt der Flugfunk, dessen Störungen (zu Recht) ziemlich schnell Peilwagen der Bundesnetzagentur vor die Hautür locken. Experimentierfreudige Nutzer berichten, dass man mit einer Antenne an Pin 7 auch mehrere 100 Meter überbrückt. Deshalb und auch wegen der Harmonischen muss man im Normalfall von einem Betrieb hierzulande abraten. (dab [28])


URL dieses Artikels:
https://www.heise.de/-4521173

Links in diesem Artikel:
[1] https://www.heise.de/hintergrund/10-Jahre-Raspberry-Pi-Gekommen-um-zu-basteln-6496406.html
[2] http://3337265
[3] https://www.heise.de/ratgeber/Arduino-ESP32-und-Pi-als-Radiosender-4521173.html
[4] https://www.heise.de/ratgeber/Dias-scannen-mit-dem-Raspberry-Pi-4936945.html
[5] https://www.heise.de/hintergrund/Kleinstrechner-Vergleichstest-Raspberry-Pi-Zero-gegen-Orange-Pi-Zero-6135156.html
[6] https://www.heise.de/ratgeber/Werbeblocker-Pi-hole-RasPi-als-DNS-Server-mit-integriertem-Ad-Blocker-nutzen-4930104.html
[7] https://www.heise.de/ratgeber/Praxistest-Raspberry-Pi-4-optimal-kuehlen-4851547.html
[8] https://www.heise.de/ratgeber/Raspberry-Pi-Anleitung-zum-Bau-eines-Nistkastens-mit-Beobachtungsfunktion-5061617.html
[9] https://www.heise.de/ratgeber/Was-Uebertakten-beim-Raspberry-Pi-4-bringt-4559418.html
[10] https://www.heise.de/ratgeber/Raspberry-Pi-4-Minimalistisches-NAS-mit-ZFS-Dateiverwaltung-selbst-bauen-4927272.html
[11] https://www.heise.de/hintergrund/100-Jahre-Rundfunk-von-Hertz-bis-Gigahertz-4521108.html
[12] https://www.heise.de/make/
[13] https://academo.org/demos/amplitude-modulation/
[14] http://dangerousprototypes.com/forum/viewtopic.php?f=56&t=2892#p28410
[15] https://www.heise.de/ratgeber/Arduino-Einstieg-Software-3226852.html
[16] http://dangerousprototypes.com/forum/download/file.php?id=5106&sid=6376f95cf5c27c50862a1841314127a2
[17] https://bitluni.net/am-radio-transmitter
[18] https://github.com/bitluni/ESP32AMRadioTransmitter
[19] https://www.heise.de/hintergrund/ESP-Boards-mit-der-Arduino-IDE-programmieren-4130861.html
[20] https://github.com/bitluni/ESP32AMRadioTransmitter/tree/master/AMTransmitterI2S
[21] https://learn.adafruit.com/circuit-playground-express-dac-hacks/transmitting-am-radio
[22] https://github.com/adafruit/Adafruit_AMRadio/archive/master.zip
[23] https://github.com/adafruit/Adafruit_ZeroDMA
[24] https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython/using-with-arduino-ide
[25] https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
[26] http://www.icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter
[27] http://www.icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter
[28] mailto:dab@ct.de