Close |
This project allows to remote control any computer with
any infrared remote control that you already have.
The idea is to control your music or video player on the computer from
your couch.
I have seen serveral projects for this purpose in internet but none of them
satisfied me.
I want to control my music player on the computer. I use MusicMatch. The program is quite old already but much better than WinAmp or Windows Media Player. The most important functionality of the program can be controled via keyboard: Play, Pause, Stop, Next Track, Previous Track. This is all I need.
My amplifier has this remote control:
The buttons that I marked in red have no function when listening to music
from the computer.
They are for the tuner and for other purposes.
When I press one of these buttons the amplifier does not do anything.
So my idea was to reuse these buttons to control the computer.
Only two parts are required: An infrared receiver chip and a Teensy 3.2 or Teensy 4.0.
The +5V power for the IR receiver comes from the USB cable.
The 3 wires are easy to solder even for a beginner.
The IR receiver TSOP38238 is very sensitive. It has a 38 kHz bandpass to
filter the signal from the remote control.
This filter is required to eliminate noise because fluorescent lamps emit
a very "dirty" light.
If you use a fluorescent lamp in your living room you may get a worse sensitivity
for the remote control.
The majority of remote controls uses a 38 kHz carrier frequency. Some use
36 kHz which will also work. (See datasheet in the Zip file)
Only few companies (like Bang & Olufsen) use a completely different frequency.
In this case you need either another receiver chip or another remote control.
You can buy this IR receiver (or a similar model) in several online shops:
Also the Teensy (US $20) can be bought from Adafruit and from Digikey. Or you buy it directly from PJRC.
The Teensy is a very versatile and very fast board with a lot
of memory.
In contrary to the Arduino boards the Teensy comes with a better software
library (TeensyDuino) that easily allows to simulate USB devices (keyboard,
mouse, joystick and more). Additionally the Teensy is much smaller (3,6 cm
x 1,8 cm) and cheaper (US $20) than Arduino boards.
Here you see some remote controls that I used for testing:
They are from a Yamaha amplifier, a Grundig amplifier (from the 1990's which
still works!) and from a LG TV. In the middle below is a remote control from
a
The infrared signals from Yamaha, LG, NEC and the LED control look like this:
This is measured at the output of the IR receiver chip. When there is no IR signal the output is high. When a carrier frequency of 38 kHz is deteced the output goes low. Or with other words: Each low phase in the above signal corresponds to a burst of 38 kHz modulated light. The shortest low phase in the signal is approx 550 µs for all the above remote controls. The entire signal consists of 67 high / low transitions. At the begining there is a longer start phase that gives the receiving microprocessor in the TV or Hifi device enough time to prepare for receiving the IR signal. The numbers below (in white) indicate the length of the low or high phase. A "1" means 550 µs. A "3" means 3 x 550 µs = 1650 µs. My source code detects automatically the "bitrate" of the IR signal.
The above signal encodes a button that has been pressed on the remote control. Each button generates another signal. But if you press a button for a longer time (e.g. to increase the volume) the remote control sends a "repeater sequence" which is always the same:
So if you press for example the "Volume Up" button, the signal in the first image is sent once and then the signal in the second image is repeated as long as you hold the button down.
I have seen on Github
and in the Teensyduino library very long code to decode IR signals. For each
and every type of remote signal an individual decoder has been written: for
Aiwa, Denon, JVC, LG, Lego, Mitsubishi, NEC, Panasonic, RC5, RC6, Samsung,
Sanyo, Sharp, Sony, Whynter. Huge libraries with thousand lines of code. And
which of them corresponds to Yamaha? And what if my model is not implemented?
Grundig is missing for example. This is surely not a universal solution.
I also found a Linux project that requires hundreds of config files. For each
and every remote control an individual config file must be written. This is
surely not my project.
There are also hardware projects in internet that use a much more complicated and more expensive hardware. I found a project that even uses a microprocessor that cannot be programmed via USB cable as the Teensy / Arduino boards. You have to buy an extra hardware programmer to upload the firmware. An absolute no-go for me!
I was searching for the simplest solution that does not depend on the type of remote signal. And I found one: I simply don't care about the meaning of each of the bits in the signal. In the first step I detect the average of the length of the short pulses (for the great majority of controls this is between 400µs and 700µs). Some remote controls use a different interval for Lo and Hi pulses. For example 400µs for Hi and 600µs for Low. Therefore my code calculates them separately.Then I calculate the multipliers. For the signal in the image above I get: 16,8,1,1,1,3,1,1,1,3,1,3,1,3,..... I don't have to understand what they mean. I just have to recognize them when they come in. Then I convert the signal into a character string and calculate a CRC 32 from that string. For each button on the remote control I get a different 8-digit hexadecimal value. My "decoder" needs less than 50 lines of C code for that.
When the signal is low I use lower-case characters and when it is high I
use upper-case characters.
For example a "1" becomes "A" or "a". And a
"3" becomes "C" or "c", etc...
But the two long pulses in the start phase (9 ms and 4.5 ms) are an exception.
They are not an exact integer multiple of a short pulse.
Therfore the first long pulse may be detected one time as 16 and another time
as 15 times the length of a short pulse.
For that reason I replace long pulses with an "X" or "x"
as their exact length is not interesting.
Lo: 9000 us --> Len: 15 --> Char: 'x' Hi: 4473 us --> Len: 8 --> Char: 'X' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 613 us short --> Len: 1 --> Char: 'a' Hi: 1633 us --> Len: 3 --> Char: 'C' Lo: 579 us short --> Len: 1 --> Char: 'a' Hi: 541 us short --> Len: 1 --> Char: 'A' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1657 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1662 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1662 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 539 us short --> Len: 1 --> Char: 'A' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1660 us --> Len: 3 --> Char: 'C' Lo: 579 us short --> Len: 1 --> Char: 'a' Hi: 541 us short --> Len: 1 --> Char: 'A' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 536 us short --> Len: 1 --> Char: 'A' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 535 us short --> Len: 1 --> Char: 'A' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1658 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 535 us short --> Len: 1 --> Char: 'A' Lo: 586 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 609 us short --> Len: 1 --> Char: 'a' Hi: 510 us short --> Len: 1 --> Char: 'A' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1636 us --> Len: 3 --> Char: 'C' Lo: 606 us short --> Len: 1 --> Char: 'a' Hi: 539 us short --> Len: 1 --> Char: 'A' Lo: 586 us short --> Len: 1 --> Char: 'a' Hi: 532 us short --> Len: 1 --> Char: 'A' Lo: 588 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 1637 us --> Len: 3 --> Char: 'C' Lo: 632 us short --> Len: 1 --> Char: 'a' Hi: 486 us short --> Len: 1 --> Char: 'A' Lo: 607 us short --> Len: 1 --> Char: 'a' Hi: 1662 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 539 us short --> Len: 1 --> Char: 'A' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 541 us short --> Len: 1 --> Char: 'A' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 1655 us --> Len: 3 --> Char: 'C' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1657 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Lo: Shortest: 579 us, Limit: 868 us, Average over 33 short intervals: 587 us Hi: Shortest: 486 us, Limit: 729 us, Average over 16 short intervals: 532 us Decoded: xXaAaCaAaCaCaCaCaAaCaAaCaAaAaAaAaCaAaCaAaCaCaAaAaAaCaAaCaAaAaCaCaCa CRC: 0x1856440C Button: Volume Up -------------------------- Lo: 9025 us --> Len: 16 --> Char: 'x' Hi: 2210 us short --> Len: 4 --> Char: 'D' Lo: 581 us short --> Len: 1 --> Char: 'a' Lo: Shortest: 581 us, Limit: 871 us, Average over 1 short intervals: 581 us Decoded: xDa CRC: 0xF4FCC4CA Button: Volume Up -------------------------- |
This is the debug output that is sent to the virtual serial COM port on the computer. You see this output for example in the "Serial Monitor" of the Arduino compiler. You see exactly what has been received and how it has been processed by the Teensy. At the end the CRC is printed which identifies the button on the remote control or the repeater sequence (marked in blue).
My code also takes care of the "repeater sequence". The repeater is always sent while you hold any button down on the remote control. It makes sense for buttons like Volume Up/Down to repeat a keystroke to the computer while the button is pressed. But it does not make sense for a button like "Pause". If you would repeat the "Pause" command, the audio/video player would permanently switch between Play and Pause while you press the button. Some remote controls do not use a repeater sequence at all. Therefore my code has a flag that you must only set for commands to be repeated.
NOTE: It is an error to regulate the volume on the computer. You should always let the volume on the computer at 100% and regulate the volume only at your amplifier.
Decoded: aXaAaAaAaAaAaAaAaAaAa Decoded: aXaAaBbAaAaAaAaAaAa Decoded: aXaAaBbAaAaAaAaAaAa Decoded: aXaAaBbAaAaAaAaAaAa Decoded: aXaAaAaAaAaAaAaAaAaAa |
But all these differences between the remote controls do not matter. My code works with any remote control.
For the MusicMatch player the following keystrokes have to be sent:
You must only adapt the function ExecuteAction()
to your needs.
You get the CRC code for each button from the debug output and just copy and
paste it into the source code. The function PressKey()
then sends
a keystroke to the computer via USB keyboard which is simulated by the Teensy.
Special Case: RC5There are remote controls that send a toggle bit. A typical example is the RC5 code which has been developed by Philips: This means that each time you press the same button on the remote control this bit is toggled. So you get two CRC codes for one button: One with the toggle bit = high and one with the toggle bit = low. In this case your code must look like this:
ProgrammingTo program the Teensy's processor you need a micro USB cable and you have to install: You have to configure the compiler like the red settings in this screenshot: With the option "Serial + Keyboard + Mouse + Joystick" the Teensy simulates a USB HID keyboard, a HID mouse and a HID joystick. Only the keyboard is used here. And "Serial" is the virtual COM port that will appear on your computer where you receive the debug output. You can read the debug output with the freeware TeraTerm
or with the "Serial Monitor" in the Arduino compiler. ATTENTION: Windows may be extremely slow when you connect the Teensy's USB cable. There are 4 USB devices simulated at once by the Teensy and Windows may take up to 10 seconds until you can access the serial port. Additionally there is a bug in the Serial Monitor of the Arduino compiler which may result in the COM port never appearing. To avoid this problem you must close the Serial Monitor each time before you upload firmware to the Teensy. TroubleshootingIf it does not work check the following steps:
Possible ExtensionsYou can do much more with this project. Additionally you could connect relays to the Teensy to switch devices on and off or you could dim your lights with the remote control. If you connect 12V LED strips or LED lamps you can use a PWM output of the Teensy at 500 Hz and amplify the signal with a MOSFET transistor like BUZ71A. You can also write a program for the computer that listens on the serial COM port for the CRC codes that are sent from the Teensy and executes more complex actions (e.g. shut down the operating system, start programs, etc..) In C# this can be done with a few lines of code using System.IO.Ports.SerialPort. A simple light switchYou can extend the main light switch of your room with a bistable relay. So you can switch the light on and off either via remote control or via light switch. A bistable relay has two coils and needs only a short pulse to switch into the other position and stays forever in this position until the other coil gets powered. You find bistable relays for example at Digikey. The PB1695-ND needs 80mA at 5V. It costs US $4,40 and switches 16A. The pin Vin of the Teensy is connected directly to the +5V of the USB cable which delivers enough current (500mA) for the relay so you don't need an extra 5V supply if the computer is running. But if you want to switch the light also if the computer is off then you need an additional 5V supply and you must cut the jumper at the bottom side of the Teensy to disconnect this 5V supply from the 5V of the USB cable.
Download
|