これは何?
Arduinoを使ったゲーム機などを作っているときにキーボードを搭載したくなることがあります。
PS/2接続のキーボードをつなげるというのもよいのですが、できれば筐体に収まるようなかわいらしいキーボードが欲しいなと思っていました。
もちろんタクトスイッチをたくさん並べてオリジナルの小型キーボードを作るのもよいのですが、、、部品もたくさん必要だし、大量のはんだ付けが必要です。制御も面倒です。
そこで今回はもっと手軽に作れるキーボードを考えてみました。
タッチパネル
今回使ったのはこれ。
aitendoで数百円で買えます。
これはいわゆるNintendo DSとかのタッチパネル部分などに使われているような感圧式のタッチパネルです。ふつうはディスプレイと重ねて使用するものですが、今回はこのタッチパネルだけを利用します。
このタッチパネルは専用ICでX,Y座標を取り出すこともできますが、中身は単純な可変抵抗なので、ArduinoだけでもX,Y座標を取り出すことができます。
参考:タッチスクリーンをArduinoから使う – SF Bay Music Tech
Arduinoとタッチパネルで音を出してみるテスト pic.twitter.com/6Yq57ni8kh
— ina_ani (@ina_ani) 2018年1月17日
この記事とはあまり関係ないですが、ここまでの知識で、このような楽器のようなものが作れます。
キーパッドプラスチック
なんといったものか、、
こういうプラスチックです。
裏返すとこんな感じ
3Dプリンタの制約上、上下両側に凸になっている形状は作れないため、2つの部品を貼り合わせるように設計します。
これをタッチパネルの上に固定することで、キーボードのボタンを作成します。
ボタンを押し込むと、裏側の出っ張りが下がり、タッチパネルの特定の個所をタッチするわけです。
特定の位置、と言っても多少はぶれるのでArduinoで値をうまいこと丸め込んで、どのキーが押されたのかを特定します。
部品の4隅に穴をあけておいて、ねじとナットで締め付けることで固定します。
完成
Arduinoにタッチパネルをつなげ3Dプリンタで作った特製パネルを使ってキーボードを作ってみた。 pic.twitter.com/wCWEZ3wcpI
— ina_ani (@ina_ani) 2018年1月17日
こんな感じ。
文字の表示はこれを使いました。
ディスプレイの制御は下記ライブラリを使いました(Arduino IDEのライブラリマネージャからインストールできました)
仕組み上、まれに隣のキーが押されるような挙動をすることがあります。閾値やタイミングの調整で減らせるかなと思っていますが、ゼロにするのは難しそうです。
ソースコード
キーボードのタッチ位置の測定部分は現物合わせで調整した値なので、あまり参考にならないです。
#include <LCD_ST7032.h>
LCD_ST7032 lcd;
#define Y1 A0
#define X1 A1
#define Y2 A2
#define X2 A3
#define SPEAKER 9
int buttonTrig;
int xavg, yavg;
char charMap[3][10] = {
{'\n', ' ', ',', 'M', 'N', 'B', 'V', 'C', 'X', 'Z'},
{';', 'L', 'K', 'J', 'H', 'G', 'F', 'D', 'S', 'A'},
{'P', 'O', 'I', 'U', 'Y', 'T', 'R', 'E', 'W', 'Q'}
};
void reset(){
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
digitalWrite(A0, LOW);
digitalWrite(A1, LOW);
digitalWrite(A2, LOW);
digitalWrite(A3, LOW);
}
void setup() {
buttonTrig = 0;
xavg = yavg = 0;
reset();
pinMode(SPEAKER, OUTPUT);
lcd.begin();
lcd.setcontrast(24);
lcd.setCursor(0, 0); //LINE 1, ADDRESS 0
lcd.cursor();
lcd.print("Hello World");
}
void loop() {
int x, y;
reset();
// x sensor
digitalWrite(X1, HIGH);
pinMode(Y1, INPUT);
pinMode(Y2, INPUT);
delay(1);
x = analogRead(Y1);
reset();
// y sensor
digitalWrite(Y1, HIGH);
pinMode(X1, INPUT);
pinMode(X2, INPUT);
delay(1);
y = analogRead(X1);
if(x != 0 && y != 0){
if(buttonTrig > 4){ // delay 4 frame to wait stable
xavg = ((xavg + x) >> 1);
yavg = ((yavg + y) >> 1);
}else{
xavg = x;
yavg = y;
}
if(buttonTrig == 8){
tone(SPEAKER, 440 + x);
byte yrow = 0;
if(yavg > 100) yrow = 1;
if(yavg > 300) yrow = 2;
if(yavg > 500) yrow = 3;
byte xrow = 0; //
if(xavg > 100) xrow = 1;
if(xavg > 150) xrow = 2;
if(xavg > 220) xrow = 3;
if(xavg > 300) xrow = 4;
if(xavg > 380) xrow = 5;
if(xavg > 430) xrow = 6;
if(xavg > 480) xrow = 7;
if(xavg > 550) xrow = 8;
if(xavg > 630) xrow = 9;
if(xavg > 690) xrow = 10;
if(charMap[yrow - 1][xrow - 1] == '\n'){
lcd.clear();
lcd.setCursor(0, 0);
}else{
lcd.write(charMap[yrow-1][xrow-1]);
}
}
buttonTrig ++;
}else{
noTone(SPEAKER);
buttonTrig = 0;
xavg = 0;
yavg = 0;
}
}