MATLABで時計アプリ (1) (timerを使って作成) 

## はじめに
簡単なMATLABアプリの例として、時計を作ってみます。
時計の中でも、最初にシンプルなデジタル時計を作ってみます。

デジタル時計は、1秒おきに表示を更新することで作成します。「1秒おき」に更新するプログラムを作成するとき、for や while でも作成できますが、ここでは timer を使って作成してみます。
timer では、一定の時間間隔でプログラムを実行するということができます。

## Figure

まずは、時計を表示するFigureを作成します。

```matlab
%% Figureの表示
figH                 = figure();              % figH: Figureオブジェクト
figH.MenuBar         = 'none';                % メニューをオフ
figH.CloseRequestFcn = @CloseRequestFcn_figH; % クローズ時のコールバック関数
figH.NumberTitle     = 'off';                 % 番号表示なし
figH.Name            = 'Digital Clock';       % タイトル
```

`CloseRequestFcn`では、Figureを閉じるときに実行するコールバック関数を指定します。何のためにこれを設定するかは後で説明します。

## 時刻のテキスト表示

MATLABでのテキストの表示方法はいくつかありますが、ここでは、Style がtext の `uicontrol` を使うことにします。

```matlab
%% Text(uicontrol)の表示
textH          = uicontrol(figH);         % textH: uicontrolオブジェクト
textH.Style    = 'text';                  % text指定
textH.Units    = 'normalized';            % Positionの単位指定
textH.Position = [0,0,1,1];               % Figure全体にAxesを表示
textH.String   = datestr(now,'HH:MM:SS'); % 文字列の指定(時刻を表示)
textH.FontSize = 100;                     % フォントサイズ
```

時刻を表す文字列は、`now` を入力引数にした `datestr`で求めることができます。
「時間:分:秒」の場合には、`datestr(now,'HH:MM:SS')` と指定します。

## timer の設定

1秒おきに表示を更新するため、timer を設定します。

```matlab
%% Timerの設定
timerH               = timer();      % timeH: タイマーオブジェクト
timerH.ExecutionMode = 'FixedRate';  % 定期的に実行するように指定
timerH.Period        = 1;            % 1秒間隔
timerH.TimerFcn      = @updateClock; % コールバック関数指定
```

`ExecutionMode`には、timer のコールバックを呼び出すタイミングを指定する方法がいくつかありますが、処理時間に関わらず定期サンプルで実行するため、`ExecutionMode` には、'FixedRate'を指定します。
また、1秒間隔で実行したいため、`Period` に1を指定します。
timer から呼び出すコールバック関数は、`TimerFcn`に指定します。

次に、timer を開始するまでの時間を指定するために、`StartDelay`を指定します。
現在の時間と次の秒がかかるまでの時間（数ミリ秒ですが・・）を以下のように設定します。

```matlab
% 開始時刻の調整(秒が変わる瞬間にできるだけ合わせる。※処理時間の若干の遅延は許容する)
curTime   = datetime(now,'ConvertFrom','datenum');  % 現在時刻
delayTime = ceil(curTime.Second)-curTime.Second;    % 次に秒が変わる時間との差分(ミリ秒)を計算

timerH.StartDelay = delayTime; % Timerの開始時刻までの遅延を指定
```

## timerの起動
timerは、オブジェクトを作成するだけでは起動しません。
start でtimer を開始させます。

```matlab
%% timerの開始
start(timerH);
```
## timerのコールバック関数定義
timerのコールバック関数を定義します。
表示文字列を更新するので、以下のようになります。

```matlab
function updateClock(~,~)
    % Timerコールバック: 表示の更新
    textH.String = datestr(now,'HH:MM:SS');       
end
```
## figureをクローズしたときの処理 (timerの停止)
FixedRate で動かす timer は、止める処理をしないと動き続けてしまいます。
figure が閉じた後にも動き続けるとエラーが出力され続けることになるので、figure の
`CloseRequestFcn` を設定し、figureが閉じられるときには、timer も削除する処理を加えます。

```matlab
%% コールバック関数の定義
function CloseRequestFcn_figH(~,~)
    % Figureを閉じたときのコールバック：timerをStopしてからクローズ
    stop(timerH);
    delete(timerH);
    delete(figH);
end
```
以上でプログラムは完成です。
すぐに動かせるようfunction としてまとめたものを再掲します。

## 完成したプログラム
```matlab:simple_digitalclock.m
function simple_digitalclock()

%% Figureの表示
figH                 = figure();              % figH: Figureオブジェクト
figH.MenuBar         = 'none';                % メニューをオフ
figH.CloseRequestFcn = @CloseRequestFcn_figH; % クローズ時のコールバック関数
figH.NumberTitle     = 'off';                 % 番号表示なし
figH.Name            = 'Digital Clock';       % タイトル

%% Text(uicontrol)の表示
textH          = uicontrol(figH);         % textH: uicontrolオブジェクト
textH.Style    = 'text';                  % text指定
textH.Units    = 'normalized';            % Positionの単位指定
textH.Position = [0,0,1,1];               % Figure全体にAxesを表示
textH.String   = datestr(now,'HH:MM:SS'); % 文字列の指定(時刻を表示)
textH.FontSize = 100;                     % フォントサイズ

%% Timerの設定
timerH               = timer();      % timeH: タイマーオブジェクト
timerH.ExecutionMode = 'FixedRate';  % 定期的に実行するように指定
timerH.Period        = 1;            % 1秒間隔
timerH.TimerFcn      = @updateClock; % コールバック関数指定

% 開始時刻の調整(秒が変わる瞬間にできるだけ合わせる。※処理時間の若干の遅延は許容する)
curTime   = datetime(now,'ConvertFrom','datenum');  % 現在時刻
delayTime = ceil(curTime.Second)-curTime.Second;    % 次に秒が変わる時間との差分(ミリ秒)を計算

timerH.StartDelay = delayTime; % Timerの開始時刻までの遅延を指定

%% timerの開始
start(timerH);

    %% コールバック関数の定義
    function CloseRequestFcn_figH(~,~)
        % Figureを閉じたときのコールバック：timerをStopしてからクローズ
        stop(timerH);
        delete(timerH);
        delete(figH);
    end

    function updateClock(~,~)
        % Timerコールバック: 表示の更新
        textH.String = datestr(now,'HH:MM:SS');        
    end

end
```
## 実行例
![simple_digitalclock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482917/053574c2-36c0-e3a4-0511-ec154a96ff03.png)

## 終わりに
MATLAB上で時計アプリを作成してみました。
また、一般的にはインタープリタ型(行に書かれた命令を順番に実行するプログラム)と考えられているMATLABですが、timer を使うと、また異なった形でプログラムができるので、これをマスターするとプログラミングの幅が拡がります。

[次](https://qiita.com/sanmojih/items/e69b8dca4286e3aba5a4)は少し応用して、アナログ時計を作ってみたいと思います。