1key-boardの作製


Attiny85ではUSBに2端子、電源、GNDに2端子使うので、残りが4つのピンがあるのでで最大物理的に4つのキーをもつキーボードが作成できる。
でリセットピンを解除して、4つのキーボードのプロトタイプを作った。
しかし、プロトタイプを作って使っているとある結論に至った・・・
結果1つで十分!!たくさんキーがある方が良いと最初は思うが、そうではなかった・・・
まず、沢山キーがっても、何を登録しているかを覚えられるのはせいぜい4つ。
アンチスクリーンモードを搭載すると今機能しているのか?していないのか?LEDのインディケーターがないとやはり不便。で3つにする?でもね・・・
物理的に、4つのキーがなくても、シングルクリック、ダブルクリック、トリプルクリック、長押しとキーのアクションで4つの動作を区別すればいいから・・結果、シンプルな1つキーのキーボードでいいのではという結論に・・・

【回路作製】


卓上のテーブルソーを使ってユニバーサル基板を切断。短編に10個の穴、長編に12個の穴を確保して切断

USBのコネクタ、タイプAを押すを取り付けるために、4の端子がホールに入るように位置をあわせてスリットを基板の端字いれる。端から3つ目の穴に合わせるようにいれた。

タイプAのUSBコネクタを半田付け。外のケース部分も大きなランドに半田して強度を持たせている。

表面側に紙を両面テープで全面に張る。


部品を刺して、回路を半田付け。今回は、PB5にスイッチをつけて、PB2にLEDをつけるように配線をしている。
Attiny85をすでに写真では実装しているが、実装前に、ライターで最低限ブートローダー書き込みしてから半田付けする。さもなければ・・・

リセットピンのPB05を使っているので、
も参考に。
実際にコマンドプロンプトから流し込んだコマンドは、

avrdude -C avrdude.conf -v -pattiny85 -carduino -PCOM22 -b19200 -Uflash:w:t85_default.hex -U lfuse:w:0xe1:m -U hfuse:w:0x5d:m -U efuse:w:0xfe:m

最も小型にできるレイアウトという事で、68Ωの抵抗二つだけは、裏側に取り付けて配線。

【スケッチ】

さくっとシングルクリック、ダブルクリック、トリプルクリック、長押しの区別をするために
Button2のライブラリーを利用。
また、TimerOneというタイマーのライブラリーも利用。
動作的には、ボタンを長押しすると、アンチスクリーンーセーバーモードに入って、約10分でタイマーの割り込みが入って、Pauseボタンを1回だけ押す動作にしている。

  Timer1.initialize(500000);
  Timer1.attachInterrupt(tfunction);
  Timer1.stop();

セットアップで、タイマーをイニシャライズして、インターラプトとスタートしたらすぐにストップ(一時停止)。ボタンが長押しされ、アンチスクリーンモードでないなら、アンチスクリーンモードにするためタイマーをTimer1.resume()で再開し、LEDを点灯。すでにアンチスクリーンモードだったら逆に、Timer1.stop()でタイマーを止めて、アンチスクリーンモードを解除して、LEDを消灯する。

はまった所は、タイマーの割り込みでキーを押す場合、一度stopをして、それからキーを送り込まないと、ずっと同じキーを押した状態になってしまう。それを回避するために、キーを送りだす前に、いったんタイマーを止めて、送って、再開という動作にする。

TimerOneのライブラリーだが8ビットのAttiny85では0.5秒までしか測れない。そこで0.5秒ごとにタイマー割り込みが入るが、カウンターを設けて目的のカウントだったら処理するようにして長時間を測定する。1714というのがその所。
ただ、キーを送り込む際にストップして送って再開をしているのでだいたいの時間になる。
まず、テストの段階では、1714の所を10とかの数字にしておいて、動作を確認。実際に実測した所、10のカウントで約3.5秒だったので、10分=600秒を3.5で割ると171.4、つまり1714カウントとしている。これで

include <TrinketKeyboard.h>
#include <TimerOne.h>
#include "Button2.h"

// Attiny85
// PB5(reset)-|   |-VCC
//        PB3-|   |-PB2
//        PB4-|   |-PB1
//        GND-|   |-PB0


const int PB5pin = 5; //For Switch
const int PB2pin = 2; //For LED


int ledState = LOW;
long cnt=0;

Button2 buttonPB5;

void setup() {
   //pinMode set for LED
   pinMode (PB2pin, OUTPUT);
  //start USB stuff
   TrinketKeyboard.begin();
  //Timer setting
  Timer1.initialize(500000);
  Timer1.attachInterrupt(tfunction);
  Timer1.stop();
  //button setting
  buttonPB5.begin(PB5pin);
  buttonPB5.setClickHandler(handlerPB0);
  //buttonPB5.setLongClickHandler(handlerPB0);
  buttonPB5.setLongClickDetectedHandler(handlerPB0);// this will only be called upon detection
  buttonPB5.setDoubleClickHandler(handlerPB0);
  buttonPB5.setTripleClickHandler(handlerPB0);
}
void loop() {
  TrinketKeyboard.poll();
  buttonPB5.loop();
  delay(1);
}
/////////////////////////////////////////////////////////////////
void handlerPB0(Button2& btn) {
    switch (btn.getType()) {
        case single_click:
            TrinketKeyboard.print("single_click");
            TrinketKeyboard.pressKey(0,KEYCODE_ENTER);
            // this should push enter key
            TrinketKeyboard.pressKey(0, 0);
            break;
        case double_click:
            TrinketKeyboard.print("double_click");
            TrinketKeyboard.pressKey(0,KEYCODE_ENTER);
            // this should push enter key
            TrinketKeyboard.pressKey(0, 0);
            break;
        case triple_click:
            TrinketKeyboard.print("triple_click");
            TrinketKeyboard.pressKey(0,KEYCODE_ENTER);
            // this should push enter key
            TrinketKeyboard.pressKey(0, 0);
            break;
        case long_click:
            if (ledState==LOW)
            {
            Timer1.resume();
            ledState=HIGH;
            digitalWrite(PB2pin, HIGH);
            }
            else {
            Timer1.stop();
            ledState=LOW;
            digitalWrite(PB2pin, LOW);
            }
            break;
          case empty:
            return;
    }
}
/////////////////////////////////////////////////////////////////
void tfunction(){

  if (cnt%1714==0) //cnt=10 correspond to 3.5 sec
  {

  Timer1.stop();
  TrinketKeyboard.pressKey(0,0x48);
  TrinketKeyboard.pressKey(0,0);
  Timer1.resume();
  cnt=0;
  }
  cnt=cnt+1;
  }
/////////////////////////////////////////////////////////////////
 

【ケーシング】

100均で売っているフォトフレームを切断して、トッププレートとボトムプレートを作成。
トッププレートはスイッチの部分とLEDの部分が干渉しないように穴をあけている。
スイッチは3.5mmの大きさなのでクリアランスを考えて4.5mmであけて、LEDは3mmなので4mmであけている。

上の写真では上からビスを通して、ナットで裏で固定しているが、そうすると高さが高くなり、USBハブやノートPCのUEBポートに刺すとこのキーボードの方が高くなってしまったので、ビスとナットを入れかえている。
ナットを上にするとシンデレラフィットで高さが丁度!!またLEDの光が透明な板に導波して板全体が光ってくれてナイス。

ノートパソコンにつけても若干ノートPCが薄いので高さの不一致あるものの、気にならないレベルでジャストフィット!




コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

ILI9341 240X320 Arduino

Attiny85 FuseRest