Keyboard buzzer to replace console bell

Vibrating Motor + Keyboard, reassembled = ?

The Idea
Being a console junky, I am always looking for ways to improve my experience at the terminal. One thing that is is dire need of improvement is the console bell. You know, the really annoying beeping sound that occurs when you pressed the wrong key, that you immediately disable when setting up a new computer. Unfortunately, the bell really does provide a useful service: that of allowing the system to notify you when you need to fix your input. It is possible to turn on a ‘visible bell,’ which inverts the foreground and background colors of the console. In practice, though, I find this almost as annoying as the bell, and disable it as well.

So what else can we try? It occurred to me that there is an obvious solution: haptic feedback! The only trouble is, I don’t know of many keyboards that have a vibrating motor built in. Of course, this is an easy thing for a DIYer to fix. It turns out that is is quite straightforward to add the vibrator motor to the keyboard, however patching a terminal program to activate the buzzer took a bit more head scratching. Instructions after the break…

Preparing the Vibrator Motor
The first step was to secure a vibrator motor. I happened to have one from an old cell phone, so I pulled it out and dusted it off. It had very short leads on it, so the first order of business was to solder some longer wires to it.
Vibrating Motor
Because the leads were so tiny and fragile, I added some shrink tubing to hold everything together. I put a small diameter tube over each wire individually, then two layers of larger shrink tubing over the whole thing. It ended up looking like this:
Vibrating Motor
Later on, I added a connector to the end of the motor leads.
Buzzer Connector

Interfacing to the keyboard
The next step was to figure out how to hook the motor up to the keyboard. Because I was using a USB keyboard, I knew that there would be a good 5v power source available. To trigger the motor, I decided to use the scroll lock LED. My initial plan was to use a sneaky signaling system where I would flash the LED faster then the eye can see, and program a microcontroller to look for the signal and turn on the vibrator. That turned out to be overkill, and I ended up switching the motor on and off using the scroll lock LED directly. I decided to modify my Microsoft Natural Ergonomic Keyboard 4000. Getting it apart was a little tricky. All the screws in the back had to be removed, then the space bar was (carefully) popped off, revealing two further screws. There was a final clip at the front center of the keyboard, which came apart easily once the space bar screws were removed.
Keyboard guts
I really lucked out choosing this keyboard- the controller board uses nice, through-hole discrete components. It was short work to hook up a multimeter and figure out which of the large resistors connected to our Scroll Lock LED. To do this, I attached one lead to a ground connection, and then probed the ends of the resistors with the other lead while toggling the scroll lock LED (tip: if the scroll lock button is disabled on your system like it is on my Ubuntu one, you can use the command ‘xset led 3′ to turn it on, and ‘xset -led 3′ to turn it off).
Probing the keyboard controller for the Scroll Lock signal
Once I identified the proper end of the proper resistor, I rigged up a transistor to drive the motor. Because the LED is being controlled from the low side (meaning it is always connected to +5v, and the controller connects and disconnects the ground side to turn it on and off), I needed to use a PNP transistor to turn the motor on and off in phase with the LED. I replaced the original resistor that was powering the LED to get a higher motor current, and added a transient suppression diode in parallel with the motor:
Schematic for Keyboard Buzzer
I soldered some leads onto the +5v and GND connections from where the USB connector interfaced with the board, and also soldered a lead to the LED wire that I had identified previously. I then built a prototype of the circuit on a breadboard, and connected it up:
Prototyping the motor driver
Once I was satisfied that the circuit would work, I mounted it on a little pc board from radio shack and stuck it in the keyboard.
All wired up
The final mechanical bit was to attach the buzzer motor to the keyboard. I decided to glue it to the left-side wrist rest, so that it would be closest to my hand when it vibrated. I had some Aleene’s 7800 adhesive laying around that I decided to try; I will try to remember to update later to tell if it worked or not. Before gluing the two parts together, I used some sandpaper to rough them up, and some IPA to clean off the sanded surfaces. I then used a ‘C’ clamp to hold the two pieces together during drying.
Buzzer, glued on.
Modifying the Terminal Program
With the hardware bit finished up, it was time to work on the software bit. So far, I had been triggering the LED on and off manually, and I needed a way to integrate the buzzer into the terminal. I first pulled down the source for gnome-terminal, but found that it was really a front-end for a library, and that I would need to compile and install the library to get it to work. Instead, I switched to Xterm, which implements its terminal functions directly.
I modified Xterm version 235 (available here) to flash the scroll lock LED instead of turning on that horrid buzzer. It turned out that I only had to patch one file, misc.c. I am not an experienced X11 programmer, so it took a while to figure that out :-). The patch follows. Of course, the best way to do this would be to modify the low-level X libraries, but that would be significantly more work.

> #define CAPSLOCKLED     1
> #define NUMLOCKLED      2
> #define SCROLLLOCKLED   3
> /* Turn the Scroll Lock LED on momentarily, to trigger a vibration motor */
> void
> VibrateBell()
> {
>     TScreen *screen = TScreenOf(term);
>     XKeyboardControl keyboard_control;
>     unsigned long mask = KBLed | KBLedMode;
>     /* Turn the Scroll Lock LED on */
>     keyboard_control.led = SCROLLLOCKLED;
>     keyboard_control.led_mode = LedModeOn;
>     XChangeKeyboardControl(screen->display, mask, &keyboard_control);
>     XSync(screen->display, false);
>     /* Wait a while */
>     usleep(100000);
>     /* Turn the Scroll Lock LED off */
>     keyboard_control.led = SCROLLLOCKLED;
>     keyboard_control.led_mode = LedModeOff;
>     XChangeKeyboardControl(screen->display, mask, &keyboard_control);
> }
< 	XkbBell(screen->display, VShellWindow, percent, which);
> //	XkbBell(screen->display, VShellWindow, percent, which);
< 	XBell(screen->display, percent);
> //	XBell(screen->display, percent);
>     VibrateBell();

After re-assembling the keyboard, the modified Xterm program was run. The vibrator does work as designed; however, the vibration is too weak to shake the keyboard, and as a result is too hard to feel well. The vibration definitely can be heard, which means that it works as a notification of sorts. I might try replacing the PNP transistor with a P-channel MOSFET, which has the potential to drive the buzzer harder. During testing, I noticed that it is currently drawing 65 mA using the current setup, while it is capable of 100 mA when connected directly to the power supply. All in all, a fun experiment!

As a side note, this method could probably be used as a simple way to control other devices using the computer. It is especially handy for ones that you want mounted in or near the keyboard. Be careful when driving devices directly from an LED signal though, in case a rogue program decides to turn it on for a long time.

This entry was posted in tech. Bookmark the permalink.

11 Responses to Keyboard buzzer to replace console bell

  1. Tom says:

    This is a very cool hack, haven’t been this exciting about something as simple as did in a long time. I’m trying it this weekend… ;)

  2. la23ng says:

    Very nice.

    I was annoyed by the PC-speaker beep too, and I replaced it with a fancy beep driver and a beep daemon that uses ALSA to play a nicer beep. The advantage of that approach is that it works irregardless of the terminal program and even on a text console.


  3. mahto says:

    @Tom: Thanks!!! I’ll be expecting photos, of course :-).

    @la23ng: That is really neat, I hadn’t thought of doing a kernel module to capture the beep events. Do you have to disable the pc speaker module when using yours? I’ll try to manufacture a plugin for your module that activates the vibrator.

  4. Intosia says:

    wow very cool :D Although i dont use linux, il try to find a way for windows :D Maybe detecting the MessageboxA api and letting the scrollock blink :)

  5. mahto says:

    Thanks Intosia! If you get it working under Windows, let me know!

  6. Pingback: Substituindo o Beep do PC at Gambiarra!

  7. It was a very nice hack ;)
    Here comes a little tip: try to glue your vibrator at your keyboard centre of mass and away from any fixations (such as screws). The place you chose is too rigid. If you choose a place that is easier to deform with your hand, the more vibration could be felt.
    Good luck!

  8. mahto says:

    Thanks Vinicius! Interesting suggestion- I chose a hard surface because I thought it would resonate and ‘amplify’ the vibrations, but maybe that just allows it to convert the vibrations into sound waves.

  9. Chris says:

    I found your instructions useful for pulling my MS keyboard apart after spilling drinking chocolate over it, the two screws behind the space bar had me foxed!
    Thanks for that. Unfortunately the keyboards looking terminal. The chocolate got to the circuit board, and in just 7 hours has managed to rust the connections.

    What’s amazing is this keyboard has a grand total of 29 screws!

    • mahto says:

      Cool,glad i Icould be of some help. Sorry to hear about your keyboard :-\. When working, it is certainly a pretty impressive little device.

  10. Pretty cool, but that’s a lot of work for a buzzer!

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>