Arduino: Tastatureingaben durchleiten in 100 Zeilen

Und weiter geht's in der Erstellung meines Arduino-Projektes. Nachdem ich beim letzten Mal gezeigt hatte, welche Problem das Arduino-Board beim Ausgeben von Tastaturinformationen hat und nachdem ich dafür eine potentielle Lösung implementiert hatte, wollte ich euch mal zeigen, was man damit zum Beispiel machen kann.

Als Grundlage verwende ich hierfür ein Arduino Leonardo und ein USB-Host-Shield der Firma Circuits@Home (z.B. bei Lipoly.de erhältlich). Es gibt auch noch eine Variante von Sparkfun - diese hat jedoch wohl mit einigen Problemen zu kämpfen und wird aus diesem Grund nicht empfohlen.
Für dieses USB-Host-Shield, das einfach auf das Arduino-Board aufgesteckt werden kann, gibt es eine Bibliothek, die man benutzen sollte, da sie einem sehr viel Arbeit abnimmt. Diese Bibliothek wird ebenfalls von Circuits@Home entwickelt - ein weiterer Grund, das Originalshield von ihnen zu verwenden. 🙂

Mit Hilfe dieser Bibliothek und der Tastaturausgabe-Lösung, die ich am Anfang des Artikels verlinkt habe, ist es möglich, in 100 Codezeilen Tastatureingaben über das USB-Host-Shield einzulesen und über die Tastaturfunktion des Arduino-Boards wieder auszugeben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <hidboot.h>

class KbdRptParser : public KeyboardReportParser {
    private:
        void handleModifiers(uint8_t mod);
    protected:
        virtual void OnKeyDown(uint8_t mod, uint8_t key);
        virtual void OnKeyUp(uint8_t mod, uint8_t key);
        virtual void OnKeyPressed(uint8_t key);
};

void KbdRptParser::handleModifiers(uint8_t mod) {
    MODIFIERKEYS modifier;
    *((uint8_t*)&modifier) = mod;

    if (modifier.bmLeftCtrl == 1) {
        Keyboard.pressKeycode(KEYCODE_LEFT_CTRL, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_LEFT_CTRL, false);
    }
    if (modifier.bmLeftShift == 1) {
        Keyboard.pressKeycode(KEYCODE_LEFT_SHIFT, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_LEFT_SHIFT, false);
    }
    if (modifier.bmLeftAlt == 1) {
        Keyboard.pressKeycode(KEYCODE_LEFT_ALT, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_LEFT_ALT, false);
    }
    if (modifier.bmLeftGUI == 1) {
        Keyboard.pressKeycode(KEYCODE_LEFT_GUI, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_LEFT_GUI, false);
    }
   
    if (modifier.bmRightCtrl == 1) {
        Keyboard.pressKeycode(KEYCODE_RIGHT_CTRL, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_RIGHT_CTRL, false);
    }
    if (modifier.bmRightShift == 1) {
        Keyboard.pressKeycode(KEYCODE_RIGHT_SHIFT, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_RIGHT_SHIFT, false);
    }
    if (modifier.bmRightAlt == 1) {
        Keyboard.pressKeycode(KEYCODE_RIGHT_ALT, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_RIGHT_ALT, false);
    }
    if (modifier.bmRightGUI == 1) {
        Keyboard.pressKeycode(KEYCODE_RIGHT_GUI, false);
    } else {
        Keyboard.releaseKeycode(KEYCODE_RIGHT_GUI, false);
    }
}

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) {
    if (digitalRead(2) == LOW) {
        handleModifiers(mod);
        Keyboard.pressKeycode(key, true);
    }
}

void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)   
{
    if (digitalRead(2) == LOW) {
        handleModifiers(mod);
        Keyboard.releaseKeycode(key, true);
    }  
}

void KbdRptParser::OnKeyPressed(uint8_t key)   
{
    // do nothing
};

USB                            HidUsb;
HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&HidUsb);
KbdRptParser                   HidKeyboardParser;

void setup() {
    if (HidUsb.Init() != -1) {
        // activate Arduino Leonardo HID keyboard driver
        Keyboard.begin();

        // enable security pin
        // will only work when
        // PIN 2 is connected to ground
        pinMode(2, INPUT);
        digitalWrite(2, HIGH);

        HidKeyboard.SetReportParser(0, (HIDReportParser*)&HidKeyboardParser);
    }
}

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

Beachtet, dass Pin 2 mit Ground verbunden sein muss, damit das ganze funktioniert. Warum ich das so gemacht habe, könnt ihr bei den Informationen zur Maus- und Tastatur-API nachlesen:

A word of caution on using the Mouse and Keyboard libraries: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as Mouse.move() and Keyboard.print() will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control.

Aber wofür ist das ganze nun gut?

Im ersten Schritt zeigt es, wie einfach es sein kann, Tastatureingaben auszulesen und Tastatureingaben zu tätigen. Wie schon gesagt: Die verfügbaren Libraries nehmen einem hierbei viel Arbeit ab. Zudem ist es ein toller Ausgangspunkt, um weiterführende Dinge zu implementieren. Man könnte statt einer normalen Tastatur zum Beispiel einen Nummernblock nehmen und das Arduino zum Taschenrechnung umfunktionieren, der beim drücken der Enter-Taste das berechnete Ergebnis an den Computer überträgt. Oder ihr seid so fies wie Darran aus Neuseeland und bastelt einen Aprilscherz, der nach einem zufälligen Muster die Tasten vertauscht. 🙂
Tastaturgesteuerte Grüße, Kenny

Schreibe einen Kommentar

Um Ihnen beim weiteren Kommentieren auf dieser Webseite die erneute Eingabe Ihrer Daten zu ersparen, wird beim Absenden Ihres Kommentars ein Cookie an Ihren Browser gesendet und von diesem gespeichert. Mit dem Absenden eines Kommentars auf dieser Webseite stimmen Sie der Speicherung und Übertragung dieses Cookies explizit zu.

Pflichtfelder sind mit * markiert.