Driverless Infrared Receiver for your Apple Remote with Arduino.

Since I’m an (Mac) OS X lover but also a broke student, my main workstation is a Hackintosh.
I’m mostly using this computer to listen music, and was quite disappointed about the fact it could not be used with my Apple Remote. So I ordered on eBay an IR Receiver from China, thus I had to wait about two or three weeks before it arrives in my mailbox.

Then, I saw my supernumerary Arduinos on my desk. Three Nano, one Mega. I also had an IR Receiver. So i came straight to the idea I could do it all by myself. So was born this project.

This page gave me the schematics and the library to convert Arduino into an HID device. After reading the HID documentation, I understood the usbkeyboard library won’t fit for this usage as the play/pause, next track, and volume functions were defined in the « Customer Device » HID specs page, while the library was configured as a keyboard device. It was a real pain in the ass to understand only with HID official documentation, but thanks, I found this page.

Using « HID Descriptor Tool » (and some hand tweaking…) I made my own HID descriptor, as follow :

PROGMEM char usbHidReportDescriptor[31] = { // USB report descriptor
0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
0x09, 0x06,                    // USAGE (Keyboard)
0xa1, 0x01,                    // COLLECTION (Application)
0x05, 0x0c,                    //   USAGE_PAGE (Consumer Devices)
0x09, 0xcd,                    //   play/pause
0x09, 0xe9,                    //   volume up
0x09, 0xea,                    //   volume down
0x09, 0xb5,                    //   next track
0x09, 0xb6,                     // previous track
0x09, 0xec,                      // mute
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x95, 0x06,                    //   REPORT_COUNT (6)
0x75, 0x01,                    //   REPORT_SIZE (1)
0x81, 0x02,                    // INPUT (Data,Var,Abs)
0xc0

};

This goes to the usbKeyboard.h file, and you’ll have to correct the descriptor size constant in the usbconfig.h file of your library.
Just a few explications :

The first two lines describes the device as a keyboard, then there’s a collection of the device capabilities in the Consumer Device page, which defines controllers for multimedia devices.

Those lines are important :

    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x95, 0x06,                    //   REPORT_COUNT (6)
0x75, 0x01,                    //   REPORT_SIZE (1)

It defines that each values will be defined on a single bit on a six bits buffer, in the order we defined before.
For instance, the buffer 0b00000001 will send a play/pause command, and 0b00000100 will send a volume down command.

I had modify a few lines in the usbkeyboard.h library file. The sendKeyStroke functions must be like that :

 

void sendKeyStroke(byte keyStroke, byte modifiers) {

while (!usbInterruptIsReady()) {
// Note: We wait until we can send keystroke
//       so we know the previous keystroke was
//       sent.
}

memset(reportBuffer, 0, sizeof(reportBuffer));

reportBuffer[0] = keyStroke;

usbSetInterrupt(reportBuffer, sizeof(reportBuffer));

while (!usbInterruptIsReady()) {
// Note: We wait until we can send keystroke
//       so we know the previous keystroke was
//       sent.
}

// This stops endlessly repeating keystrokes:
memset(reportBuffer, 0, sizeof(reportBuffer));
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));

}

 

And then, from arduino, to send, by instance, a previous track command :

                  UsbKeyboard.sendKeyStroke(8);

If you did not follow, 8 in binary is 2^3, so it will send the third command (starting form 0), which is, according to my custom HID descriptor, previous track.

With this method, I can send any command to my computer. Since it’s considered as an HID device, no drivers are required!

But then, came the second problem… The IR library uses timer… and so does the AVR-USB libray!
I took a few hours to rewrite the IR library to use ATMega’s timer1, which was not used by the AVR-USB Libray.
But then, tests showed me that the ATMega, with its 16Mhz frequency, can not be constantly interrupted by those two libray.

That’s why my project uses in fact, not only one, but two Arduino nano! One to receive the IR command, the other one to receiver them using the digital pins, and them them to my Hackintosh… and it works flawlessly!

I was about to solder the circuit when I finally received the IR Receiver from China, which costed about 13$, when my circuit, with its two Arduinos and miscellaneous components costed between 35$ and 45$. So I decided to use the the made in China thingie to save up my Arduino nano. With Twisted Melon’s Mira software, my Apple Remote can also put my computer to sleep, switch applications, work with my self-made Last.FM client and so on…

But anyway, it was a cool project : I played with the HID standard, timers in ATMega, Zener diodes, infrared command…

If you’re even more interested in this project, here are the codes, you’ll be able to guess the circuit layout. When I stopped working on it, everything was functional, but there surely is some useless functions since it’s like I’m still working on it.

IR Receiver picture

 

Cet article a été publié dans Arduino. Bookmarker le permalien. Laisser un commentaire ou faire un trackback : URL de trackback.

Laisser un commentaire

Votre e-mail ne sera jamais publié ni communiqué. Les champs obligatoires sont indiqués par *

*
*

Vous pouvez utiliser ces balises et attributs HTML <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>