2016年7月10日日曜日

Digisparkで測定器データをテンキーの代わりに入力

昨日に引き続き、最近ちょくちょくいじっているDigisparkで、ミツトヨのデジマチック出力をUSBキーボードとして認識させて入力するプログラムを作ってみた。
数値を入力したあとにエンターを押してくれるので、エクセルとかに測った数値を連続で入れるときは便利かも?

DigisparkはLEDがP1に接続されているのでこのピンはINPUT_PULLUPが使えないということでOUTPUTなREQを1番に割り当てた。
その他の入力ピンは外部プルアップを使わなくていいように、INPUT_PULLUPが可能な0,2,5を使用した。3と4はUSBで使用するのですべてのピンを使い切ったことに。
互換品のDigisparkとかでResetピンの5番ピンが使用できないやつがあるので、その場合はヒューズビット書き換えで5番ピンを使えるようにしておかないといけない。

とりあえず純正のスイッチ付きケーブルも使用できるように、P5につながってるスイッチがLOWになったときにデータを取得してUSBキーボードとして認識してるDigisparkがキーストロークするような感じにしてみた。純正ケーブルのスイッチは片方GNDに落ちてるのでINPUT_PULLUPしてLOWになったら反応という具合に。
ケーブルのピンアサインはフォーラムに落ちていたのを参考にさせてもらった。
#include "DigiKeyboard.h"
#define REQ 1
#define DAT 0
#define CLK 2
#define BTN 5//reset pin

void setup() {
  pinMode(REQ, OUTPUT);
  pinMode(DAT, INPUT_PULLUP);
  pinMode(CLK, INPUT_PULLUP);
  pinMode(BTN, INPUT_PULLUP);
  digitalWrite(REQ,LOW);
 }

void loop() {
  DigiKeyboard.update();
  if(digitalRead(BTN) == LOW){
    byte mydata[14];
    digitalWrite(REQ, HIGH);
    for(uint8_t i = 0; i < 13; i++ ) {
      uint8_t k = 0;
      for (uint8_t j = 0; j < 4; j++) {
        while( digitalRead(CLK) == LOW) {
          DigiKeyboard.update();
        }
        while( digitalRead(CLK) == HIGH) {
          DigiKeyboard.update();
        }
        bitWrite(k, j, (digitalRead(DAT) & 0x1));
      }
      mydata[i] = k;
    }
    digitalWrite(REQ,LOW);
  
    uint8_t sign = mydata[4];
    uint8_t decimal = mydata[11];
    //uint8_t units = mydata[12];

    char buf[7];
    for(int lp = 0; lp < 6; lp++){
      buf[lp] = mydata[lp+5] + '0';
    }
    buf[6] = 0;
    float num = (atol(buf));
    switch (decimal){
      case 2:
        num = num / 100;
        break;
      case 3:
        num = num / 1000;
        break;
      case 4:
        num = num / 10000;
        break;
      case 5:
        num = num / 100000;
        break;
    }
    if(mydata[1] == 0xF && mydata[2] == 0xF && mydata[3] == 0xF){
      DigiKeyboard.sendKeyStroke(0);
      if(sign == 8){
        DigiKeyboard.print("-");
      }
      DigiKeyboard.print(num, decimal);
      DigiKeyboard.sendKeyStroke(KEY_ENTER);
      DigiKeyboard.delay(60);
      while(digitalRead(BTN) == LOW){
        DigiKeyboard.update();
      }
    }
  }
}
前回はpowを使って小数点の位置を計算していたんだけどpowを使うとスケッチの容量がオーバーしてしまうのでswitch caseで対応した。さらに負の値のときのための計算も容量食うので"-"を入力するかどうかの判別をifでやるようにしたらだいぶ減ったのでこちらも変更。
前回よりもだいぶローテクになってるような気がしたんだけどこっちのほうがスケッチが小さくなったので盛り込んだ。

DigisparkのUSBキーボードエミュレーションはDigiKeyboard.update()を定期的に呼ばないと不明なデバイス扱いになってしまうので、データ受信部の中でタイムアウトとか設定していないのでとりあえずwhileの中でもDigiKeyboard.update()を読んでデバイスの認識がおかしくならないように対応。DigiKeyboard.update()がどの程度時間を食うのかわからなかったけど動いているので良しとしよう…
測定器がつながっていないと無限ループするけど不明なデバイスにはならない!

もしかしたら一旦数値をfloatにしているところも直せば小さくなるかもしれない。どうせキーを1文字ずつ打てばいい話だし…。でもこっちのほうが小数点の桁数が変わる時とかも楽だったのでそのまま。

一応2つ目から4つ目のデータが0xFかどうか確認するようにしておいた。変なデータが来ても安心?

純正のUSBインプットツールは結構高級品みたいだけどアイソレーションとかいろいろ高級な回路になってるのかなぁ?PCからノイズ乗ったりしたらUSBアイソレータとか使えばいいのかな?


0 件のコメント:

コメントを投稿