Transmit FM using Raspberry Pi and no additional hardware

rpi-fm-transmitter

Now here’s a project that actually hacks the Rapsberry Pi rather than just using it as an embedded computer. [Londons Explorer] figured out how to turn the RPi into an FM transmitter. For now it’s done entirely in the user space, but we’re sure it could be improved if someone wanted to drill down further into the hardware. For those wanting to give it a try he’s rolled everything into a simple python package.

The technique requires nothing additional except a 20cm wire to serve as an antenna. The trick is to map GPIO pin number 4 to a position in memory. The clock generator is then used to toggle this pin at 100 MHz, which is the frequency to which your radio should be tuned. A fractional divider adjusts the frequency based on the sound file being transmitted.

The proof of concept for this was able to reliably transmit at a distance of about fifty meters through several walls. The problem is that this technique is limited in the amount of data which can be sent. Right now it’s only about 6-bit audio. But descending deeper through the abstraction layers to put DMA (Direct Memory Access) to use may be able to improve upon this.

[Thanks Owen via Reddit]

Comments

  1. Brad says:

    Amazing! Simply amazing!

    • Hack Man says:

      This explains why they had to scramble to sorta get FCC certs and possibly CE… at the last minute.

      • Peter says:

        Probably not. You can almost certainly do this with any computing device (computer, micro controller, etc) with a GPIO pin. Attach a length of wire to any GPIO pin and toggle the voltage, you WILL generate RF. The FCC certification is for stray or unwanted RF leakage/generation.

  2. Andrew says:

    good job.

    I really appreciate this because it demonstrates that software processing can replace hardware processing and this conecpt eventually leads to SDR.

  3. Londons Explorer says:

    Thankyou for screenshotting the only bit of code with comments in :-). If I’d known how many people would look at this, I would have actually commented the code..

    Anyways – if anyone here is interested in improving this, drop me a line (on here or the wiki). I’d kinda like to make an asla driver which uses dma so you can use FM just like any other audio device.

    • Some guy says:

      I was thinking more like another way to do short range transmission of instructions to nearby microcontroller projects, instead of music. Say… have xbmc tell my blind closer to open or close, right from the tv. ;)

      I imagine you’d need to use some kind of checksum and such. Any thoughts?

    • Muzer says:

      Hi,

      I can’t edit your talk page as the wiki requires you to enter some Imperial College password that only you guys (presumably) know, and I don’t want to be googling around for dodgy passwords at this time in the evening.

      I just wanted to say that by default, this continues spitting out a carrier wave after it finishes until the Pi is rebooted. I added the following code to prevent this:

      * setdown_fm() – function the same as setup_fm() but with struct GPCTL setupword = {6/*SRC*/, 0, 0, 0, 0, 0,0x5a}; and add an exit(0); at the bottom, as this function only gets called as part of exiting.
      * To the top of main, I added: signal(SIGTERM, &setdown_fm); signal(SIGINT, &setdown_fm); atexit(&setdown_fm); . This registers the setdown function for the following events:
      ** Program is killed with SIGTERM
      ** Program is stopped by pressing Ctrl+C
      ** Program exits normally

      (Sorry if I’ve made a mistake writing this, it’s late and I don’t have the code on me).

      I also note that if you want this to actually be legal, you can get it to transmit in the amateur bands if you have a suitable licence (and comply to the terms of your licence, of course). Calculate the desired frequency as described on the Wiki, then you’ll probably also want to turn the bandwidth down as the default is far too much for amateur radio by changing the 25.0 in this line:

      float dval = (float)(data[j])/65536.0*25.0;

      I got good results on wideband mode on my VHF handheld by changing it to 6.25, YMMV as I don’t know if that’s actually the correct value or if perhaps there’s another (better) way I should be changing it (I only skim-read the code and changing this value seems to work so meh).

      • Pacemk says:

        Thank you for the little piece of code.
        In VHF band, this is very good indeed.

      • Londons Explorer says:

        Thank you very much.

        The reason we kept transmitting the carrier is so people could write little python games or something and would get silences between calls to play_sound rather than fuzz, but obviously it would be better to make it an option as you have done.

        When transmitting in the amateur radio bands, do remember that since it is a square wave you’ll still get lots of other sidebands, some of which will fall into all kinds of random bands.

  4. magichobo15 says:

    That’s really neat. I wonder if you could make the raspi function as a sdr with this….

  5. DanJ says:

    I love how the microprocessor is eating everything in its path. Everything is becoming a software problem. Years ago the debate was between the big iron people and the uP people. Then between the dedicated function logic people and the uP people and in years to come between the radio people and the uP people (actually the radio people seem to be jumping on this bandwagon big-time).

    This is a neat hack. London’s Explorer, how do you recon a supersampled 9.5 bits compares with traditional FM radio (aside from not being in stereo)?

    • Londons Explorer says:

      Quality is currently mediocre, but it’s mostly a software problem (due to linux running other apps on the cpu instead of ours…). With that fixed, it is nearly the same quality as broadcast FM. We can probably get to around 13 bits precision.

  6. draeath says:

    I bet you that carrier is -dirty-

    Any chance to slap a scope on it? I’d be curious about how much splatter you get because of carrier harmonics (there’s no way you’re getting a clean sine from that)

    • RP says:

      It shouldn’t be too much worse than a Class C output section. It would help a lot to add an LC tank circuit between the GPIO pin and the antenna

    • Jean says:

      You can achieve a neat carrier with a filter.

      • localroger says:

        I ended up on the wrong end of the argument on the Parallax Propeller forum because, while you can use a trick like this to generate RF (and in fact a lot more flexibly) the PLL jitter creates birdies around the carrier which cannot effectively be filtered out. It’s a cool demonstration but not really legal or practical for regular use. Until someone puts the RPI version on a spectrum analyzer we simply don’t know whether the output is acceptable.

        • Mike FIeld says:

          The out output is going to be pretty bad. Assuming you can radiate all of the square wave only about 2/3rds of the energy will be on the desired frequency, the rest wll be unwanted EMI. That doesn’t even allowing for the jitter in the signal.

          Square waves are rich in odd harmonics. How long will it be until somebody figures out that if you spew junk on 1575.42MHz (fifth harmonic of 324MHz) you can build your very own Raspberry Pi powered GPS jammer?

          • Leif says:

            Clean square waves aren’t so bad… no you don’t want to send them to the antenna but harmonics are easy to filter out with a few passive components. It’s spurs that are near but not on the actua desired frequency that you need to worry about.

        • Londons Explorer says:

          You can probably get some good stats on this with matlab. Consider an ideal 100Mhz FM signal, sample in time to 500Mhz, and then quantize in amplitude to 1 bit. then do an FFT on the result. Post pictues… :-P

        • Londons Explorer says:

          Ok – matlabbing done… Assuming the Rpi gpio is linear (which is with lack of further info the best we can do), the FM transmitter also transmits at the 3rd, 5th, etc. harmonics as expected. The power of these transmissions is 1/3, 1/5 etc. again as expected.

          There is also noise near the FM signal (ie. hard to filter) as you state, but it is 40dB down from the main signal, so shouldn’t be too bad.

  7. Ultrawipf says:

    This is so awesome :) tried it myself with just a wire and i god great quality in the whole house. Amazing how powerful this is. So easy. Awesome hack.

  8. rj says:

    Ok, so you use an LFSR to generate the white noise source to make a crude 16-to-1-bit converter; why not use sigma-delta instead? Should be comparably fast and more precise.

    • Londons Explorer says:

      Yes, and Yes. It was a hack, and the lfsr was a nice one-liner. You would get better quality with delta sigma for certain. The DMA version we have been thinking about will use Pulse width modulation (since that is implementable, whereas delta sigma isn’t really possible with the dma command set within a sensible amount of memory).

  9. nixphoeni says:

    It’d be interesting to see if you could receive FM broadcasts using a similar technique. Even if you couldn’t make it into an FM tuner you might be able to make a simple short-range wireless connection between two devices.

    • Mike FIeld says:

      Maybe If you use a high impedence input (CMOS?) or a mosfet front end you could use it as a 1-bit ADC, follow it with a little bit of DSP and you should get a signal.

      Much like a very cude version of this guy’s home built GPS receiver : http://www.holmea.demon.co.uk/GPS/Main.htm

      • Londons Explorer says:

        I am concerned that a floating input with no filtering at all may pick up 50Hz way way way more than it picks up 100Mhz, so you won’t get any of the signal you want… It could work with a basic filter and amplifier on the input though. Processing data in real time at 100Mhz will be challenging though…

  10. orenbeck says:

    EXCELLENT work and it’s a wonderful demonstration of less being more. Commented code is one of those pass/fail deals for those who want praise instead of anger. The time to comment while writing code- Vs time spent needlessly reverse engineering can be a hugely nonlinear swap. Good show by posting commented code !

    The comments about FCC/Regulatory oversight sort of fall short of strong enough warnings. Anyone doing this is welcomed, nay begged..to do some range testing for us! That’s a quickest real world test of if we’ve worries ahead or not at all. In theory- it’s damned unlikely that ranges in tens of feet will ever be there for dumb wire bits or board foils. But let’s be sure. Past reasons?

    We used a concept of best situational practices. Defines shortest form as a brutal crude proof -of-concept can get away as is but not to push it past just that.

    More than that initial run deserves some care about consequences. As broader use above the “yes- it works” demos and/or minimal operating testing needs attention to what you are doing to others around you. So you don’t replicate what 6m did to TV decades ago.

    Harmonics of Hacked gear WILL shower bandwidth with General Cruddy Splatter Badness to a damage level often way understimated. Examples are out there for examination. Especially when Hack/Make spaces are having Colo with Repeater inputs. Or someone gets the why not.. of trying this on Six Meters and doing things to TV and Aircraft bandspace!

    There’s good reasons for being careful but not too careful in many areas. RF’s reach is a damage multiplier even if we’d think it stupidly paranoid at first glance. The risk of Hackerdom getting bad press or people getting hurt is why being mindful about range is a Very Good Idea.

  11. maleckii says:

    Why 100 MHz? Why not 1 MHz? A HF transmitter at raspi prices is amazing, even a low power one. The range would be quite a bit better too.

  12. For FCC compliance, an unlicensed broadcaster (ie, you) must adhere to limits imposed by FCC Part 15. The limit is “250 µV/m at a distance of 3 meters from the antenna.” That’s equivalent to 0.01 microwatts. (http://en.wikipedia.org/wiki/Title_47_CFR_Part_15#Unlicensed_broadcasting)

    Does the RPi’s GPIO pin violate this? Well, the GPIO pin can provide more power than that. The 3.3 V GPIO pin has a current limit of 16 mA, so the pin can theoretically provide 0.0528 W (3.3 V * 16 mA = 0.0528 W).

    I’m not sure how that relates to the output power of the transmitter though. Does anyone who knows more about RF have any ideas about this?

    • Fernan says:

      If we use a lambda/2 dipole and we integrate the Poynting vector in order to get the radiated power in the vacuum, we get that P0= 36.6*(I^2), if we use 0.016 A we get P0=9.36mW but we are using a lambda/4 monopole (the wire) we are radiating half of power than the lambda/2 dipole so we have P1=P0/2=4.68mW.
      By the Friis transmission equation the power that reach those 3 meters would be:
      Prx = Ptx*Grx*Gtx*(lambda/4/pi/R)^2
      R= 3 meters
      Gtx is the directivity of a lambda/4 monopole == lambda/2 dipole that is 1.64
      If we asume an isotropic antenna at the receptor that has a gain of 1
      And also we can calcula lambda=c/f=3 we can estimate a recieved power
      Prx = 48.65uW which is more than the FCC limit.

    • Mike FIeld says:

      The output is only 0.8V RMS at about 50 Ohm, giving about 12mW into a perfectly matched 50 Ohm antenna.

      From http://en.wikipedia.org/wiki/Signal_strength
      “…if the average power to a half-wave dipole antenna is 1 mW, then the maximum electric field at 313 m (1027 ft) is 1 mV/m (60 dBµ).”

      So in theory, at a range of 313m this can have 48x the maximum allowed power at 3m!

  13. yabapolido says:

    This and text-to-speech plus a small bash script and voilá :)
    Working like a charm, scaring the sh*t out of neighbours :)

  14. yabapolido says:

    Did anyone managed to change the frequency?
    Damn, either my math sucks, or 5.0CF is never 5.050505 :| :| :| :|
    HELP

  15. Leif says:

    I see you testing this with a ham ht. Have you tried this at all on ham frequencies?

  16. NewCommentor1283 says:

    1) the FCC is NOT the poliece of the entire world. PERIOUD. end of story. FACT

    2) GPIO pins have had the capability of doing this since… well… waaay before 1990. that is for SURE. im pretty sure its been done at lower frequencies by AVR and PIC

    3) odd harmonics are nasty little buggers! you _think_ your only transmitting on one freq. when in reality your splattering the entire VHF, 1/8 of the UHF, aircraft, cellphone/900mhz, and anything else that gets in its way! trust me, ive done it accidentally and wondered why all the TV’s radios and 900mhz stuff stops working when powering on my “low bandwidth” transmitter

    PS: you _KNOW_ your transmitting _something_ when you touch the antenna and get a mild RF burn ;)

  17. John P says:

    Correct me if I’m wrong, but don’t most commercially available fm radio receivers (for music) only allow tuning at frequencies like 100.1, 100.3, 100.5 and so on… unless it were an sdr or analog tuner? At least my car doesn’t allow even numbers due to bandwidth spacing…

  18. SteveHaD says:

    This is uber cool. Very very impressed!

  19. wardy says:

    Interesting things can happen on a simple wire antenna at high frequencies.

    A while back i soldered about 30cm of bell wire to an IO pin on a Parallax P8X32A microcontroller to generate RF noise (for diagnostic purposes while working in an RF shielded chamber) and it worked beautifully. Fascinating thing was that the measured peak to peak voltage at the end of the antenna wire was over 40 volts. Forty. Four zero. The P8X32A runs off 3.3 volts supply. RF is black magic.

    • orenbeck says:

      I suspect the accuracy of that 40 V p2p if there’s any “load” applied. Yes- there’s a set of rational models for how the voltage is developed as such. But it’s all about discovering what is a real voltage and what’s a phantom read or just picoamp volts.

      That really impressive static spark for example- It’s got V but no W averaged over longer than the discharge event. Stings like hell, can ESD oxide layers even, but it’s not usable bulk power.

      BtW, all the comments about harmonics and spurs/spikes et all- They’re often an understated danger by far. Intermod with nearby radios or just exciting any nearby nonlinear junctions can be badness indeed. Playing with crudity like these schemes called “Direct RF” anywhere near oh- Repeater Diplexers that have dicey shielding can spread the ungood. Same with underestimating the crud range..Fifty feet sphere? in one environment is safe. In another place that could be not good for several neighboring rooms.

      I perhaps did not make it clear enough:

      Be damned aware of what risks really are of viable concern and which are no sweat. And what you’re betting with if you’re wrong. Bunging up someone’s music radio- or a baby monitor- Or life safety radios. All protected by our good practices. Or not.

  20. kamathln says:

    I wonder what happens when you use two gpio pins like this and can control the interference.

    • Londons Explorer says:

      Sadly the R pi doesn’t have hardware to do this – only GPIO4 can do FM…

      Other chips can probably do this, and with it you could probably do some interesting beamforming!

  21. Kay says:

    Anyone want to take a crack at what it would take to port this to one of those stuffy Beaglebones? My first impression was to change the GPIO to what the bone uses, but after looking at the code I’m a little mystified at how it even works…

    • Londons Explorer says:

      Yes, it looks like it would be possible (this design would be possible on any system with a clock speed > ~ 200Mhz), but the specifics of how the GPIO’s can be controlled from a clock module in the beaglebone is totally different from the Raspberry Pi, because the chip is TI based rather than Broadcom based, so you would effectively have to re-implement the whole thing. :-(

      It looks quite a bit harder to do in the beaglebone, because it doesn’t seem to have the ability to connect a configurable clock signal to a gpio, so instead you’d have to generate the signal in software, which would be pretty tough to do at 100Mhz, and even tougher to do with linux running.

  22. Mega1mpact says:

    I made a small hack that allows you to easilly set the frequency. It does the trick quite nicely.
    Source: http://pastebin.com/EWw0iMXT
    Screen: http://ezyimg.com/0DDX84

  23. This has been done using drastically less hardware, namely an Atmel ATtiny45 microcontroller and a battery:

    http://spritesmods.com/?art=avrfmtx

  24. Drone says:

    Anyone know what happened to the source and Wiki pages for this project? I just get a 500 Internal Server Error as of post time. In-fact I get a 500 error for http://www.icrobotics.co.uk/ .

  25. Joe Blow says:

    The paragraph before the C program at the bottom of the page states the .wav file should be 16 bit 44.1kHz mono, but the usage comment at the end of the C program states the .wav file should be 16 bit 22.5 KHz mono. Which should it be?

    • Oliver Mattos says:

      The newest version uses 22 kHz. The reason for this is because during FM transmission, the audio needs to go through a filter (called pre-emphisis). This filter amplifies high frequencies. If the signal were 44kHz, then the highest frequencies would be super amplified and would interfere with the stereo detection circuitry in the receiver.

      Obviously, a bandpass filter could solve this, but I couldn’t be bothered to implement one… :-P

  26. Ispeakhat says:

    badbios like…maybe,,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 96,742 other followers