3

I'm playing with the Arduino Leonardo Keyboard.print() command, but I'm facing a annoying problem:

When I print a double quote, it will not appear and also will make to disappear the next character (i.e.):

Keyboard.print("echo \"This is a demo\"");

Output:

echo his is a demo

And when I use this line:

Keyboard.print("echo -This is \"a demo-");

Output (note the umlaut over the a instead of getting "a):

echo 'This is ä demo'

I suspect that the problem is that my computer is configured to use Spanish layout.

What source code file can I change to fix this? I can't find the defines used by Keyboard.print()

2 Answers 2

1

In your particular case, the double quote is to be entered (using the Spanish keyboard layout) by Shift + the physical key labelled 2. On a US keyboard, Shift + the physical key labelled 2 is "@".

Thus, this simply will get the desired result (the Arduino library assumes a US keyboard layout):

Keyboard.print("echo @This is a demo@");

More general solution

More generally, strings can be encoded as in the following table (the exact mappings depend on the particular keyboard layout - this will work for many European keyboard layouts).

If the physical key (and modifier key, if any) exists on the US keyboard to get the character typed out using the non-US keyboard layout, then this method works fine.

To get   Use   Notes
--------------------------------------------
;        <     Will result in Shift action
:        >     Will result in Shift action
(        *     Will result in Shift action
)        (     Will result in Shift action
/        &     Will result in Shift action
?        _     Will result in Shift action
=        )     Will result in Shift action
&        ^     Will result in Shift action

-        /
+        -
_        ?

"        @     Will result in Shift action

,        ,     The same
.        .     The same
#        #     The same

Even more general solution

Even more generally, some keys are not on the US keyboard (e.g. the 102th key on European keyboards for the original PC keyboards, often with <, >, \, and |), and it is not possible to use Keyboard.print().

Instead, use the low-level HID().SendReport() function - with code 100 (decimal) for the first parameter for the 102th key. See the library source code, Keyboard.cpp (/libraries/Keyboard/src/Keyboard.cpp), for how to use HID().SendReport().

Alternative solution

Some operating systems enable entering characters using the keyboard and a numeric code.

This is at the expense of making it operating-system dependent (but making it independent of the active keyboard layout).

For example, Ctrl + Shift + U on Linux (GUI only, dependent on the window manager(?)). For the particular problem (the Unicode code point for " is 0022), without any functional abstraction to reduce the redundancy:

Keyboard.print("echo ");

Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press('u');
Keyboard.releaseAll();
Keyboard.print("0022");
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();

Keyboard.print("This is a demo");

Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press('u');
Keyboard.releaseAll();
Keyboard.print("0022");
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();

Unicode code points can be found at unicode-table.com.

Media keys

Even though the media keys are listed in the table (e.g. code 128 for "Volume Up" on page 53), they do not work using the method described in the previous section. But there is a solution.

Platform

This was tested with:

  • Arduino Leonardo
  • The Spanish keyboard layout was added to the Linux settings and activated. There were 14 different ones to choose from, but I used the one labelled "Spanish". It was verified that "@" actually resulted in an output of """. It was also verified that the Ctrl + Shift + U method worked.
  • Linux, Ubuntu 19.10 (Eoan Ermine), but with the buggy GNOME replaced by Cinnamon.
  • The Arduino Leonardo connected to an extra current port of a D-Link USB hub (necessary, for unknown reasons - probably a local problem)
  • Arduino IDE v. 1.18.10
5
  • I know this because I have implemented it for a macro keyboard where the keyboard layout is (usually) Danish in the operating system (Windows or Linux). May 8, 2020 at 15:07
  • 1
    Excellent answer!
    – 0x2b3bfa0
    May 9, 2020 at 3:52
  • (Code 128 for "Volume Up" is on page 56, not 53.) May 19, 2022 at 14:48
  • 1
    (For a future update: The first link doesn't actually show the double quote will be entered by Shift + 2. It ought to be replaced by something better. For example, this one.) Sep 17 at 10:18
  • (For a future update: Both "#" and "?" will also result in a Shift action (Shift + 3 and "/", respectively). And consider using Markdown tables, if available. 102th102nd (?).) Sep 21 at 19:36
5

The Arduino assumes a US keyboard layout. The thing with keyboards is they don't actually send the letters or symbols that are printed on the keys. Instead the send a scan code that defines where on the keyboard the key is. It is then up to the computer to convert those scan codes into actual letters and symbols, and that is performed by the keyboard mapping selected in the operating system.

Some special keys are known as dead keys. These don't actually print a character on their own - instead they are used to modify the next key pressed - for instance the key which occupies the space a " would be on a US keyboard, on a Spanish keyboard, is a dead key which modifies the next key by adding an umlaut to it.

Since the Arduino doesn't know that you have a Spanish mapping, when you send a " it just sends what it believes is the location of that character on a keyboard, and of course it gets that wrong since it assumes the wrong keyboard layout.

So there are two things you can do to "fix" it:

  1. Change your keyboard layout to US, but that will mean your normal keyboard will stop working properly.
  2. Change how the Arduino thinks the keyboard is laid out, but that means lots of work to find the right scan codes.

The Arduino's keyboard layout is stored in the file HID.cpp in the Arduino core (hardware\avr\cores\arduino or somewhere like that - I forget off hand) and is the _asciimap array. It is a list of the first 128 ASCII characters and the keyboard scancode mappings for them, including modifier keys like Shift. You will have to find the scan codes for the keys you want to map on your keyboard layout and change the codes in that list. For instance, the character " is listed as:

0x34|SHIFT,    // "

Which is scan code 0x34 (52 decimal) coupled with the SHIFT modifier. You will have to discover (maybe Google can help) what the 0x34 should be changed to so that it moves the " to wherever it is on a Spanish keyboard.

2
  • +35: Thank you very much! When I find the exact file location I'll tell you it!
    – 0x2b3bfa0
    Oct 21, 2015 at 9:05
  • In my computer is located in /usr/share/arduino/hardware/arduino/cores/arduino/HID.cpp. I'll try to override these mappings with some custom ones.
    – 0x2b3bfa0
    Oct 21, 2015 at 9:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.