n:bit信号機(歩行者信号つき)

n:nitを接続して信号機をつくりましょう。
n:bitのLEDは車用、micro:bitのLEDは歩行者用の信号にします。
信号機の設計図はIchigoJam信号機(こちら参照)と同様にしました。

プログラム設計

n:bitのLED(緑、黄、赤)は車用、micro:bitのLED(5×5dot)は歩行者用として使用します。

・最初は、車用LEDは「青色」、歩行者用は「止まれ」表示します。

・Aボタンが押したら、歩行者が渡れるよう信号を切り換えます。
・車用LEDを「黄色」にします。
・2秒後に車用LEDを「赤色」にします。
・さらに2秒後に歩行者用表示を「すすめ」にします。
・5秒後に歩行者表示を6回点滅させます。
・歩行者用表示を「止まれ」にします。
・1秒後に車用LEDを「緑色」にします。


プログラムの作成

input.onButtonPressed(Button.A, function () {
pins.digitalWritePin(DigitalPin.P0, 0)
pins.digitalWritePin(DigitalPin.P1, 1)
basic.pause(2000)
pins.digitalWritePin(DigitalPin.P1, 0)
pins.digitalWritePin(DigitalPin.P2, 1)
basic.pause(2000)
images.createBigImage(
. . . . . # . # . .
. . . . . . # # # .
. . . . . . . # . #
. . . . . . # # . .
. . . . . # . . # #
).scrollImage(1, 200)
basic.pause(5000)
for (let index = 0; index < 6; index++) {
led.setBrightness(0)
basic.pause(200)
led.setBrightness(255)
basic.pause(500)
}
images.createImage(
. . # . .
. # # # .
. . # .
. # # # .
. # . # .
).showImage(0)
basic.pause(1000)
pins.digitalWritePin(DigitalPin.P2, 0)
pins.digitalWritePin(DigitalPin.P0, 1)
})
pins.digitalWritePin(DigitalPin.P0, 1)
images.createImage(
. . # . .
. # # # .
. . # . .
. # # # .
. # . # .
).showImage(0)


でじたるかくれんぼ

プログラムを設計する

micro:bitには、ブルートゥースという無線機能が標準で備わっており、同じ無線機能がある装置と通信をすることができます。
もちろん、 micro:bitどうしの通信もできます。
この機能を利用して、隠されたmicro:bit(子:hider)から発信される電波を、もう一台の探索用micro:bit(鬼:seeker)で受信して、電波の強弱を見分けて探し当てるプログラムをつくります。


HIDERの作成

・1秒に1回電波を発信する(数字の1を送信する)。
・音を鳴らす。

radio.setGroup(9)
basic.showNumber(9)
basic.forever(function () {
radio.sendNumber(1)
music.playTone(523, music.beat(BeatFraction.Sixteenth))
basic.pause(1000)
})

隠すmicro:bitのプログラムです。
まず、 「最初だけ」 のブロックを用意します。
「無線のグループ」命令で、相手と通信するための番号を決めます。
micro:bitでは、グループIDと呼びますが、テレビのチャンネルと同じと考えてよいでしょう。
つまり同じ グループID (チャンネル)同士で通信するための番号です。
グループIDは、0~255までの範囲で任意に決めることができますが、今回は9にしました。
グループIDは、「最初だけ」で一度設定するだけで機能します。

つぎに、「ずっと」のブロックを用意します。
このなかで「無線で数値を送信」命令を実行したとき、 micro:bit から電波が発信されます。
このときに、指定した(数値)の値を送信しています。
今回は1を送信するようにしましたが、このかくれんぼプログラムでは送信した値は使わないので、実際にはどんな値でもよいでしょう。
本来の通信の処理では、送信した数値や文字を相手が受信することで、いろいろなことをおこなうようにつくります。

この処理を1秒ごとに繰り返します。

これで、 隠すmicro:bitのプログラムは終わりです。
ダウンロードをしてmicr:bitにプログラムを保存してください。


SEEKERの作成

・受信した電波の強さを計測してグラフ(LED)で表示する。
・電波の強さに応じて、高い音、低い音を鳴らす。

radio.onReceivedNumber(function (receivedNumber) {
led.plotBarGraph(
150 + radio.receivedPacket(RadioPacketProperty.SignalStrength),
110
)
music.playTone(-20 * radio.receivedPacket(RadioPacketProperty.SignalStrength), music.beat(BeatFraction.Eighth))
basic.clearScreen()
})
radio.setGroup(9)
basic.showNumber(9)

無線のグループIDをHIDERと同じ9にします。
これも「最初だけ」で設定すればOKです。

「無線で受信したとき-(receivedNumber)」命令で、 電波を一度でも受信したときの処理を行います。
電波が受信できなければ、処理は行われません。つまり、「最初だけ」で実行した命令のままの状態になりますので、9を表示したままの状態になります。
「ずっと」の青色ボックスは使いません。

.

グラフの表示

「受信したパケットの(信号強度)」では、電波強度 (単位はdb(デシベル))によって-42から-128までの値が入ります。
-42は電波が強いので、 すぐそばに電波を発信しているmicro:bitがあることになります。
-128に近いならば電波が弱いことになります。
グラフ表示するためには、この電波強度のマイナス値のままだと不便です。
そこで 150をたすことによって、 値が108から22まで変化するようにしています。
グラフの最大値は110にしています(なぜか考えてみてください)。

左:電波の強さが-強いとき(-42db) 右:電波が弱いとき(-128db)


音を鳴らす

「音を鳴らす」命令で音が鳴るのですが、 micro:bit単体では音はなりません。そこで、n:bitというシールド基板を接続してそちらのスピーカーで音を出しています。
 音は、周波数を設定することで鳴るのですが、人間が聞こえる音は、一般的に20から20000Hz(ヘルツ)と言われています。
周波数が低いほど音も低く、高いほど高音になります。
「音を鳴らす」命令 の(真ん中のド)は、262Hzになります。

さて、今回の 「音を鳴らす」命令 では、受信した電波の信号強度に-20を乗算しています。
これは、840から2560Hz(電波強度は-42から-128)の音を出すこと意味します。
したがってHIDERが近いときは、だいたい上のラ(880Hz)の音になり、
離れるほど高い音が鳴ることになります。


かくれんぼ探し

さあ、それでは隠れているHIDERを、SEEKERで探索して見つけましょう。
まず、 HIDERのmicro:bitを外観では見えないように隠します。隠すときはスピーカも切っておいたほうがよいでしょう。
n:bit基板のP0 Selectorスイッチを、SからPに切り替えると音は鳴りません(代わりに緑LEDが点滅します)。 

電波は壁などの通り抜け、上下方向にも発信されますので、いろいろ試して探しましょう。

LEDでナナイロづくり 2

WS.LED命令を簡単に使うための、便利なサブルーチンをまとめました。
WS.LED命令の基本的なプログラミングはこちら「LEDでナナイロ」も参考にしてください。

  1. SET_WS.LED LED色の設定
  2. GET_WS.LED LED色の取得
  3. STR_WS.LED 一括色設定
  4. SHIFT_WS.LED LEDシフト設定
  5. LUMINA_WS.LED 輝度設定
  6. CLS_WS.LED 全LED消灯


1.LED色の設定
@SET_WS.LED(I,C,L)

1000 @SET_WS.LED(I,C,L)
1010 IF I>33 THEN I=33
1020 IF (L<1||L>255)&&(C%8) THEN L=20
1030 LET[I*3],C&1*L,C>>1&1*L,C>>2&1*L
1040 RETURN

・LED位置I番の配列(GRBの3か所)に、変数C(色)と変数L(明るさ)を設定します。
———————————————————————
変数 I LED点灯位置
0~33 (LEDの数は最大34個まで)
———————————————————————
変数 C 色
0■無(光らない)、1緑、2赤、3黄、4青、
シアン(青緑)、6マゼンタ(紅紫)、7
———————————————————————
変数 L 輝度
1~255(範囲外は強制的に20)
———————————————————————
※変数L=0は無効にしています。LED光らせたくないときは、変数Cに0を設定してください。
もし、変数Lの0を有効にするときは、1020行目を削除してください。

※変数Cは下位3ビット分しか使用していません。C=9は、C=1と同じ色です。マイナス値でも何かしら光ります(ABS(C%8)と同じ)。

※変数Lも下位8ビットしか使用していません。L=256はL=0と同じ明るさです(ABS(L%256)と同じ)。

サンプルプログラム1

10 L=100
20 FOR C=1 TO 7
30 FOR I=0 TO 11
40 GSB @SET_WS.LED(I,C,L)
50 WS.LED 12
60 WAIT 10
70 NEXT
80 NEXT
90 END


2.LED色の取得
@GET_WS.LED(I,C,L)

2000 @GET_WS.LED(I,C,L)
2010 IF I>33 THEN I=33
2020 C=([I*3]&&1)+([I*3+1]&&1)*2+([I*3+2]&&1)*4
2030 L=[I*3]|[I*3+1]|[I*3+2]
2040 RETURN

・LED位置I番の、色と明るさを、変数Cと変数Lに取得します。
現在WS.LED命令で光っているLEDの値を知ることができます。
・ただし、@SET_WS.LEDサブルーチンで設定したRGB値でないと正しい値を取得できません。
———————————————————————
変数 I
LED位置を指定する
0~33
———————————————————————
変数 C
変数Iで指定したLED位置の色が返る。
0■無(光らない)、1■緑、2■赤、3■黄、4■青、
5■シアン(青緑)、6■マゼンタ(紅紫)、7■白

変数 L 
変数Iで指定したLED位置の輝度が返る。
0~255

サンプルプログラム2

10 FOR I=0 TO 11
20 C=RND(8)
30 L=RND(255)
40 GSB @SET_WS.LED(I,C,L)
50 NEXT
60 WS.LED 12
70 WAIT 120
80 FOR I=0 TO 11
90 GSB @GET_WS.LED(I,C,L)
100 ? I,C,L
110 NEXT
120 END


3.一括色設定
@STR_WS.LED(S,(I,C,L))

3000 @STR_WS.LED(S,(I,C,L))
3010 FOR I=0 TO LEN(S)-1
3020 C=ASC(S+I)-48
3030 GOSUB @SET_WS.LED(I,C,L)
3040 NEXT

3050 RETURTN

・文字列を使用して、一度に色設定を行います。
———————————————————————
変数 S 色パターン
文字列で0~7をLED数分を指定します 。最大34文字。
———————————————————————
変数 L 輝度
———————————————————————
※変数 I 位置
 変数 C 色
これらの変数は文字列の文字パターンを作るために使います。
そのため、I,Cの値は、文字列最後の文字の設定値が入ります。

※@SET_WS.LEDサブルーチンを呼びますが、
つぎの行のように、直接置き換えてもよいです。
ただし、各変数の範囲チェックはしません。
3030 LET[I*3],C&1*L,(C&2&&1)*L,(C&4&&1)*L

※LEN(S)命令では、文字数を取得できます。これを利用するとWS.LEDの引数に直接使用できて便利です。
10 S=”12345″
20 GSB @STR_WS.LED(S,(I,C,L))
30 K=LEN(S):WS.LED K

サンプルプログラム3

10 S=”123456700000″
20 L=50
30 GSB @STR_WS.LED(S,(I,C,L))
40 WS.LED 12
50 END


4.LEDシフト設定
@SHIFT_WS.LED(R)

4000 @SHIFT_WS.LED(R)
4010 IF R<0 THEN GOTO @WSREV
4020 COPY #900,#800,R*6:COPY#806,#900,R*6
4030 LET[0],[(R*3],[R*3+1],[R*3+2]:RETURN
4040 @WSREV:R=-R
4050 LET[R*3],[0],[1],[2]
4060 COPY #900,#806,R*6:COPY#800,#900,R*6:R=-R:RETURN

・WS.LEDで点灯しているLED色を右または左に1つシフトします。
・ Rが正数(+)だと右、負数(-)だど左にシフトします。
———————————————————————
変数 R シフト個数
  整数(+プラス)なら右方向へ、R個分のLED色を1つずらす。
  負数(ーマイナス)なら左方向へ1つずらす。
———————————————————————

※内部処理では、配列を3個分をずらしています。
※変数Rには通常はWS.LEDの数と同じ値を設定しますが、1以下は意味をなしません。また、33はエラーになるので、最大シフトは32個までです。
※シフトして空いたLED位置には、シフト前の変数R値の値を代入します。つまりR=12のとき、右シフトとなり、12個目LEDの色が、1個目に入ります。

※IchigoJamBASICのCOPY命令は、 コピー元の領域とコピー先の領域が重なっていると正しく動作しません(c言語のmemcopyと同等)。そこで、画面表示用のメモリエリア(#900)に一旦コピーしています(c言語のmemmoveと同じ)。
画面表示がおかしくなるので、不都合であればキャラクタ用のメモリエリア(#700)に変更するとよいでしょう。
4020 COPY#700,#800,R*6:COPY#806,#700,R*6
4060 COPY#700,#806,R*6:COPY#800,#700,R*6:R=-R:RTN

サンプルプログラム4

10 CLV
20 S=”123456700000″
30 R=LEN(S)
40 L=50
50 GSB @STR_WS.LED(S,(I,C,L))
60 WS.LED 12
70 WAIT 120
80 FOR M=1 TO 24
90 GSB @SHIFT_WS.LED(R)
100 WS.LED 12
110 WAIT 30
120 NEXT
130 WAIT 180
140 R=-R
150 GOTO 80


5.輝度設定
@LUMINA_WS.LED(L,V,I)

5000 @LUMINA_WS.LED(L,V,I)
5010 IF V<1 OR V>34 OR !L THEN RETURN
5020 IF L>255 THEN L=255
5030 FOR I=0 TO V*3-1
5040 IF [I] THEN [I]=L
5050 NEXT
5060 RETURN

・WS.LEDで点灯している輝度を変更します。
———————————————————————
変数 L 変更する輝度 (1~255)
変数 V 変更するLED個数 (1~34)
いずれも範囲外の設定なら、サブルーチンは実行しない。
———————————————————————
変数 I 位置
文字列の文字パターンを作るために使います。
変数V×3-1と同じ値が入ります。

サンプルプログラム5

10 CLV
20 S=”123456700000″
30 L=75
40 GSB @SET_WS.LED(S,(I,C,L))
50 WS.LED12
60 WAIT 120
70 FOR L=100 TO 0 STEP -5
80 V=LEN(S)
90 GSB @LUMINA_WS.LED(L,V,I)
100 WS.LED12
110 WAIT 10
120 NEXT
130 END




OMAKE

WS.LED用のサブルーチンを応用して12個のLEDサークルをイルミネーションのように光らせるプログラムです。

10 @ARUN:’OTARU LED-DEMO 2020
20 CLS:CLV:R=12
30 L=50
40 S=”112233445566″
50 GSB @STR_WS.LED(S,(I,C,L))
60 WS.LED 12
70 WAIT 180
80 FOR M=1 TO 12
90 GSB @SHIFT_WS.LED(R)
100 IF R>0 WS.LED 12:WAIT 12
110 IF R<0 WS.LED 2,6:WAIT 50
120 NEXT
130 WAIT 60
140 R=-R
150 IF R>0 S=”666655554444333322221111″:R=24
160 IF R<0 S=”123456712345″:R=-12
170 GOTO 50

光を追いかけるロボットカー

明るいほうはどっち?

光ロボットカーの動き

左目  ANA(2)
右目  ANA(5)

前進  OUT 4,1 OUT 2,1
後退  OUT 5,1 OUT 3,1
左折  OUT 4,0 OUT 2,1
右折  OUT 4,1 OUT 2,0



プログラムを考えよう

Mission1.「光が当たったら前進!」

光センサーをひとつだけ使って、光が当たったら前進するという、シンプルな動きです。

左側光センサーANA2の値を読み込んで、変数L に入れます。
このプログラムでは、センサー値を1/100にして、明るさが0から10の数値になるようにしました。
数字が大きいほど明るいことを意味します(30行目)。

もし、明るさが5よりも小さいならば、光ロボットカーを止めます。
光ロボットカーの両方のモータを停止する命令は、OUT 0 です(50行目)。

もし、明るさが5以上なら、光ロボットカーを前進させます。
両方のモータを回す命令は、OUT 4,1: OUT 2,1です(60行目)。

最後に、0.1秒(6/60)待って、センサ入力に戻ります(100,110行目)。

 昼間や日光のよく当たる場所では、懐中電灯で光を当てなくても、勝手にロボットカーが動く場合があります。
その場合は、明るさの基準を5ではなく、7や8にしてください。
 光ロボットカーの走らせる場所によっては、明るさの基準を下げたり上げたりして、最適な値をみつける必要があります。

10 ‘HIKARI-ROBOT1
30 L=ANA(2)/100
40 ? L
50 IF L<5 OUT 0

60 IF L>=5 OUT 4,1: OUT 2,1
100 WAIT 6
110 GOTO 30

 


Mission2.「光スキ! 明るい方向へ走れ」

右側光センサーANA5も加え、左右のセンサーで、光の方向へロボットカ-を走らせましょう。

さて、ANA5は電源を入れた直後は入力ポートとして機能しません※1。
事前にANA5として使えるよう、おまじないが必要です(20行目)。

ANA2とANA5の準備ができたならば、それぞれセンサーの値を読み込みます。
ANA2は左=変数L、ANA5は右=変数R、として読み込みます(30行目)。

もし、右も左も両方とも明るさが5よりも小さい(暗い)なら、光ロボットカーを止めます(50行目)。

もし、右と左の両方とも同じ明るさなら、光ロボットカーを前進させます(60行目)。

もし、左側のほうが明るい(左>右)なら、光ロボットカーを左へ向けます。
左へ進みたい場合は、左モーターは停止して、右モーターのみを前進させます。
左モーターを止める命令は、OUT 4,0
右モーターを前進させる命令は、OUT2,1
(70行目)

もし、右側センサーのほうが明るい(左<右)なら、光ロボットカーを右へ向けます。
左モーターを前進させる命令は、OUT 4,1
右モーターを止める命令は、OUT2,0
(80行目)

IF命令の最後のGOTO100命令は必要です。
もう少し正しく説明すると、50行目のIF命令だけGOTO100が必要なのです。
70,80,90行目のGOTO100はなくても良いのです。

10 ‘HIKARI-ROBOT2
20 OUT1,-1
30 L=ANA(2)/100:R=ANA(5)/100
40 ?”ヒカリ スキ”,L,R
50 IF L<5 AND R<5 OUT 0:GOTO 100
60 IF L=R OUT 4,1: OUT 2,1:GOTO 100
70 IF L>R OUT 4,0: OUT 2,1:GOTO 100
80 IF L<R OUT 4,1: OUT 2,0:GOTO 100
100 WAIT 5
110 GOTO 30

※1 IchigoJamCPUのOUT1(出力)と ANA5(入力)は、IO端子を共有しており、切り替えて使用できる仕組みです。
OUT1,-1とすると以降はANA(5)として使用できます。
OUT1,1等を実行するとOUT端子になります。


Mission3. 「光はきらい・・ 光から逃げる」

ひかりが当たったら、逃げるプログラムです

10 ‘HIKARI-ROBOT3
20 OUT1,-1
30 L=ANA(2)/100:R=ANA(5)/100
40 ? “ヒカリ キライ”,L,R
50 IF L<5 AND R<5 OUT 0:GOTO 100
60 IF L=R OUT3,1:OUT5,1: GOTO 100
70 IF L>R OUT3,0:OUT5,1: GOTO 100
80 IF L<R OUT3,1:OUT5,0: GOTO 100
100 WAIT 5
110 GOTO 30


Mission4. 「光は好き!でも、強い光は嫌い・・」

さて、光ロボットカーに、もう少しわがままを聞いてもらうようにしましょう。
1.光があればそちらによっていく(Mission1の動き)。
2.でも、強すぎる光はキライなので、光から逃げるようにします(Mission3の動き)。
  2秒間は光から逃げる動きをしますが、その後は、また光があれば寄っていきます。

10 ‘HIKARI-ROBOT4
20 OUT 1,-1

30 L=ANA(2)/100:R=ANA(5)/100
40 ? “ヒカリキ スキ” L,R
45 IF L>7 AND R>7 GOTO 200
50 IF L<5 AND R<5 GOTO 300
60 IF L=R OUT 4,1:OUT 2,1: GOTO 100
70 IF L>R OUT 4,0:OUT 2,1:GOTO 100
80 IF L<R OUT 4,1:OUT 2,0:GOTO 100
100 WAIT 5
110 GOTO 30

200 CLT:OUT 0
210 L=ANA(2)/100:R=ANA(5)/100
220 ? “ヒカリ キライ”,L,R
230 IF L=R OUT 5,1:OUT 3,1: IF L<5 GOTO 280
240 IF L>R OUT 5,1:OUT 3,0
250 IF L<R OUT 5,0:OUT 3,1
260 WAIT 5
270 IF TICK()<120 GOTO 210
280 OUT 0
290 GOTO 30


300 OUT 0:H=L:?:?”ヒトヤスミ”
310 LED1:L=ANA(2)/100:R=ANA(5)/100
320 IF L>H OR R>H OUT 0:GOTO 30
330 IF !RND(500) OUT 4,1: OUT 2,1
340 IF !RND(100) OUT 4,0: OUT 2,1: WAIT 10*RND(7)
350 IF !RND(100) OUT 4,1: OUT 2,0: WAIT 10*RND(7)
360 WAIT 10
370 OUT 0
380 GOTO 310



LEDでナナイロづくり

IchigoJam BASIC 1.4.1にて、フルカラーLEDをコントロールする命令が追加されました(2019/12/6)。

 そこで、このLED基板と新命令を使って、いろいろな色を光らせるプログラムを組んでみましょう。
今回使用したLED基板は12個のLEDが円形に並んだWS2812 12ビット RGBリングです。
他に24個や7個の円形や、テープ状のもの、8個のスティック型などがありますが、WS2812というLED部品が載っているものならば、どれでも試せると思います。


IchigoJam基板とは次の図のようにつなげます。

IchigoJam側    LED基板側   
 VCC(3.3V)  ー  VCC      
 GND     ー  GND      
 LED      ー  IN       
           OUT(繋がない) 


LEDを光らせる新しい命令です(参考:WS.LED命令) 。

WS.LED 光らせるLED数 [, 繰り返し数]

 WS.LED 12 のような命令になりますが、残念ながらこれだけでは光りません。
あらかじめ、それぞれのLED位置に相当する配列に、色(約1600万色の中から1色)をRGB値で設定する必要があります(参照:RGB Wikipedia )。

次の例では、1番目のLEDが緑色に光ります(GRBの順であることに注意)。

[0]=100:[1]=0:[2]=0
OK
WS.LED 12
OK

配列[0]に、緑色の値 = 100 (0~255までの値で明るさを指定)
配列[1]に、赤色の値 = 0  (赤色は光らない)
配列[2]に、青色の値 = 0  (青色は光らない)


 しかし、この方法では色の組み合わせが多く配列も複雑なため、プログラミングが難しいです。
そこで、簡単にプログラミングができるように、7色に限定し た「LED色設定」サブルーチンを作りました。
(サブルーチン命令:GSB命令

LED色設定: @SET_WS.LED(I,C,L)

1000 @SET_WS.LED(I,C,L)
1010 IF I>33 THEN I=33
1020 IF(L<1 OR L>255)AND(C%8) THEN L=20
1030 [I*3]=C&1*L
1031 [I*3+1]=C>>1&1*L
1032 [I*3+2]=C>>2&1*L
1040 RETURN

変数 I LED点灯位置
0~33 (LEDの数は最大34個まで)
———————————————————————–
変数 C 色
0■無(光らない)、1緑、2赤、3黄、4青、
シアン(青緑)、6マゼンタ(紅紫)、7
———————————————————————–
変数 L 輝度
1~255(範囲外は強制的に20にする。100以上はあまり変わらない)
———————————————————————–
※以下のPRINT命令を入れておくと動きがわかりやす
 1025 PRINT “I=”;I,”C=”;C,”L=”;L
※「色設定サブルーチン」の詳細説明はこちらを参考に(別サイト)。
※WS.LED命令用の便利なサブルーチン集をこちらに追加しました(2019/10/29)。


I=0:C=1:GSB 1000
OK
WS.LED12
OK

I=1:C=2:GSB 1000
OK
WS.LED12
OK

I=2:C=3:GSB 1000
OK
WS.LED12
OK

I=3:C=4:GSB 1000
OK
WS.LED 12
OK

I=4:C=5:GSB 1000
OK
WS.LED12
OK

I=5:C=6:GSB 1000
OK
WS.LED12
OK

I=6:C=7:GSB 1000
OK
WS.LED12
OK

面倒な配列を考えなくても、変数Iと変数Cを設定してサブルーチンを呼ぶだけで、色を設定してくれます。
あとは、WS.LED命令を実行するだけです。

LEDを消すには、変数Cの色を0にします 。
例えば、3番目のLEDを消すには、、、

I=2:C=0:GSB 1000
OK
WS.LED12
OK

すべてのLEDを消すには、CLV命令が便利です (参考:CLV命令) 。

CLV
OK
WS.LED 12
OK





Mission !

色設定サブルーチンは、一度に一か所のLEDしか設定できません。
複数のLEDを設定するには、 FOR~NEXT命令を使うと便利です。
この命令は、指定した変数が条件を満たすまで順番に処理を繰り返してくれます(参考:FOR命令)。
今回のLED基板のように、順番に並んでいるLEDをコントロールするのには、すごく相性がよい命令なのです。

LEDの光らせ方を、つぎのミッションプログラムで試しましょう。
同時に、FOR~NEXT命令の使い方も理解してみましょう。

※以下のMissionプログラムを実行するときは、予め「色設定サブルーチン」を事前に入力しておいてください。


Mission1(FOR命令の使い方1)

LED位置(変数I)の0から11の順番に、色(変数C)を設定して、12個すべてのLEDを光らせます(40~80行目)。
プログラムをRUNして、画面に ? が表示されたら、0~7の色コードを入力して、何色が光るかみましょう。

10 ‘WS.LED1 設定した色で12個全部のLEDを光らせる
20 CLV
30 INPUT C
40 FOR I=0 TO 11
50 GSB 1000
60 WS.LED 12
80 NEXT
100 END


※次のプログラムを加えると、 LED位置(変数I) の変わり方がわかります。
45 PRINT “I=”;I

※ INPUT命令の代わりに、RND命令で 色(変数C)の値を決めると、RUNするたびに、IchigoJamが気まぐれに色を決めてくれます。
30 C=RND(7)+1

※次のプログラムを追加すると、1秒毎にLEDが順に光ります。
70 WAIT 60

※FOR命令は必ず1回は実行します。

RUN
?4
OK


Mission2(FOR命令の使い方2 二重ループ)

Mission1のプログラムを基本に、色(変数C)もFOR命令で変化させて、7色全部を光らせます。
FOR~NEXTが入れ子になっているのに注目してください。

10 ‘WS.LED2 七色を順番に光らせる
20 CLV
30 FOR C=1 TO 7
40 FOR I=0 TO 11
50 GSB 1000
60 WS.LED 12
70 WAIT 10
80 NEXT
90 NEXT
100 END



※次のプログラムを加えると、変数CとIの変わり方がわかります。
45 PRINT “C=”;C,”I=”;I


Mission3(FOR命令の使い方3 STEPオプション)

FOR命令のSTEPオプションを使うと、LEDを光らせる位置を飛ばすこともできます。
FOR I=0 TO 11 STEP 2
これは、変数Iが、0,2,4,・・,8,10 と2づつ増えていきます。

10 ‘WS.LED3 LEDをひとつ置きにひからせる
20 CLV
30 FOR C=1 TO 7
40 FOR I=0 TO 11 STEP 2
45 PRINT “C=”;C,”I=”;I
50 GSB 1000
60 WS.LED 12
70 WAIT 10
80 NEXT
90 NEXT
100 END



※STEPの値を3や5や11に変更して試しましょう。
11以上だとどうなるか?
また、0にするとどうなる?

※STEPは省略できます。省略した場合は、STEP 1 と同じ動きになります。


Mission4(FOR命令の使い方4 STEPオプション2)

Mission3までのプログラムでは、LEDが右回りに順に点燈しました。
左回りに光らせるにはどうすればよいでしょうか。
これも、STEPオプションで解決できます。

FOR I=11 TO 1 STEP -1
こうすると、変数Iが、11,10,9,・・・,2,1,0 と1づつ減っていきます。

変数Lの値で明るさも変えましょう。
L値は1~255までの範囲です。
L=8

10 ‘WS.LED4 ひかりを逆回転させる
20 CLV: L=8
30 FOR C=1 TO 7
40 FOR I=11 TO 0 STEP -1
45 PRINT “C=”;C,”I=”;I,”L=”;L
50 GSB 1000
60 WS.LED 12
70 WAIT 10
80 NEXT
90 NEXT
100 END


※STEP -1 としたときは、TOの値が初期値Iより小さくなければいけません。例えばつぎは文法エラーになります。
FOR I=11 TO 12 STEP -1

※次のプログラムを加えると、光が一周すると2秒停止します。これは、サンプル2や3でも同じように動きます。
85 WAIT 120

※次のように変更すると、プログラムをずっと繰り返しますね。
100 GOTO 30

※LEDを点灯したとき、最初は明るく、徐々に暗くして点灯するようにしてみましょう。
変数Lを、FOR~NEXTを利用して変化させます。
ヒント:42 FOR L=50 TO 5 SETP ?




Mission5(応用プログラム1)

Mission1を応用して、簡易ルーレットを作ってみました。
光が回って見えるようにするには少し工夫が必要です。
50行目で、現在のLED位置に紫色(C=6)を設定しています。
80行目で、今度はLED位置に無色(C=0)に設定することでLEDを消しています。

サブルーチンの呼び出し方法も、ラベル方式にしました。

ルーレットを止めるときは、[ESC]キーを押します。
しかし、このプログラムでは少し問題が起きます??。どこが問題なのか探してみてください。

10 ‘WS.LED5 ルーレット
20 CLV
30 L=15
40 @LOOP: FOR I=0 TO 11
45 PRINT “I=”;I
50 C=6: GSB @SET_WS.LED(I,C,L)
60 WS.LED 12

70 WAIT 3
80 C=0: GSB @SET_WS.LED(I,C,L)
90 WS.LED 12

100 NEXT
110 GOTO @LOOP



※BEEP命令を追加して、ルーレットに合わせて音も出せます。
60 WS.LED12: BEEP 5,10

※次のプログラムをどこかに追加すると、IchigoJam基板のタクトスイッチを押したら止まるようになります。
??に入る行番号を探してください(ヒント:LEDが光ったあとに押す?)。
?? IF BTN()=1 THEN END


Mission6.(応用プログラム2)

センサー(光や音など)の値によって変化するレベルメータ―です。

ANA2にアナログセンサーを接続します。
センサーの値は0~1023ですが、90で除算しているので、Aの値には0~11になります(30行目)。
0~11であれば、LED位置と簡単に比較できるようになります。
LED位置(変数I)よりセンサー値(変数A)が大きければ、色(変数C)を設定します(C=4:青)。そうでなければ、色はなし(C=0)を設定します(50行目)。
センサー値が0であれば、どのLED位置にも色は設定されないので、ひかりません。

WS.LED命令もFOR~NEXTの後に実行するようにしています。
LED位置すべての色設定を終えてからLEDを表示することで、処理も速くなります(80行目)。

10 ‘WS.LED6 レベルメーター
20 CLV:L=100
30 A=ANA(2)/90
40 FOR I=0 TO 11
50 IF A>I THEN C=4 ELSE C=0
60 GSB @SET_WS.LED(I,C,L)
70 NEXT
80 WS.LED 12
90 GOTO 30


※次を加えると、変数I,C,Lの変わり方が画面に表示されます。
45 PRINT “I=”;I,”C=”;C,”L=”;L

※このサンプルプログラムでは、センサー値が0だとLEDは光りませんが、次のように比較条件式を変えると、最低1コは必ず光らせることができます。
50 IF A>=I THEN C=4 ELSE C=0

※ 次のプログラムを加えると、 レベルが高いほど(センサー値が高いほど)明るくひからせることができます。
LED位置(変数I)の小さい順に、 輝度(変数L)に、
5,6,9,14,21,30,41,54,69,86,105,126 の値が入力されます。
55 L=5+I*I


Mission7.(応用プログラム3)

加速度センサーを使った傾き計です。

写真の加速度センサーはX,Y,Z軸の3軸センサーですが、このプログラムでは、X軸のみを使います。
ANA2に接続されたX軸の加速度センサーから、0~1023の値を得ます。
この加速度センサーの値は、水平のときに、約510になります。

変数Aに、右に傾けると+1~+11以上、左に傾けると-1~-11以上になるように計算しています(30行目)。

変数Aが0なら水平なので、LEDは光らせません(50行目)。

変数Aが正数(+)なら右に傾いているので、LEDを右回りにマゼンダ色を光らせます。
IF命令が続いていますが、色を設定するプログラムは、サンプル6と同じ仕組みです(60行目) 。

変数Aが負数(ー)なら左に傾いているので、LEDを左回りにシアン色を光らせます(70行目) 。

10 ‘WS.LED7 傾き計
20 L=100
30 A=(ANA(2)-510)/10
40 FOR I=0 TO 11
50 IF A=0 THEN C=0
60 IF A>0 THEN IF A>I THEN C=6 ELSE C=0
70 IF A<0 THEN IF A<I-11 THEN C=5 ELSE C=0
80 GSB @SET_WS.LED(I,C,L)
90 NEXT
100 WS.LED 12
110 GOTO 30


※ 次のプログラムを加えると、変数A,I,Cの変わり方がわかります。
15 CLS
85 LC 0,0
86 ?”A=”;A, “I=”;I, “C=”;C,


君だけが開けられる、ひみつの箱

サーボモータとセンサを使って、自分しか知らないパスコード(開け方)で解除する、小箱を作ろう。
サーボモータの制御方法とパスコードの処理方法をIchigoJamで学びます。

【必要な材料】

  1. IchigoJam基板(FW ver1.3.1以上)×1
  2. 箱 1300 × 1700 × 600 (Daiso:WOODENBOX 木のボックス74)  ×1
  3. ミニサーボモータ   ×1
  4. タッチセンサ(他に、光、スイッチ等やボリュームなども応用可能)   ×1
  5. 電池ボックス単三4本  × 1
  6. スペーサ、ねじなど

※箱は加工しやすい木製がよい。また、蓋がスライド式で透明だと作りやすい

配線図

プログラム準備

サーボモータ

1 ‘サーボモータ(鍵)
10 PWM 2,100
20 WAIT 60
30 PWM 2,200
40 WAIT 60
50 GOTO 10

2 ‘アナログジョイスティック
10 OUT 1,-1 :’OUT1をANA5に機能切換
20 ? ANA(2),ANA(5),IN(1)
30 GOTO 20


3'2桁の暗号
10 P=5: GSB @PASS
20 IF P ?"PASS1 OK" ELSE ?"PASS1 NG"
30 P=1: GSB @PASS
40 IF P ?"PASS2 OK" ELSE ?"PASS2 NG"
50 END

100 @PASS:CLT: K=0: LED0
110 IF IN(2)=0 GOSUB 500
140 IF TICK()<120 GOTO 110
150 BEEP5: IF K=P LED1: RTN
160 P=0:RTN

500 @COUNT: IF IN(2)=0 CONT
510 BEEP: K=K+1 : ?K
520 CLT: RTN



でじたる百葉箱(温度ロガー)

5V充電ケースとIchioJam本体+センサ基板(LCD+LED付き)。

測定場所でオートランさせて計測を開始。
計測した温度はLCDで確認しEEPROMへ自動記録。

計測終了後は、EEPROMの記録データを表示させて、模造紙のグラフ用紙( 1センチ四方のマス目模造紙 )にプロットする。
グラフ用紙は、温度と回数の比を2:1にして、温度変化を見やすくした。

各グループ3~4カ所を計測。

サンプルプログラムは 10秒間隔で10分間(60プロット)の測定例


1 ‘LCDオンドケイ by NEXTDAY SAVE0
10 CLS: L=1:C=1
20 [0]=(ANA(2)*32-500)/10
30 LC 0,0: ?”IchigoTemp 10sec”
40 LC 0,1: ?”No.”;C, [0];”゚C “
50 GOSUB @LCD

60 LED 1
70 IF [0]>20 OUT 1
80 IF [0]>25 OUT 3
90 IF [0]>30 OUT 7

99 LRUN1
100 @continu

110 BEEP
120 WAIT 60*10
130 C=C+1: IF C <= 60 GOTO 20

140 LRUN2



29000 END
29010 @LCD
29020 LET[96],640,64,#5639,#C6C,#C080,64
29030 Z=I2CW(62,#8C3,5)
29040 Z=I2CW(62,#8C0,3,#900,16)
29050 Z=I2CW(62,#8C8,3,#920,16)
29060 RTN

【プログラム概要】
10行目 初期化
    変数L:EEPROMへの記録数(1固定)
    変数C:測定した回数(最初は1回目)
20行目 温度センサのアナログ値を摂氏温度に変換
50行目 LCDへ測定値を表示
99、100行目 EEPROMへ温度を記録
120行目 10秒間待つ
130行目 6回/分×10分=60回の測定を繰り返す
140行目 EEPROMから測定した温度をリスト表示する

29000行目 Display on LCD (hidden subroutine)
     LCD表示サブルーチン
     LIST命令では非表示。

測定値から温度の求め方
温度センサーMCP9700は、温度を電圧で出力するセンサーです。
1. 温度センサーMCP9700は、0度のとき0.5Vを出力
2.0.01V毎に1度
3.ANA(2)には、MCP9700の出力電圧を読み取り、0(0V)から1023(3.3V)の範囲です。
4.


‘ ———————————————–SAVE1
‘ EEPROMデータ書き込み(I2Caddress 80)
‘ ———————————————–
‘ LRUN1   配列[n]の値をEEPROMへ書き込み(DATA追加)
‘  実行後は、LOAD0のプログラムの100行目へジャンプする
‘ LRUN1,1111 EEPROMのデータを初期化(DATA消去))
‘  実行後は、LOAD0を実行して終了

‘ L 記録する配列の長さ
‘ [0]~[L-1] EEPROMに書き込みする値
‘ M EEPROMに書き込まれたデータ数
‘ N EEPROMの書き込み先アドレス

1000 @EWRIT:’Write to EEPROM SAVE1(INIT)
1010 N=0:IF !L ? “EEPROM Write Error L=0!”:BEEP:END
1020 IF I2CR(80,#8E6,2,#8E4,2) ?”EEPROM I2C ERROR!”:BEEP:END
1030 M=M+1
1040 N=M*L*2
1050 N=N<<8|N>>8&#FF
1060 R=I2CW(80,#8E6,2,#800,L*2)
1070 N=0
1080 R=I2CW(80,#8E6,2,#8E4,2)
1100 IF FILE()=1 LRUN0,100
1110 RTN

1111 @EINIT:N=0:M=0: ‘EEPROM Initialization
1112 IF I2CW(80,#8E6,2,#8E4,2) ?”EEPROM I2C ERROR!”:BEEP:END
1113 ?”EEPROM ヲ ショキカ シマシタ”
1114 IF FILE()=1 LOAD0
1115 RTN


‘ ———————————————–SAVE2
‘ EEPROMデータ表示(I2Caddress 80)
‘ ———————————————–
‘ LRUN2   EEPROMの全データを1画面ごとに表示(SPCキーで次)
‘ LRUN2,2222 で、EEPROMの全データを1画面に集計(L=1のみ対応)
‘  実行後は、LOAD0のプログラムを実行(温度測定)
‘※IchigoJamが整数32256までしか扱えないため、LRUN2,2222は1000個以上の集計は表示がおかしくなる。

‘ M EEPROMに書き込まれたデータ数
‘ N EEPROMの読み込み先アドレス

‘ I カウンタ(レコード)
‘ J カウンタ(データ)
‘ Q データ表示用カウンタ(0~22)
‘ X プロット位置(X座標)
‘ R,S プロット位置(Y座標)
‘ T 最大値
‘ U 最小値
‘ Z I2C用
‘F 表示モード 0:グラフ、1:リスト

2000 @EREAD:F=1:’Read from EEPROM SAVE2
2010 CLS:N=0:Q=0:R=0:S=0:T=-30:U=99:IFI2CR(80,#8E6,2,#8E4,2)?”EEPROM I2C ERROR!”:BEEP:END
2020 IF M<1 ?” NOT DATA”:GOTO @END
2030 IF !L INPUT”DATA length?”,L
2040 FOR I=1 TO M
2050 N=I*L*2:N=N<<8|N>>8&#FF:Z=I2CR(80,#8E6,2,#800,L*2)
2060 IF F Q=Q+1:X=30:?DEC$(I,4);” ,”; ELSE X=I*30/M
2070 FOR J=0 TO L-1
2080 IF F ?[J];”,”;:GOTO@L2
2090 R=R+1:S=S+[J]
2100 IF T<[J] T=[J]
2110 IF U>[J] U=[J]
2120 @L2:NEXT
2130 IF F GOTO @L3
2140 IF X=Q GOTO @L4 ELSE GSB @GDSP:GOTO@L4
2150 @L3:?
2160 IF Q<23 GOTO @L4
2170 IF !INKEY() AND !BTN() CONT ELSE Q=0
2180 @L4:NEXT
2190 @END:LC0,23,1
2200 IF !INKEY() AND !BTN() CONT
2210 IF FILE()=2 LOAD0
2220 RTN

2222 @GRAPH:’EEPROM Graph
2230 F=0:GOTO @EREAD+10

2240 @GDSP
2250 LC0,0:?”サイコウ”;T;” サイテイ”;U;” データ”;M;
2260 LCX,35-(S/R):?”*”;:Q=X:R=0:S=0
2270 LCX,20:IFI>999?I/1000;
2280 LCX,21:IFI>99?I%1000/100;
2290 LCX,22:IFI>9?I%100/10;
2300 LCX,23:?I%10;
2310 LC0,5:?”30″:LC0,10:?”25″:LC0,15:?”20″
2320 RTN

「LRUN2」の表示例
「LRUN2,2222」の表示例

※EEPROMへの書き出しと読み出しプログラムは、福野さんのコードを参考にして作成しました。
https://fukuno.jig.jp/2192(福野泰介の一日一創

HEART★6基板を、ゲーム用のコントローラにするワザ

ルーレットで使用した、HEART★6基板を、ゲーム用のコントローラに改造しよう。
まずは、ボタンを押したときの状態を次のプログラムで確かめます。

10 PRINT IN(4),IN(3),IN(2),IN(1),””,IN(9),BTN()
20 WAIT 5
30 GOTO 10

INとBTNは、ボタンを押したときの状態が違うことに注意してください。

IN(x):ボタンが押されると入力が0、押されていないと1(プルアップ)
BTN():ボタンが押されると入力が1、押されていないと0(プルダウン)

では、IchigoJam定番の「川下り」ゲームを改造して、キー操作からHEART★6基板のボタンに改造する方法を説明しましょう。

オリジナルのプログラム

1 ‘KAWAKUDARI 2018 http://fukuno.jig.jp/2194
10 CLS:X=16
20 LC X,5:?”O”
30 LC RND(32),23:?”*”
35 WAIT 3
36 X=X-BTN(28)+BTN(29)
40 IF SCR(X,5)=0 GOTO20

1 ‘KAWAKUDARI 2018 http://fukuno.jig.jp/2194
10 CLS:X=16
20 LC X,5:?”O”
30 LC RND(32),23:?”*”
35 WAIT 3
36 X=X-BTN(28)+BTN(29)
40 IF SCR(X,5)=0 GOTO20

  1. まず、HEART★6基板のどのボタンをどのように使うかきめましょう。今回は、IN(4)は左、IN(1)は右にします。
  2. 次に、プログラムからキーボード入力の個所を探します。このプログラムでは、BTN命令を使っていますね。
  3. 次に、BTN命令の使い方を理解します。これは、プログラミングする人によって考え方が違うことから、どのように使おうとしたのか(仕様を)考える必要があるためです。このプログラムでは、BTN(28)は←キー、BTN(29)は→キーを押したときに1になることを利用して動きを決めていました。
  4. これで、BTN(28)はIN(4)、BTN(29)はIN(1)に置き換えれば良いことがわかります。 X=X-!IN(4)+!IN(1)
  5. でもちょっと待って!。
    IN命令の状態を確かめたとき、ボタンを離す=1、押す=0、となり、BTN命令を逆でした。
    BASICにはこんなときに使える式が用意されていて、式NOT(省略形 ! )があります。
    式NOTは、0なら1、1なら0するという性質があります。
    36 X=X-!IN(4)+!IN(1)
  6. まとめると、以下のようなプログラムが完成します。
    さらに、IN(3)で再ゲームできるように50行目を追加しました。

HEART★6で操作できるように修正したプログラム

1 ‘KAWAKUDARI 2018
10 CLS:X=16
20 LC X,5:?”O”
30 LC RND(32),23:?”*”
35 WAIT 3
36 X=X-!IN(4)+!IN(1)
40 IF SCR(X,5)=0 GOTO20
50 IF IN(3) CONT ELSE RUN

INKEY命令を使っている場合は、少し改造方法が異なります。

10 CLS:X=16
20 LC X,5:?”O”
30 LC RND(32),23:?”*”
34 WAIT 3
35 K=INKEY():CLK
36 X=X-(K=28)+(K=29)
40 IF SCR(X,5)=0 GOTO20

10 CLS:X=16
20 LC X,5:?”O”
30 LC RND(32),23:?”*”
34 WAIT 3
35 ‘ K=INKEY():CLK
36 X=X-(IN(4)=0)+(IN(1)=0)
40 IF SCR(X,5)=0 GOTO20

6分タイマー

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

【サンプル】

タイマーは、1分単位で時間をセットし、時間が来たらアラームが鳴ります。
SAVE0にプログラムを保存しておけば、BTNを押しながら電源を入れると、タイマーのプログラムが自動スタートします。

1.プログラムスタート時はタイマーセットモードです。
セット中の時間分だけLEDが点灯します。
ボタンを操作して時間をセットします。
IN1(SW1) -1分減らす(最小1分)
IN4(SW4) +1分増やす(最大6分)
IN3(SW3) セット完了&スタート

2.タイマー動作中は、1秒毎にLEDの光が一周し、残り時間の数だけLEDが点滅します。
IN2(SW2)ボタンを押すとキャンセルとなり、1.のタイマーセットモードになります。

3.時間が来たら、全LEDが点滅し、アラームが鳴ります。
どれかボタンを押すと、1.のタイマーセットモードになります。

【ソースコード】

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 CLT:BEEP5,100

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点灯パターン値を設定します。
 [1] OUT3の点灯値      ”000100=4
 [2] OUT3,2の点灯値     ”000110=6
 [3] OUT3,2,1の点灯値    ”000111=7
 [4] OUT6,3,2,1の点灯値   ”100111=39
 [5] OUT6,5,3,2,1の点灯値  ”110111=55
 [6] OUT6,5,4,3,2,1の点灯値 ”111111=63
※LED3の位置(基板頂点)を基準にした点灯値を配列設定することで、プログラムをわかりやすくしています。
 変数C タイマーセットの値。初期値3分。
 CLO IchigoJamポートのリセット。
    これをしないとボタン(IN1~IN4)が利かなくなることがあります。

20行目~ タイマー設定モード
 現在のタイマ設定値のLEDを点灯させて、40-50行目でボタンが押されるのを待ちます。ボタンの値は変数Sに入力されます。
70行目 ボタンによって設定された時間をセットします。1~6分の範囲チェックも同時に行います。
80行目 IN3ボタン(セット完了)が押されるまで、タイマー設定を繰り返します。
90行目 TICK値をゼロにリセットしてタイマーを開始します(BEEP音で合図)。

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

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

1000行目 ボタン入力サブルーチン
     変数Sに、SW1(IN1)からSW4(IN4)の論理和をセットします。
     SW1が押されたとき、S=1、
     SW2が押されたとき、S=2、
     SW3が押されたとき、S=4、
     SW4が押されたとき、S=8、がセットされます。
     例えば、SW1とSW4が押されていた時は、S=9となります。

※TICK()命令の応用例
TICK()の値は0~16383を常に繰り返し変化します。
この性質を利用すると、特定の数値パーターンを作ることができます。
たとえば、

A=TICK()/60
 これは、1秒ごとに、0,1,2,3,4,5,0,1,・・が変数Aに値が入ります。さらに、

A=TICK()/60%2 
 これは、1秒ごとに0,1,0,1,0,1,0,・・が変数Aに値が入ります(%は余りを求める計算式)。

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 オフセット

【ソースコード:かんたん版】

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

障害物を回避! センサーろぼっとカー 2019

ロボットカーを走らせよう。 進め! 止まれ! 右! 左!
壁(モノ)にぶつからない工夫は?
思いどおりに走らせるは?

【構成】
1.IchigoDake ×1 (FW ver1.2.3)
2.DAKE★IOx ver1.0 ×1 (Nextday)
3.二回路DCモータドライバ DRV8835 ×1 (秋月電子) 
 http://akizukidenshi.com/catalog/g/gK-09848/
4.シャープ測距モジュール GP2Y0E02A (アナログ出力)×1 (秋月電子)
 http://akizukidenshi.com/catalog/g/gI-07546/
5.FA130互換モータユニットタイヤ付き × 2(左右)
 https://www.mabuchi-motor.co.jp/motorize/branch/motor/
6.電源 単4(1.5V) × 2本
7.車体 × 1 ()


センサおよびモーターの動作テストプログラム

1 ‘DAKE ROBOT CAR TEST V0 2019/01/06
10 A=ANA(2)
20 B=A/25-4
30 PRINT A,BIN$(0,B)40 K=INKEY()
50 IF K=#30 OUT 0 :’数字キー0 のとき 停止 
51 IF K=#31 OUT 10 :’数字キー1 のとき 前進 OUT4,1 OUT2,1
52 IF K=#32 OUT 20 :’数字キー2 のとき 後退  OUT5,1 OUT3,1
53 IF K=#33 OUT 12 :’数字キー3 のとき 右旋回 OUT4,1 OUT3,1
54 IF K=#34 OUT 18 :’数字キー4 のとき 左旋回 OUT5,1 OUT2,1
55 IF K=#35 OUT 8 :’数字キー5 のとき 右折(L正転) OUT4,1
56 IF K=#36 OUT 2 :’数字キー6 のとき 左折(R正転) OUT2,1
57 IF K=#37 OUT 4 :’数字キー7 のとき 右折(R逆転) OUT3,1
58 IF K=#38 OUT 16 :’数字キー8 のとき 左折(L逆転) OUT5,1
999 GOTO 10


【サンプルプログラム】
 運転プログラムはSAVE0に保存します。
走らせるときはタクトスイッチを押しながら電源スイッチを入れて、コースに置きます。
 もう一度タクトスイッチを押すと、走り出します。

【ソースコード】

1 ‘DAKE ROBOT CAR by NEXTDAY
10 L=5: OUT 0
20 IF BTN()=0 THEN ? ANA(2): LED TICK()/30%2: CONT
30 @START
40 OUT 10: WAIT 1
50 IF ANA(2)<650 THEN CONT
60 OUT 0: WAIT 60
70 IF ANA(2)<450 GOTO @START
80 IF L=1 THEN OUT20: WAIT 80: OUT 0: WAIT 40
90 IF RND(3) THEN OUT16 ELSE OUT4
100 WAIT 30
110 L=L-1: IF L>0 GOTO @START
200 BEEP 5,100
999 RUN

【プログラム説明】
10行目 障害物検知回数、変数Lの初期化(5回検知したらリカバリ)
20行目 IchigoJam基板のタクトスイッチが押されるまで待つ
    そのとき、LEDは0.5秒おきに点滅させる。
30行目 @START :プログラム繰り返し点
40行目 前進。 WAITは距離センサの出力が安定するまでの時間。

50行目 手前10cm以内に障害物がなければ、この行を繰り返す。
60行目 障害物を検知したら、1秒停止。
70行目 再度、手前約20cm以内障害物がなければ@STARTへもどる。
    50行目より遠くの距離まで判断すること
    これは、人間が手や足でセンサーにかざしたときの対策。
80行目 障害物検知回数が残り1回なら、大きく後退。
    これは、袋小路などに入りこんで左右だけでは脱出できないときの対策
90行目 通常の障害物検知の時は、左右のどちらかに曲がる。
    RND(2)だと、0,1対象なのでRND(3)にして偏りをつけた。
100行目 単純に0.6秒停止。この命令はなくても、ほかには影響しない。
110行目 障害物検知回数をカウントし、なくなるまで@START
200行目 ここからリカバリー処理。
    現在はBEEPして、再度プログラムを実行するだけ。
    応用として、ここで360度ゆっくり回転して、
    センサで一番空いている方向を探すルーチンを入れてもよい。