IR remote to keyboard

Hi guys,

I want to use my TV remote to send keyboard commands to my computer. So if I press the fast forward button on my TV remote, I want to send CTRL + F to my computer, which is fast forward for windows media player. So there are two parts that I need to work through. The first part to decode the IR signal being sent by the remote and a second part to send the signal to the computer. I can do both of these parts separately, but I cant get them to work together. I could probably get the project working if I used two arduinos, but ideally I should be able to do it on the one arduino.

So, to read the IR remote code, I used Ken Shirriff’s popular and easy to use library

Everytime I press the remote up button for example, I get a short code, such as B54A30CF. Each button has a different code, so I can easily work out which button is pressed based on the code received. Its easy and works well.

Next I needed to send a signal to the computer. Again, instead of reinventing the wheel, I have used some code from the practical arduino book that can be found http://www.practicalarduino.com/projects/virtual-usb-keyboard

I have also built that project, it works well and can be used to send keyboard commands.

So then I figured, hey, I just need to combine the two parts now to make a working solution. BUT its not working out that easily and I think it has something to do with the timer. Which is where Im asking for some expert help…

So here is my code:

#include "UsbKeyboard.h"     
#include <IRremote.h>

#define BUTTON_PIN 12
int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

// If the timer isr is corrected
// to not take so long change this to 0.
#define BYPASS_TIMER_ISR 1

void setup() {
  pinMode(BUTTON_PIN, INPUT);
  digitalWrite(BUTTON_PIN, HIGH);
  
    Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  
#if BYPASS_TIMER_ISR
  // disable timer 0 overflow interrupt (used for millis)
  TIMSK0&=!(1<<TOIE0); // ++
#endif
}

#if BYPASS_TIMER_ISR
void delayMs(unsigned int ms) {
   /*
  */ 
  for (int i = 0; i < ms; i++) {
    delayMicroseconds(1000);
  }
}
#endif

void loop() {
  
  
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
    }
  
  UsbKeyboard.update();

  digitalWrite(13, !digitalRead(13));

  if (digitalRead(BUTTON_PIN) == 0) {
    
    //UsbKeyboard.sendKeyStroke(KEY_B, MOD_GUI_LEFT);
    
    UsbKeyboard.sendKeyStroke(KEY_H);
    UsbKeyboard.sendKeyStroke(KEY_E);
    UsbKeyboard.sendKeyStroke(KEY_L);
    UsbKeyboard.sendKeyStroke(KEY_L);
    UsbKeyboard.sendKeyStroke(KEY_O);

    UsbKeyboard.sendKeyStroke(KEY_SPACE);

    UsbKeyboard.sendKeyStroke(KEY_W);
    UsbKeyboard.sendKeyStroke(KEY_O);
    UsbKeyboard.sendKeyStroke(KEY_R);
    UsbKeyboard.sendKeyStroke(KEY_L);
    UsbKeyboard.sendKeyStroke(KEY_D);
    //UsbKeyboard.sendKeyStroke(KEY_B, MOD_GUI_LEFT);

    UsbKeyboard.sendKeyStroke(KEY_ENTER);
#if BYPASS_TIMER_ISR  // check if timer isr fixed.
    delayMs(20);
#else
    delay(20);
#endif
    
   }

}

The problem is, as soon as I use the "irrecv.enableIRIn(); // Start the receiver " code, my project stops being recognised as a usb keyboard. If I remove that code, my project is recognised by the computer as a keyboard, but obviously the code is incomplete and it wont work. Any help would be great.

Where did you have UsbKeyboard.h from? Using the link you provided I cannot find that code. It's probably not a timer issue but an interrupt issue but without the code I cannot confirm.

You can download UsbKeyboard.h from http://code.rancidbacon.com/ProjectLogArduinoUSB

I don't have answer for you yet but found a possible issue. In the notes of your USB library they disable the Timer0 interrupt (time keeping of Arduino) because that seems to fix a problem. Although this fix doesn't seem to be enabled for UsbKeyboard.h it tells us that some of the USB code is quite time dependent. The IRremote library (receiving part) installs a timer interrupt called once every 50us. Maybe this interrupt brings the internal time keeping of the USB driver out of sync.

The USB library has some ugly parts. In the initialization code the zero out the whole port D (digital pins 0-7), so I would expect problems with the serial communication more than with the IR reception.

Have you compiled the USB driver yourself or did you just use the precompiled version? What wiring do you use?

Thanks for the quick replies. Pylon what you are saying does make sense. The Practical Arduino book does say: "Now for the USB setup. Because USB is extremely time-critical we need to mess with the interrupts a bit to ensure the Arduino will enumerate itself properly with the host computer"

Does the arduino have more than one timer that I could use? Could I modify the IRremote library to simply use a different timer?

I havent complied any drivers. After uploading the code to the arduino the Windows keyboard drivers are automatically loaded. I believe this may be in part because of the hardware (few resistors and a zener or two). I followed the hardware layout on that pratical arduino website.

My current wiring is the keyboard wiring, as per that website, then I have just added an IR receiver that sends its signal to D11.

If worst comes to worst I will just use two chips, then they can each use their own timer. Its just means its more components, cost etc.

Cheers

Well Im beginning to see that this might be a difficult option. The arduino book goes on to say : "One thing to note about the example sketch is that it doesn’t introduce any delays inside the main program loop. It’s critical that the loop executes quickly so just about the only thing you can do inside the loop is read digital inputs: if you try to do anything that will slow down the program, the host computer may fail to get a response at a critical time and decide the device is misbehaving. If that happens the host will de-enumerate the device and your fake keyboard will stop working."

Not only that, but Im having a bit of trouble sending the computer the CTRL + F keys. It seems to work, in Microsoft Word it will bring up the search function, but in Media Centre, nothing happens. It should work, because if I press those keys on my keyboard, the correct function works in both programs...

Im now thinking the easiest option is going to be to pull the circuit board out of an old keyboard and wire my IR receiving arduino up to it. The circuit board will look after all the USB side of things and the arduino will take the IR signal and turn on different digital pins to simulate a key press on a keyboard.

Only problem is, it wont be as flexible if I wanted to add different key combinations to the setup further down the track. If I can use an arduino, I adding new keystrokes would be as simple as uploading a new sketch.

If anyone has any info though I would very happy to try it.

Perhaps a Teensy would suit you better.

It can be programmed using the Arduino IDE, but it has native (hardware) support for USB, unlike the Arduino.

PaulS I think youre spot on. After spending a bit of time looking into the arduino, I realised it would take some serious coding to get it to work. And Im not a good coder. Im more electronics. The program would happily output a keypress, but it was a very quick keypress and it appears some programs dont expect that. So, on my keyboard when I hit CTRL F, the computer recognises it as a command. But the arduino would do it so fast that some programs I assume would ignore it.

I ended up pulling an old usb keyboard apart, grabbing the circuit out of it and mapping all 104 keys by hand. It took me a couple of hours. By shorting a particular two out of about 25 pins, I could simulate any key on a keyboard and I could easily adjust the time that the keys were held for in the arduino code. This way I would only need one arduino and one keyboard circuit. To short the pins out I was going to use 4016 analogue switch IC's, but using 3 IC's only gave me about 12 keys. In future if I wanted to use another key it would be a hassle to add the hardware.

So then I looked into the Teensy. I even found someone who has done a similar project using a remote to send keyboard commands. The code looked so simple it wasnt funny, was very flexible if I wanted to change or add keyboard combinations and only needed the one part - the teensy.

Ive ordered one but now need to wait for it to travel down here to Australia. Once it arrives though I think it will make my project very easy.

Thanks for your help and ideas all!