工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装

必要な部品と材料

Arduino UNO(またはLCDキーパッドシールド互換ボード) ×1
LCDキーパッドシールド ×1

使用するアプリとオンラインサービス

プロジェクト概要

YAKINDU Statechart Toolsを使って状態機械モデルからC++コードを生成し、LCDキーパッドシールド搭載のArduinoで動くデジタル腕時計を作ります。

元のモデルはDavid Harelの論文「従来の状態機械・状態図形式の広範な拡張」で例示されていたデジタルウォッチです。これをYAKINDUで再構築し、Arduino上で動作させました。

デジタルウォッチの仕様

90年代に流行った多機能デジタルウォッチを想像してください。ストップウォッチ、複数アラーム、毎正時のビープ音など。

入力ボタン: On/Off、Mode、Set、さらにLight On/Off。

Modeボタンで以下のモードを切替:

メニュー内ではOn/Offボタンで設定変更、Setボタンで時刻/アラーム設定。ストップウォッチはLight On/Offボタンでスタート/ストップ、ラップ機能も搭載。チャイムとバックライト制御も内蔵(初期版ではArduino未接続)。

状態機械モデル

Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装
Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装
Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装
Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装
Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装
Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装

モデルはグラフィカル(状態図)とテキスト(定義部)の2部構成。定義部でイベント、変数、操作を定義し、状態図で論理を記述。

内部イベントとして100msごとにtime変数をインクリメント:

every 100 ms / time += 1

この100msステップから現在時刻をHH:MM:SS形式で計算:

display.first  = (time / 36000) % 24;  // 時
display.second = (time / 600) % 60;    // 分
display.third  = (time / 10) % 60;     // 秒

状態機械呼び出し毎にupdateLCD操作で表示更新:

display.updateLCD(display.first, display.second, display.third, display.text)

合成状態、履歴、サブダイアグラム、出口ノード等のモデリング要素を活用し、可読性を確保。詳細はユーザーガイド参照。

LCDキーパッドシールド

シンプルなHMI(人間-機械インターフェース)に最適。5つのユーザーボタン+リセットボタンを装備。5ボタンはすべてA0ピンに接続され、分圧回路で各ボタンの電圧が異なるため、analogRead(0)で判別可能。

メーカーによって値は異なります。以下は実測値:

Arduinoで作るデジタル腕時計 - 有限状態マシンによる実装

閾値判定コード:


#define NONE 0
#define SELECT 1
#define LEFT 2
#define DOWN 3
#define UP 4
#define RIGHT 5

static int readButton() {
  int result = analogRead(0);
  if (result < 50)   return RIGHT;
  if (result < 150)  return UP;
  if (result < 300)  return DOWN;
  if (result < 550)  return LEFT;
  if (result < 850)  return SELECT;
  return NONE;
}

状態機械とのインターフェース

生成されたC++コードが提供するインターフェースを実装して状態機械を制御します。ボタン入力をイベントに変換する際、チャタリング除去(デバウンス)が必須。でないとイベントが複数回発火し、予測不能な動作になります。

ここでは立下りエッジ(ボタン離し)検出方式でデバウンス:


int oldState = NONE;

static void raiseEvents() {
  int buttonPressed = readButton();
  delay(80);              // 80ms待機(50msより安定)
  oldState = buttonPressed;
  if (oldState != NONE && readButton() == NONE) {
    switch (oldState) {
      case SELECT: stateMachine->getSCI_Button()->raise_mode();  break;
      case LEFT:   stateMachine->getSCI_Button()->raise_set();   break;
      case DOWN:   stateMachine->getSCI_Button()->raise_light(); break;
      case UP:     stateMachine->getSCI_Button()->raise_light_r(); break;
      case RIGHT:  stateMachine->getSCI_Button()->raise_onoff(); break;
      default: break;
    }
  }
}

全体の構成

メインプログラムは3要素で構成:


DigitalWatch* stateMachine = new DigitalWatch();
CPPTimerInterface* timer_sct = new CPPTimerInterface();
DisplayHandler* displayHandler = new DisplayHandler();

setup()


void setup() {
  stateMachine->setSCI_Display_OCB(displayHandler);
  stateMachine->setTimer(timer_sct);
  stateMachine->init();
  stateMachine->enter();
}

loop()


long current_time = 0;
long last_cycle_time = 0;

void loop() {
  raiseEvents();                              // 入力イベント発火
  last_cycle_time = current_time;
  current_time = millis();
  timer_sct->updateActiveTimer(stateMachine,  // 経過時間でタイマー更新
                               current_time - last_cycle_time);
  stateMachine->runCycle();                   // 状態機械1サイクル実行
}

例題の入手

YAKINDU Statechart Tools IDEに付属の例題として入手可能:

File → New → Example → YAKINDU Statechart Examples → Next → Arduino - Digital Watch (C++)

IDEはこちらからダウンロード。30日トライアル後、非商用利用は無料ライセンス取得可能!

製造プロセス

  1. Arduinoで作るモニター用Ambilightシステム:没入感アップの自作ガイド
  2. Arduinoデジタルダイス: LCD表示の乱数ジェネレーター自作
  3. Arduinoで超音波レベーション(浮遊)装置を自作:ステップバイステップガイド
  4. Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
  5. ArduinoとMAX30100で作るリアルタイムIoT心拍数モニター
  6. Arduino UNO WiFi Webサーバー:ブラウザからLEDをON/OFF制御
  7. Arduinoで作る自作デジタルペット「Tamaguino」─ 3Dプリンター製ケース付き完全ガイド
  8. DIY Arduino スマートウォッチ — Apple Watch 風腕時計を自作
  9. Arduinoで自動化するChrome恐竜ゲーム – LDRとPythonで障害物を検知してジャンプ
  10. Arduino NanoとRDA5807Mで作るコンパクトFMラジオ
  11. 有限ステートマシン設計:コンセプトから実装まで