Unlocking some puzzles requires building a better key... board
Hi, this is Matt from the Windows Performance team. Sometimes we are presented with problems that defy our usual troubleshooting and require a creative approach. In a recent case, we needed a way to test the responsiveness of an application as text was typed into its fields. Initially, we tested the program using a script that used the SendKeys method to time entry time. Unfortunately, these tests aren’t completely realistic, since the script can be affected by the processor utilization on the system, and the script can’t create hardware interrupts like a keyboard does. Realizing that only real keyboard input would be a valid test, and that the rate of typing needed to be reproduced exactly for each test, I set about building an automated keyboard.
First, I found an old PS/2 style keyboard that hadn’t been used in years and opened it up. Luckily, it was old enough to use all through-hole components, which made it easier to modify. The main component I cared about was the keyboard encoder, which was a COP943C. A search online turned up a datasheet for the keyboard encoder with a sample circuit design that looked very similar to this keyboard. The document shows there are a couple of steps to determining which pins need to be shorted to generate a particular key.
Each key has an ID number that is shown in figure one of the PDF (figure one below). After finding the proper ID, a table is consulted to determine the row and column pins used to create that key code (figure two below). Finally, those row and column numbers are translated into physical pins on the encoder using the schematic diagram (figure three below). For example, the letter ‘a’ is number 31. The matrix shows 31 is made with the L5 (column 6) pin and C6 (row 3) pin. The pin out shows this to be physical pins 14 and 19. When tested, shorting these pins creates an ‘a’.
See the video:
Figure 1: Key Codes
Figure 2: Key Code Matrix
Figure 3: Encoder Pin Out
Now that we know how the keyboard circuit works, we need a method to generate key “presses.” For this, I found a board I assembled a year or two ago using a PCB and components from moderndevice.com. The board is an Arduino clone that is based on Atmel’s ATmega168 microcontroller. One of the great things about using an Arduino is their IDE, which allows for C programming with a number of pre-defined functions to make development quick. Also, the boot loader is already taken care of, which makes the work easier.
Wiring the board to the keyboard was straightforward. Figure 4 shows how to control a relay with an Arduino, and triggering a keyboard is rather similar. A resistor is placed between a digital out pin of the Arduino and the base pin of a transistor. The collector then goes to one pin of the keyboard encoder needed to type the letter desired, and the emitter goes to the other pin.
Figure 4: Arduino-controlled Relay [ii]
In order to save on solder joints, I decided to chain together the transistors, which affected the key selection. Additionally, because I wanted to leave the encoder in the original circuit and some of the pins were blocked by other components (resistors, capacitors), specific pins were selected. Figure 5 shows the layout of the transistors. These were soldered to a prototyping board with hook up wire to connect back to a breadboard with resistors and the Arduino and hook up wire soldered directly to the pins of the keyboard encoder.
Figure 5: Transistor Layout
These pins selected allowed characters a, s, z, space, and enter to be typed. All that remained was to write some software to trigger the transistors. The code first sets the digital pins to output and logic low, turns on a LED to show it is working, then waits 3 minutes to allow time for the PC to boot and application in question to be launched. The LED then goes out for a five-second warning, and then the loop sequence begins. The loop turns on the LED, types “as z” followed by enter, then turns off the LED and sleeps for 2.5 seconds before starting again.
// Sample code to drive keyboard encoder
// Matt Burrough
// September, 2008
int ledPin = 13; // Use digital pin 13 for a status LED
int sPin = 3; // Connect pin 3 to the transistor connected to the s leads
int aPin = 4; // Pin 4 is for a
int zPin = 5; // Pin 5 is z
int enterPin = 6; // Pin 6 is enter
int spacePin = 7; // Pin 7 is space
int holdKey = 30; // Milliseconds to "hold" each key down
int betweenKeys = 50; // Milliseconds to wait between key presses
void setup() { // Initial setup code (runs at power-on)
setupPin(ledPin); // Set up each pin with function below
setupPin(sPin);
setupPin(aPin);
setupPin(zPin);
setupPin(enterPin);
setupPin(spacePin);
digitalWrite(ledPin, HIGH); // Turn on the LED to show the board is on
delay(180000); // Wait 3 minutes to allow time for PC to boot
digitalWrite(ledPin, LOW); // Turn off the LED
delay(5000); // Wait 5 seconds
}
void loop() {
digitalWrite(ledPin, HIGH); // Turn the LED on
typeKey(aPin); // Type keys
typeKey(sPin);
typeKey(spacePin);
typeKey(zPin);
typeKey(enterPin);
digitalWrite(ledPin, LOW); // Turn the LED off
delay(2500); //Pause 2.5 seconds
}
void setupPin(int pin) { // Used to set up pins...
pinMode(pin, OUTPUT); // Set the digital pin as output
digitalWrite(pin, LOW); // Turn off the pin
}
void typeKey(int pin) { // Type a key...
digitalWrite(pin, HIGH); // "Press down" on a key
delay(holdKey); // Hold down the key
digitalWrite(pin, LOW); // "Release" the key
delay(betweenKeys); // Pause between keys
}
|
Figure 6: Code Sample
That’s how I made an automated keyboard. I hope that you’ve found this post interesting; I’ll leave you with a photo of the finished product.
[i] https://www.national.com/an/AN/AN-734.pdf
[ii] https://www.arduino.cc/playground/uploads/Learning/relays.pdf
Comments
Anonymous
October 10, 2008
Arduinos are a ton of fun just to play with but that's way cool that you got to work with them as part of your paying job :-).Anonymous
June 18, 2012
Updated video link: www.youtube.com/watch