TinyPCRemote – An ATtiny85 Based Infrared PC remote control

Here’s a cheap way to build your own fully customisable infrared PC remote control. If you already have a suitable infrared remote control going spare you can build one of these for under £4, it will allow you to use most infrared remote controls to issue keyboard commands (single characters or a string) on your PC. Using a surplus remote control it could be used as a cheap media centre remote control with XBMC etc. or would be great for causing some mischief by covertly taking control of someone’s computer. I’ve tested it on several Linux and Windows boxes and one Mac and it has worked fine on them all so far.

At the heart is an 8 pin ATtiny85 microcontroller running at 16MHz using the internal oscillator with a Vishay TSOP31238 IR sensor handling the IR reception and USB implemented with V-USB. Each remote control button can trigger a single keyboard character or series if characters as well as meta keys such as shift and alt.

I couldn’t find any guides for using V-USB on the ATtiny85 under the Arduino environment so have detailed what I did in full here. Other than changing the default PIND, pin and timer settings the key seems to be that when using the internal oscillator like I am here it needs to be calibrated for each individual chip as the timing for USB is so critical.

Schematic and Stripboard layout

Here is the schematic for the USB infrared receiver:

and a stripboard layout:

 

Parts List:
Atmel ATtiny85-20PU Microcontroller
8 pin DIP socket
Vishay TSOP31238 IR sensor
100nF ceramic capacitor
1 x 2K2 resistor
2 x 68R resistors
2 x 3.6V Zener diodes (must be 0.5W or less)
Through hole male USB A connector
Stripboard, 18 holes by 6 rows

 

Code
You can download my TinyPCRemote code for the ATtiny85 on Github here.
You will also need: vusb-for-arduino and Tiny-tuner

 

Getting your remote control codes
To get the codes from your chosen remote control I’ve provided a sketch in the above repository that can be run on an Arduino or compatible board which will output the code on the serial monitor as each button is pressed, it’s designed so that you can just plug the IR sensor straight into the headers across Ground, D13 and D11 as shown below:

Once the sketch is loaded on the Arduino open the serial monitor at 9600 baud and press each button on your remote control in turn and you will see the corresponding code output on the serial monitor, don’t worry if the code repeats for each button press. Simply copy and paste the codes into the TinyPCRemote sketch and define the key/s that you want it to press when detected, replacing the existing definitions and duplicating as necessary for as many buttons as you need. There will be an upper limit as to how many can be configured, limited by flash and RAM, I haven’t tested to find the limit but it should allow for plenty of codes.

 

V-USB Configuration
The USB side of things is handled by V-USB, a very useful open source software-only implementation of the USB 1.1 standard for Atmel AVRs created by Objective Development. I used the vusb-for-arduino variant.

Unzip the file and copy the UsbKeyboard directory to your Arduino library location and restart the Arduino IDE if it was running. Now you need to edit a couple of files to change the port and pin numbers to be compatible with the ATtiny85.

Firstly edit usbconfig.h and under “Hardware Config” change

#define USB_CFG_IOPORTNAME D
to
#define USB_CFG_IOPORTNAME B

and

#define USB_CFG_DMINUS_BIT 4
to
#define USB_CFG_DMINUS_BIT 0

and under “Optional Hardware Config” change:

#define USB_CFG_PULLUP_IOPORTNAME D
to
#define USB_CFG_PULLUP_IOPORTNAME B

Note that we’re not actually connecting the pullup via a pin but this still needs to be set to a valid port in order to compile.

Optionally you can also change the manufacturer and device name in the following defines:

#define USB_CFG_VENDOR_NAME
#define USB_CFG_DEVICE_NAME

Finally, in UsbKeyboard.h change:

PORTD = 0; // TODO: Only for USB pins?
DDRD |= ~USBMASK;
to
PORTB = 0; // TODO: Only for USB pins?
DDRB |= ~USBMASK;

 

Programming the ATtiny85
Programming the ATtiny85 can be accomplished via an Arduino and the ArduinoISP sketch that is included in the examples section of the Arduino IDE or a dedicated ICSP device.

To program the ATtiny85 via an Arduino connect it as follows:

Arduino ATtiny85
D13 Pin 7
D12 Pin 6
D11 Pin 5
D10 Pin 1
5V Pin 8
GND Pin 4

 

Calibrating the oscillator
The timing for USB is critical and the oscillator for each individual ATtiny85 chip will almost certainly need to be calibrated, to do this download TinyTuner from here and put it in your Arduino libraries directory. You are also going to need an FTDI adapter or some other sort of serial converter so you can read the output.
Connect your ATtiny85 up to the Arduino and use the burn bootloader function of the Arduino IDE to set it to run at 8MHz by choosing the “ATtiny85 @ 8MHz (internal oscillator;BOD disabled)” board setting under Tools > board and then using the Tools > Burn Bootloader option. Note that as with the ATtiny84 this doesn’t actually burn a bootloader, all we are doing is setting the relevant fuses to configure the microcontroller, in this case we are temporarily setting it to run at 8MHz as tiny-tuner won’t run at our final 16MHz speed.
Load the “Interactive_to_Serial_with_Details” TinyTuner sketch from the tiny-tuner examples onto the ATtiny85, connect PB3 (pin 2) to RXD on the FTDI adapter and PB4 (pin 3) to TXD as well as 5V and ground.

Now open a terminal app on your PC and connect to the port of the serial adapter, eg. on linux “miniterm.py /dev/ttyUSB1“, reset the ATtiny85 and you should get a welcome message, now repeatedly press x slowly (once a second or so is fine) until you get a result like:

Copy-and-paste the following line of code at the top of setup…
OSCCAL = 0x9C

Copy the result from tiny-tuner into the TinyPCRemote sketch replacing the OSCCAL = 0x9C; line in setup() as appropriate.

 

Final Setup
Once you have entered the OSCCAL calibration value and your remote control codes along with the resulting keys you want to be entered  then you are ready to load the TinyPCRemote sketch onto the ATtiny85.

First use the burn bootloader function again to set the ATtiny 85 to 16MHz by using the “ATtiny85 @ 16MHz (internal PLL;4.3V BOD)” board setting then upload the sketch in the normal manner.

If you are testing it on a breadboard as I did when developing it then you will probably had to disconnect the connections to the Arduino for the USB to work, I got away with just disconnecting the SCK connection (wire from Arduino D13 to ATtiny pin 7/PB2).

If you now plug the the TinyPCRemote into a USB port hopefully pressing the remote control buttons will result in the corresponding characters appearing on your screen as if typed on your keyboard.

If not run dmesg and look for any errors, if everything is working you should see something like the following (I don’t know how you can view similar logs on Windows or Mac):

input: zorg.org TinyPCRemote as /devices/pci0000:00/0000:00:13.5/usb1/1-9/1-9.2/1-9.2.1/1-9.2.1:1.0/input/input18
generic-usb 0003:4242:E131.0006: input,hidraw2: USB HID v1.01 Keyboard [zorg.org TinyPCRemote] on usb-0000:00:13.5-9.2.1/input0

Note that I’ve changed the manufacturer and device names in usbconfig.h to be zorg.org and TinyPCRemote respectively.

If you get device descriptor read errors like:

usb 1-9.2.1: new low-speed USB device number 28 using ehci_hcd
usb 1-9.2.1: device descriptor read/64, error -32

then your computer is seeing the device but you probably have a timing problem. Make sure your ATtiny is set to 16MHz using the internal PLL and that you have calibrated it correctly using tiny-tuner.

 

49 thoughts on “TinyPCRemote – An ATtiny85 Based Infrared PC remote control

  1. Thanks a million, I was looking for this everywhere. If I wanted to use this with a crystal, what changes in software?

    Sam

  2. Just removing the OSCCAL line should be enough, no need to calibrate if using a crystal but everything else should be fine as is. Just put a crystal and bypass caps on and use the correct “burn bootloader” option to set the fuses.

    Cheers,
    Nathan

  3. Yes, you would still have to add the USB connector/diodes/resistors though, you can’t use the Uno USB connector for V-USB.

    The connection shown on the schematic going from D- on the USB plug to pin5/PB0 on the ATtiny would have to go to D2 on the Arduino instead and the one going from D+ to pin7/PB2 would have to go to D4. You wouldn’t have to make the changes in usbconfig.h or do the calibration.

    In the main code you would need to drop the OSCCAL = 0x9C; line and change TIMSK&=!(1<

    and change:
    #define IRpin_PIN PINB
    #define IRpin 4

    to

    #define IRpin_PIN PINB
    #define IRpin 3

    and

    pinMode(4, INPUT); // Make sure IR pin is set as input

    to

    pinMode(11, INPUT); // Set IR pin as input

    and put the IR receiver across ground, D13 and D11 as shown in picture for the code learner above.

    That should do it.

  4. I want to use a crystal for this circuit, but I have a question.

    According to your circuit, the TSOP31238 IR is connected to Tiny85 Pin3, this will occupied the pin for crystal. Based on Tiny85 datasheet, the crystal must connect to Pin2 & Pin3 of Tiny85.

    Should I connect the TSOP31238 IR to Pin6 of Tiny85 since Pin6 is not using currently.

  5. The tinycodereader always assumes that pin 3 (digital pin 11) is used. Thus it only works on the Uno’s. On the ATMEGA 2560 Digital pin 11 is actually mapped to pin 5. Why digitalread(11) wasn’t used I don’t know. But in its current form, IRPin 3 needs to be changed to IRPin 5 for the 2560. Only took me 2 hrs to figure out why it wasn’t working :)

  6. Also took me a little while to figure out that I had to install the attiny libs into my sketchbook’s hardware directory to get those boards to show up.

    Unfortunatly on the current Ubuntu LTS (12.04) tinytuner fails to compile :(

  7. Well using a 12 MHz crystal now so it’s ok (I will try compiling it again later), but alas. I think It is using the crystal right and V-usb is configured right, it does show up as a usb keyboard with my usbid name.

    However I get no keys from it. I’ve added the loop to always print KEY_A initially (so loop() { usb.update(); sendKey(KEY_A); but then it doesn’t even get recognized anymore. So it’s very picky as to when sending of keys is allowed. I quickly checked with a scope and the crystal is nicely resonating and the IR receiver is nicely sending pulses on input (also the keyscanner program ran just fine on the atmega of course).

    So kinda puzzled as to why it won’t work on the tiny. Gotta figure out a way to output some debugging first :)

  8. Fantastic write up. Nathan, fancy making the USB stick for me? I’m happy to do the programming! This would be so handy in my line of work…

  9. Hi folks,

    Is there a way to make Attiny85 emitter that complements this little gadget? I just need to send a few inputs such as scrolling with a mouse but using IR instead. Is this possible?

  10. What other AVR can be used instead of ATTiny85? We have difficulty procuring ATTiny85 in India. ATMega8L, ATMega16A, ATMega32A, ATMega168, ATTiny2313A-PU are the only available options. Thanks in advance and need not to mention that it was indeed a great article!

  11. @P Mehta It could be modified to work with anything that can be loaded with an Arduino bootloader so any of those should be possible. I’d probably use the 2313 as it is smallest and can be used with the arduino-tiny bootloader.

    @Temoor Yes, hardware wise you would just need to replace the IR receiver with an IR emitter and resistor. There is some code here using a modified version of Ken Shirriff’s IR library that works on the ATtiny and could be used as a basis to build a transmitter from.
    https://github.com/TKJElectronics/ATtinyRemote
    I used Ken’s library when I made my web based IR remote control here:
    http://nathan.chantrell.net/20120119/building-a-web-based-infrared-remote-control/

  12. Hi Nathan,

    Really appreciate your work.
    I use the code of your listenForIR() function on an ATtiny13 to remote control a couple of relays but it doesn’t work, though it does compile without problems. It seems that the system can’t read the code correctly. Is this some kind of a timing problem?

    On the ATtiny13 I am using the internal oscillator at 9.6MHz as guided here: http://arduino4projects.com/programming-an-attiny13a-using-arduino-servo-interpreter/

    Any advice please?

    Thanks in advance.
    Dave

  13. Hi

    I checked and does compile for DigiSpark, but after upload does not enumerate. Likely they are using different pinouts on the USB

    Can you do a version of the writeup on which pin defines to change for DigiSpark?

  14. Actually ignore that – DigiSpark already ported the Library: This works for me:

    #include “DigiKeyboard.h”
    // IR sensor connected to PB4 = ATtiny85 physical pin 3
    #define IRpin_PIN PINB
    #define IRpin 0

    #define MAXPULSE 5000 // max IR pulse length, default 5 milliseconds
    #define NUMPULSES 100 // max IR pulse pairs to sample
    #define RESOLUTION 2 // time between IR measurements

    uint16_t pulses[NUMPULSES][2]; // pair is high and low pulse
    uint8_t currentpulse = 0; // index for pulses we’re storing
    void setup() {
    // don’t need to set anything up to use DigiKeyboard
    pinMode(0, INPUT); // Make sure IR pin is set as input
    }

    void loop() {
    DigiKeyboard.update();

    unsigned long irCode=listenForIR(); // Wait for an IR Code

    // Process the pulses to get our code
    for (int i = 0; i < 32; i++) {
    irCode=irCode<0&&(pulses[i][0] * RESOLUTION)<500) {
    irCode|=0;
    } else {
    irCode|=1;
    }
    }

    // —————————————————————————————
    // Enter IR codes and keystrokes to send below, see keyboard_commands.txt for list of keys
    // —————————————————————————————

    if (irCode==3225414803) { // Single character example, "1"
    DigiKeyboard.sendKeyStroke(KEY_1);

    } else if (irCode==3631585319) { // String example with trailing space, "hello "
    DigiKeyboard.sendKeyStroke(KEY_H);
    DigiKeyboard.sendKeyStroke(KEY_E);
    DigiKeyboard.sendKeyStroke(KEY_L);
    DigiKeyboard.sendKeyStroke(KEY_L);
    DigiKeyboard.sendKeyStroke(KEY_O);
    DigiKeyboard.sendKeyStroke(KEY_SPACE);

    } else if (irCode==3631589399) { // String example with enter, "world ”
    DigiKeyboard.sendKeyStroke(KEY_W);
    DigiKeyboard.sendKeyStroke(KEY_O);
    DigiKeyboard.sendKeyStroke(KEY_R);
    DigiKeyboard.sendKeyStroke(KEY_L);
    DigiKeyboard.sendKeyStroke(KEY_D);
    DigiKeyboard.sendKeyStroke(KEY_ENTER);

    } else if (irCode==3631583789) { // Modifier key example “^c”
    DigiKeyboard.sendKeyStroke(KEY_C, MOD_CONTROL_LEFT);

    } else if (irCode==3631592969) { // Raw code example Home key = 74
    DigiKeyboard.sendKeyStroke(74);

    // Duplicate for as many buttons as required

    }

    } // loop end

    // IR receive code
    int listenForIR() {
    currentpulse = 0;
    while (1) {
    unsigned int highpulse, lowpulse; // temporary storage timing
    highpulse = lowpulse = 0; // start out with no pulse length

    while (IRpin_PIN & _BV(IRpin)) { // got a high pulse
    DigiKeyboard.update(); // needs to be called often
    highpulse++;
    delayMicroseconds(RESOLUTION);
    if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
    return currentpulse;
    }
    }
    pulses[currentpulse][0] = highpulse;

    while (! (IRpin_PIN & _BV(IRpin))) { // got a low pulse
    DigiKeyboard.update(); // needs to be called often
    lowpulse++;
    delayMicroseconds(RESOLUTION);
    if (((lowpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
    return currentpulse;
    }
    }
    pulses[currentpulse][1] = lowpulse;
    currentpulse++;
    }
    }

  15. THIS circuit is similar to what digispark is? how is attiny communicating with usb?can this not be directly programmed by usb just like digispark,,,without the need of arduino as ISP

  16. No, as it stands it has no bootloader and needs to be programmed via ISP. I think it should be possible to put the Micronucleus bootloader that the Digispark uses on it but will probably need a crystal (to get round the calibration issue) and might need some pin changes, I haven’t looked to see what the Digispark uses. Reminds me, I really need to do something useful with those.

  17. Nathan,
    Thanks for publishing this tutorial! I am not a programmer and I am new to electronics…can you point me in the right direction to use an IR signal as a toggle switch using an ATtiny 84? I am not having any problems using Ken Shirriff’s IR library with an UNO, but I can’t get anything going on the tiny.
    Thanks!

  18. I’m struggling with getting the calibration sketch to compile. Specifically, I’m using an ATTiny85 with the Sparkfun/Adafruit Tiny Programmer and the 1.05 IDE. I’ve got the blink sketch to work and have burned it at 8Mhz (with a corresponding change in blink rate).

    When I tried to verify the Interactive_to_Serial_with_Details sketch, I get an error “‘Serial’ was not declared in this scope”. Any thoughts on what I’m missing?

    Interactive_to_Serial_with_Details.pde: In function ‘void setup()’:
    Interactive_to_Serial_with_Details:138: error: ‘Serial’ was not declared in this scope
    Interactive_to_Serial_with_Details.pde: In function ‘void loop()’:
    Interactive_to_Serial_with_Details:169: error: ‘Serial’ was not declared in this scope
    Interactive_to_Serial_with_Details:232: error: ‘Serial’ was not declared in this scope
    Interactive_to_Serial_with_Details.pde: In function ‘void Serial_printP(const char*)’:
    Interactive_to_Serial_with_Details:244: error: ‘Serial’ was not declared in this scope
    Interactive_to_Serial_with_Details.pde: In function ‘void Serial_printPaddedIntger(long int, int)’:
    Interactive_to_Serial_with_Details:285: error: ‘Serial’ was not declared in this scope
    Interactive_to_Serial_with_Details:291: error: ‘Serial’ was not declared in this scope
    Interactive_to_Serial_with_Details:294: error: ‘Serial’ was not declared in this scope

  19. I switched to your recommended core and am making progress. Thanks.
    Now, in my terminal window I see the text telling me to type x and the column headers but there is no additional text after sending the x’s.
    It appears that I’ve got it wired up correctly. I may try to download a different terminal emulator as a fix.

  20. Hi!
    I really appreciate this tutorial of yours!
    I bought the same components and did everything you said, it all works well!

    I have an attiny85v, the low power version of attiny85. It runs up to 10MHz and can run on 3.3V.
    So, I wonder if I need to change the code to work on 10MHz so that the Attiny85v runs on 3.3V?
    This is because I do not have to use two Zener diodes for the two data lines and only one Zener diode for the attiny85v.

    My attiny85v, 10MHz OSCCAL = 0xAC
    My attiny85, 20MHz OSCCAL = 0x8F
    Maybe the OSCCAL itself settles the problem?

    Thanks! :)

  21. Wow, thank you very much for the heads up! Really saved me a lot of time, instead of trying to get it to work on 10Mhz.

    Just now I tried using this attiny remote to do volume up and volume down, both of them does not work, but others like keyboard left and right works very well.

    http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
    page 56,
    It says Usage ID for volume up and volume down are 128 and 129 respectively. Is it that V-USB does not support up to that range?

    (I did some research just now and seems like in Windows, they require the USB device to be as an Audio HID.)

    Thanks!

  22. Think I’ve found the problem, nothing over code 101 was working due to a limitation in the UsbKeyboard library. With the following mod it is working on my Linux box now at least.

    Look in UsbKeyboard.h for the following:

    0x25, 0x65, // LOGICAL_MAXIMUM (101)

    and change to:

    0x25, 0xE7, // LOGICAL_MAXIMUM (231)

    and change:

    0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)

    to:

    0x29, 0xE7, // USAGE_MAXIMUM (Keyboard Application)

    You should be now be able to just use those codes in the sketch, eg.
    UsbKeyboard.sendKeyStroke(128);
    or add names for them in the UsbKeyboard.h file.

  23. Hello, sorry for responding late…
    I have tried changing the LOGICAL and USAGE MAXIMUM, and the result is still the same.
    I have also tried sending keystrokes:
    UsbKeyboard.sendKeyStroke(129); //volume down
    UsbKeyboard.sendKeyStroke(0xAE); //volume down
    UsbKeyboard.sendKeyStroke(0xEA); //volume down
    UsbKeyboard.sendKeyStroke(128); //volume up
    UsbKeyboard.sendKeyStroke(0xAF); //volume up
    UsbKeyboard.sendKeyStroke(0xE9); //volume up

    From:
    http://msdn.microsoft.com/en-us/windows/hardware/gg462991.aspx
    and:
    http://msdn.microsoft.com/en-nz/library/windows/desktop/dd375731%28v=vs.85%29.aspx

    From what I have read on forums, the 129 and 128 keystroke seems to be working on Linux but not Windows.

    And also there seems to be a need to run the USB as Consumer Device or somekind of multimedia device (not normal keyboard) but I don’t know how to deal with those…

  24. Hi, atomos! How is your project going? I’d like to see your progress :)
    And also, if you don’t mind, make a tutorial on how to make it xD

  25. Any idea if the usb interface could be made to work with an android phone (usb on the go) port?

    The reason I ask, I’ve seen many diy ir remotes for the android that’s connected to the audio jack, and has a 2 leds back-to-back for the ir transmission.

    One (possible) exception to that, are the commercial products out there… ex.
    http://dakotek.en.alibaba.com/product/852523661-218297365/IR_emitter_IR_blaster_mono_phone_3_5mm_mono_phoe_RJ45_mono_phone_.html

    They too plug into a standard 3.5mm jack, but the emitter side is so small on those that I don’t see how they would have 2 leds. How the heck are they able to generate the usual 38khz needed for most remote controls?

  26. Hi Nathan,

    Was there any reason you didn’t build off of Ken Shirriff’s IR library? It would be great if we code get the IR code maker, like SHARP, SONY, ect. It would seem that Ken’s library requires ISR and other decoding logic that would give the V-USB library issues. Did you find that to be the case?

    Also, I got your code working on my ATTiny85 but one thing isn’t correct (for Sharp remotes at least) is the return codes spit out by your decoder app. Example, the Sharp IR code for the number ’4′ button is:

    0×4082 (in binary: 100000010000010)

    But your decoder spits out:
    0xC082 (in binary: 1100000010000010)

    There seems to be an extra bit.
    Out of the box the decoder app didn’t work for my Sharp remote, I had to alter the following line otherwise I get the same repeated IR code regardless of what button on the Sharp remote I hit:

    FROM:
    #define RESOLUTION 2 // time between IR measurements

    TO:
    #define RESOLUTION 1 // time between IR measurements

    What values would I supply the following if I wanted to capture IR pulses at 50 microsecond intervals?

    #define MAXPULSE 5000 // max IR pulse length, default 5 milliseconds
    #define NUMPULSES 100 // max IR pulse pairs to sample
    #define RESOLUTION 2 // time between IR measurements

    Thanks.
    Moe

  27. Hi Moe,

    It’s been a while since I looked at this but I recall there was a lot that would need changing to get Ken’s library working on the ATtiny85 as it uses a lot of lower level and timing specific stuff so I went with this simpler solution which got me up and running quickly with the remotes I wanted to use.

    Not sure why the code differs but as long as it is consistent then it should still be usable?

    The MAXPULSE define is in microseconds so for 50 you should just change to:
    #define MAXPULSE to 50

    Cheers,
    Nathan

  28. Hi there Nathan,

    I would like to thank you for posting this project. I was looking to build a simple Attiny85 IR remote control that simply switches on or off a relay or led. I have edited your code slightly to serve this purpose and would like to share the code here for those who wish do the same.

    I attached a 16MHZ crystal to the Attiny and selected pin 2 (physical pin 7) for the input of the IR receiver.

    Keep up the good work.

    //———————————————————————————————————————-
    // TinyPCRemote
    // Original code by Nathan Chantrell http://nathan.chantrell.net
    // Modified by Electro_Phunk. Email me for questions or comments at ubuildpc@gmail.com, alternatively discus your issues on Nathan’s forum
    // Receives infra red codes and turns on or off the output pin
    //
    // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence:
    // http://creativecommons.org/licenses/by-sa/3.0/
    //———————————————————————————————————————-

    #define IRpin_PIN PINB
    # define IRpin 2

    #define MAXPULSE 5000 // max IR pulse length
    #define NUMPULSES 100 // max IR pulse pairs to sample
    #define RESOLUTION 2 // time between IR measurements

    uint16_t pulses[NUMPULSES][2]; // pair is high and low pulse
    uint8_t currentpulse = 0; // index for pulses we’re storing

    void led(){

    digitalWrite(0, HIGH);
    delay(500);
    digitalWrite(0, LOW);
    delay(500);
    }

    void setup() {

    pinMode(2, INPUT); // Make sure IR pin is set as input
    pinMode(0, OUTPUT);

    }

    void loop() {

    unsigned long irCode=listenForIR(); // Wait for an IR Code

    // Process the pulses to get our code
    for (int i = 0; i < 32; i++) {
    irCode=irCode<0&&(pulses[i][0] * RESOLUTION)= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
    return currentpulse;
    }
    }
    pulses[currentpulse][0] = highpulse;

    while (! (IRpin_PIN & _BV(IRpin))) { // got a low pulse
    // UsbKeyboard.update(); // needs to be called often
    lowpulse++;
    delayMicroseconds(RESOLUTION);
    if (((lowpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
    return currentpulse;
    }
    }
    pulses[currentpulse][1] = lowpulse;
    currentpulse++;
    }
    }

  29. i build a IR keyboard reciever based on your design.. im using a 168 + crystal.
    and it has been working fine..

    reinstalled Debian. and now it gets detected. (shows in LSUSB)
    but disapears again.
    once in a while i can get a few chars sent with my remote before it quits.

    it works flawlessly on win7.. have been toying with longer delays
    and calling usbupdate more often.

    any ideas why it quit working on a new debian. worked fine on the old one?

    thanks

  30. Nop… still no good.. and no… i dont get it either.. its just a usb keyboard..
    just about as configuration and software independent as yo can get…
    works just fine on anything but my debian xbmc box…
    where it also worked fine till i updated it..
    i will play around with it.. keep you posted.

  31. @kyndal could be the timing or interrupt issue, my setup is vusb (HIDSerial) + IRRemote (ken shirriffs) @ 328 + crystal. It work fine on a windows platform but broken pipe on a linux.

  32. Nathan, I wanted to thank you for sharing your work and doing a great job of explaining it. I went through the process using a UNO as ISP and prototyped the circuit. Here are a few notes of my experience in case it can help others who might face similar issues.

    I could not get a hold of a TSOP31238 sensor and I used instead the TSOP38238. I have a Harmony (Logitech) remote I want to read with this receiver and I kept getting erratic codes using the code reader sketch. In the end a more detailed look at the datasheet for the TSOP38238 indicated that this sensor is tuned not only for the 38 Khz carrier but also for specific protocols. My remote is blasting codes for Panasonic and Samsung equipment and the sensor was not picking those commands properly.

    I was able to find another remote, one for an old Creative Labs external sound card and confirmed using IRLib that this remote was using NEC which is compatible with the TSOP38238. So I went back to the code reader sketch and sure enough, the codes began to come in and I was able to use them.

    The other issue I encountered was that the remotes seem to blast the commands twice. I always get at least 2 blasts for each button press. This behavior causes my computer to double each of the simulated key presses. In an attempt to fix this I changed

    #define RESOLUTION 2
    to
    #define RESOLUTION 8 (determined through experimentation)

    This change debounced the commands and I now get the desired 1 simulated key press per remote button press but I would like to ask you if you thought this would be the appropriate way to handle this behavior? I am afraid it might cause other issues down the line although I still have not seen any.

  33. By the way, I ordered a new IR receiver that I believe will be closer to the TSOP31238 and will handle all protocols, at least according to the datasheet. This sensor is the Vishay TSMP1138 in case others are interested. It even has the same pin layout and spacing as the TSOP31238 :).

  34. What software on the PC side can this work with? Can it work with IRScrutinizer?

    It would be a nice if could do what the CommandFusion IR-Learner does.. 30khz-455khz with CCF import!

  35. Greetings Nathan, Thank you for a excellent tutorial. I succeeded in using your tutorial to make a IR remote with atmega8. Everything works fine, Xp recognises the device as HID but after a while the communication breaks and i need to unplug the device and reconnect it to re-establish the communication. Might be a usb polling issue. Could you help me in resolving this. Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.