davidfindlay.org

a man, a plan, a cake: nirvana

iPod Remote

3/2/2010 UPDATE: See update post.
4/14/2010 UPDATE: See here if you have a v1.4 PodBreakout board.

UPDATE:
Better photos up on Flickr.

I've been desperately short of Arduino play time in the last few months, but I did finally find time to finish my Arduino-based iPod remote (well, version 1.0 of it anyway). My remote has a single button that toggles between Play and Pause on the iPod. I wanted one like that for my car so I could easily pause my iPod Touch without having to: find it, unlock it; find the touch-screen pause button; and finally, pause it.

So how to go about this?

Well, the iPod dock connector actually exposes a serial connection to the iPod. You can see this on the pinout, the best online version of which I found on pinouts.ru. This serial connection can be used by docks, or in my case an Arduino, to interact with the iPod. The iPod speaks AAP on its serial port: the Apple Accessory Protocol. There are several modes in AAP that you can interact with an iPod over serial in, but Simple Remote (mode 0x02) is by far the easiest, as it has no responses to deal with. Simple Remote mode allows you to play and pause the iPod, change tracks, adjust the volume and so on. Since that covered my needs it's what I implemented first. (I've also implemented part of Advanced Remote (mode 0x04) as we'll briefly see later.)

With the pinout and protocol documentation in hand I ordered a couple of cheap iPod charging cables to hack on. However, when they arrived I realized that my soldering skillz were nowhere near good enough to make the connections I was going to need. Luckily I am not the first person to have this problem, and SparkFun has the solution: the PodGizmo breakout board:

PodGizmo

The PodGizmo has connections to all the pins on the dock connector and gives you through-holes to solder things onto: perfect!

I proceeded to hook up wires to the serial I/O pins (12 and 13), serial ground (11) and to pin 21: the rather curious-sounding "Accesory Indicator / Serial Enable" pin. The level of resistance between this pin and ground apparently tells the iPod what kind of accessory it is connected to. Since I wanted to use the serial interface, I went with a 500kOhm resistor, to select the "related to serial communication / used to enable serial communications Used in Dension Ice Link Plus car interface" mode.

With my connections made, I was about to hook it up to my Arduino, but then I remembered that the serial output of the Arduino is 5V. I wasn't sure what the iPod wanted but I guessed it probably only wanted 3.3V. I didn't know what to do, so I googled around for a bit looking at various level-shifting solutions. Some you could make from a few components but I was concerned they wouldn't be able to switch fast enough to get a good serial signal. Luckily, during my googling I came across another SparkFun gem: the
BOB-08745 Logic Level Converter.

Logic Level Converter

This little guy lets you talk serial (or I2C, SPI, etc) at one voltage on one side and another voltage on the other side. Again: perfect!

So with the level converter added to the mix, I was ready to hook it up to the Arduino.

Of course, hooking up wasn't going to do much without some code to talk Apple Accessory Protocol, so that was the next task. I wrote an Arduino library for the parts of the Apple Accessory Protocol that I was going to need, and a bit more besides. I posted it on
github in case anyone else wanted to use it. It comes with a couple of example sketches: a play/pause one using Simple Remote mode (wonder where I got that idea from); and one for Advanced Remote mode that pulls back information for the track that the iPod is currently playing. The latter could form the basis of an Arduino-based dock that showed track information on an LCD display, for example.

Here's the example Simple Remote sketch. I'm using almost exactly this for my remote, the only difference being that I'm using an active-low on my switch with the Arduino's internal pull-up to avoid having an external resistor for the switch:



During development I used an
Arduino Mega so that I could have a real serial port for the iPod and a real one for debugging messages. I probably could just have used the SoftwareSerial library with a regular Arduino for debugging, but since I had the Mega around, I used it. My library defaults to having debugging messages disabled, but you can configure it in your setup() method to route those messages to any serial port you like.

Once I had it working to my liking I transferred the sketch over to an
Arduino Nano, since it would fit in an Altoids tin (of course). This is what it looked like at this point:

iPod Serial - Tidied Up

You can see I'm just using a simple push button for the play/pause action. The Nano is sitting on a little breadboard and you can just see the resistor I have connected to pin 21. I probably should have just put the resistor on the PodGizmo breakout board, but I didn't.

Next came testing it with my iPod Touch:

Testing

Everything checked out, so next I switched out the little button for a REALLY BIG BUTTON:

Easy Button Installed

As you can see it's an Easy Button from Staples; I just took out the Easy Button's batteries, soldered wires to either side of its switch, and routed them out through the hole conveniently left by the battery lid. The Nano is sitting on an Altoids tin at this stage, but it's not yet
in the tin. That came next, thanks to Mr Dremel:

Dremeling Done

I took it out to the car, hooked up the Nano's USB cable to my USB car adaptor (similar to
this one on Amazon, but you can get them lots of places), and tried it out. It worked pretty well, but there was one problem: I was still using a cable to connect the headphone socket on the iPod to the line-in jack on my car. The audio wouldn't go out the headphone socket unless I plugged the dock cable in first and then the headphone cable. As you've probably realized by this point, it was completely stupid of me to still be using a headphone cable: the dock connector has connections for line out! Having caught up with my smarter readers, I took the remote into the lab at work and add hooked up the line-out cable. This gives me true line out instead of the volume-adjusted headphone output, saves wear and tear on the headphone socket on my iPod, and avoids the what-to-connect-first problem, as there's only one thing to connect.

So how does it work? It works great, thanks! The only real quirk I've noticed is that when I first connect it, my 2G iPod Touch will play audio out of its internal 'speaker' for a couple of seconds before realizing that it's connected to the dock and switching over. It even pauses the iPod when I turn off the car, presumably because the iPod sees the dock go away when the Nano loses power.

No doubt someone will point out that the Nano is a gazillion times overpowered to do a couple of serial I/O sequences, and they'd be right. But: I already had the Nano anyway; and I plan on expanding the remote soon (dash-mounted,
arduinix-powered, nixie tube track status action anybody?).

Django Time

I was back home in Scotland in June and my dad happened to mention a problem he was having at work: he does forensic computer analysis and had written a case tracking system for his department in Access. However, the data model wasn’t normalized and he was finding it difficult to extend it to meet their growing needs. I’m not familiar with Access but I poked around a bit and did some googling, and it seemed like we could get it to at least support a couple of his desired changes, but it wasn’t going to be pretty.

It got me to thinking though, and when I got back to the States, I decided to try out re-implementing the system using Django. Django is a web framework for Python, and I had been meaning to find time to try it out for a while. You define your data models as Python objects and Django handles the ORM to get your data in and out of a database. It also provides APIs to query and manipulate the data easily from Python, and templating to help you display data in web pages.

I won’t presume that I could describe Django better than its authors, however, so here’s its features lifted straight from djangoproject.com:

Object-relational mapper
Define your data models entirely in Python. You get a rich, dynamic database-access API for free — but you can still write SQL if needed.
Automatic admin interface
Save yourself the tedious work of creating interfaces for people to add and update content. Django does that automatically, and it's production-ready.
Elegant URL design
Design pretty, cruft-free URLs with no framework-specific limitations. Be as flexible as you like.
Template system
Use Django's powerful, extensible and designer-friendly template language to separate design, content and Python code.
Cache system
Hook into memcached or other cache frameworks for super performance — caching is as granular as you need.
Internationalization
Django has full support for multi-language applications, letting you specify translation strings and providing hooks for language-specific functionality.

What particularly attracted me to Django is its amazing out-of-the-box administration interface. Django was developed in a news room environment, so they put together a pretty full-featured administration interface that lets journalists enter news articles, mark them for display on the newspaper’s public pages, and so on. The public-facing part of the site then uses Django’s template system in conjunction with is MVC framework to retrieve and present the data entered via the admin interface.

In my use case, the system would only be used by a small number of people, all of whom would have at least some form of administrative access. So, I figured I could get a pretty usable system without having to do any ‘webby’ stuff at all. And that’s been pretty much my experience: the bulk of the system is in two Python source files: one that defines the data model; and one that customizes the administration interface.

Django works with multiple databases, including SQLite, for which I have a definite soft spot. It also comes with a for-development web server built-in. Given the small number of users, I hoped that I could use SQLite and the built-in web server for the final version, thereby saving my dad from having to install and maintain database and web servers. The built-in server isn’t meant to be used in production, but we’ll see how it does. The system doesn’t have enough run time on it yet, but if it proves unreliable then switching to a full web server won’t be too painful. I don’t foresee SQLite being a bottleneck, but if it does we can switch it to MySQL or Postgres or something, although I’d need to convert the data to do that probably.

The Django site has an excellent four-part tutorial that walks you through most of its aspects. It was certainly enough to get me going. The online documentation for the APIs is also very good. It didn’t take long at all to get a proof-of-concept up and running for my dad to try out. We used basecamp to keep track of things as we worked through the nitty gritty of the design, git to track the source, and a couple of Django sites at my web host so my dad could play with the system as it came together (kudos to Andrew at dreamhost for helping me get Passenger WSGI going with Django by the way).

In just a few weeks of working on it spare time the system is up and running, complete with a couple of reports (HTML and CSV) and some features not envisaged at the outset (ain’t that always the way?). I even wrote an importer that took the old cases from Access via a CSV file and imported them into the new one, using Django’s model classes so that I didn’t even have to write a single INSERT statement.

If you're a pythony sort of person then I highly recommend taking a look at Django for your next webby projecty thingy.

Sample Screen Shot