Slug Radio: Internet Radio with NSLU2 / arduino

Discussion about my Wifi Radio project at http://mightyohm.com/wifiradio/ or my WL-520gU talk at NOTACON.
Schwabinger
Posts: 49
Joined: Sat Dec 04, 2010 12:04 am
Location: Munich, Germany

Slug Radio: Internet Radio with NSLU2 / arduino

Post by Schwabinger »

Inspired by Jeff's wifi radio, I started my project using a nslu2 "slug" as the basis for an internet radio a few weeks ago.

I wanted to build a tuning device so I could listen to radio without using any pc, monitor or keyboard.
  • - Tuning as well as setting the volume should be done the old fashioned way by turning a knob.
    - Seeing the station name on a display would be nice, but not a must
    - Device should have a built in amp with a speaker (sound quality not important at the beginning)
This is how the "Slug Radio" looks at the moment:

http://www.flickr.com/photos/rigasw/set ... 708689711/

OS installation
===============

I installed SlugOS 5.3 beta on a 4 GB stick (excellent description on how to do that in unslung.org: http://www.nslu2-linux.org/wiki/SlugOS/ ... ugOSSystem)
Installed a Delock USB 7.1 sound adapter (12,- Euros); this soundcard on a stick has only enough power for headphones; so later in the project I built an amp based on IC LM386
Made soundcard work: http://www.nslu2-linux.org/wiki/HowTo/SlugAsAudioPlayer
Installed MPD and MPC (mpc is from an "optware feed". See last step of the os install docu above)
Configured xinetd service "podcast-bounce", so I can add stations in the "m3u" or "pls" syntax. Excellent solution!
(http://mpd.wikia.com/wiki/Hack:podcast-bounce)

Filling the playlist
====================

The following web site lists a lot of international radio stations that broadcast over the web.
So I searched for my favourite stations that provide m3u or pls URLs.

http://www.listenlive.eu/index.html

The string "http://linksys:8082/?feed" is part of the proxy "podcast-bounce":

mpc add http://linksys:8082/?feed=http://www.dr ... ng/dlf.m3u
mpc add http://linksys:8082/?feed=http://www.dr ... kultur.m3u
mpc add http://linksys:8082/?feed=http://www.dr ... wissen.m3u
mpc add http://linksys:8082/?feed=http://stream ... ern1_1.m3u
mpc add http://linksys:8082/?feed=http://stream ... uell_1.m3u
mpc add http://linksys:8082/?feed=http://www.bb ... /eneuk.pls
mpc add http://linksys:8082/?feed=http://live-t ... eradio.m3u
mpc add http://linksys:8082/?feed=http://stream ... p3_128.m3u # DRS4 News live
mpc add http://linksys:8082/?feed=http://www.ra ... ve/mp3.m3u # Radio Swiss Jazz
mpc add http://linksys:8082/?feed=http://www.wd ... rtmund.m3u # WDR 2 Ruhrgebiet
mpc add http://linksys:8082/?feed=http://yp.sho ... id=1002362 # Old Time Radio
mpc add http://linksys:8082/?feed=http://stream ... ssik_1.m3u
mpc add http://linksys:8082/?feed=http://stream ... ern2_1.m3u
mpc add http://linksys:8082/?feed=http://stream ... ern3_1.m3u
mpc add http://linksys:8082/?feed=http://www.ei ... nslive.m3u
mpc add http://linksys:8082/?feed=http://newsta ... listen.pls # Newstalk Irland
mpc add http://linksys:8082/?feed=http://mp3str ... listen.pls # ORF info radio
mpc add http://linksys:8082/?feed=http://sc19.a ... 3_w50a.m3u # Nordwestradio
mpc add http://linksys:8082/?feed=http://s8.med ... listen.pls # Radio Luxemburg
mpc add http://linksys:8082/?feed=http://www.li ... /90elf.m3u
mpc add http://linksys:8082/?feed=http://82.201 ... 10Gold.m3u
mpc add http://linksys:8082/?feed=http://www.wn ... eam/fm.pls
mpc add http://linksys:8082/?feed=http://www.wo ... fm.mp3.m3u


That makes a playlist of 23 stations.
To listen to one, one has to enter:

mpc play nn

Connecting the hardware
=======================
To use the serial interace on the nslu2's board, one has to solder three pins in the right postion.

The description is here:

http://www.nslu2-linux.org/wiki/HowTo/AddASerialPort
My friend Matthias did that for me ...
As the slug and the arduino operate with different voltages you need a voltage divider with two resistors as used and described in Jeff's WiFi radio.


Setting up the arduino
===================
Arduino's analog pins 0 and 1 are connected to two 10K pots.

One pot is for setting the volume, the other for selecting the station.

Every second arduino sends a 4 character digit over the serial port to the slug; the first two digits represent the station, digit three and four the volume:

Code: Select all

 // map is used to convert the 1024 pot values into chunks of 1024 / numbStations
  
  int tunerValue = map(sensorValue, 0, 1023, 1, numbStations);

// Value 80 is more than enough
  int volValue =map(volumeValue, 0, 1023, 0, 80);


// send tuner value and volume in one line
// seperate with command "cut" in linux
// fill up with a leading zero if tunerValue or volValue < 10
// so we send always four digits to the slug

  if (tunerValue < 10) {
    Serial.print(0);
  }
    Serial.print(tunerValue);
 if (volValue < 10) {
    Serial.print(0);
  }
    Serial.println(volValue);
LED tuning indicator
=================
I did a first successful test with a 2x16 lcd display; but till I have done all the wiring in a neat way, I live with a simple one led tuning indicator:

When pressing a pushbutton, a blinking led signals the number of the current station.
(Numbers from 1 to 4 are signalled with a short blink, the five is displayed with
a long blink.)

Code: Select all

/* LED as tuning indicator

Number of selected station is signaled using one led and a push-button:

Numbers from 1 to 4 are signalled with a short blink, the five is displayed with 
a long blink:

example:

Long - Long - short - short - short - short signals: Station 14

For the remainder the modulo function is used.
*/    

 NofFive = tunerValue / 5;
 NofRemainder = tunerValue % 5;
 
 buttonState = digitalRead(buttonPin);

if (buttonState == HIGH) {
 delay(400);
 int i;
 for (i=0; i < NofFive; i++) {
   digitalWrite(ledPin, HIGH);
   delay(400);
   digitalWrite(ledPin, LOW);
   delay(600);
 }
 
 for (i=0; i < NofRemainder; i++) {
   digitalWrite(ledPin, HIGH);
   delay(200);
   digitalWrite(ledPin, LOW);
   delay(200);
 }
}
Activating the serial interface on the slug
===================================
The only way that I found to activate ttyS0 on the slug was using "minicom" which is sent in the background using command "screen".
The following script loops till we get a value greater 99 via the serial port.

That would mean a value between 0100 and 2390

0100: Station 01, volume 00
2390: Station 23, volume 90

when we get a proper input, the loop ends and the script "testinterface.sh is started.

Code: Select all

#!/bin/sh
# set -x
case "$1" in
  start)

/bin/beep -r 5
inputline=99
       until [ $inputline -gt 99 ]
    do
/bin/kill -9 $(pidof SCREEN)
/bin/sleep 20
/usr/bin/screen -d -m -L /usr/bin/minicom
/bin/sleep 15
inputline=$(head -n 1 < /dev/ttyS0)
/bin/beep -r 1
   done
/bin/beep -r 3
while true
do
nice -n -20 /root/testinterface.sh
done
 exit 0
;;
  stop)
echo -n "stopp das Ding"
killpid=$(/bin/cat < /root/pid_of_interface)
/bin/kill -9 $killpid
kill -9 $(pidof minicom)
/usr/bin/screen -wipe
/bin/sleep 10
;;
esac
exit 0
~
~
"Testinterface.sh" is an adapted version of Jeff's interface.sh script.
"cut" is used, to extract the values for volume and station.
When you change the station, this is indicated by a very short beep ...
mpc is called, whenever either the volume or the station value changes:

Code: Select all

# Some configuration settings
# set -x

VOLUME=50
oldvol=50
trap 'kill $! ; exit 1' SIGINT  # exit on ctrl-c, useful for debugging
                                # kills the display.sh process before exiting
echo $$ > /root/pid_of_interface

# mpd setup
/opt/bin/mpc -q volume $VOLUME      # adjust this to suit your speakers/amplifier
oldstation=1    # var to keep track of what station we're playing


while true      # loop forever
do
   inputline=99 # clear input

   # Loop until we get a valid tuner position from arduino
     until [ $inputline -gt 99 ]
   do
    inputline=$(/usr/bin/head -n 1 < /dev/ttyS0)
   done

# echo "Inputline: " $inputline 

VALUE=$(echo $inputline | /usr/bin/cut -c 1-2) # strip out the station part
# echo "vALue: " $VALUE


VOLUME=$(echo $inputline | /usr/bin/cut -c 3-4) # strip out the vol part

#echo "vOOlume: " $VOLUME

if [ "$VOLUME" -ne "$oldvol" ]
then
/bin/beep -f 6000 -l 30
/opt/bin/mpc -q volume $VOLUME
oldvol=$VOLUME
fi

   # if station has changed, we need to change position in the playlist

   if [ "$VALUE" -ne "$oldstation" ]
  then

# jetzt=$(/bin/date)
#echo $jetzt >> /root/played
#echo $VALUE >> /root/played
/opt/bin/mpc -q play $VALUE 2>> /root/mpc_log
/bin/beep -f 9000 -l 30
fi
oldstation=$VALUE 
#echo $oldstation >> /root/played
done
LM 386 based Amp
================
I built a very simple amp, based on a LM386, 4 capacitors and a resistor.
It amplifies the volume by 20.
The sound coming out of the 0,5 watt speaker is not hifi quality .. but good enough for this project.

The amp is powered by arduino's 5 volt exit, so no additional battery is needed.

Still open / unsolved
==================
  • - Before you boot, you have to switch the cable, that goes from arduino's TX to slug's RX to gnd. Otherwise the slug will not boot (described in AddASerialPort above).
    - I never tried the serial way back from the slug to arduino. When I used the 2x16 lcd display, it showed the station names, that I had put in the arduino code
    - Stick sometimes needs several minutes to boot. dmesg says "fs successfully recovered". I did a fsck on a linux box; the file systems seems to be ok.
    - every second you hear a click from the serial port, that is cought by the amp ... may be I can improve the shielding.
User avatar
mightyohm
Site Admin
Posts: 1064
Joined: Fri Apr 03, 2009 10:29 pm
Location: Seattle, WA
Contact:

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by mightyohm »

The audio amp in my wifi radio is noisy too. It picks up all sorts of noise, mostly from the wireless. It's quiet enough that you don't hear it unless no station is playing. It's on my "fix someday" list. :D

The serial port issue is interesting. Have you tried adding a 3K resistor as mentioned at
http://www.nslu2-linux.org/wiki/HowTo/AddASerialPort
Connect a 3K resistor between pins one and two of the serial port pads on the SLUG and the problem will go away. Any TTL level driver can drive into 3K yet the resistance is low enough to prevent AC pick-up.
Schwabinger
Posts: 49
Joined: Sat Dec 04, 2010 12:04 am
Location: Munich, Germany

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by Schwabinger »

I was so happy that we finally got the three pins soldered to the slug's board (without breaking it)... so I did not dare to solder the resistor on the board.
I consider getting one more slug on ebay and try it with this machine.

An idea for a solution is to read serial input that comes from the slug to arduino (this line is in place from the beginning of the boot process.). If the slug sends a first "ping", arduino could use that as a signal to switch the one wire from Gnd to TX (Could that be done with a transistor??)

The little tick every second from the built in speaker is not too loud; sounds like a little machanical clock.

I uploaded a little movie that shows the Slug Radio in action:

http://www.flickr.com/photos/rigasw/536 ... 708689711/

Thanks for your help!

Schwabinger
User avatar
mightyohm
Site Admin
Posts: 1064
Joined: Fri Apr 03, 2009 10:29 pm
Location: Seattle, WA
Contact:

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by mightyohm »

Looks like it's working great. :-)
Schwabinger
Posts: 49
Joined: Sat Dec 04, 2010 12:04 am
Location: Munich, Germany

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by Schwabinger »

Some improvements for the slug radio:

Station lock
==========
in the meantime I have more than 30 stations on my list. So it happens from time to time that it toggles between two stations; the more stations I will add, the more often this problem will occur.

So I implemented a button that sets a station lock. As soon as the button is pressed, the tuner value that is sent to the slug, cannot change any more.

Code: Select all

// Switch between normal and freeze mode:

buttonFreezeState = digitalRead(FreezeButtonPin);

switch(programState) {
  case NonFreezeMode:
  if (buttonFreezeState == HIGH) {
     digitalWrite(FreezeLedPin, HIGH);
    programState = FreezeMode; }
  break;
case FreezeMode:
  if (buttonFreezeState == HIGH) {
     digitalWrite(FreezeLedPin, LOW);
    programState = NonFreezeMode;
  }
  break;
  
  default:
  programState = NonFreezeMode;
  break;
}

..

  
if (programState == NonFreezeMode) {
  tunerValue = map(sensorValue, 0, 1023, 1, numbStations);
 }
 


Podcasts on the slug
=================
In additon I made use of the ability of "podcast-bounce" (see above) to play modcasts with mpd / mpc.
Padcast stations are added to the playlist in this format:

Code: Select all

mpc add http://linksys:8082/?feed=http://www.br-online.de/podcast/b5-fuer-bergsteiger/cast.xml # P: B5 Bergsteiger
mpc add http://linksys:8082/?feed=http://www.br-online.de/podcast/funkstreifzug/cast.xml # P: B5 Funkstreifzug
stefan
Posts: 6
Joined: Sun Jan 30, 2011 3:08 pm

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by stefan »

Another alternative to your station lock would be to use a rotary encoder (http://www.sparkfun.com/products/9117). If you kept track of your last station and worked out whether you had incremented forward or backward there would be no way for the station to toggle. Would require a number of digital pins as opposed to one analog, however.

Alternatively, a capacitor between your analog input and ground will help clean up the signal and may reduce noise enough that the station lock become unneccesary. Try a 47uF or so. The larger the value, however, the longer it will take to change stations - this also depends on the value of potentiometer you are using. I would experiment with values until you get an acceptable speed / toggling response. This won't stop the problem getting worse with more stations, however, which the rotary encoder would.

Stefan
Schwabinger
Posts: 49
Joined: Sat Dec 04, 2010 12:04 am
Location: Munich, Germany

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by Schwabinger »

Hi Stefan,

the idea with the rotary encoder sounds promising! (But actually the skipping problem only exists on both ends of the pot's range .... it is supposed to be linear ... but on both ends you have to turn a much longer way till you reach the next station, compared to a middle-postion!)

Another simple software solution could be the implementation of different groups: one group for news stations, one for classical music, one for other music, one for podcasts .... with a simple push-button one could select the group that one wants to hear.

And:

My SlugRadio (aka "Sluguino") has a display now :-)

http://www.flickr.com/photos/rigasw/540 ... 708689711/

Stay tuned!

Schwabinger
Schwabinger
Posts: 49
Joined: Sat Dec 04, 2010 12:04 am
Location: Munich, Germany

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by Schwabinger »

SlugRadio has a programable push button now. Now I can find my favourite station even faster.

Pressing a push btton saves the current station number in EEPROM.

This is part of the code:

Code: Select all

buttonState = digitalRead(buttonPin);

switch(StationKeyState) {

  case NonStationKeyMode:
 
  // you have to be in freeze mode;  then pressing the station button will save the current station value im eeprom.
  if (buttonState == HIGH & programState == FreezeMode) {
   digitalWrite(ledPin, HIGH);
   delay(300);
   digitalWrite(ledPin, LOW);
   EEPROM.write(0, tunerValue);
   
}
   // pressing the station botton in regular operation will get the station value from eeprom.
   if (buttonState == HIGH) {
   tunerValue = EEPROM.read(0);
   StationKeyState = StationKeyMode; 
    digitalWrite(ledPin, HIGH);

  }
   break; 
 
case StationKeyMode:
  if (buttonState == HIGH) {
     StationKeyState = NonStationKeyMode;
     digitalWrite(ledPin, LOW);
  }
     break;
  
    
  default:
  programState = NonStationKeyMode;
  break;
}
Next I will try a ShiftIN register to handle 8 buttons.

Schwabinger
Schwabinger
Posts: 49
Joined: Sat Dec 04, 2010 12:04 am
Location: Munich, Germany

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by Schwabinger »

Now we have 8 pushbuttons handled with a shiftIn register:

Image
8 Pushbottons by RigasW, on Flickr

The green buttons are used to address favourite stations. Red and yellow are still unused.

What I soon will try is a pause button for podcasts.

Greetings

Schwabinger
User avatar
mightyohm
Site Admin
Posts: 1064
Joined: Fri Apr 03, 2009 10:29 pm
Location: Seattle, WA
Contact:

Re: Slug Radio: Internet Radio with NSLU2 / arduino

Post by mightyohm »

Nice work! :D

Do you have an updated schematic?
Post Reply