June 5th, 2009

DIY Wifi Radio

DIY WiFi Radio

You like listening to radio and your favourite stations use Internet broadcasting? Or you’re sick of commercials between songs or the radio man spoiling the song with some announcement? Here is an award worthy project for you. With this wifi radio you have wireless connectivity to the Internet so you have a huge variety of radio stations to tune in, mp3 decoding, 44.1kHz 16 bit stereo audio, 4W amplifier with two 4 inch speakers, LCD display all this in a very nice vintage looking compact case. Total cost under 100$.

Asus WL-520GU was the choice for the wireless router. For under 50$ it’s a good platform for an embedded Linux system, its only shortcoming would be that it lacks built-in audio. This problem was solved with an USB audio adapter SYBA SD-CM-UAUD for 8$. Notice however the Asus router only supports USB 1.1 which is enough for audio, WL-500GP v2 can be used for USB 2.0. The router has a Broadcom BCM5354KFBG SoC CPU running at 200Mhz, 4MB flash and 16MB SRAM.

The most important part of the project is hacking the WL-520GU. Since it is just a router you will need to write new firmware to turn in into a wifi radio. This is done on the serial port which is pretty easy to access. The chosen open source Linux distribution that supports this router was OpenWRT. In the link you will find a precompiled image, thanks to the designer and builder of this project.

The LCD interface communicates with the WL-520GU by serial using ATmega168 microcontroller. On one of the analog inputs of the Atmel a potentiometer is connected and rotating the pot will make the radio jump to next station.

This is really an advanced project and i just love how it turned out. Lots of information on how to build one yourself is available in the link and I’m sure if you decide to go for it you will not regret it.

DIY Wifi Radio: [Link]

Most of us started the embedded programming by blinking a led, and reading a simple input from a push button, which was the correct way to do it, step by step.  I already explained the importance of pull-up(down) resistors in a previous article, but now lets take a closer look at the actual digital input and output handling.

Lets start at the input reading, more experienced programmers use the terms bit masking, yes that sounds great but what is it, you probably wondered. In other words bit masking means that only the relevant bits are considered the others are disregarded.

At this moment consider the micro controller input as a simple 8bit variable PINB which can hold any value from 0-255, and we have connected the led and push button like this:

Simple led

We have the input and output on the same PORTB, we must read the PB5 pin and control the PB0 pin, after configuring the direction of those pins we must check the state of the PB5 pin, which is the number 5 bit in our 8bit variable, since we are interested only about PB5, the other bits doesn’t hold relevant information. How to check only the 5th bit? Some basic Boolean algebra knowledge is needed here:

and or table

By masking the irrelevant bits we can focus only to the input we are interested about, for this the AND operation is needed, the PB5 is the 5th bit, so if we clear all the other bits and leave the 5th “unharmed” we have the useful information, this is made with:   PINB&0b00100000 (& is the bit level and operation in C, ob0010.. is the binary representation ), if the 5th bit was 1 then the result will be 0b00100000, if not then the result is 0b00000000(just zero). When we put (PINB&0b00100000) into a condition, like if(PINB&0b00100000) the only bit that will count is the 5th, which is what we want, the other bits won’t matter.

Now you will say, that if() expression looks “ugly” and you are right, it isn’t easily readable and has a great potential for typo error, the other way to reference that binary number is this: (1<<5) 1 shifted to left by 5 position, so if(PINB&(1<<5)) will give the same result, and the compiler sees no difference. If you look at that condition you see instantly which bit is checked, the typo error possibility is also greatly reduced.

Some of you might say that these are a lot of operations, first to read the value than make the and operation then check the result and this will increase the program size, well most of the micro controllers have special assembler instructions for bit level testing, and the C compilers are clever enough to use them, so that if statement will result in only one line of assembler code, although make sure to activate the size optimization of your compiler!

Now lets see how to control the digital port output bit by bit, the LED is connected to PB0, we must change only that bit and leave the rest unchanged, imagine the case when you have other components connected to the other pins, you certainly don’t want to bother them.

PORTB |= 0b00000001;  //this line will only set (one) PB0 pin  PORTB &=0b11111110;  //this line will only clear (zero) PB0 pin

Those lines of code are really ugly and you should avoid this programming style, the equivalent is like this:

PORTB |= (1<<0); //set bit   PORTB &= ~(1<<0);  //clear bit, the ~ operator is the bit level negation

Both operations reference the actual value of the port and with the logical operations the other bits remain unchanged. To further improve the code styling I recommend the use of macro’s, for example:

#define IS_BIT(a,p)    (a&(1< #define SET_BIT(a,p) a |=  (1< #define CLR_BIT(a,p) a &= ~(1<

Now our if statement will look like this if(IS_BIT(PINB,5)) and the PB0 control like this SET_BIT(PORTB,0); CLR_BIT(PORTB,0);  Again don’t worry about the program size, because the micro controller has dedicated assembler instruction for setting or clearing just one bit, and the compiler will use that.

Learn to master the bit level operations because in embedded programming it is crucial, especially for digital I/O handling.

In the next article I will explain how to use this technique with 7 segment display and matrix keyboard.

© 2007-2011 YourITronics | Any logo, trademark and project represented here are property of their respective owners | Wordpress | Privacy Policy    RSS