Клавиатура Arduino стартует строчными буквами (но не должна)

Поэтому я записал пример KeyboardMessage на свой Arduino SS Micro ATmega32U4.

Когда я открываю редактор и нажимаю кнопку, я предполагаю, что вывод будет

Зоу нажал кнопку XX раз.

("Z" означает, что я использую немецкую клавиатуру)

В некоторых редакторах (Arduino IDE, LibreOffice) это предположение выполняется.

Однако в некоторых других редакторах (Linux Shell, gedit) в большинстве случаев выводится

Зоу нажал кнопку 1 раз.

начиная со строчной буквы "z".

Я использую тестовый компьютер Debian. Единственное, что я изменил в скетче, это buttonPin, так как моя кнопка припаяна к 11-му контакту.

Я заметил, что эта проблема не возникает при повторном нажатии кнопки вскоре после первого сообщения. Чтобы исследовать это, я написал небольшой набросок, чтобы найти пороговое значение.

Вот что у меня получилось (в gedit)

output

Как видно из строки 8, даже после 70 миллисекунд начало в верхнем регистре ненадежно, однако где-то после 250 миллисекунд ошибка возникает каждый раз.

Мои вопросы:

  1. В чем может быть причина этой проблемы?
  2. Как это можно исправить (при необходимости я также приветствую обходной путь)?

Если вам нужна дополнительная информация, сообщите мне.

[править] Немного изменив скрипт, я заметил, что проблема возникает не только в начале строки, но и (хотя и реже) позже в выводе. См. строки 24, 31 и 52, например

, 👍0

Обсуждение

Вероятно, далеко, но включены ли у вас какие-либо плагины gedit (например, плагин ChangeCase)? Кроме того, я ненавижу быть педантичным, но вы уверены, что «маленький набросок» соответствует результату? «Маленький набросок» имеет пробел между числом и миллисекундами (т. е. должно давать «90 миллисекунд», а не «90 миллисекунд», как показано выше). Кроме того, «маленький набросок» выводит заглавную букву М в сообщении, которое в приведенном выше примере все в нижнем регистре., @GMc

Спасибо за ваш комментарий! У меня действительно включены некоторые плагины gedit, однако они не должны менять регистр. Я также пробовал в оболочке Linux и получил тот же результат. По поводу изменений в скетче: вы правы - эти две вещи я изменил после запуска скетча. Однако я не хотел запускать его снова, так как это занимает довольно много времени., @speendo

да, я только что перечитал и увидел комментарий о оболочке Linux. Эх, далековато это было :-), @GMc

Без каких-либо знаний в этой области я предполагаю, что «медленные редакторы» работают лучше, чем «быстрые редакторы», и что клавиша Shift каким-то образом проглатывается где-то между ардуино и компьютером., @speendo

Что произойдет, если вы отключите обычную клавиатуру во время ее работы?, @Majenko

@Majenko только что попробовал: все точно так же., @speendo

В качестве средства отладки вы можете попробовать использовать xev для просмотра событий клавиатуры. Когда я нажимаю Shift-Y на клавиатуре, xev показывает четыре различных события: KeyPress(Shift\_L), KeyPress(Y), KeyRelease(Y), KeyRelease(Shift\_L). Вы видите одни и те же события в том же порядке? См. также [Ввод с клавиатуры](https://wiki.archlinux.org/index.php/Keyboard_input) в Arch Linux Wiki (поучительно, даже если вы не используете Arch)., @Edgar Bonet

используйте keyboard.press() и keyboard.release() для отправки состояний клавиши Shift в нужное время, @jsotola

Извините за поздний ответ. @EdgarBonet спасибо за совет xev. Я написал небольшой скетч, который должен печатать «ON», когда я нажимаю кнопку на Arduino. Это вывод в xev: https://nopaste.xyz/?b4efb9869c386975#22qZaCvBxQ2HfuTxEGszxdxnLbf18qTNuuCToR9JfwpA. В таком редакторе, как gedit, это читается как «oN»., @speendo

@jsotola это был бы возможный обходной путь. Однако, таким образом, мне нужно было бы различать те символы, которым нужна кнопка переключения, и те, которым она не нужна. Я надеялся, что библиотека клавиатуры поможет мне., @speendo


1 ответ


Лучший ответ:

1

Я не уверен, что у меня есть ответ на вашу проблему, просто набор наблюдения, которые, надеюсь, направят вас в правильном направлении.

Согласно вашей ссылке без вставки, когда вы отправляете "ВКЛ", первые четыре события клавиатуры, полученные xev: нажатие (Shift_L), нажатие (O), отпустить(Shift_L), отпустить(о). Можно заметить, что нет смысла отпуская клавишу Shift, если ее нужно сразу нажать еще раз, но давайте предположим, что простое зажатие Shift не такое уж и полезное оптимизация. Деталь, которая поражает меня, заключается в том, что последние два события посмотрите назад: обычно вы отпускаете букву перед отпусканием Shift. В результате отпускания Shift первым событие отпускания клавиши O сообщает нижний регистр "o" как keysym. Я попробовал этот обратный способ отпускание клавиш на настоящей клавиатуре, но как в gnome-терминале, так и в gedit правильно зарегистрировал заглавные буквы.

Еще одна деталь, очевидная в дампе xev, заключается в том, что нажатие двух клавиш (Дерьмо и О) происходят в одно и то же время. То же самое для соответствующего ключевые релизы. Глядя на источник библиотеки клавиатуры, он появляется что оба нажатия клавиш отправляются на ПК как единый «клавишный отчет». Такой же для ключевых релизов. Это противоречит тому, что делает настоящая клавиатура: срабатывание клавиш Shift сообщается немедленно, независимо от нажаты ли другие клавиши.

Вы можете попробовать изменить библиотеку клавиатуры так, чтобы нажатия на Смены отправляются в собственных отчетах. Может быть, что-то вроде этого (предупреждение: полностью не проверено):

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) {                     // это заглавная буква или другой символ, достигнутый с помощью shift
            _keyReport.modifiers |= 0x02;   // модификатор сдвига влево
+           sendReport(&_keyReport);        // отправляем саму клавишу Shift
            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) {         // это непечатаемый ключ (не модификатор)
        k = k - 136;
    } else if (k >= 128) {  // это ключ-модификатор
@@ -281,7 +283,7 @@ size_t Keyboard_::release(uint8_t k)
            return 0;
        }
        if (k & 0x80) {                         // это заглавная буква или другой символ, достигнутый с помощью shift
-           _keyReport.modifiers &= ~(0x02);    // модификатор сдвига влево
+           has_shift = true;
            k &= 0x7F;
        }
    }
@@ -295,6 +297,10 @@ size_t Keyboard_::release(uint8_t k)
    }
 
    sendReport(&_keyReport);
+   if (has_shift) {
+       _keyReport.modifiers &= ~(0x02);    // модификатор сдвига влево
+       sendReport(&_keyReport);            // отпускаем shift после отпускания буквы
+   }
    return 1;
 }
 

В качестве альтернативы, как предложил @jstola в комментарии, вы можете попробовать нажмите клавишу Shift отдельно. Может быть, вам не нужно заботиться о отпускание клавиши, или о любом символе, кроме первого (поскольку это единственный тот, который, кажется, вызывает проблемы). Минимальный обходной путь, который можно попробовать:

Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.println("ON");
,

Спасибо, @EdgarBonet! Я могу подтвердить, что ваше решение работает на моем компьютере. Однако возникает вопрос, не является ли «оригинальная» реализация Arduino неисправной. Я бы посоветовал вам подать запрос на их реализацию., @speendo

кстати, проблема возникает не только с первым символом, но иногда и с более поздними., @speendo

@speendo: я не хочу отправлять запрос на вытягивание, так как у меня нет Arduino на базе 32U4 для его тестирования. Я бы сделал это, если вы готовы помочь с тестированием: предоставить минимальный тестовый скетч, запустить его и сообщить о результатах на странице запроса на включение., @Edgar Bonet

Конечно, я готов помочь. Используя эту библиотеку (https://github.com/NicoHood/HID), вы также можете протестировать свой код на другой плате Arduino (в этой библиотеке я впервые столкнулся с ошибкой). Но я бы также выделил вам дешевую плату Pro Micro. как небольшое признание вашей работы. Просто скажите мне, какое решение (я) вам больше всего нравится :), @speendo