前回の続き。

プログラム

10年以上、ほぼ使っていなかった Digistump 。 今回も、思い知る、その容量の小ささ。

最初はお手軽に、Pimoroni で購入した I2C で繋げる光るロータリーエンコーダーを利用しようとしたが、Arduino用のseesawライブラリを組み込むと、6Kbytesを越えてしまい、メモリが足りない。

しょうがないので、ロータリーエンコーダーの動作を検知するプログラムを自作する。

GPIO の INPUT_PULLUP

まず、なぜか。いやまあわかるけど、 P1 が INPUT PULLUP として利用できなかった。 本体上のLEDと同期しているので、無理目ではあるけど、 できない という記述を見つけられないので、正し仕様はわからず。

SWITCH A と SWITCH B の INPUT PULLUP には、 PINP0 と P2 を利用する。

ロータリーエンコーダーの回転検出

ロータリーエンコーダーは、2つのスイッチのON/OFFの組み合わせで、回転方向を検出することができる。

実際には、4回の状態変化を検出できる。

時間経過SWITCH ASWITCH B
t0OFFOFF
t1ONOFF
t2ONON
t3OFFON
t4OFFOFF

t0 から t4 までの時間経過は、 カチ っと1メモリ動かす時間なので、数百msec くらい。

  • t1 SWITCH A が先に ON になり、ちょっと遅れて SWITCH B も ON
  • t3 SWITCH A が先に OFF になり、ちょっと遅れて SWITCH B も OFF

逆回転では、SWITCH B が先に変化する。

最初は、 t0->t1 になるところで回転方向を取得していたがうまくいかない。 DEBUGをいれてみると、 t1 のタイミングがとれてない。 どうやら、 t4 直後に USBのキーボードとしてキー入力を送信するコストで t1 が間に合わず、検出漏れしてる感じ。

ということで、 t3->t4 のタイミングで回転方向を検知するようにした。

プッシュスイッチ

これは簡単、シンプルな、PULLUPスイッチ。 が、モデルによっては、 PIN P5 が使えないこともあるらしい。

自分の使った Digistump 初号機では、 P5 も正しく動作した。

code

one_button.cpp · Gistcpp
#include <Arduino.h>
#include <DigiKeyboard.h>
#include <DigiUSB.h>
#include <stdlib.h>

int _switch_a, _switch_b, _switch_push;

#define SWICTH_A_PIN 0
#define SWICTH_B_PIN 2
#define LED_PIN 1
#define PUSH_PIN 5

void setup()
{
  pinMode(SWICTH_A_PIN, INPUT_PULLUP);
  pinMode(SWICTH_B_PIN, INPUT_PULLUP);
  pinMode(PUSH_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  _switch_a = _switch_b = _switch_push = 0;

  for (int i = 0; i < 5; i++)
  {
    digitalWrite(LED_PIN, HIGH);
    delay(50);
    digitalWrite(LED_PIN, LOW);
    delay(100);
  }
}

void loop()
{
  int a, b, p;

  a = digitalRead(SWICTH_A_PIN);
  b = digitalRead(SWICTH_B_PIN);
  p = digitalRead(PUSH_PIN);

  if (_switch_push != p)
  {
    if (p)
    {
      // SPACE
      DigiKeyboard.sendKeyStroke(0);
      DigiKeyboard.sendKeyStroke(KEY_SPACE);
    }
    _switch_push = p;
  }

  if (_switch_a == a && _switch_b == b)
  {
    // no change
    return;
  }

  if (!a && !b)
  {
    //
    // 1 -> 0
    // END OF MOVING
    //
    if (_switch_a && !_switch_b)
    {
      // #define KEY_ARROW_LEFT 0x50
      DigiKeyboard.sendKeyStroke(0);
      DigiKeyboard.sendKeyStroke(0x50);
    }
    else if (_switch_b && !_switch_a)
    {
      // why don't define KEY_ARROW_RIGHT
      DigiKeyboard.sendKeyStroke(0);
      DigiKeyboard.sendKeyStroke(0x4f);
    }
  }

  _switch_a = a;
  _switch_b = b;

  delay(1);
}

3D データ

ケースと合うように、ペットボトルキャップのデータは、数mm くらい低くなるように修正した。