RF Remote Control

One of the many things I do is conduct computer programming seminars all around the country (see the AWC page for more about that). A while back I decided I wanted a remote control "clicker" for my laptop. Just something I could use to change slides in power point.

What a shock! Those suckers are expensive! I did get one of those cheapo Packard Bell IR remotes you see on the surplus market. But they have a range of maybe 10 to 15 feet and don't work very well. Besides, the remote is huge.

My solution turned out to be cheap and it works great. First, go to Radio Shack and pick up a wireless door chime (63-874). These cost 19.99. While you are there, pick up some wire and a female DB9 connector. Try out the doorbell before you make any modifications. Once we cut it up, Radio Shack won't take it back if it doesn't work, I suspect.

The transmitter is fine as it is (just throw out the little bracket that it comes with for wall mounting). You have to open up the receiver. Remove the two screws from the back and release the tab in the battery compartment. The PC board has one screw you have to remove to free the whole assembly.

The first step is to cut the speaker wire (unless you want it to boing out loud). Next, locate R44. It is the resistor to the right of the channel switch (I think it is a 200K resistor if memory serves). The channel switch is the switch inside the battery compartment. Use your X-ray vision to observe the pads that connect to R44. One side is fat and blobby. This is ground. Solder a wire to that pad from the foil side. The other side has a thin trace. Solder a wire to that pad, too.

If you have a VOM or a scope, this is a good time to put the batteries in and watch the wire that connects to R44's thin trace. When you push the button you should see a clear logic-level transistion!

Use something sharp to punch a hole in the plastic shield that covers the keyhole used to mount the receiver. Run the wires through this hole and the keyhole in the cover. Use some RTV silicon or silly putty or something to plug the hole and strain relief your wires. Resassemble the case.

Now you can wire the ground wire and the other wire to your DB9 connector. Connect the ground wire to pin 5 of the DB9. The other wire can go to DCD (or RLSD, if you prefer) on pin 1 of the DB9.

Other Uses

My original intent was to make this a remote for the PC, and I've provided some software below for that. However, this would make a nice general RF remote. Especially since the transmitter already has external connections. You could remotely monitor a level or limit switch, for example. Although I connected the hot wire to DCD on the serial port, you could connect it to a general purpose I/O pin on a microcontroller (like a Basic Stamp) or to some other logic circuitry. Give it a try!

Software

Here's a simple console program you can use to have the remote press the Enter key for you when you push the remote button. This is a console program, and you can exit it by pressing any key:

#include <windows.h>
#include <iostream.h>
#include <conio.h>

// Send key to system
void PostVirtualKeyEvent (BYTE bVirtKey, BOOL fUp)
        {
        keybd_event(bVirtKey,
          MapVirtualKey(bVirtKey,0),fUp?KEYEVENTF_KEYUP:0,0);
        }


void main(int argc,char *argv[])
        {
        HANDLE comport;
        char *port="COM1";
        char c[33]="\r";
        char cm='\xFF';
        if (argc>=2) port=argv[1];
        if (argc>=3&&*argv[2]!='\'') cm=atoi(argv[2]);
        if (argc>=3&&*argv[2]=='\'')
                {
                strncpy(c,argv[2]+1,sizeof(c));
                c[strlen(c)-1]='\0'; // eat ending quote
                }
// Open com port
        comport=CreateFile(port,GENERIC_READ|GENERIC_WRITE,
               0,NULL,OPEN_EXISTING,0,NULL);
        if (comport==INVALID_HANDLE_VALUE)
                {
                int n=GetLastError();
                char errno[33];
                wsprintf(errno,"%x",n);
                MessageBox(NULL,"Can't open port",errno ,MB_OK|MB_ICONSTOP);
                return;
                }

        cout<<"Remote V1.0 by Al Williams\n";
        cout<<"Using "<<port;
        if (cm=='\xFF') cout<<" String="<<c;
        cout<<"\n\n";
        cout<<"Press any key to exit\n";
        cout<<"Command line: REMOTE [port [decimal_VK_code]]\n";
        cout<<"          or: REMOTE [port ['string']]\n";
        cout<<"Notice: this version supports upper/lower case letters "
              "and digits in strings!\n";
        cout<<"There is no support for control/alt characters, or shifted "
              "special characters.\n";
        cout.flush();
        DWORD stat,mask;
// We want to see when RLSD (DCD) changes
        if (!SetCommMask(comport,EV_RLSD))
                {
                MessageBox(NULL,"Can't set event mask",
                   "REMOTE",MB_OK|MB_ICONSTOP);
                return;
                }
        while (1)
                {
                Sleep(50);
                GetCommModemStatus(comport,&stat);
                if (_kbhit())            // exit request?
                        {
                        _getch();
                        if (MessageBox(NULL,"Quit Remote?",
                           "Remote",MB_YESNO|MB_ICONQUESTION)==IDYES)
                                return;
                        }
                if (stat&MS_RLSD_ON)   // CD on?
                        {
// Send current window a key stroke
                        HWND focus=GetForegroundWindow();
                        if (focus)
                                {
                                char *cp=c;
                                if (cm!='\xFF')  // character
                                        {
                                        PostVirtualKeyEvent(cm,FALSE);
                                        PostVirtualKeyEvent(cm,TRUE);
                                        }
                                else while (*cp)  // string
                                        {
                                        if (isupper(*cp))
                                          PostVirtualKeyEvent(VK_SHIFT,FALSE);
                                        PostVirtualKeyEvent(toupper(*cp),FALSE);
                                        PostVirtualKeyEvent(toupper(*cp),TRUE);
                                        if (isupper(*cp))
                                          PostVirtualKeyEvent(VK_SHIFT,TRUE);
                                        cp++;
                                        }
                                }
                        Sleep(1000); // debounce
                        }
                }
        }

[Tips]

[Home]