工場改善 IoT Arduino開発

現場の悩みに解決手段を

M5StakCでBluetoothストップウォッチ作ってみた2

前回の記事から500件のメモリ機能とまとめてキーボード入力追加してみました。
現場に持っていくことを想像したらPC持っていくのが手間だと思ったからです。
だんだん凝り始めて高性能なストップウォッチになってきました。


3000円で結構な時間遊べてコスパいいっす。

趣味なら時間もお金も、労力もある限り費やして探求できるし、おもしろいですね。

そもそも趣味と仕事って金になるかならないかという指標があると思いますが、色々考えるそうと言えるものもあれば、そうでも無いような事があるし、境目って曖昧だと私は思うのですよ。

あとワーク・ライフ・バランスとか聞いたことありますが、ワークもライフだろって突っ込みたいのです。
なんでも分けたがる人には理解されないですよね。なんかブラック企業の経営者っぽいし。


この記事を立てたのも趣味です。でも仕事にも生かして、誰かが喜んでくれたら満足なのです。
そして結果的にお金になったらさらに幸せです。




さて本質の追求はここまでにして本題です。

機能は以下としました。
Aボタン:スタート(+Bluetoothキーボード入力)、ストップ
Bボタン:ストップ(2度押しで保存したメモリをすべてBluetoothキーボードで入力)
Cボタン:リセット(メモリのカウントもリセット)

f:id:kesokonpatata:20210703002416j:plain

【プログラム】

/*
  キーボードライブラリをインストール
  https://github.com/asterics/esp32_mouse_keyboard
  ・最大約49日まで
  ・件数は500まで
*/

#include <BleKeyboard.h> //Bluetooth HIDプロファイルの設定ライブラリ、キーボード送信用 
BleKeyboard bleKeyboard("M5StickC StopWatch 001"); //Bluetoothペアリング時の表示名

#include <M5StickC.h>

uint32_t tm;
uint32_t startTime;
uint32_t LastTime;

bool stopF = false;
uint32_t stopTime;
uint32_t stopTimeSum;

uint16_t count;
uint16_t datasize = 500;
uint32_t lapArray[500];
uint32_t timeArray[500];

uint16_t BtnF;
uint32_t i;
bool flag = true;

void m5lcd() {
  M5.Lcd.fillScreen(BLACK);  //背景色
  M5.Lcd.setTextColor(WHITE); //テキストカラー
  M5.Lcd.setTextSize(1);     //文字サイズ

  M5.Lcd.setCursor(5, 0); M5.Lcd.println("StopWatch:001");
  M5.Lcd.setCursor(95, 0);

  if (BtnF == 1) {
    if(flag == true){
      M5.Lcd.setTextColor(GREEN);
    }else{
      M5.Lcd.setTextColor(WHITE);
    }
    flag = !flag;
    M5.Lcd.print("Start");
    M5.Lcd.setTextColor(GREEN);
  } else if (BtnF == 2) {
    M5.Lcd.print("Stop");
    M5.Lcd.setTextColor(RED);
  } else if (BtnF == 3) {
    M5.Lcd.print("Reset");
    M5.Lcd.setTextColor(YELLOW);
    M5.Lcd.setCursor(0, 10);
    M5.Lcd.printf("Battery\n");
    M5.Lcd.printf("  Warn :%6d\n"  , M5.Axp.GetWarningLevel());  // バッテリー残量警告 0:残あり, 1:残なし
    M5.Lcd.printf("  Temp :%6.1f\n", M5.Axp.GetTempInAXP192());  // AXP192の内部温度
    M5.Lcd.printf("  V(V) :%6.3f\n", M5.Axp.GetBatVoltage());    // バッテリー電圧(3.0V-4.2V程度)
    M5.Lcd.printf("  I(mA):%6.1f\n", M5.Axp.GetBatCurrent());    // バッテリー電流(プラスが充電、マイナスが放電)
    M5.Lcd.printf("VBus(USB)\n");
    M5.Lcd.printf("  V(V) :%6.3f\n", M5.Axp.GetVBusVoltage());   // USB電源からの電圧
    M5.Lcd.printf("  I(mA):%6.1f\n", M5.Axp.GetVBusCurrent());   // USB電源からの電流
  } else if (BtnF == 4) {
    M5.Lcd.setTextColor(RED);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(5, 10); M5.Lcd.print("Start writing data");
  } else if (BtnF == 5) {
    M5.Lcd.setTextColor(BLUE);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(5, 10); M5.Lcd.print("Data writing");
    M5.Lcd.setCursor(5, 25); M5.Lcd.print("completed");
  } else if (BtnF == 6) {
    M5.Lcd.setTextColor(BLUE);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(5, 10); M5.Lcd.print("Count limit");
    M5.Lcd.setCursor(5, 25); M5.Lcd.print("Please reset");
  } else {
    //起動時
    M5.Lcd.setTextColor(YELLOW);
  }

  if (BtnF < 4) {
    if (count > 0) {
      M5.Lcd.setTextSize(3);
      M5.Lcd.setCursor(5, 15); M5.Lcd.printf("Cnt:%d",count);
      M5.Lcd.setTextColor(WHITE);
      M5.Lcd.setTextSize(2);
      M5.Lcd.setCursor(5, 42); M5.Lcd.printf("Lap :%.2f", (float)lapArray[count] / 1000.0);
      M5.Lcd.setCursor(5, 62); M5.Lcd.printf("Time:%.2f", (float)timeArray[count] / 1000.0);
    }
  }
}
void setup() {
  //  Serial.begin(115200);  //通信速度bps
  delay(30);
  bleKeyboard.begin();   //BLE接続開始

  M5.begin();

  M5.Axp.ScreenBreath(10); //バックライトの輝度(デフォルト12)
  setCpuFrequencyMhz(80); //CPU周波数を下げる(デフォルト240)
  M5.Lcd.setRotation(1);
  m5lcd();

  //  Serial.println("M5Stack StopWatch");
}


void loop() {
  M5.update();
  int axpButton = M5.Axp.GetBtnPress();

  //Aボタンでタイマー開始、ラップタイム記録
  if (M5.BtnA.wasPressed()) {
    if (startTime == 0) {
      startTime = millis();
      LastTime = startTime;

      //      Serial.println("RAPCOUNT,RAP,TIME");

      BtnF = 1;
      m5lcd();

      //Bluetooth HIDプロファイルで送信
      bleKeyboard.print("RAPCOUNT"); bleKeyboard.write(KEY_TAB); //TAB(0xB3)をBluetooth送信
      bleKeyboard.print("LAP"); bleKeyboard.write(KEY_TAB);  //TAB(0xB3)をBluetooth送信
      bleKeyboard.print("TIME"); bleKeyboard.write(KEY_TAB); //TAB(0xB3)をBluetooth送信
      bleKeyboard.write(KEY_RETURN); //改行(0xB0)をBluetooth送信

      //ストップ後の再開
    } else if (stopF == true) {
      tm = millis();

      stopTime = tm - stopTime;
      stopTimeSum += stopTime;

      stopF = false;
      //Serial.println("Timer Restart");

      //LCD表示
      BtnF = 1;
      m5lcd();

      //ラップタイム
    } else {
      tm = millis();
      count += 1;

      //配列に入力
      lapArray[count] = tm - LastTime - stopTime;
      timeArray[count] = tm - startTime - stopTimeSum;

      LastTime = tm;
      stopTime = 0;

      //serial出力
      //      Serial.printf("%d,%.2f,%.2f\r\n", count, (float)lapArray[count] / 1000.0, (float)timeArray[count] / 1000.0);

      //LCD表示
      if (count <= datasize) {
        BtnF = 1;
        m5lcd();

        //Bluetooth HIDプロファイルで送信
        bleKeyboard.print(count);    bleKeyboard.write(KEY_TAB); //TAB(0xB3)キー
        bleKeyboard.print((float)lapArray[count] / 1000.0, 2); bleKeyboard.write(KEY_TAB); //TAB(0xB3)キー
        bleKeyboard.print((float)timeArray[count] / 1000.0, 2); bleKeyboard.write(KEY_TAB); //TAB(0xB3)キー
        bleKeyboard.write(KEY_RETURN); //改行(0xB0)キー

      } else {
        BtnF = 6;
        m5lcd();
      }
    }


  } else if (M5.BtnB.wasPressed()) {  //Bボタンでタイマーリセット
    count = 0;
    startTime = 0; LastTime = 0;
    stopF = false; stopTime = 0; stopTimeSum = 0;

    //    Serial.println("Timer Reset");

    BtnF = 3;
    m5lcd();


  } else if (axpButton == 2 && stopF == true) {  //Bボタン2回押しデータの一括送信
    //    Serial.println("Data write");
    BtnF = 4;
    m5lcd();

    bleKeyboard.print("RAPCOUNT"); bleKeyboard.write(KEY_TAB); //TAB(0xB3)をBluetooth送信
    bleKeyboard.print("LAP"); bleKeyboard.write(KEY_TAB);      //TAB(0xB3)をBluetooth送信
    bleKeyboard.print("TIME"); bleKeyboard.write(KEY_TAB);     //TAB(0xB3)をBluetooth送信
    bleKeyboard.write(KEY_RETURN); //改行(0xB0)をBluetooth送信


    for (int j = 1; j <= count; j++) {
      delay(350);

      bleKeyboard.print(j);    bleKeyboard.write(KEY_TAB); //TAB(0xB3)キー
      bleKeyboard.print((float)lapArray[j] / 1000.0, 2); bleKeyboard.write(KEY_TAB); //TAB(0xB3)キー
      bleKeyboard.print((float)timeArray[j] / 1000.0, 2); bleKeyboard.write(KEY_TAB); //TAB(0xB3)キー
      bleKeyboard.write(KEY_RETURN); //改行(0xB0)キー
    }
    delay(500);

    BtnF = 5;
    m5lcd();

  } else if (axpButton == 2 && stopF == false && startTime > 0) {//電源ボタンでタイマーストップ
    stopTime = millis();
    stopF = true;

    //    Serial.println("Timer Stop");

    BtnF = 2;
    m5lcd();
    
  }
  
  if (i % 50 == 0 && BtnF == 1) {
    m5lcd();
  }
  
  //PCロックが掛からないように一定時間にShiftキーを押す
  if (i % 6000 == 0) {
    //    Serial.println("Shift");
    setCpuFrequencyMhz(240);
    M5.Axp.ScreenBreath(12); //バックライトの輝度(デフォルト12)
    bleKeyboard.write(0x81); //KEY_LEFT_SHIFT
    M5.Axp.ScreenBreath(10); //バックライトの輝度(デフォルト12)
    setCpuFrequencyMhz(80);
    i = 0;
  }
  i += 1;

  delay(10);
}

【困ったこと】

2次元配列でラップタイムと累計時間入れてみたんですが、累計時間の値がおかしくてどうにもこうにもならんかったので、一次元配列でラップタイムと分けました。
配列の使い方調べてたらポインタとか出てきてややこしくて泣きそうです。
わかりそうな気になったんですが、わかりませんでした。

【次やりたいこと】

①時間と②要素作業の手書き→PCへ手打ちの作業で①時間の手作業は減らせそうですが、②要素作業の手書きはどうしたもんかです。
指定のフォーマットの紙を印刷してそれに書いた後、スキャナーで取り込んでOCRで文字認識とかしたいなぁPythonでもありそうなんですが、使えるかなぁ。
ちょっと挑戦してみます。