Arduino клавиатура

Суть такова: Есть код, который при нажатии на клавиатуре правого Ctlr должен включать светодиод, а при отпускании - тушить (в будущем планируется навесить релюшку для включения/выключения домофона). Делать внешний обвес (с дополнительной кнопкой) не хочется, хочется именно через клавиатуру и именно через правый (или хоть какой) Ctrl (им обычно не пользуюсь).

Собственно код программы такой:

#if ARDUINO >= 10606        //Долго искал, сначала ошибки сыпались
#include <Keyboard.h>       //Где-то на задворках такое решение встретил
#define HID_SendReport(id,data,len) HID().SendReport(id,data,len)
#endif                      //Без этого не работает (не компилирует)

#include <hidboot.h>
#include <SPI.h>

//  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .
//  Работа с ПК
class KeyboardOut {
    private:
        KeyReport _keyReport;   //8 bytes of coding
        void send_report();
    public:
        size_t press(uint8_t mod, uint8_t key);
        size_t release(uint8_t mod, uint8_t key);
};

KeyboardOut keyboard_out;

//  Нажатие в ПК
size_t KeyboardOut::press(uint8_t mod, uint8_t key) {
    uint8_t i;
    _keyReport.modifiers |= mod;
    if (_keyReport.keys[0] != key && _keyReport.keys[1] != key && 
    _keyReport.keys[2] != key && _keyReport.keys[3] != key &&
    _keyReport.keys[4] != key && _keyReport.keys[5] != key) {
        for (i = 0; i < 6; i++) {
            if (_keyReport.keys[i] == 0x00) {
                _keyReport.keys[i] = key;
                break;
            }
        }
        if (i == 6) {return 0;}
    }
    send_report();
    return 1;
}

//  Отпускание в ПК
size_t KeyboardOut::release(uint8_t mod, uint8_t key) {
    uint8_t i;
    _keyReport.modifiers &= mod;
    for (i = 0; i < 6; i++) {if (0 != key && _keyReport.keys[i] == key) {_keyReport.keys[i] = 0x00;}}
    send_report();
    return 1;
}

//  Отправка в ПК
void KeyboardOut::send_report() {HID_SendReport(2, &_keyReport, sizeof(KeyReport));}

//  . . . . . . . . . . . . . . . . . . . .
//  Работа с клавиатурой
class KeyboardIn : public KeyboardReportParser {
    protected:
        void OnKeyDown (uint8_t mod, uint8_t key);
        void OnKeyUp (uint8_t mod, uint8_t key);
};

KeyboardIn keyboard_in;

/*
    KEY_LEFT_CTRL       0x80
    KEY_LEFT_SHIFT      0x81
    KEY_LEFT_ALT        0x82
    KEY_LEFT_GUI        0x83
    KEY_RIGHT_CTRL      0x84
    KEY_RIGHT_SHIFT     0x85
    KEY_RIGHT_ALT       0x86
    KEY_RIGHT_GUI       0x87
*/

//  Нажатие от клавиатуры
void KeyboardIn::OnKeyDown(uint8_t mod, uint8_t key) {
    keyboard_out.press(mod, key);
    if(key == 0x84) {digitalWrite(4, HIGH);}        //Если клавиша правый Ctrl - зажечь
    if(mod == 1) {digitalWrite(4, HIGH);}   //Если модификатор Ctrl - зажечь
    PrintHex<uint8_t>(key, 0x80);               //Какая клавиша нажата
}

//  Отпускание клавиатуры
void KeyboardIn::OnKeyUp(uint8_t mod, uint8_t key) {
    keyboard_out.release(mod, key);
    if(key == 0x84) {digitalWrite(4, LOW);} //Если клавиша правый Ctrl - потушить
    if(mod == 1) {digitalWrite(4, LOW);}        //Если модификатор Ctrl - потушить
    PrintHex<uint8_t>(key, 0x80);           //Какая клавиша отжата
}

USB UsbHost;
HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&UsbHost);

//  . . . . . . . . . . . . . . . . . . . .
void setup() {
    pinMode(4, OUTPUT);
    UsbHost.Init();
    delay(200);
    HidKeyboard.SetReportParser(0, (HIDReportParser*) & keyboard_in);
}

void loop() {
    UsbHost.Task();
}

Дополнительно используется библиотека USB_Host_Shield_Library_2.0

Но вот в чём заковырка: Буквы, цифры он нормально даёт, с Shift и Alt тоже. Но если отдельно нажимать Alt, Ctrl, или Shift - ничего не происходит... Я пробовал и клавишу Ctrl отлавливать и его модификатор... Но модификаторы работают только, если нажата ещё какая клавиша (буква-цифра) :(

Пытался искать по библиотеке: но в итоге просто прыгал от одного файла к другому, потом к третьему, потом к файлам самой ардуины и обратно... Целый день словно белка в колесе - результата ноль :(

Как можно отловить Ctrl с клавиатуры?

В данной реализации ардуина втыкается в разрыв между клавой и компом (клава в USB Shield, Ардуина в комп), т.к. Ctrl надо ловить с моей рабочей клавиатуры. Слышал можно ещё 2 провода данных от USB выкинуть (сделать типа разветвителя) и с них "слушать", но это вроде для Аемел студии.

Проблема ещё и в том, что слчетание Alt + Shift не работает (для переключения языка), дык ещё и Shift словно залипает (нажимаю Shift, потом кнопку буквы, потом отпускаю кнопку буквы - получаю большую букву, отпускаю Shift, нажимаю следующую букву (Shift отпущен), отпускаю (Shift всё ещё отпущен) - снова получаю большую, третяя уже нормально. Это закономерность, так всегда и со всеми буквами-цифрами).

Можно-ли как-то подобным приведённому выше методу получать нажатия ещё и Shift, Alt, Ctrl, причём без всяких модификаторов? Их я и сам могу, если что, добавить.

На вопрос тех, кто не думает отвечать на мой, а только начать кислотно тошнить: А зачем тебе это? Навесь на сопли микрокнопку/тумблер/бытовой выключатель/автомат/релейный пускатель/голые 2 проводка - и их зажимай... Мне интересно именно с клавиатуры - места на столе мало, даже микрокнопку некуда нормально воткнуть (привинтить/приклеить), поэтому интересно именно такое решение. Так что варианты с выносными кнопками/проводками/тумблерами не рассматриваются...

Ардуина свежая, библиотека тоже, ардуина на 32u4 всё поддреживает (иначе-б сыпались ошибки при попытке скомпилировать).


Ответы (0 шт):