I recently came up with an idea that required me to build a device to log the songs played on a radio station. There are a few ways to go about this, you could scrape the data from their streaming radio service, you could use something like Shazam to identify the songs and record them, or you could use the RDS data encoded in the radio signal. I decided to go the RDS way.
Nearly everyone is familiar with the RDS data stream even if they don't know it. Newer car stereos that display the current song playing get this from the RDS data. The FM radio station is first demodulated. In this demodulated signal at 57 kHz there is double side-band suppressed carrier that contains the RDS data.
The initial method I chose to receive this signal didn't work. I planned to use a software defined radio approach using an RTL-SDR dongle and a Raspberry Pi, but I just couldn't get it to work. After some Googling I came up with Plan B. Use an FM radio receiver IC that contained an RDS decoder and connect that to a Raspberry Pi. Luckily, Sparkfun had a breakout board for the si470x that was perfect for the job.
I didn't want this to be a massive project so I grabbed publicly available code and modified it for my purposes. The code was tested until it could run for long periods without crashing. There's no exception handling, I just reduced the errors until the system was stable. I could have spent another couple days making it "perfect", but what's the point, this isn't a product or a permanent installation, it has to run for a week or so and give me usable data, and it's doing that. Currently at around 45 hours.
The code for this project is available from github. I urge you to have a read of the README file there it contains more information about the code.
Based on code from
Stephen Phillips http://blog.scphillips.com/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/
Andrea Fabrizi https://github.com/andreafabrizi/Dropbox-Uploader
|Raspberry Pi and si470x based RDS receiver/logger|
The system above looks complicated, but it really isn't. The white brick in the lower left is a USB power supply. The Raspberry Pi is the device at the top left, connected to it by jumper wires is the si470x breakout board. The Pi is also connected to a USB 3 hub that has a Wi-Fi dongle and a USB 2 hub connected to it. That may sound strange, but the Pi can't recognise USB 1.1 devices plugged into a USB 3 hub, so you need a USB 2 hub in there to allow the connection of the mouse and keyboard. Yeah, I could have done this via an SSH terminal, but as I was connecting wires directly to the Pi it just seemed easier to be at the device while I did it.
The software is simple as well. I modified the original code to just constantly poll the si470x receiver, log the RDS messages with timestamps and station frequency, and then rotate the logs hourly. The script was also configured to run as a background service on start-up. So if it loses power, it should just automatically start logging again.
I also planned to run the dropbox_uploader utility on a schedule with a cron job to backup the log files. I wrote the script to do this, but it seemed easy enough to run it manually every now and then.
|RDS log file|
The RF signal chain is important, you need a good signal to get the RDS data. Even if you can hear the station clearly you still might not be able to receive song names. The si470x breakout board uses the headphone wiring as the FM radio antenna, just like most phones, if you want the radio to work you have to use some type of headphone. The presence on a human body also boosts the signal. This is a nice solution in most cases, but I couldn't sit there wearing headphones for a week. Well, I could but I don't think I'd have a job at the end of the project. I guess that'd be a bad thing, maybe.
To get a good signal I took a folded dipole antenna made of ribbon cable I just happened to have and used that, I put it on a table and put some books on the end to stop it rolling up.
|300 ohm Folded dipole ribbon cable antenna|
The folded dipole has a 300 ohm balanced output, but I needed a 75 ohm unbalanced signal, so the antenna was connected to a balun.
|300 - 75 Ohm Balun|
To get the coax signal into the breakout board I used a simple adapter. In terms of impedance matching it's not ideal, but I did the best I could with the rest of the chain so it turned out OK.
|Coax to 3.5mm plug|
Connecting the Raspberry Pi to the si470x breakout board is relatively easy, just be careful GPIO 23 is actually pin 16, don't know who came up with that idea.
I had a lot of fun with this project. It took a week of coding and fiddling in my spare time to get it working. I'm pretty happy with that. I'm usually more self concious about my coding ability, but you know what, fuck it. I made something that does what I want, and if anyone has issues with my code they're more than welcome to improve it and do whatever they want with it. I'd love that. That's why it's out there, to help the next person that comes along.