0

So I flashed the KeyboardMessage example to my Arduino SS Micro ATmega32U4.

When I open an editor and push the button, I would assume the output to be

Zou pressed the button XX times.

(The "Z" is because I use a German keyboard)

In some editors (Arduino IDE, LibreOffice) this assumption is fulfilled.

However, in several other editors (Linux Shell, gedit), most of the times the output is

zou pressed the button 1 times.

starting with a lower case "z".

I use a Debian Testing computer. The only thing I changed in the sketch was the buttonPin as my button is soldered to pin 11.

I noticed, that this problem doesn't occur when the button is pressed a second time shortly after the first message. To investigate this, I coded a little sketch to find the threshold.

This is what I got (in gedit)

output

As line 8 shows, even after 70 millis, the upper case start is not reliable, however, somewhere after 250 millis, the error occurs every time.

My questions are:

  1. What could be the cause for this issue?
  2. How can it be fixed (if necessary, I also welcome a workaround)?

Please tell me if you need any additional information.

[edit] After slightly altering the script, I noticed, that the problem doesn't only occur on the start of a line, but also (although less often) later in the output. See lines 24, 31 and 52 for example

enter image description here

10
  • 1
    Probable a long shot, but do you have any gedit plugins (e.g. ChangeCase plugin) enabled? Also, I hate to be pedantic, but are you sure the "little sketch" matches the output? The "little sketch" has a space between the number and millis (i.e. should produce "90 millis", not "90millis" as shown above). Also, the "little sketch" outputs a capital M in Message - which are all lower case in the above example.
    – GMc
    Commented Sep 5, 2020 at 9:30
  • 1
    yes, i just reread and saw the comment about linux shell. Oh, well it was a long shot :-)
    – GMc
    Commented Sep 5, 2020 at 9:41
  • 1
    What happens if you unplug your normal keyboard while it's running?
    – Majenko
    Commented Sep 5, 2020 at 10:55
  • 1
    As a debugging aid, you may try to use xev to see the keyboards events. When I press Shift-Y on my keyboard, xev shows four distinct events: KeyPress(Shift_L), KeyPress(Y), KeyRelease(Y), KeyRelease(Shift_L). Do you see the same events in the same order? See also Keyboard input in the Arch Linux Wiki (instructive even if you are not using Arch). Commented Sep 5, 2020 at 17:57
  • 1
    use keyboard.press() and keyboard.release() to send the shift key states at the correct time
    – jsotola
    Commented Sep 5, 2020 at 21:22

1 Answer 1

1

I am not sure I have the answer to your problem, just a collection of observations that hopefully steer you in the right direction.

According to your nopaste link, when you send "ON", the first four keyboard events received by xev are: press(Shift_L), press(O), release(Shift_L), release(o). One may notice that there is no point in releasing the Shift key if it's going to be pressed again right away, but let's assume that simply holding Shift is not such a useful optimization. The detail that strikes me is that the last two events look backwards: you usually release the letter before releasing Shift. As a result of releasing Shift first, the release event for the O key reports lowercase "o" as a keysym. I tried this backward way of releasing the keys on a real keyboard, but both gnome-terminal and gedit correctly registered the uppercase letters.

Another detail apparent in the xev dump is that the two key presses (Shit and O) happen at the exact same time. Ditto for the corresponding key releases. Looking at the source of the Keyboard library, it appears that both key presses are sent to the PC as a single "key report". Same for the key releases. This is contrary to what a real keyboard does: actuations on the Shift keys are reported immediately, irrespective of whether other keys are actuated.

You may try to modify the Keyboard library so that the actuations on Shift are sent in their own reports. Maybe something like this (warning: completely untested):

diff --git a/src/Keyboard.cpp b/src/Keyboard.cpp
index 4a948f6..9fbf7b6 100644
--- a/src/Keyboard.cpp
+++ b/src/Keyboard.cpp
@@ -239,6 +239,7 @@ size_t Keyboard_::press(uint8_t k)
        }
        if (k & 0x80) {                     // it's a capital letter or other character reached with shift
            _keyReport.modifiers |= 0x02;   // the left shift modifier
+           sendReport(&_keyReport);        // send the shift key by itself
            k &= 0x7F;
        }
    }
@@ -270,6 +271,7 @@ size_t Keyboard_::press(uint8_t k)
 size_t Keyboard_::release(uint8_t k) 
 {
    uint8_t i;
+   bool has_shift = false;
    if (k >= 136) {         // it's a non-printing key (not a modifier)
        k = k - 136;
    } else if (k >= 128) {  // it's a modifier key
@@ -281,7 +283,7 @@ size_t Keyboard_::release(uint8_t k)
            return 0;
        }
        if (k & 0x80) {                         // it's a capital letter or other character reached with shift
-           _keyReport.modifiers &= ~(0x02);    // the left shift modifier
+           has_shift = true;
            k &= 0x7F;
        }
    }
@@ -295,6 +297,10 @@ size_t Keyboard_::release(uint8_t k)
    }
 
    sendReport(&_keyReport);
+   if (has_shift) {
+       _keyReport.modifiers &= ~(0x02);    // the left shift modifier
+       sendReport(&_keyReport);            // release shift after releasing the letter
+   }
    return 1;
 }
 

Alternatively, as suggested by @jstola in a comment, you may try to press the Shift key by itself. Maybe you don't need to care about the key release, or about any character but the first one (as it is the only one that seems to cause problems). A minimal workaround to try would be:

Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.println("ON");
4
  • Thanks, @EdgarBonet! I can confirm, that your solution works on my computer. However, this raises the question if the "original" Arduino implementation is faulty. I would encourage you to file a pull request on their implementation.
    – speendo
    Commented Sep 10, 2020 at 19:16
  • by the way, the problem doesn't only occur in the first character but also sometimes on later ones.
    – speendo
    Commented Sep 10, 2020 at 19:17
  • 1
    @speendo: I am reluctant to submit a pull request, as I do not have a 32U4-based Arduino to test it. I would do it, though, if you are willing to help with the testing: provide a minimal test sketch, run it, and report the results on the pull request page. Commented Sep 10, 2020 at 19:54
  • Of course I am willing to help. Using this library (github.com/NicoHood/HID) you could also use test your code with another Arduino board (this is the library where I first experienced the error) But I would also fund you a cheap Pro Micro board as a little recognition for your work. Just tell me what solution(s) you like best :)
    – speendo
    Commented Sep 10, 2020 at 21:01

Your Answer

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

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