タッチパネルと3Dプリンタで激安自作キーボードを作ってみた。

これは何?

Arduinoを使ったゲーム機などを作っているときにキーボードを搭載したくなることがあります。

PS/2接続のキーボードをつなげるというのもよいのですが、できれば筐体に収まるようなかわいらしいキーボードが欲しいなと思っていました。

もちろんタクトスイッチをたくさん並べてオリジナルの小型キーボードを作るのもよいのですが、、、部品もたくさん必要だし、大量のはんだ付けが必要です。制御も面倒です。

 

そこで今回はもっと手軽に作れるキーボードを考えてみました。

 

タッチパネル

今回使ったのはこれ。

www.aitendo.com

aitendoで数百円で買えます。

これはいわゆるNintendo DSとかのタッチパネル部分などに使われているような感圧式のタッチパネルです。ふつうはディスプレイと重ねて使用するものですが、今回はこのタッチパネルだけを利用します。

 

このタッチパネルは専用ICでX,Y座標を取り出すこともできますが、中身は単純な可変抵抗なので、ArduinoだけでもX,Y座標を取り出すことができます。

参考:タッチスクリーンをArduinoから使う – SF Bay Music Tech

 

 この記事とはあまり関係ないですが、ここまでの知識で、このような楽器のようなものが作れます。

 

キーパッドプラスチック

なんといったものか、、

こういうプラスチックです。

f:id:inajob:20180117232914p:plain

裏返すとこんな感じ

f:id:inajob:20180117233026p:plain

3Dプリンタの制約上、上下両側に凸になっている形状は作れないため、2つの部品を貼り合わせるように設計します。

これをタッチパネルの上に固定することで、キーボードのボタンを作成します。

ボタンを押し込むと、裏側の出っ張りが下がり、タッチパネルの特定の個所をタッチするわけです。

f:id:inajob:20180117234023p:plain

特定の位置、と言っても多少はぶれるのでArduinoで値をうまいこと丸め込んで、どのキーが押されたのかを特定します。

 

f:id:inajob:20180201004036p:plain

部品の4隅に穴をあけておいて、ねじとナットで締め付けることで固定します。

完成

 こんな感じ。

文字の表示はこれを使いました。

www.aitendo.com

 

ディスプレイの制御は下記ライブラリを使いました(Arduino IDEのライブラリマネージャからインストールできました)

github.com

 

仕組み上、まれに隣のキーが押されるような挙動をすることがあります。閾値やタイミングの調整で減らせるかなと思っていますが、ゼロにするのは難しそうです。

 

ソースコード

キーボードのタッチ位置の測定部分は現物合わせで調整した値なので、あまり参考にならないです。

 

#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;
  }
}