Cherry-Tastatur mit OLED – Teil 2

1

03.11.2017 von plaintron

Auswahl einer geeigneten HID-Library

Weiter geht es mit meinem Tastatur-Umbau. Im ersten Teil habe ich über die Auswahl des Controllers geschrieben und mich letztendlich für einen Teensy++ 2.0 entschieden.

Teensy-Boards können, wie auch Arduino-Boards mit 32u4-Controller, als HID-Client arbeiten (Human Interface Device), also eine Tastatur, eine Maus oder einen Joystick imitieren. Zu den Standard-Funktionen des Leonardo-Boards gehören entsprechende Befehle, die in den Bibliotheken Mouse und Keyboard zusammengefasst sind.

Mit Keyboard.begin() wird die Keyboard-Klasse gestartet und kann dann etwa mit print oder press Befehle via USB an den PC senden. Das funktioniert standardmäßig allerdings nur mit normalen Zeichen und nicht für Sondertasten und speziellen Betriebssystem-Funktionen (z.B. Lautstärke, Browsersteuerung). Außerdem brauchen wir auch eine Unterstützung für Tastenkombinationen.

Für den Teensy sind diverse HID-Bibliotheken verfügbar. Die Suche nach der richtigen Bibliothek hat einigen Zeitaufwand und diverse Tests erfordert. So bin ich bei der sehr umfangreichen Library „keybrd“ gelandet, welche mehrere Tastatur-Ebenen unterstützt, mit Port-Expandern arbeiten kann und außerdem durch ein umfangreiches Tutorial gut dokumentiert ist. Von dieser Bibliothek nutze ich nur einen Teil und habe außerdem eine kleine Veränderung vorgenommen, um damit Hardware-Makros bauen zu können.

Die Library ist sehr ordentlich und professionell programmiert, macht es durch konsequente Verkapselung allerdings auch nicht ganz leicht, vom Arduino-Sketch in die Library einzugreifen.

Der Tastatur-Scanner

Folgende Dateien der keybrd-Library habe ich verwendet:

#include <Code_Sc.h>
#include <Row.h>
#include <Scanner_uC.h>
#include <ScanDelay.h>

Kernstück der Library ist der sogenannte „Scanner“. Diese Klasse tastet zeilenweise die einzelnen Kontakte der Tastatur ab. Jeder Taste ist ein Objekt zugeordnet, das ihren aktuellen Status repräsentiert. Interessant ist hier die sehr klug ausgeführte Entprellung. Wenn ein Taster geschlossen wird, erzeugt er eine Folge von An- und Aus-Zuständen, die ohne Entprellungsmaßnahme als mehrfacher Tastendruck interpretiert würde. Die einfachste Entprellung ist ein Delay. Das senkt allerdings die maximale Tippgeschwindigkeit, wenn es zu lang ist, oder wird unzuverlässig, wenn es zu kurz ist. Die keybrd-Bibliothek nutzt einen getakteten Ringpuffer, in dem alle Ereignisse eines Tasters gespeichert werden. Erst wenn eine definierte Anzahl von aufeinander folgenden Ereignissen identisch ist (z.B. 10x hintereinander „Taster geschlossen“), wird das Tastatur-Ereignis ausgewertet und gesendet.

By MuhannadAjjan (Own work) [CC BY-SA 4.0], via Wikimedia Commons

Ein Scanner-Objekt wird durch Übergabe des aktiven Logik-Levels (high oder low) sowie  eines Arrays für die zu lesenden Pins erzeugt:

const uint8_t readPins[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18};
const uint8_t rowPins[] = {25,26,27,28,29,30,31,32};
const uint8_t num_cols = sizeof(readPins)/sizeof(*readPins);
const uint8_t num_rows = sizeof(rowPins)/sizeof(*rowPins);

Scanner_uC scanner(LOW, readPins, num_cols);

Im Code oben ist noch ein Array rowPins zu sehen. Das sind die Ausgänge, über welche jeweils ein Puls auf die Zeilen der Tastatur-Matrix gelegt wird.

Damit der Controller weiß, bei welcher Taste welcher Scancode an den PC geschickt werden soll, brauchen wir eine Matrix, ein zweidimensionales Array, in dem alle Tastencodes gespeichert sind. Fast alle Scancodes sind im Teensy-Code durch Konstanten vordefiniert.

const uint16_t keys_row[num_rows][num_cols] = {
 {KEY_TILDE,KEY_F1,KEY_F2,KEY_5,KEY_6,KEY_F8,KEY_MINUS,KEY_EQUAL, ...},
 {KEY_TAB,KEY_CAPS_LOCK,KEY_F3,KEY_T,KEY_Y,KEY_F7,KEY_LEFT_BRACE, ...},
 {KEY_ESC,KEY_NON_US_BS,KEY_F4,KEY_G,KEY_H,27,KEY_QUOTE,KEY_F6, ...},
 {5,1,2,KEY_B,KEY_N,28,KEY_SLASH,4,KEY_SPACE,KEY_RIGHT_ALT, ...}, 
 {KEY_Z,KEY_X,KEY_C,KEY_V,KEY_M,KEY_PERIOD,ASCII_23,KEY_COMMA, ...}, 
 {KEY_A,KEY_S,KEY_D,KEY_F,KEY_J,KEY_L,KEY_SEMICOLON,KEY_K, ...}, 
 {KEY_Q,KEY_W,KEY_E,KEY_R,KEY_U,KEY_O,KEY_P,KEY_I,3, ...},
 {KEY_1,KEY_2,KEY_3,KEY_4,KEY_7,KEY_9,KEY_0,KEY_8,KEY_F10, ...}
};

Im Ausschnitt oben zeige ich nur einen Teil dieser Matrix, damit er hier nicht das Layout sprengt. An einigen Stellen steht kein Scancode, sondern eine Zahl < 30. Diese kennzeichnen die Makrotasten und werden später verwendet, um statt den Scancode zu senden eine Tastenfolge zu erzeugen.

Nun brauchen wir noch Arrays für die Tasten- und die Zeilen-Objekte:

Key* ptrsKeys[8][18]; 
Row* scanrows[8]; 
ScanDelay scanDelay(9000);

Außerdem wird noch die Scan-Geschwindigkeit mit ScanDelay festgelegt. Weiter geht es in der Setup-Routine des Sketches:

void setup()
{ 
 Serial.begin(9600);
 for(uint8_t r = 0; r < num_rows; r++){
   scanrows[r] = new Row(scanner, rowPins[r], ptrsKeys[r], num_cols); 
   scanrows[r]->setDelegate(checkMacro, r); 
   for(uint8_t i = 0; i < num_cols; i++){ 
     ptrsKeys[r][i] = new Code_Sc (keys_row[r][i]); 
   }
 } 
}

Serial dient nur zum debuggen. In einer Schleife werden nun die Row-Objekte erzeugt. Diese benötigen eine Referenz zum Scanner, dem zugehörigen Zeilenpin (rowPins[r]), den Tasten-Objekten (ptrsKeys[r]) sowie die Anzahl der Tasten in der jeweiligen Zeile. Die Zuordnung der jeweiligen Tastenfunktionen erfolgt dann in der inneren Schleife.

Die Loop selbst ist nun sehr übersichtlich:

void loop()
{ 
 for(uint8_t i = 0; i < num_rows; i++){
   (*scanrows[i]).process(); 
 } 
 scanDelay.delay(); 
}

Bei jeden Schleifendurchlauf wird die process-Methode einer jeden Matrix-Zeile aufgerufen, welche sich dann um Debouncing und Kommunikation mit dem PC kümmert. Zwischen den Durchläufen findet eine Verzögerung statt. Diese wird nicht mit dem normalen delay()-Befehl vorgenommen, damit der Controller in der Zwischenzeit andere Aufgaben abarbeiten kann. Das ist auch notwendig, wie wir in einem der nächsten Teile dieses Beitrags sehen werden. Mit diesem Code ist die Tastatur auf jeden Fall schon funktionsfähig, nur die Zusatzfunktionen für die Arbeit mit Makros fehlt noch.

Teil 1: https://plaintron.wordpress.com/2017/11/02/cherry-tastatur-mit-oled-teil-1/

 

Advertisements

Ein Kommentar zu “Cherry-Tastatur mit OLED – Teil 2

  1. […] Cherry-Tastatur mit OLED, Teil 2 […]

    Gefällt mir

Kommentieren

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Blogverzeichnis - Bloggerei.de
%d Bloggern gefällt das: