HEART★6 タイマー

HEART★6基板(OUT1~6にLED,IN1~IN4にボタンを追加したシールド基板)とIchigoDakeを使った、6分タイマーです。


1.使い方

1分単位でタイマー時間をセットし、時間が来たらアラームを鳴らします。
LEDが6個なので、6分までセットできます。

  1. プログラムスタート時は、タイマーセットモードです。
    +−ボタンで時間を設定し、セットした分だけLEDが点灯します。
  2. スタートボタンを押すとカウントダウンが始まります。タイマー動作中は、1秒毎にLEDの光が一周し、残り時間(分)の数だけLEDが点滅します。
  3. キャンセルボタンを押すととカウントダウンをやめ、1.のタイマーセットモードにもどります。
  4. 時間が来たら、全LEDが点滅し、アラームが鳴ります。
    どれかボタンを押すと、アラームを止めて、1.のタイマー設定にもどります。

2.しくみ

使い方をもとに、プログラムで動かすしくみを考えます。そして、考えたとおりの動きや形になるように、プログラムを組んでいきます。

プログラムを組む時は、機能ごとに処理をまとめると便利です。このようにまとめたプログラムのことを「ルーチン」と呼びます。
今回はルーチンの先頭にラベル(@で始まる名前)を付けて、まとめました。
本来ラベルは、GOTOなどの飛び先に使うものですが、ルーチン名に使うのもまま違いではありません。逆に他の人がプログラムを理解しやすくなるメリットもあります。
1 初期設定(@INIT)
2 タイマーをセットするルーチン(@SET)
3 カウントダウンルーチン(@TIMER)
4 アラームルーチン(@ALM)


2.1 ボタンの用途を決める

ボタンの用途は、使いやすさも考えて決めます。
両端のボタンをタイマーの時間増減ボタンにし、中央のボタンを、スタート・キャンセルにしました。
もしこれが逆だと、中央のボタンで時間設定しているときに、両端にあるスタートボタンに指が触れてしまい、誤操作するかもしれません。


ボタン

用途
命令
押す:0
放す:1
IN1-1分減らす=LEDを1つ消す(最小1分)
(セット時のみ有効)
IN(1)
IN2タイマーキャンセル
(タイマー動作中のみ有効)
IN(2)
IN3タイマースタート
(セット時のみ有効)
IN(3)
IN4+1分増やす=LEDを1つ点ける(最大6分)
(セット時のみ有効)
IN(4)

ちなみに、IN1ボタンを「時間を減らす-」、IN4ボタンを「時間を増やす+」にしましたが、+-逆の方が自分に合っているかもしれません。
その場合は、入れ替えてもかまいません。
どのような使い方にすか決めるのは、作る人や使う人のことを考えて決めてよいのです。


2.1 タイマーをセットする

各ボタンが押されたかどうかは、IN命令の結果で調べます。

  • IN1ボタンを押したなら、

10 C=3
20 @SET
40 IF IN(1)==0 || IN(2)==0 || IN(3)==0 || IN(4)==0 CONT
50 IF IN(1)==1 && IN(2)==1 && IN(3)==1 && IN(4)==1 CONT
70 C=C-(IN(1)&&C>1)+(IN(4)&&C<6)
75 ? ”C=”;C,IN(4),IN(3),IN(2),IN(1)
80 IF IN(3) GOTO @SET

各ボタンが押されたかどうかは、IN命令の結果で調べます。


2.3 LEDの点灯

LEDの点灯状態で、何分のタイマーなのか分かるようにします。
HEART★6基板のLED3の位置が、時計の12時と同じ位置なので、ここを1分めとして右回りに点灯させるのがわかりやすいでしょう。
6分タイマーまでの点灯状態を次の表のようにします。

点灯するLED命令動作
LED(OUT)3OUT4(’000100)1分タイマー
LED(OUT)3,2OUT6(’000110)2分タイマー
LED(OUT)3,2,1OUT7(’000111)3分タイマー
LED(OUT)3,2,1,6OUT39(’100111)4分タイマー
LED(OUT)3,2,1,6,5OUT55(’110111)5分タイマー
LED(OUT)3,2,1,6,5,4OUT63(’111111)6分タイマー

OUT命令の値がバラバラなので、これだとLEDを点灯させるのにすこし不便です。そこで、配列に順番にOUT命令の値を入れて使うことにします。
こうすることで、OUT[C] というプログラムを書くことで、変数Cを”分”とみなして扱うことができるようになります。


2.4 カウントダウン

タイマーがスタートしたら、点滅しながら1分(60秒)毎にLEDを1つづつ消していきます。

変数Cに”分”が入っているので、WAIT3600を使って1分づつ処理してもよいですが、他の処理ができないので少し残念です。
そこでカウントダウンルーチンでは、つぎのようにプログラムして他の処理(LEDの点滅)もできるようにします。

90 CLK
100 @TIMER

 ・・・
 ・・・
140 IF TICK()<C*3600 GOTO @TIMER


2.5 アラームを鳴らす


3.プログラム

1’HEART*6タイマー v1.0 by NEXTDAY
10 LET[1],4,6,7,39,55,63:C=3:CLO

20 @SET
30 OUT [C]
40 GSB @SW(S): IF S CONT
50 GSB @SW(S): IF !S CONT
60 BEEP 20
70 C=C-(S=8&&C>1)+(S=1&&C<6)
80 IF S<>4 GOTO @SET
90 BEEP5,100:CLT

100 @TIMER
110 OUT 1<<(TICK()%60)
120 IF TICK()/15%2 THEN OUT [C-TICK()/3600]
130 GSB @SW(S): IF S=2 BEEP 50,50:GOTO @SET
140 IF TICK()<C*3600 GOTO @TIMER

150 @ALM
160 PLAY”O5$B8C6″
170 OUT TICK()/10%2*63:GSB @SW(S): IF !S CONT
180 BEEP
190 GOTO @SET

1000 @SW(S):S=!IN(4)*8+!IN(3)*4+!IN(2)*2+!IN(1):RTN

【プログラム説明】

10行目 配列[1]~[6]にLED点灯パターンを設定する
    LED3(基板頂点)が1分めになるように点灯パターンを作る
 変数C タイマー設定の初期値(3分)
 CLO IchigoJamの入出力ポートをリセット(ボタン誤動作の防止)

20行目~ @セット ラベル(タイマー設定)
    現在のタイマ設定値をLED点灯する
40-50行目 いずれかのボタンが押されるのを待つ
70行目 押されたボタンによってタイマ設定を+ー1する
    1~6分の範囲チェックもここで行う
80行目 IN3ボタン(タイマースタート)が押されていなければ、20行目に戻り、タイマー設定を続ける
90行目 TICK値をゼロにリセットしてタイマーを開始する
     BEEP音も鳴らしてタイマースタートの合図する

100行目~ @タイマー ラベル(カウントダウン)
110行目 60tick(1秒)毎にLED点灯を回転させる
120行目 15tick(0.25秒)毎に残り時間のLED数を点灯さる(110行目と合わせて、結果的に点滅も行う)
130行目 IN2ボタン(キャンセル)が押されていれば、20行目(タイマー設定)へ行く
140行目 セットした時間まで、100行目へ行き、タイマーを繰り返す

150行目~ @アラーム ラベル
160行目 アラームを鳴らすためPLAY文を実行する($で繰り返し鳴らす)
170行目 何かボタンが押されるまで、全LEDを点滅して待つ(この行を繰り返す)
190行目 20行目へ行き、タイマー設定へ戻ります。

1000行目 全ボタン一括入力サブルーチン
     SW1(IN1)からSW4(IN4)の排他的論理和を、ビットパターンにして変数Sにいれる

4.Tips

タイマープログラムでは、いろいろなプログラミングテクニックを使っています。ゲームやロボットなどにも使えるので、いろいろ試してみてください。

【複数LEDをパターン点滅させるTips(TICK命令の応用)】

TICK()の値は、実行する度に0~16383を繰り返して変化しています。LEDを決まったパターンで点滅させるときに、この性質を利用しすると便利です。

A=TICK()/60

 これは、1秒ごとに、0,1,2,3,4,5,0,1,・・の値が変数Aに入ります。
100 OUT 1<<TICK()/60:CONT
 のように繰り返し実行すると、LEDが順番に点灯していきます。

A=TICK()/60%2 
 これは、1秒ごとに0,1,0,1,0,1,0,・・の値が変数Aに入ります(%は余りを求める計算式)。
LED TICK()/60%2を繰り返し実行すると、IchigoJam基板のLEDが1秒毎に点滅します。
OUT 7,TICK()/60%2 でも同じ光らせ方ができます。

A=TICK()/30%6+1
 これは、0.5秒(30Tick)ごとに、6で割った余り+1、
つまり、1,2,3,4,5,6,1,2,3,・・の値が変数A入ります。

次の式を使えば、自分の好きな時間で数値パターンを作ることができるのです。
【書式】  TICK()/t%n+c
 t  変化時間(1/60秒単位=t/60秒毎)
 n 出力範囲(2なら0,1,0,1・・、3なら0,1,2,0,1,2)
 c オフセット

タイマープログラムでは、さらに応用して、複雑な点灯・点滅を作りました。
110行目の OUT 1<<(TICK()%60)
120行目140行目の OUT [C-TICK()/3600]
170行目の OUT TICK()/10%2*63

【ボタン入力をビットパターンで入力するTips】

1000行目のプログラムは、変数SにIN1からIN4の論理和を計算して入れています。
もう少し、わかりやすいBASIプログラムにすると次のようになります。

1000 @SW(S)
1010 S=0
1020 IF IN(1)==0 THEN S=S+1
1030 IF IN(2)==0 THEN S=S+2
1040 IF IN(3)==0 THEN S=S+4
1050 IF IN(4)==0 THEN S=S+8
1060 RETURN


IN1,IN2,IN3,IN4ボタンのいずれかが押されていると、変数Sがぞれ1,2,4,8の値になります。
どのボタンも押されていなければ0になります。
IN1とIN4ボタンが同時に押されていたなら、変数Sには9が入ります。
全部のボタンが同時に押されていたなら、変素Sには15が入ります。

つまり、各ボタンのON/OFFの全組合せは、0から15までの値になります。この値をしらべれば、どのボタンが押されたか判断できるのです。

【条件式のTips】

IchigoJamでは、条件式を0か0以外で判断しています。
そのため120行目のような書き方ができます。
IF TICK()/15%2 THEN ・・・

わかりやすくすると、
IF (TICK()/15%2) != 0 THEN ・・・ となります。
つまり、式の結果が0以外ならTHEN以降を実行してくれるのです。

=<>


5.おまけプログラム

・IchigoJam用
モニターとキーボードが付いているIchigoJamだけでも使えるプログラムです。一応、OUT命令もあるので、HEART★6基板のLEDも残り時間を点灯します。

20 @SET
70 INPUT”タイマーセット(1-6)?”,C
80 IF C<1 OR C>6 THEN BEEP: GOTO @SET
90 CLT:BEEP5,100

100 @TIMER
110 T=TICK()/3600: ?”アト “;C-T;”フン”
120 OUT C-T,1 : WAIT 10
130 OUT 0 : WAIT 10
140 IF T<C GOTO @TIMER


160 PLAY”O5 $B8C3″
190 GOTO @SET


この教材は「Creative Commons — CC BY-SA 4.0」の下に提供されています。

NPO法人NEXTDAY with TEAM IchigoJam ほっかいどう