M5Stackキーボードを利用する
2020.03.27
YouTubeでポイントを説明しています。画像をクリックすると再生できます。
今回はM5Stack用キーボードをラズベリーパイで利用します。
M5Stack用カード型キーボード UNIT CardKB は、M5Stackにフル機能のQWERTY(クワーティ)配列キーボードを実装できるユニットです。
QWERTY配列は、デファクトスタンダードなキー配列です。
CardKBでは、複数のボタンの組み合わせ(Sym + Key、Shift + Key、Fn + Key)で豊富なキーの値を出力することが可能です。
Grove Aポート(I2Cインタフェース)経由でM5Coreと通信します。アドレスは0x5Fに設定されています。

このキーボードの特徴は、普通のキーボードのようにファンクションキーやシフトキーを押しながら、別のキーを押すことはしません。
ファンクションキーなどを押して、LEDが点滅している間に、別のキーを押すといった感じで、片手操作が可能です。
■Arduino Leonardo(Pro Micro)のHID(キーボード)機能を使う
Arduino LeonardoはPCなどとUSB接続したとき,自身をHID(ヒューマン・インターフェイス・デバイス/入出力装置)として認識させる機能が標準で備わっています。
CardKBをI2C接続でLeonardoを介することで、キーボードとして利用することが可能になります。
HID機能はArduinoの中でもATmega32u4マイコンを搭載したLeonardoやMicro,ProMicro,他にDue,Zeroなど限られたボードで動作します。
■構成図

テスト環境は以下の通りです。
・UNIT CardKB
・Arduino Leonardo (micro, Pro Micro)
・Raspberry Pi Zero W
ラズパイのディストリビューションは、Raspbian Stretch です。
■Arduino Leonardo 動作確認
開発環境に、PlatformIOを用います。
詳細は、→ Arduino開発環境構築 PlatformIO
を参考にしてください。
$ platformio device list
/dev/ttyACM0
------------
Hardware ID: USB VID:PID=2341:8036 LOCATION=1-1:1.0
Description: Arduino Leonardo
/dev/ttyAMA0
------------
Hardware ID: 20201000.serial
Description: ttyAMA0
$ platformio boards "Leonard"
Platform: atmelavr
---------------------------------------------------------------------
ID MCU Freq. Flash RAM Name
---------------------------------------------------------------------
leonardo ATMEGA32U4 16MHz 28KB 2.50KB Arduino Leonardo
leonardoeth ATMEGA32U4 16MHz 28KB 2.50KB Arduino Leonardo ETH
プロジェクトの作成
$ mkdir -p ~/leonardo/M5Stack
$ cd ~/leonardo/M5Stack
$ platformio init -b leonardo
動作確認 - L チカ・プログラム
ArduinoはD13にLEDが接続されていることが多いのですが、Leonardoはそれが接続されていません。
Leonardo では。RXはD17、TXはD30をLOWにするとLEDを点灯できます。
$ vi src/led.ino
#define TX_LED 30
#define RX_LED 17
void setup() {
pinMode(TX_LED, OUTPUT);
pinMode(RX_LED, OUTPUT);
}
void loop() {
digitalWrite(TX_LED, LOW);
delay(1000);
digitalWrite(TX_LED, HIGH);
digitalWrite(RX_LED, LOW);
delay(1000);
digitalWrite(RX_LED, HIGH);
delay(1000);
}
$ platformio run -t upload
■CardKB と Leonardo のI2C接続
CardKB | | Leonardo |
SCL | - | 3 |
SDA | - | 2 |
5V | - | Vcc |
GND | - | GND |
CardKB 添付のGroveケーブルを切断して、片側にピンヘッダーを取り付けます。
CardKB と Leonardo をI2C接続します。

ラズベリーパイとLeonardoをUSBケーブルで結ぶとこんな感じになります。

全体の様子です。ラズパイとLeonardoはUSBケーブルで繋がっています。
■キーボード入力の検出
まずは、キーボードからの入力を検出してみます。
→ Ref.M5Stack Arduinoサンプルコード(GitHub)
キーボードの打鍵情報を検出して表示するプログラムを書いてみました。
アスキーコードの範囲を超えるキー情報は16進で表示しています。
$ vi detectKey.ino
#include <Wire.h>
#define CARDKB_ADDR 0x5F
void setup()
{
Serial.begin(115200);
Wire.begin();
}
void loop()
{
Wire.requestFrom(CARDKB_ADDR, 1);
while(Wire.available()) {
int key = Wire.read();
if (key != 0) {
if (key>0x7F) {
Serial.println(key, HEX);
} else {
Serial.println((char)key);
}
}
}
}
platformIO のデバイスモニターで確認してみます。
$ platformio device monitor -p /dev/ttyACM0 -b 115200
--- Miniterm on /dev/ttyACM0 115200,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
a
9A
CardKB の [A]を押すと、a と表示され、ファンクションキー[fn]を押した後に[A]を押すと、16進表記で 9A と表示されます。
ボタンの組合せによるコード情報は下記を参照してください。
→ Ref.CardKB ドキュメント
■Arduino Leonardo をUSBキーボードとして認識させる
ここまでの操作は、ラズパイにTeraTermで接続した状態でも確認できましたが、
HID機能を利用する際には、ラズパイに直接モニターを繋ぐか、VNC接続した状態で、LXターミナル上で確認作業を行ってください。
USBキーボードとして認識させるには、KeyboardライブラリーのKeyboard.begin()を使用します。
ここでは、CardKB の [fn] を押した後に、[SPACE]を押すと、Arduino Leonard がキーボードをエミュレートし、
再度、[fn]と[SPACE]でエミュレートを解除するようにデザインしています。
キーボードをエミュレートしている状態で、CardKB のキーを押すと、ラズベリーパイに普通のキーボートと同様に
文字を入力することができるようになります。
$ vi emulateKeyboard.ino
#include <Wire.h>
#include <Keyboard.h>
#define CARDKB_ADDR 0x5F
boolean emulate = false;
void setup()
{
Serial.begin(115200);
Wire.begin();
}
void loop()
{
Wire.requestFrom(CARDKB_ADDR, 1);
while(Wire.available()) {
byte key = Wire.read();
if (key != 0) {
if (key==0xAF) { // [fn]+[SPACE]
if (emulate) {
Keyboard.end();
emulate = false;
} else {
Keyboard.begin();
emulate = true;
}
} else {
if (emulate) {
if (key<=0x7F) Keyboard.write(key);
}
}
}
}
}
$ platformio run
/home/pi/leonardo/M5Stack/src/zw_0801_emulateKeyboard.ino:2:22: fatal error: Keyboard.h: No such file or directory
********************************************************
* Looking for Keyboard.h dependency? Check our library registry!
*
* CLI > platformio lib search "header:Keyboard.h"
* Web > https://platformio.org/lib/search?query=header:Keyboard.h
*
********************************************************
$ platformio lib search "header:Keyboard.h"
Found 7 libraries:
Keyboard
========
#ID: 891
Allows an Arduino/Genuino board with USB capabilites to act as a Keyboard.
Keywords: device, control
Compatible frameworks: Arduino
Compatible platforms: Atmel AVR, Atmel SAM, Espressif 32, Espressif 8266, Intel ARC32, Microchip PIC32, Nordic nRF51, Nordic nRF52, ST STM32, Teensy, TI MSP430
Authors: Arduino
...
$ platformio lib show 891
....
Versions
--------
1.0.1, released Tue Mar 8 16:05:47 2016
1.0.2, released Wed May 9 08:02:23 2018
...
ライブラリーをインストールします。
$ platformio lib install 891
Keyboard @ 1.0.2 has been successfully installed!
$ platformio run -t upload
■補足:Keyboard.print()
Keyboardライブラリーはprint()およびprintln()関数をサポートしています。
→ Ref. Arduino Keyboard
しかし、Keyboard.print() を使うと、一部のアスキーコードが別のコードに置換されてしまいます。
Keyboard ライブラリー は以下のような場所に配置されています。
$ sudo find / -name Keyboard.h -print
/home/pi/leonardo/M5Stack/.pio/libdeps/leonardo/Keyboard_ID891/src/Keyboard.h
....
$ vi /home/pi/leonardo/M5Stack/.pio/libdeps/leonardo/Keyboard_ID891/src/Keyboard.cpp
....
同じディレクトリにある、Keyboard.cpp をみても print()関数の記述がないので、どこかで別のソースコード内でオーバーライドされているようです。
write()関数は1バイト送信なので、print()と同様に文字列を扱えるように、emulateKeyboard.ino に独自に関数を追加します。
void writeln(char *cmd) {
while (*cmd) {
Keyboard.write(*cmd);
cmd++;
}
// Keyboard.write(0x0d);
}
※改行したくない場合もあるので、改行コードの送信はコメントアウトしています。
■応用例
ここまでの内容では、普通にUSBキーボードを接続して打鍵したほうが早いという結果に終わってしまいます。
ここからが重要です。CardKBにショートカットキーを対応させます。ファンクション[fn]、シンボル[Sym]、シフト[↑]キーを合わせると50個以上の設定が可能です。
下記の例では、[fn]キーを押した後に、[m]を押すと、コンソールにメディアプレーヤーの起動用のコマンドが自動的に入力され、演奏が開始されます。
if (key!=0xAF) {
if (emulate) {
if (key>0x7F) {
switch(key) {
case 0xAC: // [fn]+[m]
writeln("mplayer /home/pi/Music/*\n"); break;
default: break;
}
} else {
Keyboard.write(key);
}
}
}
今回はキーボードを接続していますが、Arduino にセンサーを接続して、取得したデータにより、自動的にコマンドを入力するようなことも可能です。
アスキーコード以外の制御コードも、Keyboard.write()関数で送信できるので、Windowsパソコンでも応用が効くと思います。
Arduino Leonardoを介して、Androidスマホなど、その他のデバイスのキーボードとしても使えます。
こんな感じで実装してみると、おしゃれに演出できます。
Arduino Leonardo ElectroCookie Pink Edition

emulateKeyboard.ino コーディング例
#include <Wire.h>
#include <Keyboard.h>
#define CARDKB_ADDR 0x5F
boolean emulate = true;
void setup()
{
Serial.begin(115200);
Wire.begin();
Keyboard.begin();
}
void writeln(char *cmd) {
while (*cmd) {
Keyboard.write(*cmd);
cmd++;
}
}
void loop()
{
Wire.requestFrom(CARDKB_ADDR, 1);
while(Wire.available()) {
byte key = Wire.read();
if (key != 0) {
if (key==0xAF) { // [fn]+[SPACE]
if (emulate) {
Serial.println("stop keyboard emulating");
Keyboard.end();
emulate = false;
} else {
Serial.println("start keyboard emulating");
Keyboard.begin();
emulate = true;
}
} else {
if (emulate) {
if (key>0x7F) {
switch(key) {
case 0xA2: // [fn]+[l]
writeln("ls -al\n"); break;
case 0xAC: // [fn]+[m]
writeln("mplayer /home/pi/Music/*\n"); break;
default:
break;
}
} else {
// [Sym]+[d] mozc
Keyboard.write(key);
}
} else {
if (key>0x7F) {
Serial.println(key, HEX);
} else {
Serial.println((char)key);
}
}
}
}
}
delay(10);
}
【参考文献】
・M5Stack用カード型キーボードユニット UNIT CardKB スイッチサイエンス
・Arduino Leonardo(Pro Micro)のHID(キーボード)機能を使う(ショートカットキー実行,コマンド実行)
|