• You are not logged in.
  • Index
  • General
  • Arduino-based hardware keyboard remapper

Arduino-based hardware keyboard remapper

  • Started by darkness
  • 49 Replies:
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Having read a few threads on a hardware implementation of colemak on the forums but no one really posted a solution, I decided to take the plunge and purchased an Arduino Leonardo with a USB Host Shield 2.0 and went ahead to hack up a hardware implementation that I can use at work and practically anywhere as long as there is a USB keyboard. After around a week of tweaking the code, I have managed to more or less complete the code to a point where it is usable now.

Features of the Arduino keyboard interpreter:
- able to switch keyboard mapping using hotkeys (Ctrl-Shift-0 is qwerty, Ctrl-Shift-1 to 4 is tarmak1 to tarmak4, and Ctrl-Shift-5 is colemak)
- word game! Generates random words for practising the layout (Ctrl-Shift-Space)

I have published the code on github for anyone who's interested:
https://github.com/darkytoothpaste/keymapper

You would really only need the .ino and .h files to compile in the Arduino IDE.

I would appreciate if anyone who wishes to use the code to drop me a note to give me some feedback, thanks!

Last edited by darkness (25-Nov-2012 20:55:12)
Offline
  • 1
  • Reputation: 80
  • From: Oslo, Norway
  • Registered: 13-Dec-2006
  • Posts: 4,393

I had to look up what Arduino is. Fascinating stuff. Could you please post some images of what your stuff roughly looks like? And maybe some more explanation of what it'd take for someone else to get their own.

Is it clunky or compact? Can it be in a nice plastic box or something, or will it be open to dust and dirt? How much did you pay for it? How many hours would I need to spend on something like this? Etc etc.

Thanks for doing this! ;)

*** Learn Colemak in 2–5 steps with Tarmak! ***
*** Check out my Big Bag of Keyboard Tricks for Win/Linux/TMK... ***

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Unfortunately I am unable to take a picture right now at work due to restrictions on the use of cameras. However, the setup will look something like this, except that this picture shows an Arduino Uno while I am using an Arduino Leonardo.

arduino_uno_plus_host_shield.jpg

I wouldn't really call the setup compact, but neither is it clunky. According to the Arduino website, the PCB measures 2.7 inch by 2.1 inch (excluding the connector portions). After stacking up with the USB host shield, the height is approx 1 inch. I currently don't have any covers for the setup, though I'm scouting around for materials to house the setup.

For someone using the Leonardo with the USB host shield 2.0 (like me), I would say that it's probably as good as plug-and-play. This would roughly translate to the following steps:

- assemble the Leonardo with the USB host shield
- download the Arduino IDE (right now is version 1.0.2)
- download the USB host shield 2.0 library (I forked a version to support modifier keys such as ctrl, shift and alt, but either my version or Oleg's original should work perfectly fine)
- download my sketch for the keyboard remapper
- compile the code and upload to the Arduino

I'm estimating that all the above steps should take no more than an hour.

As I'm not residing in the US, I paid a slight premium for all the hardware. It's around USD65. But I'm sure it would be cheaper in the US.

For anyone not using the Leonardo (say, for example, using the Uno), then there would be more tweaking required as the Uno does not natively support USB HID and hence some firmware flashing and probably additional coding to support the HID mode would be required to get the setup to work. I'm guess that should take around a day or two (including debugging time).

There is also a possibility to build something even smaller using the mini version of the USB host shield along with a teensy. An example can be found here:

https://www.pjrc.com/teensy/td_libs_USBHostShield.html

While the picture shows the two PCBs mounted side by side on a perf board, it is also possible to somehow stack them together with all the appropriate wiring and soldering and proper electrical insulation between the two boards. That would make the setup somewhat like a USB flash drive, which is convenient! That would then be quite close to the QIDO mentioned in the other hardware thread at around 70% of the cost and more features!

Offline
  • 0
  • Reputation: 80
  • From: Oslo, Norway
  • Registered: 13-Dec-2006
  • Posts: 4,393

This is so fascinating! Oh, and thanks for using my Tarmak layouts! ;)

• Can it be powered by the USB connector only, or do you need an extra power supply?
• Do/could you have LEDs showing what the remapper is up to?
• Is the AltGr modifier supported? I suppose you can't actually send symbols but key presses...
• Could your solution support the CapsLock as an Extend modifier (see my sig topic) as well?
      - If so, would it be possible to code new modifiers in the Extend mappings
         (for instance, type Caps+A+4 to get Alt+F4, or Caps+S+T+N for Shift+Ctrl+Left to select the previous word)?
• Also, another modifier (for instance ScrollLock) to make the current layout Mirrored?

Last edited by DreymaR (27-Nov-2012 11:59:53)

*** Learn Colemak in 2–5 steps with Tarmak! ***
*** Check out my Big Bag of Keyboard Tricks for Win/Linux/TMK... ***

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Wow, that's a lot of question, I'll try my best to answer. ;-)

DreymaR said:

• Can it be powered by the USB connector only, or do you need an extra power supply?

There is no requirement for an external power supply for this particular application.

DreymaR said:

• Do/could you have LEDs showing what the remapper is up to?

On the standard Arduino boards, they have a built-in LED that you can control. I have mapped it currently now to simply be off when it's qwerty layout and on when it's any of the tarmak or colemak layouts. I had plans to make them blink at various rates for various layouts but did not get down to doing it. On the Arduino boards, there are also multiple digital out pins that you can put various LEDs on for various status updates if you choose to. I even went so far as to explore how to use the capslock, numlock and scrolllock lights to give some feedback on the current status, but based on the existing USB host shield library, the HID address and the locking key status is not passed out to the user-program and hence I dunno how to program the lights (yet). Need to brush up on my programming skills... ;-p

DreymaR said:

• Is the AltGr modifier supported? I suppose you can't actually send symbols but key presses...

I'm not familiar with the AltGr key, but the modifications that I made to Oleg's host shield library was intended to pass on any key presses that are not remapped transparently to the computer. However, I may need to tweak that part accordingly if I have more info/debugging on it.

BTW, my program currently has a bug (actually it was oversight on my part) that does not pass on more than 2 simultaneous key presses (besides modification keys). I need to find time to correct that part of the program.

DreymaR said:

• Could your solution support the CapsLock as an Extend modifier (see my sig topic) as well?
      - If so, would it be possible to code new modifiers in the Extend mappings
         (for instance, type Caps+A+4 to get Alt+F4, or Caps+S+T+N for Shift+Ctrl+Left to select the previous word)?
• Also, another modifier (for instance ScrollLock) to make the current layout Mirrored?

Currently, the host shield library traps the locking keys (caps, num and scroll) and does not pass it on to the user program. I also looked into this briefly just two days ago as I was contemplating mapping the capslock to backspace as per "classical" colemak. The only way now is to address the HID directly without using the library functions, or to change the library functions to pass on locking key presses to the user program for remapping. I have not gone on to explore this area yet.

Actually I have quite a fair bit of ideas right now that I'm thinking of implementing:

- keep track of all keystrokes and map a counter to every keystroke so that it can generate a "heat map" on what keys are most frequently used. I wanted to do this as I know that I almost rarely never use the left shift for shifting (only the right) and hence if I have a log of all the keys that I used, then rarely used keys can potentially be used for me to remap to more useful functions or even macros.

- allow customised remapping of keys (programmable keyboard similar to the Anykey or Typematrix).

However, if this program is only for myself then it may not be too productive to invest too much time on these "fanciful" features and instead I will focus on the core features.

Offline
  • 0
  • Reputation: 3
  • Registered: 21-Apr-2010
  • Posts: 776

Well it sounds good so far.

You could always log your key strokes  with software instead.

Ask a stupid question but do all USB keyboards send out the same signals?   Can you swap in any keyboard?

Perhaps it should default to no light, and have the light on for Qwerty - save those polar bears from drowning and all of that...

It must have at least 16 key roll over to keep up with the speed of my fingers... ;)

(On a tangential note, there is a unit that has a hdmi in and out, that you can use for something like a television overlay - Tweets while you're watching the telly.)

--
Physicians deafen our ears with the Honorificabilitudinitatibus of their heavenly Panacaea, their sovereign Guiacum.

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

I just did some more tweaking tonight and found a much simpler solution to implement the features that we have been discussing above (capturing of locking keys, toggling of locking key lights, handling multiple key presses). All I needed to do was to pull in the virtual function from Oleg's library and implement it in my own code. Dunno why I missed that altogether.

I will be releasing a minor bug fix later (wrong handling of the Shift-Ctrl keys), but will release a major revision to the code probably this weekend when I have more time to tweak the code to achieve the above features.

In my case, since I can't install any software at work, all my solutions have to be in hardware (which is what motivated me to develop this solution in first place!)

From what I have been reading, since all USB keyboards have to be USB HID complaint, the keyboard scan codes are actually all the same, i.e. you should have no problem swapping in any keyboards. However, any custom keys outside of the HID definition which is handled via a software driver (e.g., a gaming keyboard) cannot be recognised by the Arduino without some customised code.

BTW, apparently even with the current "1KRO bug" in my code, it works perfectly fine for fast typing. It only doesn't work when you need to detect multiple key presses, e.g. wasd or arrow keys for gaming. ;-)

P.S.: "keys" is really hard to type on tarmak1!!!! ;-p Muscle memory problem...

Last edited by darkness (27-Nov-2012 16:49:13)
Offline
  • 0
  • Reputation: 3
  • Registered: 21-Apr-2010
  • Posts: 776

I thought that NKRO with usb  was limited anyway?

I looked at the Corsair K60 Vengeance, and that purports to have 20 key roll over USB, which surprised me.

I've been glued to my Ps2 port thinking it's better.  I read that it uses less power somewhere.  But perhaps that's moot.  Well it is with your adapter anyway.

If you have media keys - do you end up with multiple USB devices (not sure if that's the right expression,) listed?  How do you filter them out?

Last edited by pinkyache (27-Nov-2012 18:27:12)

--
Physicians deafen our ears with the Honorificabilitudinitatibus of their heavenly Panacaea, their sovereign Guiacum.

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

USB supports up to a maximum of 6KRO, as it is limited by the USB HID protocol. I would be surprised if anyone needs to press 20 keys at one go for any practical purpose on a PC, other than, perhaps, a piano software.

The reason why I needed to go with USB instead of PS2 is simply becoz I only have access to a USB keyboard. PS2 keyboards are kind of hard to find nowadays. Further more, I just recently acquired a Microsoft Natural Ergonomic Keyboard 4000 and I need to get my investment worth back... ;-)

I never used any of the media keys on my keyboard, so out of curiosity I tested it out with and without my Arduino. Apparently, the Arduino currently filters out all the media keys causing them not to work. Plugging the keyboard directly to the computer works. I will take a closer look at the code again to see why the media keys are being filtered out this weekend.

Oh, and it is not recognised as a new device, since it has to be specifically coded in the Arduino for it to enumerate itself as a new USB device.

Last edited by darkness (27-Nov-2012 19:45:09)
Offline
  • 0
  • Reputation: 80
  • From: Oslo, Norway
  • Registered: 13-Dec-2006
  • Posts: 4,393

My suggestion for the LED would be to let it flash a number of times each time you switch layout, to tell you which layout you switched to. If it keeps blinking all the time I'm sure I'd find it immensely annoying after a while.

Yeah, and one more request from the module guy: Wide/Angle mod. Of course, both Mirrored and Wide/Angle can be added as variant layouts. But it'd be truly wonderful if they could be stacked on top of each other in addition to the layout choice.

I think I heard that the USB keyboards with more than 6KRO set a different bus speed or use more than one bus or something. Not likely to be necessary I guess. Keep in mind though, that with my wishes the real and remapped modifiers can quickly pile up – so I think the nominal 6KRO will be a must. ;)

Last edited by DreymaR (29-Nov-2012 08:14:34)

*** Learn Colemak in 2–5 steps with Tarmak! ***
*** Check out my Big Bag of Keyboard Tricks for Win/Linux/TMK... ***

Offline
  • 0
  • Reputation: 0
  • From: Canada
  • Registered: 29-Nov-2012
  • Posts: 13

Great idea!  Thanks for posting the code as well.  Teensy 3 + USB shield would be very compact, cheap solution for this (as it runs on 3.3V unlike previous Teensy's, it will interface nicely with the shield without additional parts).

I work for Keyboardio and post code on GitHub

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Gents, I have actually found a even  cheaper way of implementing the hardware keyboard mapper without the relatively expensive USB Host Shield! It is simply based on the idea that a USB keyboard can be interpreted as a PS/2 keyboard, and there are already PS/2 libraries available on the Arduino.

Here's a picture of my setup:
IMG_4882.jpg

I took a USB extension cable and snipped it and wired it to the Arduino. As you can see, there are only 4 wires that needs to be wired. Then connect up to a USB keyboard, run some sample codes, and viola! Therefore, in theory, all that is required is a teensy, some USB adapters and some wires to complete the project.

The only problem now is that the PS/2 scancodes are completely different from the USB ones and I would need to write my own code for handling locking keys and packaging the serial data into USB HID compliant packets for sending them out back to the host computer.

Offline
  • 0
  • Reputation: 80
  • From: Oslo, Norway
  • Registered: 13-Dec-2006
  • Posts: 4,393

You're my hero these days. ;)

*** Learn Colemak in 2–5 steps with Tarmak! ***
*** Check out my Big Bag of Keyboard Tricks for Win/Linux/TMK... ***

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Look here: https://www.pjrc.com/teensy/projects.html

The idea I have right now is exactly like that shown in the Keyboard Redneckifier. I had always been intending to integrate the teensy into my Microsoft Ergonomic 4000, and looks like someone had the exact same idea as well!

Offline
  • 0
  • Reputation: 80
  • From: Oslo, Norway
  • Registered: 13-Dec-2006
  • Posts: 4,393

Oo, there's a lot of interesting stuff on that page:
A Keyboard FAQ for Teensy (interesting read!)

A keyboard controller by Hasu on GeekHack! This includes "Happy Hacking" extra layers like I want.
The HumbleHacker keyboard (serious stuff!)
An entry on keyloggers (more serious stuff!)

DIY foot pedals
Another footpedal project

Last edited by DreymaR (30-Nov-2012 11:32:25)

*** Learn Colemak in 2–5 steps with Tarmak! ***
*** Check out my Big Bag of Keyboard Tricks for Win/Linux/TMK... ***

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Bad news, I did more research and found that the "direct connection" method only works for keyboards that are specifically designed to work on both the USB and PS/2 interface. The keyboard that I tested out (Logitech Cordless Keyboard) happened to be one of those types which is the reason why it worked. When I plugged in my gaming keyboard (Logitech G510), it did not work at all.

So looks like the need for the USB Host Shield cannot be avoided, unless it is a PS/2 keyboard or PS/2-capable keyboard.

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

As promised, I have extensively revised the code to make it simpler and more capable. The code can be found at the usual github page:

https://github.com/darkytoothpaste/keymapper

I can probably add more functionality such as mirrored modes and customised programming if there are more interest. If not, the current code probably serves my purpose (for now). ;-) Feel free to modify as deem fit to suit your needs.

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

Just a small update, I have just ordered a teensy 2.0 with a USB Host Shield mini. Will be toying around with them when it arrives to build a "QICO" like stick. ;-)

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

I have finally gotten down to posting the completed teensy + mini usb shield project. Pictures as follows!

The size of the boards are really small compared to the Arduino!
2012-12-27174130_zpsc1d21d54.jpg

Soldering in progress...
2012-12-27231507_zpsed460402.jpg

Soldering complete!
2012-12-28003317_zpsfa120ac2.jpg

Another view
2012-12-28003403_zps69db5dfe.jpg

The other side
2012-12-28003517_zps23b6dc37.jpg

After shrink wrapping
2013-01-07064859_zps2a3d45b4.jpg

The updated code to work with Teensy has been uploaded to github as per the link in the OP.

Offline
  • 0
  • Reputation: 80
  • From: Oslo, Norway
  • Registered: 13-Dec-2006
  • Posts: 4,393

You rock! I was actually wondering here the other day how your project was getting along. Your shrink-wrapped end result looks near perfect - compact and fairly robust too I think?

I want to do this. It's been too long since I fiddled with electronics and I've never fiddled with programming controllers but the time has come thanks to your excellent posts here. Your previous instructions still stand then: Get an Arduino Teensy with USB host shield, download your code (and your library?) and compile? Any more instructions necessary before I embark on this exciting journey?

*** Learn Colemak in 2–5 steps with Tarmak! ***
*** Check out my Big Bag of Keyboard Tricks for Win/Linux/TMK... ***

Offline
  • 0
  • Reputation: 0
  • Registered: 24-Feb-2011
  • Posts: 40

That's a sexy little construction, well done

Offline
  • 0
  • Reputation: 3
  • Registered: 21-Apr-2010
  • Posts: 776

Plus one!  Looks totally unobtrusive.  Great stuff.

--
Physicians deafen our ears with the Honorificabilitudinitatibus of their heavenly Panacaea, their sovereign Guiacum.

Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

DreymaR, glad that this little project triggered your interest to go back to dabbling with electronics! The general instruction still stands:

1. Get a Teensy 2.0 (make sure it is the one with no pins, as you will be doing your own soldering) together with the 3.3V regulator (impt!)

2. Get the USB host shield mini (buying a 100uF capacitor is optional but recommended, see next step)

3. Connect up the Teensy with the host shield (as per instructions from prjc website: https://www.pjrc.com/teensy/td_libs_USBHostShield.html)

4. Download the Teensyduino version of Arduino

5. Download the USB host shield library

6. Download my code, compile, and upload to the Teensy

So far the hardware is chugging along just fine. After the shrink wrap, it is fairly robust. There are some minor caveats that you should be take note:

- there is some bug with my current code that may result in some of the key getting "virtually stuck", such that the key ends up repeating itself indefinitely. The only way to stop it is to unplug the teensy. It happens very infrequently so i didn't really spent time to debug it. If you are going to try it as well then i guess it would gimme incentive to resolve the issue. ;)

- all of the media keys would not work. I dunno what is the cause of it. Oleg (the creator of the host shield) told me it is related to the boot protocol. However, i could not resolve this problem. It is not an issue for me (since i don't use media keys). But if you do then this may be a show stopper for you.

Last edited by darkness (17-Jan-2013 04:24:18)
Offline
  • 0
  • Reputation: 0
  • Registered: 16-Jan-2013
  • Posts: 4

Hi Darkness,

Thanks for your work! I'm working on some of these stuff and your code really helps.

What is the reason behind using teensy instead of arduino? Where is the wiring information?

I want to point out that the reason media keys do not work is because they are not in the USB boot keyboard specification, which is a barebone spec intended for BIOS manipulation, and does not includes things like multimedia keys, capslock numlock LED and such. See the "Consumer Page" and "LED page" and "Keyboard Indicators" section on USB keyboard specifications. http://www.usb.org/developers/devclass_docs/Hut1_11.pdf

I'm not sure how bad it is to implement these, if it's just forwarding the entire raw packet, it shouldn't be too bad.

Thanks,

Last edited by cfishy (16-Jan-2013 23:24:06)
Offline
  • 0
  • Reputation: 1
  • Registered: 19-Nov-2012
  • Posts: 20

cfishy, the only reason why I went with a Teensy instead of an Arduino is size. I wanted an implementation that is similar to a USB thumb drive. However, when I first started developing it, I was working on it using an Arduino Leonardo with the full size USB host shield. Only when I had certain level of confidence that I could achieve what I wanted did I went ahead to buy the Teensy with the mini host shield.

The wiring for the Teensy can be found here: https://www.pjrc.com/teensy/td_libs_USBHostShield.html. I have also edited my "instructions" post to make it clearer and easier with all the links included.

One thing I forgot to mention is that the 3.3V regulator and the capacitor are also necessary purchases for using Teensy. The details are as given in the link above.

Oleg also told me that the host shield should support the media keys just fine, but I have not delved deep enough into the issue as of now. Perhaps I would if there are more interest in this project.

Last edited by darkness (17-Jan-2013 04:24:56)
Offline
  • 0
  • Index
  • General
  • Arduino-based hardware keyboard remapper