Build your own Wifi radio using Microcontroller ATmega16
The internet hosts lots and lots of online radiostreams, most of them with a certain theme, ranging from old time classics to Tibetian riverdancing. I must admit that I love to listen to them while I’m building stuff, as I can choose the music I like without listening to the same cd’s over and over again.
The only problem is that I always needed to have a computer neaby to get an internet connection. So I looked around to buy one, but they are quite expensive and besides that, it is a lot more fun to make your own.
As I had no clue at all about how to do the wifi and internet part of the project, I searched the net for clues and I stumbled upon www.mightyohm.com. This site belongs to Jeff Keyzer and he has an excellent step by step tutorial on it for hacking a wifi router into a wifi radio. If you follow his instructions, you will end up with a working radio but I decided to build my own graphical interface for it and my own case.
I really wanted this project to look as nice as possible, so I invested a lot of time in designing and building the case. I hope that this build is awesome enough to have a chance in the lasercutter contest or the makerbot contest as I would love to have one of these machines. They would allow me to make even nicer looking and more intricate cases and parts and I wouldn’t have to bother my friends to mill parts for me ; ( in fact I might be able to help them out then).
I would like to thank Jeff Keyzer for helping me with setting up the router correctly, Izaak for helping me with out with the CNC part and my wife for helping me with the veneer.
What do we need for this project?
First of all, we’ll need an ASUS WL-520gu wireless router. This router will handle the internet connection and also play the music.
Secondly, we’ll need a RS232 to usb converter (3,3V version). We will need that to hack the router. I used a couple of xbees to do this as they are 3,3V and a few wires less on my desk is always handy. If you don’t have those you can buy converter cables all over the net (here for instance).
We’ll also need a USB sounddevice. I used a creative SB0270 external soundcard that I had lying around for years but you can buy very cheap small thingies everywhere. If you’re not sure whether the sounddevice you have will work, then you can go to the forum on www.mightyohm.com. There is a list there with working devices.
There are 2 options to make the sound audible. You can either use an external amplifier or you can use an internal one. I actually combined the 2 options. I used a kit (K-VOTI-003 on www.voti.nl) for the internal amplifier but I also added audio output (stereo cinch) on the back for an external amplifier. Ofcourse you can build you own amplifier too but I was a bit short in time
If you use an internal amplifier, then you will need some speakers too.
I also added a headphone connector to the front.
For the interface we’ll need:
- A graphical LCD: I used a monochrome 240*128 LCD (LCD-21 on www.voti.nl)
- An ATmega16 or 32: The size is depending on the amout of graphics you want to display. I used an smd version but ofcourse you can make your project with thru-hole components.
- A DS1307 Real Time Clock
- Battery holder + 3V battery: CR2032 in my case
- A 32.768kHz quartz crystal
- A rotary encoder: I used an alps encoder with pushbutton
- A 10K potentiometer
- A bunch of resistors: 3 x 1K5, 2 x 4K7, 4 x 10K
- BSS138: 2 x for the level converter
- Some male and female headerpins
- A connector for your programmer
- 3 double switches
- 5 led’s
For the case we’ll need a lot of 18mm MDF and some real wood veneer.
The front and the backpannel are made of alucobond which is a sheet of poylethylene sandwitched between two 0.8mm layers of aluminium.
We’ll also need 5 holders for the LED’s and a powerconnector.
Hacking the ASUS Router
I won’t go into much detail on how to do the hacking of the Asus WL-520gu, as it is fully explained on the mightyohm-website. You only need to follow it until part 5 because after that we’ll build a different interface and case. Jeff Keyzer deserves all the credits for this part an I also want to thank him for helping me out with the problems that occured.
Steps 1 and 2 are a general introduction but it is nice to read them as they contain some interesting information.
The fun begins in step 3! Void the warranty (Yay!!) by opening the case of the ASUS. When it is opened you need to locate where you can solder a 4 pin male header. It is located near the silkscreen ASUS logo. Soldering the headerpins was a bit tricky. Best way to do it is to remove all the solder that is in the holes before you even try.
In step 4, you’ll install OPENWRT on the router. Follow this step very closely as it is possible that you break your router forever when you do something wrong. If you succeed in installing OPENWRT, you can continue with setting up your internetconnection in the second part of step 4.
In step 5 you will install mpd (music player deamon) and configure it. If you have completed step five, you should hear some music!
After completing these 5 steps, you can carry on with this instructable.
Add an external mpd client
At this stage, you could close the router again and use an external mpd client to control your radio. In this instructable we will also build an interface but having a way to acces the player while testing is always good.
You can download a lot of mpd clients at http://mpd.wikia.com/wiki/Clients, even for you Iphone. I downloaded and installed the Ario client. To do so, I needed to install GTK+ too (http://sourceforge.net/projects/gtk-win/files/latest/download).
When you have installed the program, you need to set up the connection. By host you add the ip-address of your router and by port 6600. When done click the connect button and you should be able now to control your radio from your pc.
Building the interface (hardware)
Building up the interface is not very difficult. It can be done on a piece of veroboard or you can make your own PCB.
Connect the LCD to the microcontroller
I would love to tell you what pins need to be connected to what but every LCD has it’s own pinout. You can find the right way to do it in your datasheet.
When working with graphical LCD’s, I’ll always us port A for the data pins and the higher part of port C for the control pins. That leaves me portc.0 and portc.1 for I2C communications.
Don’t forget to add the 10K potentiometer between Vee , V0 and Vss for brightness adjustment .
My LCD had an internal resistor for the LED so I just hooked it up to 5V and GND. You could ofcourse connect the LED with one of the PWM pins on your microcontroller to controle the brightness, but I didn’t opt for that.
Connect the DS1307 to the microcontroller
Connect pin 5 of the DS1307 to portc.1 of the microcontroller ande pin 6 to portc.0. Don’t forget to add the two 4K7 pullup-resistors to those lines. Add the crystal to pin 1 and pin 2 of the DS1307 and add the batteryholder between pin 3 (positive) and pin 4 (negative). Then hookup pin 8 to 5V and pin 4 to GND.
Connect the rotary encoder to the microcontroller
The pushbutton will have 2 pins on your rotary encoder and the encoder itself will have 3 pins. Connect one pin of the pushbutton to INT0 or portd.2 on the microcontroller and the other pin to GND. Then connect the middle of the 3 other pins to GND, one to INT1 or portd.3 and the last one to portd.4.
All the lines to the microcontroller need a 1K5 pullup-resistor.
Connect your microcontroller to the RS232 pins on the router
If you look at the pins on the router, you will notice that one of them is connected to a thick diagonal trace. That pin is 3,3V and lets call it pin 1. Pin 4 is GND, pin 2 is RX and pin3 is TX.
Connect RX to TDX on your microcontroller (portd.1) and TX to RDX (portd.0). But because our microcontroller needs 5V and the router 3,3V, We’ll need a level converter. You can learn how to build one in one of my other instructables or you can buy one online.
Don’t forget to add your programming link.
That is all we need to start programming the interface.
Step 5 Setting the baudrate and echo
Before we can start to communicate with our router, we need to change its baudrate. The routers baudrate is 115200 and we want it to be 9600 (I was told that 19200 works fine too). Another thing we should change is the echo. Now the router echos back every charater that we sent to it and that would make our Uart-buffer a mess, so we need to turn that off.
I tried to write a script for the router to change those 2 things and to make that script autostart when the router starts up. The script was working fine but it just wouldn’t start by itself (most probably something caused by my inexperience). So I decided to look for a script that was running for sure at startup and add a few lines to that.
I found a script named diag.sh in the etc/ folder. It drives the LED’s in front of the router. So I added my code to that script and it worked like a charm.
To do that yourself, telnet or shh to router and type vi etc/diag.sh into your console. Now you should see the code. Press I to edit and add stty 9600 -echo < dev/tts/0 just below the header. Then press Esc and : x enter to save it and to close the editor. Then type reboot into your console to reboot the router.
When the router has rebooted, the baudrate should be correct and the echo off.
Step 6 Communications with the ASUS
Communication with the router may seem a bit daunting (well it did to me), especially when you are new to it. But it isn’t as difficult as it seems.
Sending commands to the router
First we need to decide what we want the radio to do. We basically want it to:
- change station
- change volume
If we look into the list of commands for mpc we see that:
- the command for play = mpc play
- the command for pause = mpc pause
- the command for stop = mpc stop
- the command for volume = mpc volume [+/-] num (numeric value)
The changing of the station is a bit more difficult. To be able to change to another station, mpc needs to know it’s address. Easiest way to do so is to preload all our favorite stations into a playlist on the player. So at the beginning of our code we will add the command:
mpc add address for each station we want to preload into the router.
Before we start to add stations, we could issue a mpc clear command. This will clear all previous lists, just in case we made any changes to our list.
After all this is done, we can change the station with the mpc play num command, where num is the position of the station in our added playlist.
In Bascom, sending these commands to the router is very easy. Everything is done with PRINT:
PRINT “mpc play” or PRINT “mpc volume +5”
There is no need to add a Carridge Return (CR or ascii 013) to the command as the PRINT statement adds that by itself.
So as you can see, sending commands to the router isn’t difficult at all!
Requesting and receiving info from the router
Requesting and receiving info from the router is a bit more difficult. Again, we’ll need to decide what info we want to receive from the router. When you read part 6 on www.mightyohm.com, you’ll see that there is lots of info that you can get, but we only want to know:
- the name of the station
- the title of the song
- the volume
The request for receiving the station and title is done with the following command:
echo “currentsong” | nc localhost 6600 | grep -e “^Title: ” -e “^Name: ” ( mind the capital T and N)
and for the volume:
echo “status” | nc localhost 6600 | grep -e “^volume: ” (No capital here)
So in bascom that would give:
Print “echo ” ; Chr(34) ; “currentsong” ; Chr(34) ; ” | nc localhost 6600 | grep -e ” ; Chr(34) ; “^Title: ” ; Chr(34) ; ” -e ” ; Chr(34) ; “^Name: ” ; Chr(34) ; ” > /dev/tts/0″
Print “echo ” ; Chr(34) ; “status” ; Chr(34) ; ” | nc localhost 6600 | grep -e ” ; Chr(34) ; “^volume: ” ; Chr(34) ; ” > /dev/tts/0″
Again there is no need to add a CR.
When we send one of these requests, we’ll receive something into our buffer immediately. Now we need to arrange all the data in our buffer into useful stuff.
Luckily for us the router labels its info. Before the stationname it adds Name: , before the title title , and before volume volume. So we’ll let our code search for the appropriate label and read the buffer from that point until it encounters a CR or until the buffer is empty. After all the info is extracted from the bufffer, we simply empty the buffer so that it can be used for another request.
To do so we start with reading the buffer into a string. After that we can simply clean the buffer so that there are no unwanted characters left. We will look in our string for one of the labels with the var = INSTR( string , substr ) statement. This will return the position of our label in our main string.
position = Instr( Uart_in_string, “Name: “)
This will give us the position of the first character of the label. If you don’t want to add the label onto your screen, then just add the amount you need to start reading behind the label. In this case:
position = position + 6
From here we need to determine how long the data is. So from the point position we’ll start to read one character at a time until we find a CR or until we reached the last character of the string. We use the var = MID(var1 ,st [, l] ) statement where var1 = the source, st = starting point and I = the amount of characters to read. So in our case:
Length = 0 Do Incr Length Position = Position + length Temp = MID(Uart_in_string ,Position , 1 )
Loop Until Temp = Chr(13) or Temp = “”
So now we know the length of our data and the only thing that is left to do, is to extract the data from the source string. Again with the Mid statement:
Name = Mid(Uart_in_str, position length)
The same will work for the title and the volume.
Now we didn’t discuss yet how to read from the buffer and how to empty it. Reading from the buffer is done with var = INKEY(). This will return the ascii value of the first byte in the buffer and then remove that character from the buffer. We just add every single received character together into a string containing the whole or part of the buffer.
Do Uart_buffer = Ischarwaiting() Ischarwaiting() tells how many characters there are waiting in the buffer
If Uart_buffer > 0 Then Uart_in = Inkey() Uart_in_str = Uart_in_str + Chr(uart_in) Chr transforms the ascii value into the real character
End If Loop Until Uart_buffer = 0 Or Len(uart_in_str) = 255 Len gives us the length of a string
To empty the buffer, just read everything into a string until Ischarwaiting() = 0
This was everything you needed know to communicate with your router. All the rest of the code are mostly cosmetic: graphic stuff and so on.
Leave a Comment
You must be logged in to post a comment.