{"id":114,"date":"2013-03-19T00:07:04","date_gmt":"2013-03-19T00:07:04","guid":{"rendered":"http:\/\/www.nicassio.it\/daniele\/blog\/?p=114"},"modified":"2014-11-04T20:45:07","modified_gmt":"2014-11-04T20:45:07","slug":"building-a-raspberry-pi-car-radio","status":"publish","type":"post","link":"http:\/\/www.nicassio.it\/daniele\/blog\/?p=114","title":{"rendered":"Building a Raspberry PI Car Radio"},"content":{"rendered":"<p>Today i&#8217;m going to write about my new project, a Raspberry PI powered radio car. For now it can provide only basic functionalities, but it can be easily improved by upgrading the software, on which i didn&#8217;t focus very much so far.<\/p>\n<dl class=\"wp-caption alignnone\" id=\"\" style=\"width: 1155px;\">\n<dt class=\"wp-caption-dt\"><\/dt>\n<\/dl>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone\" alt=\"\" src=\"https:\/\/lh3.googleusercontent.com\/-FvzM728uzLo\/UUYOb1hG-kI\/AAAAAAAAH0E\/c-jtuNIMGGo\/s1145\/20130317_192703.jpg\" width=\"687\" height=\"515\" \/><\/p>\n<p>In this post i will explain how I configured the PI to accomplish the task.<\/p>\n<p><strong><\/strong><strong>What I used in this project?<\/strong><\/p>\n<ul>\n<li>a Raspberry PI<\/li>\n<li><span style=\"line-height: 1.714285714; font-size: 1rem;\">a standard 16&#215;2 character LCD display (HDD44780 compatible)<\/span><\/li>\n<li>usb speakers<\/li>\n<li>a button<\/li>\n<li>a wheel from an old mouse<\/li>\n<li>a box<\/li>\n<\/ul>\n<p><strong><\/strong><strong>The idea<\/strong><\/p>\n<p>The idea is to make a car radio capable of playing music from a usb pen plugged in the PI. My radio can only shuffle the songs found, but that&#8217;s just about software, it can be improved in many ways, that is where a lot of customization may take place.<\/p>\n<p><b>Getting the display working with the PI<\/b><\/p>\n<p>The first thing to do is to understand how to drive the LCD display from the PI. This is made by connecting the display to the PI&#8217;s GPIO, and then sending the commands from the programming language, usually using a library for the\u00a0HDD44780 standard.<\/p>\n<p><span style=\"line-height: 1.714285714; font-size: 1rem;\">I did this from python, but I won&#8217;t touch this part in this post because I followed <a title=\"a nice tutorial about this from Adafruit\" href=\"http:\/\/learn.adafruit.com\/drive-a-16x2-lcd-directly-with-a-raspberry-pi\/overview\" target=\"_blank\">a nice tutorial about this from Adafruit<\/a>.<\/span><\/p>\n<p>After I was able to write to the display, I wrote a little python script to print something to the display from the command line, which could be useful to write something to the lcd from a shell script later:<\/p>\n<p><code><br \/>\n#!\/usr\/bin\/python<br \/>\nfrom Adafruit_CharLCD import Adafruit_CharLCD<br \/>\nimport sys<br \/>\nlcd = Adafruit_CharLCD()<br \/>\nlcd.begin(16,1)<br \/>\nlcd.clear()<br \/>\nlcd.message(sys.argv[1])<br \/>\n<\/code><\/p>\n<p><strong>Playing music through USB speakers<\/strong><\/p>\n<p>To play music through a USB device, the PI must be configured properly. In my case, I had some operation to do before everything worked, and my speakers are still showing some problems when playing from the PI (I hear a little noise, but i didn&#8217;t search enough to tell it can&#8217;t be resolved).<\/p>\n<p>Anyway, if you want to use your PI as a car radio, you probably want the USB speakers to be the default audio device for it. You can do this by editing the\u00a0<em>\/etc\/modprobe.d\/alsabase.conf<\/em> adding the following line, or modifying the relative line if it already exists with another value (which in raspbian should be the case):<\/p>\n<blockquote><p>options snd-usb-audio index=0<\/p><\/blockquote>\n<p>I had also another problem which seemed to be quite common, and I also had to add another line at the end of that file, to avoid an &#8220;expected delay&#8221; error which I discovered running\u00a0<em>dmesg<\/em>:<\/p>\n<blockquote><p>options snd-usb-audio nrpacks=3<\/p><\/blockquote>\n<p>I choose the higher value which didn&#8217;t give me errors in the log. After modifying the file i restarted alsa with<\/p>\n<blockquote><p>sudo service alsa-utils restart<\/p><\/blockquote>\n<p>This wasn&#8217;t enough to play music through the speakers, I also had to specify the right device when i played the music with\u00a0<em>mplayer<\/em>. I had to discover the name of the device running the following command:<\/p>\n<blockquote><p>aplay -L<\/p><\/blockquote>\n<p>which gives a list of the recognized devices, from which i selected the right one, and finally got mplayer to play some mp3s:<\/p>\n<blockquote><p>mplayer -ao alsa:device=front my_music_file.mp3<\/p><\/blockquote>\n<p><strong>Usb automount and autoplay<\/strong><\/p>\n<p><span style=\"line-height: 1.714285714; font-size: 1rem;\">Now that the display is working correctly and we can play music through the speakers, let&#8217;s figure out how to handle the mounting\/umounting actions:<\/span><\/p>\n<p><span style=\"line-height: 1.714285714; font-size: 1rem;\">The next step is to configure the PI to automatically mount any usb drive plugged in. This can be done by using the <\/span><em style=\"line-height: 1.714285714; font-size: 1rem;\">usbmount\u00a0<\/em><span style=\"line-height: 1.714285714; font-size: 1rem;\">software avaiable in the raspbian repository:<\/span><\/p>\n<blockquote><p>sudo apt-get install usbmount<\/p><\/blockquote>\n<p>Now, I want to autoplay music when the usb is plugged in, so I add a custom script to the default usbmount script folder\u00a0<em>\/etc\/usbmount\/mount.d\u00a0<\/em>:<\/p>\n<p><code><br \/>\n#!\/bin\/bash<br \/>\npython \/home\/pi\/lcd\/char\/print.py \"Madre foca:<br \/>\nPlaying music..\"<br \/>\nsudo -u pi mplayer -slave -input file=\/home\/pi\/fifofile -ao alsa:device=front -shuffle $UM_MOUNTPOINT\/* $UM_MOUNTPOINT\/*\/* $UM_MOUNTPOINT\/*\/*\/*<br \/>\n<\/code><\/p>\n<p>The first command uses the python script I created before to print something to the LCD when music is starting, while the third line starts the playback.<\/p>\n<p>As you can guess, the <em>$UM_MOUNTPOINT variable contains the path to the mounted drive.<\/em><\/p>\n<p>The <em>-slave<\/em>\u00a0mplayer option is a very useful way to let you send commands to mplayer even if it&#8217;s backgrounded. It tells mplayer to read input commands from a file, but if we provide a\u00a0<em>fifo\u00a0<\/em>file instead of a normal one, mplayer will read from it only when we will write something. This allows mplayer to be controlled by writing to a file, from python, shell or whatever you prefer. To create a fifo file you should use<\/p>\n<blockquote><p>mkfifo \/home\/pi\/fifofile<\/p><\/blockquote>\n<p>If you want to know more on the <em>-slave<\/em> option of mplayer, see <a href=\"http:\/\/www.mplayerhq.hu\/DOCS\/tech\/slave.txt\">here<\/a>.<\/p>\n<p>I had to add the\u00a0<em>sudo -u pi<\/em>\u00a0part because it seemed that the user of usbmount wasn&#8217;t allowed to read from the fifo, I don&#8217;t know exactly why.<\/p>\n<p>Finally, I also created a script for the umount event, which simply killed mplayer, and placed it in the\u00a0<em>\/etc\/usbmount\/umount.d<\/em> directory:<\/p>\n<p><code><br \/>\n#!\/bin\/bash<br \/>\npython \/home\/pi\/lcd\/char\/print.py \"Music stopped.<br \/>\nI'm a super PI.\"<br \/>\nkillall mplayer<br \/>\n<\/code><\/p>\n<p><strong>Connecting the inputs: the button and the wheel<\/strong><\/p>\n<p>I&#8217;m not very good with electronics, so i won&#8217;t explain this part very deeply, also because that&#8217;s pretty basic.<\/p>\n<p>The scheme to read the state of a button should be something like this:\u00a0<a href=\"http:\/\/www.nicassio.it\/daniele\/blog\/wp-content\/uploads\/2013\/03\/20130318_214714-e1363639912560.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-120\" alt=\"20130318_214714\" src=\"http:\/\/www.nicassio.it\/daniele\/blog\/wp-content\/uploads\/2013\/03\/20130318_214714-e1363639912560-225x300.jpg\" width=\"225\" height=\"300\" srcset=\"http:\/\/www.nicassio.it\/daniele\/blog\/wp-content\/uploads\/2013\/03\/20130318_214714-e1363639912560-225x300.jpg 225w, http:\/\/www.nicassio.it\/daniele\/blog\/wp-content\/uploads\/2013\/03\/20130318_214714-e1363639912560-768x1024.jpg 768w\" sizes=\"(max-width: 225px) 100vw, 225px\" \/><\/a><\/p>\n<p>The mouse wheel should have three connectors, and it behave like two button together, with the central pin in common. The only thing to know about it is that the two &#8220;buttons&#8221; are switched on and off while you turn the wheel, but one of them is triggered a little before the other, giving you information about the direction.<\/p>\n<p>I decided to use a wheel (or two button) and an additional button to provide basic input for a &#8220;menu&#8221; structured OS for the radio, which is the minimal input for a fair usability.<\/p>\n<p><strong><\/strong><strong>Reacting to the inputs<\/strong><\/p>\n<p>The last thing to do is to react to the input of the user, writing the real &#8220;operating system&#8221; for our radio. I wrote this in python, and the interface is really minimal, providing the wheel to control the volume and the button to skip to the next song.<\/p>\n<p>As usual the code is really bad written, and it should be used only to understand how it works. I encourage you to write a real interface, you could really do anything with that.<\/p>\n<p>The script (bad written of course) is this:<\/p>\n<pre>import RPi.GPIO as GPIO\r\nimport time\r\nimport os\r\nfrom Adafruit_CharLCD import Adafruit_CharLCD\r\n\r\nlcd = Adafruit_CharLCD()\r\nlcd.begin(16,1)\r\nlcd.clear()\r\nlcd.message(\"Hello!nI'm the SuperPI.\")\r\n\r\ndef left():\r\n    lcd.clear()\r\n    lcd.message(\"Volume up\")\r\n    os.system(\"amixer set PCM 5+\");\r\n    print \"left\"\r\n\r\ndef right():\r\n    lcd.clear()    \r\n    lcd.message(\"Volume down\")\r\n    os.system(\"amixer set PCM 5-\");\r\n    print \"right\"\r\n\r\ndef pressed():\r\n    print \"pressed\"\r\n    lcd.clear()\r\n    lcd.message(\"Skipping tonnext song\")\r\n    f = open('\/home\/pi\/fifofile','w')\r\n    f.write('seek 100 1n')\r\n    f.close()\r\n\r\nGPIO.setmode(GPIO.BCM)\r\nGPIO.setup(4, GPIO.IN)\r\nGPIO.setup(18,GPIO.IN)\r\nGPIO.setup(2,GPIO.IN)\r\n\r\nlast_a = False\r\nlast_b = False\r\nlast_c = True\r\npaired = True\r\ni=0\r\nwhile True:\r\n    a = GPIO.input(4)\r\n    b = GPIO.input(18)\r\n    c = GPIO.input(2)\r\n    #print \"4: \"+str(a)+ \" 18: \" + str(b)\r\n    if c == False and c != last_c:\r\n        pressed()\r\n\r\n    if a != b and paired:\r\n        if a != last_a:\r\n            left()\r\n        else:\r\n            right()\r\n        paired = False\r\n    else:\r\n        paired = True\r\n    i+=1\r\n    last_a = a\r\n    last_b = b\r\n    last_c = c\r\n    time.sleep(0.01)<\/pre>\n<p>Note that it uses the previous created fifo to send to mplayer the command to skip to the next song.<\/p>\n<p><strong>Assembling<\/strong><\/p>\n<p>I&#8217;m sure that anyone can assemble this project better than I did. And to prove it i&#8217;ll show a picture:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone\" alt=\"\" src=\"https:\/\/lh6.googleusercontent.com\/-baAwETMPko8\/UUeHwlfJjfI\/AAAAAAAAH18\/vpmVDZJzpRI\/s1145\/20130318_222855.jpg\" width=\"1145\" height=\"859\" \/><\/p>\n<p><strong><\/strong><strong>The video<\/strong><\/p>\n<p>Here&#8217;s a little video (in italian) in which I show the (few) functionalities of the radio:<\/p>\n<p><iframe loading=\"lazy\" src=\"http:\/\/www.youtube.com\/embed\/bvHKw5pso3c\" height=\"315\" width=\"560\" allowfullscreen=\"\" frameborder=\"0\"><\/iframe><\/p>\n<p>I&#8217;m thinking, when I have some spare time, to extend its functions by attaching a webcam and trying to do something more complex, given the wide range of possibilities the PI can offer.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today i&#8217;m going to write about my new project, a Raspberry PI powered radio car. For now it can provide only basic functionalities, but it can be easily improved by upgrading the software, on which i didn&#8217;t focus very much so far. In this post i will explain how I configured the PI to accomplish &hellip; <a href=\"http:\/\/www.nicassio.it\/daniele\/blog\/?p=114\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Building a Raspberry PI Car Radio<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[13,9,1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=\/wp\/v2\/posts\/114"}],"collection":[{"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=114"}],"version-history":[{"count":1,"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=\/wp\/v2\/posts\/114\/revisions"}],"predecessor-version":[{"id":345,"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=\/wp\/v2\/posts\/114\/revisions\/345"}],"wp:attachment":[{"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=114"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nicassio.it\/daniele\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}