MYU BASIC COMPILER (myubasic.exe)
ホーム | パーツ | 工作例 | ロボコン | ロボット教室 | ロボット制御
メロディのプログラム | センサープログラム | RCサーボの制御 | 入出力プログラム | モーターのPWM制御 | LEDの制御 | 計測と制御
MYUROBO転送ソフト | 構造化ドリトル | エクセルで制御 | エクセルで計測 | ミュウアセンブラ | 688基盤 | MYUROBO2基板
ミュウロボ命令一覧 | ミュウアセンブラ一覧 | 構造化ドリトル制御命令一覧
◆触覚を使ったロボットの説明はこちら!
●MYU BASIC プログラム | 言語仕様 | リファレンス | 入出力プログラム | LEDの制御 | サンプルプログラム
MYU BASIC は、GOTO文を使わないVisual Basicライクな構造化言語です。複雑な入出力処理も簡単で見やすいプログラムを書くことができます。
MYU BASIC COMPILERは、MYU BASIC言語をミュウロボ命令にコンパイルします。コンパイルしたミュウロボ命令は転送ケーブルを通して制御基板に転送して実行します。

MYU BASIC COMPILER (myubasic12.zip) はここからダウンロード(1.1M V1.24 2010/9/16版)できます。
※V1.24 REMOTEによるリアルタイム計測機能追加
※V1.23 WINAPI版、保存拡張子対応
※V1.22 REMOTEボタン追加、転送速度改善
※CD-ROM・USBメモリ・サーバーなどから起動可能
※V1.21+ REMOTEボタン追加、COMポート設定変更→
PIC16F688対応版、V1.2の場合、CPUを選択してコンパイルします。→
※Bug fix版、メモリ管理修正 For Next修正
※V1.12 転送速度UP & Bug Fix版、ローカル変数不備修正
※V1.11 LoopProc命令の追加
※CPUが16F688の場合、16F630を選択してコンパイルしても動作しますが逆の場合は転送エラーとなります。また転送ケーブルとつないだままSTEPボタンを押すとステップ動作します。
※Bug fix版、Step-不備修正その他
※V1.09 2進定数追加
※Bug fix版、myubasic.ini修正 PA=修正
※V1.08 For文でシステム変数(PCなど)が使える。リテラル定数追加。
●起動方法
myubasic12.zipを展開してmyubasicホルダをCD-ROM・ハードディスク・サーバー・USBメモリなどにコピーしてください。ホルダ中のmyubasic.exeを実行するとMYU BASIC COMPILERが起動します。myubasic.exeを直接実行するのでインストール制限のある学校などでも使えます。
またsetup.exeを実行するとインストールされます。正常にインストールされた場合、Windowsスタート->すべてのプログラム->myubasuc->myubasicをクリックすると立ち上がります。ディスクトップにもMyuBasicのショートカットが出来ます。

●よくある質問
Q、Vistaで起動できません。
A、アイコン上で右ボタンを押し「管理者としてこのプログラムを実行する」→許可で実行できます。
 または「コントロールパネル」→「ユーザーアカウント」→「ユーザーアカウント制御の有効化または無効化」→「ユーザーアカウント制御(UAC)を使って・・・」のチェックを外すと普通に立ち上がります。
Q、パソコンにRS-232Cポートがありません?
A、変換ケーブルが必要です。Googleで"USB RS232 変換"と検索してみてください。
変換ケーブルは1,000円-5,000円ぐらいです。
※変換ケーブルは付属の専用ドライバをインストールする必要があります。

●プログラム
MYU BASIC COMPILERを立ち上げてください。編集ボックス内でプログラムを作っていきます。
読込ボタンを押してmyubasic2.mbsを読み込んでください。COMPILEボタンを押しコンパイルすると下の画面になります。
右下のボックスにコンパイルされたミュウロボ命令が表示されます。ミュウアセンブラ一覧ミュウロボ命令一覧と合わせてご覧ください。
PCとミュウロボ制御基板とを転送ケーブルで接続し、転送ボタンを押すとプログラムが転送されます。'ピ'・・と音がして転送が始まり最後に'ピピ'と鳴れば転送終了です。転送ケーブルを抜きリミットスイッチを押すとプログラムが実行されます。
※二分木の動作イメージはこちら

編集ボックス
  MYU BASICプログラムを編集する場所です。
命令リスト
  MYU BASICで使われる命令リストです。命令はミュウロボ命令とMYU BASIC制御命令に分かれています。
  命令をクリックすると解説ボックスにその命令の説明が表示されます。
  命令をダブルクリックすると編集ボックスに反映されMYU BASICプログラムを作っていくことができます。
解説ボックス
  命令リスト内の命令をクリックすると命令の解説が表示されます。
読込ボタン
  MYU BASICプログラムを読み込みます。拡張子は.mbs
保存ボタン
  編集ボックスのMYU BASICプログラムを保存します。拡張子は.mbs
クリアボタン
  編集ボックス内をクリアします。
COMPILEボタン
  編集ボックス内のMYU BASICプログラムをミュウロボ命令にコンパイルします。
転送ボタン
  コンパイルされたミュウロボ命令をミュウロボCodeに変換して送信します。
REMOTEボタン
  Remote Controlダイヤログが現れ、転送ケーブルを繋いだままでロボットをリモコン操作できます。→
COMポート設定ドロップダウンリスト
  COMポートを設定します。
CPU設定ドロップダウンリスト
  基板のCPUを選択します。(16F630,16F688,16F88)

◆命令のカスタマイズ
myubasic.iniやstartup.txtを編集すると命令をカスタマイズすることができます。

■REMOTEボタンを使ったリアルタイム計測
688タイプとMYUROBO-2基板は、アナログ入力やパソコンとの双方向通信ができます。パソコンから計測の命令を送り結果をパソコンに表示することができます。また、RCサーボをパソコンからリモートコントロールできます。

◆アナログ値のリアルタイム計測
REMOTEボタンを押し、AN2ボタンを押すと8BITアナロク計測が行われ、結果が上のテキストボックスに表示されます。
※アナログポートは、右の設定ドロップダウンリストで変更できます。

◆デジタル値のリアルタイム計測
REMOTEボタンを押し、PORT-Aボタンを押すとポートAの値が2進数と16進数で表示されます。
※ポートは、右の設定ドロップダウンリストで変更できます。

◆RCサーボのリモコン操作
REMOTEボタンを押し、スクロールバーをクリックするかスライドすると基板のRCサーボをコントロールできます。 。
※RCサーボは、右の設定ドロップダウンリストで変更できます。



●はじめてのMYU BASICプログラミング 触覚を使ったロボットの説明はこちら!

ミュウロボ基本セットを素材に簡単なプログラムを作ってみます。
myubasic.exeを立ち上げ命令リストの"前進"をクリックしてください。下の解説ボックスに説明が表示されます。
続けて"前進"をダブルクリックしてください。左側の編集ボックスに"前進"が表示されます。スペース" "続けて"10"と入力し改行キーを押します。
同様に"右回り 5"と入力します。

前進 10
右回り 5

MYU BASICは、最初に命令、スペース、引数の順で書いていきます。引数が複数の場合、半角のコンマで区切って続けます。引数の数は命令によって異なります。詳しくはリファレンスをご覧ください。
プログラムはこれで終わりです。動作は前進を1秒行い右回り0.5秒です。次にCOMPILEボタンを押します。
右下のボックスにコンパイルされたミュウロボ命令が表示されます。次にパソコンとミュウロボ制御基板とを転送ケーブルで接続し、転送ボタンを押すとプログラムが転送されます。'ピ'・・と音がして転送が始まり最後に'ピピ'と鳴れば転送終了です。転送ケーブルを抜きリミットスイッチを押すとプログラムが実行されます。手順はコンパイルして転送です。
プログラムする → COMPILEボタンを押す → 転送ケーブルを接続する → 転送ボタンを押す → ケーブルを抜きリミットスイッチを押す
転送されたプログラムは電源を切っても覚えています。ロボットの電源を入れリミットスイッチを押すと何回でも実行できます。

次に上のプログラムの上下に次の命令を追加してください。
Do
  前進 10
  右回り 5
Loop


ミュウロボ基本セット
DoとLoopは制御文といってセットになっています。間の<文>(命令)は段落を付けると見やすくなります。同様にIf EnfIf、For Nextなどの制御文も内部に段落をつけて書くとプログラムが見やすくなります。制御文はMYU BASIC言語仕様をご覧ください。
※TABキーを使うと段落をつけるのに便利です。
これをコンパイルして転送/実行してみます。ロボットは多角形を描くような動きを繰返すはずです。Do Loopは間にはさまれた<文>を繰返し実行します。このように制御文を使うとおもしろい動きが実現できます。またプログラムは保存ボタンを押してファイル名を指定し保存するようにしてください。
※繰返し実行する制御文をループ文といいます。他にFor Nextループなどがある。
※Do...Loopは無限ループとなりプログラムは永遠に終了しません。ループから抜けるにはDo...Loop内で ExitDo 命令を使います。
※また Do WHile <式>...Loop や Do...Loop While <式> など条件を付けたループ文を使うとループから抜けられます。

次はFor Next文です。ここではTIMEという名前の変数を使っています。変数は値(テータ)を入れる入れ物です。変数は使う前にはByte TIMEと変数名を宣言しなければなりません。ここではTIMEとしましたが変数名は自由につけられます。
※MYU BASICで扱う値は、Byte型の整数(0 〜 255)です。688タイプやミュウロボ2基板では、Int型の整数(-32768 〜 32767)が扱える

<変数名、プロシージャ名、関数名について>
半角の英文字で始まり英文字、数字、'_'が使用できる。大文字、小文字の区別はしない。また、文字数の制限はない。
※'TIME' も 'time' もMYU BASICでは同じと判断されます。

Byte TIME
For TIME=1 To 10
  前進 TIME+TIME  //TIMEの倍前進する
  右回り 5
Next

上のFor Nextでは変数TIMEの値を1から10まで1づつ増やしFor Nextの間の<文>(命令)を繰返し実行します。
前進の引数(パラメータとも呼ぶ)に注目してください。TIME+TIMEと<式>が使われています。このようにMYU BASICでは引数に<式>が使えます。ここではTIMEの2倍が前進の引数になります。<式>の中で使えるものはこちら!
※    前進 <<TIME  //左シフト演算子を使ってもTIMEの倍前進する
また//以下は次の行までコメントが書けます。コメントを残しておくと後からプログラムの内容が理解しやすくなります。
これをコンパイル/転送/実行すると渦巻き旋回のような動きをします。
If EndIf、Do Loop、For Nextなどの制御文は入れ子構造といって内部に別の制御文を書くことができます。その際も下のように制御文どおしセットで段落を付けて書くと見やすくなります。

Byte TIME,V
For V=1 To 5
  For TIME=V To 10
    前進 TIME+TIME  //TIMEの倍前進する
    右回り V
  Next
Next

MYUROBO-1基板は入力ポートを4個持っています。In1には標準でリミットスイッチが接続されています。下の例は入力ポートの状態を調べ、前方のリミットスイッチが障害物を感知したら後退して向きを変えるプログラムです。MYU BASIC言語仕様リファレンスと一緒にご覧ください。
最初はIfLo(1) Thenを使った例です。If文は条件が成り立ったらThenからEndIfまでの<文>(命令)を実行します。
※入力ポートはプルアップされています。入力のない状態はHigh、リミットスイッチが押されるとLowとなります。(Highは 1、Lowは 0)

前進 10        //最初に1秒前進をする
Do
  前進       //引数を省略すると0にセットされ待ち時間なしで次の命令を実行できる
  IfLo(1) Then   //リミットスイッチ(In1)が押された場合ThenからEndIfの間を実行
    後退 10
    左回り 10
  EndIf
Loop

下は関数 In() を使ったプログラムです。同じ動作をします。In(ポート番号)は、High=1、Low=0として返す

前進 10        //最初に1秒前進をする
Do
  前進       //引数を省略すると0にセットされ待ち時間なしで次の命令を実行できる
  If In(1)=0 Then   //In1が押された場合LowとなりThenからEndIfの間を実行
    後退 10
    左回り 10
  EndIf
Loop

下は Else を使った例です。Elseは、If文の条件が成り立たなかった場合、ElseからEndIfまでの<文>(命令)を実行します。

前進 10        //最初に1秒前進をする
Do
  If In(1)=0 Then   //In1が押された場合LowとなりThenからElseの間を実行
    後退 10
    左回り 10
  Else            //条件が成り立たなかったらElseからEndIfの間を実行
    前進
  EndIf
Loop

条件ループ文を使った例です。これも同じ動作をします。

前進 10        //最初に1秒前進をする
Do
  Do While In(1)  //In1がHigh(リミットスイッチが押されていない状態)の間、Do Loop間を繰り返し実行
    前進
  Loop
  後退 10
  左回り 10
Loop

WaitIn1命令を使った例です。

前進 10      //最初に1秒前進をする
Do
  前進
  WaitIn1    //スイッチ(In1)が押されるまで直前の命令(前進)を実行
  後退 10
  左回り 10
Loop

PA(ポートA)、PC(ポートC)の値を直接読んだり出力することでも同じことが出来ます。詳しくはこちらをご覧ください。
※ここでは2進数(B'101')や16進数(&h10)を使っています。2進数や16進数はこちらをご覧ください。

PC=B'101'            //ポートCに前進の信号を出力
Wait 10              //1秒のウエイト
Do
  PC=B'101'          //ポートCに前進の信号を出力
  If (PA AND &h10)=0 Then //ポートAのビット4(In1)がLowならThenからEndIfの間を実行
    PC=B'100010'      //ポートCに後退の信号を出力
    Wait 10          //1秒のウエイト
    PC=B'11'         //ポートCに左回りの信号を出力
    Wait 10          //1秒のウエイト
  EndIf
Loop

MYU BASIC V1.2では命令の引数を省略すると引数が 0 にセットされます。
※上の例の前進のように引数を省略すると前進の信号を出した後、待ち時間なしで次の命令を実行できます。

DEFINEは第1引数の名前を定義して第2引数から次の行までの<文>に置き換えます。解かりやすい命令や定数を定義したりします。
※定義名は数字以外で始まり半角アルファベット、全角文字、数字が使えますが半角と全角の混在は禁止です。

DEFINE ARG,10
DEFINE Uターン,後退 ARG 左回り ARG
前進 ARG        //最初に1秒前進をする
Do
  前進       //引数を省略すると0にセットされ待ち時間なしで次の命令を実行できる
  IfLo(1) Then   //リミットスイッチ(In1)が押された場合ThenからEndIfの間を実行
    Uターン
  EndIf
Loop

プログラムで何回も同じ処理をすることがあります。この部分をサブルーチン(部品)化するとプログラムが見やすくコンパクトになります。MYU BASICではプロシージャと関数にあたりますが両者の違いは関数は値を返しますがプロシージャは返しません。
下は前のプログラムにメロディのプロシージャを追加したものです。最初と障害物を感知した時、動作します。
★動画(368K)はこちら

MELODY        //MELODYの呼び出し 引数は省略
Do
  前進       //引数を省略すると0にセットされ待ち時間なしで次の命令を実行できる
  IfLo(1) Then   //リミットスイッチ(In1)が押された場合ThenからEndIfの間を実行
    MELODY    //プロシージャMELODYの呼び出し
    後退 10
    左回り 10
  EndIf
Loop
Proc MELODY(W)      //プロシージャMELODYの宣言 呼び出しに引数が省略されたのでWは内部のローカル変数となる
  停止 10
  For W=48 TO 34 Step -2 //Wの増減値をStep -2で指定、Wを48から34まで2づつ減らしFor Next間を繰返し実行する
    PulsOut 2,W    //第2引数Wのパルス幅の音を0.2秒鳴らす
  Next
EndProc

プロシージャや関数はそのままではなにも動作しません。呼び出しによって動作し処理の終わりとともに呼ばれた場所に戻ります。どこに在ってかまいませんがプログラムの見やすさを考えると後半に置いた方が良いでしょう。
※最初に実行する部分(上の例ではMELODYからLoopまで)をメインプログラム、プロシージャや関数部分をサブプログラムと呼びます。

MYU BASICでは変数を使った演算ができます。下のプログラムはリミットスイッチが障害物を感知した回数をカウントし、3回ごとにメロディを2回鳴らすというものです。

Byte C         //変数Cを宣言
MELODY        //MELODYの呼び出し 引数は省略
C=0          //Cをゼロにする
Do
  前進       //引数を省略すると0にセットされ待ち時間なしで次の命令を実行できる
  IfLo(1) Then    //リミットスイッチ(In1)が押された場合ThenからEndIfの間を実行
    C=C+1     //Cを+1する
    If C=3 Then  //Cが3なら
      MELODY
      C=0
    EndIf
    MELODY    //プロシージャMELODYの呼び出し
    後退 10
    左回り 10
  EndIf
Loop
Proc MELODY(W)      //プロシージャMELODYの宣言 呼び出しに引数が省略されたのでWは内部のローカル変数となる
  停止 10
  For W=48 TO 34 Step -2 //Wの増減値をStep -2で指定、Wを48から34まで2づつ減らしFor Next間を繰返し実行する
    PulsOut 2,W    //第2引数Wのパルス幅の音を0.2秒鳴らす
  Next
EndProc

プロシージャと違い関数は値を返します。下の例は、PAMASK() という関数の値(戻り値という)を プロシージャ BZ の引数として使っています。このように関数は引数など<式>の中で使うことができます。
このプログラムを実行して0,1ビット(In2とIn3)をアース(電池の-とつなぐ)してみてください。ブザーの回数が変わるはずです。
※関数は<式>以外でもプロシージャのように独立して使うこともできます。

//プロシージャと関数の使用例:ポートAの0,1ビット(In2とIn3)の状態をブサーの回数で知らせる
Do
  BZ PAMASK() //プロシージャBZの呼び出し 引数に関数PAMASK()を使う 関数の呼び出しは、引数のない場合でも()で囲う
  Wait 10   //1秒のウエイト
Loop
Proc BZ(C)    //引数だけブザーを鳴らせる
  Do While C  //Cが0以外ならDo Loop間を繰り返す
    Buzzer 1 //ブザーを0.1秒鳴らす
    Wait 1
    --C    //C=C-1
  Loop
EndProc
Function PAMASK()  //プロシージャや関数の宣言は、引数の無い場合でも()で囲う
  PAMASK=PA AND 3 //関数名に代入することで戻り値になる ポートAの0,1ビットをマスクして戻り値とする
EndFunction

※myubasic.iniを編集(例えば、'前進'を'FF'に変える)すると命令をカスタマイズすることができます。
※いろいろなロボットの工作例はこちら
※メロディなど音階の設定はこちら
※ゆっくり前進したいなどモーターのスピードをコントロールするにはこちら
※RCサーボの制御はこちら
そのほかいろいろなことが出来ます。詳しくは下のMYU BASIC言語仕様やリファレンスなどをご覧ください。

MYU BASIC言語仕様(V1.2)

【コメント】  	// 以下は次の行までなにも実行しない。注釈などを書く

【定義】    	DEFINE 定義名,<文>		第1引数の名前を定義して第2引数から次の行までの命令に置き換える
        	※定義名は数字以外で始まり半角アルファベット、全角文字、数字が使えるが半角と全角の混在は禁止

【変数宣言】  	Byte 変数,変数,配列(定数)・・・
        	Int  変数,変数,配列(定数)・・・	Int(-32768 〜 32767)型の変数宣言(16F688 88専用)

【代入文】   	変数=<式>
 
【ステートメント】	命令 <式>,<式>   	引数の数は命令によって異なる 引数を省略すると 0 にセットされる

【制御文】   	If <式1> Then    	<式1>=0なら偽 0以外なら真<文1>を実行する
        	  <文1>
        	ElseIf <式2> Then   	<式2>=0なら偽 0以外なら真<文2>を実行する:省略可
        	  <文2>
        	ElseIf <式3> Then   	<式3>=0なら偽 0以外なら真<文3>を実行する:省略可
        	  <文3>
        	Else          	偽なら<文4>を実行する:省略可
        	  <文4>
        	EndIf

        	IfHi(1-4) Then     	入力ポートIn(1-4)がHighなら真<文1>を実行する
        	  <文1>
        	ElseIf <式> Then   	<式>=0なら偽 0以外なら真<文2>を実行する:省略可
        	  <文2>
        	Else          	偽なら<文3>を実行する:省略可
        	  <文3>
        	EndIf

        	IfLo(1-4) Then     	入力ポートIn(1-4)がLowなら真<文1>以下を実行する
        	  <文1>
        	ElseIf <式> Then   	<式>=0なら偽 0以外なら真<文2>以下を実行する:省略可
        	  <文2>
        	Else          	偽なら<文3>を実行する:省略可
        	  <文3>
        	EndIf

        	Do   			Do Loop間を繰返し実行
        	  <文>
        	Loop

        	Do While <式>    	<式>が0以外ならDo Loop間を繰返し実行
        	  <文>
        	Loop

        	Do
        	  <文>
        	Loop While <式>    	<式>が0以外ならDo Loop間を繰返し実行

        	ExitDo     		Do Loopからの抜け出し

        	For 変数=<式:初期値> To <式:最終値> Step <定数:値>  変数に初期値を代入
        	  <文>        	Step値が正の場合、変数<=最終値なら<文>を実行
        	Next           	Step値が負の場合、変数>=最終値なら<文>を実行
                	                        	変数はStep値が加算され終了値以内ならFor Next間を繰返す
                	                        	※Stepを省略するとStep 1となる

【プロシージャ】	Proc <プロシージャ名>(Int <ローカル変数>,Int <ローカル変数>,・・) Intを省略するとByte型になる
        	  <文>        					※Int(16F688 88専用)
        	EndProc

        	ExitProc    		プロシージャからの抜け出し

【関数】     	Function <関数名>(Int <ローカル変数>,Int <ローカル変数>,・・) Intを省略するとByte型になる
        	  <文>        					※Int(16F688 88専用)
        	  <関数名>=<式> 	関数の戻り値
        	EndFunction

        	ExitFunction   		関数からの抜け出し

<式>のなかで使用できるもの
1、10進定数   	A=123
2、16進定数    	A=&hF0 A=H'11'+H'1F'  A=&h1F+1
3、2進定数    	A=B'10110011' AND B'00001111'
4、リテラル定数 	A="A"  A="@"+1
5、変数     	A=A+B  B(A+1)=0
6、システム変数 	PA(ポートA)、PB(ポートC)、T1H、T1L(タイマ1(0.008mSec)の上位・下位8ビット)
        	PB(ポートB) (16F88専用)
        	例 A=PA  PC=&h1f  T1H=0  A=T1L
        	TRISA=<定数> 設定専用:ポートAの入出力をビットごと(0:出力 1:入力)に設定する(16F688 88専用)
        	TRISB=<定数> 設定専用:ポートBの入出力をビットごと(0:出力 1:入力)に設定する(16F88専用)
        	TRISC=<定数> 設定専用:ポートCの入出力をビットごと(0:出力 1:入力)に設定する(16F688専用)
        	READRS    取得専用:シリアルポートのデータがある場合はその値が返され無い場合は0が返される
        	GETRS     取得専用:シリアルポートから1バイトデータを読み込むまで待ち、値を返す(16F688 88専用)
        	RS=<式>     設定専用:シリアルポートに8BIT キャラクタデータを出力する(16F688 88専用)
        	DECRS=<式>  設定専用:シリアルポートに8BIT 10進データを出力する(16F688 88専用)
        	DEC16RS=<式> 設定専用:シリアルポートに16BIT 符号付10進データを出力する(16F688 88専用)
        	HEXRS=<式>  設定専用:シリアルポートに8BIT HEXデータを出力する(16F688 88専用)
        	HEX16RS=<式> 設定専用:シリアルポートに16BIT HEXデータを出力する(16F688 88専用)
7、算術演算子  	+ - * / MOD(剰余) A=A+1  A=B*(A+1) A=1+B/3 A=10 MOD 3   ※* / MOD (16F688 88専用)
8、関係演算子  	= > < >= <= <>  真なら1、偽なら0を返す
9、論理演算子  	AND OR XOR  A=A AND &H1F
10、()      	()内の計算は最優先
11、<<単項   	1ビット左シフトする  B=<<A  Aの倍がBに入る  Aは変化しない。
12、>>単項   	1ビット右シフトする  B=>>A  Aの半分がBに入る  Aは変化しない
13、-単項    	符号反転  A=-A  A=-(1-2)
14、Not 単項   	単項が0なら1、0以外なら0を返す A=Not A
15、++変数    	インクリメント演算子 ++A Aを+1する B=++A Aが1の場合AもBも2となる
16、--変数    	デクリメント演算子 --A Aを-1する B=--A Aが1の場合AもBも0となる
17、In(定数)	デジタル入力ポート In(ポート番号)の値をHigh=1、Low=0として返す
18、AN(定数)	アナログ入力ポート AN(ポート番号)の値を8BIT(0-255)の値で返す(16F688 88専用)
19、AN10(定数)	アナログ入力ポート AN10(ポート番号)の値を10BIT(0-1023)の値で返す(16F688 88専用)
20、関数(<式>,<式>,・・)

演算子の優先順位について
単項演算子(++ -- << >>) > 算術演算子(* / MOD) > 算術演算子(+ -) > 関係演算子 > 論理演算子 の順で計算する
※* / MOD はCPUが16F630の場合、使えません。

関係演算子を使った計算:真なら1 偽なら0を返す
1=0:偽 1=1:真 1=2:偽  1=1+1 計算結果は0 ※算術演算子を優先、関係演算子を後に計算
1>0:真 1>1:偽 1>2:偽  1+1>1 計算結果は1
1<0:偽 1<1:偽 1<2:真
1>=0:真 1>=1:真 1>=2:偽
1<=0:偽 1<=1:真 1<=2:真
1<>0:真 1<>1:偽 1<>2:真

論理演算子を使った計算:AND 論理積 OR 論理和 XOR 排他的論理和
B'00001111' AND B'00010001' 計算結果はB'00000001'(1)
B'00001111' OR B'00010001' 計算結果はB'00011111'(31)
B'00001111' XOR B'00010001' 計算結果はB'00011110'(30)

※MYU BASICではInt型変数(16F688 88専用)を使わないかぎり値は全てByte型(0-255)となり以下の注意が必要です。
※Byte型の-1は255と判断されます。1-2の計算結果は255となり、255(-1)+1は0となります。
※一般に-1<0は真ですがByte型では255<0と判断され偽となります。
※同様にFor A=-1 To 1 もA=255 To 1と判断されFor Nextループを実行しません。
※またFor A=x To 255の場合、Aが255の次に0に戻る為、無限ループとなります。
※同様にFor A=x To 0 Step -1の場合、Aが0の次に255となる為、無限ループとなります。
※Int型変数(16F688 88専用)の場合、この問題はありません。
※T1L,T1Hは連動して動く125KHzの16ビットタイマです。T1Lは0.008mSec,T1Hは0.008x256=2.048mSecで動作し
524.288mSecで一周します。
※CPUがPIC16F688 88の場合、T1Lは0.004mSec,T1Hは0.004x256=1.024mSecで動作し262.144mSecで一周します。

<変数名、プロシージャ名、関数名について>
半角の英文字で始まり英文字、数字、'_'が使用できる。大文字、小文字の区別はしない。
文字数の制限はない。また文字数によってコンパイルされるプログラムサイズは変化しない。

<変数>
変数はByte型またはInt型(16F688 88専用)で宣言してから使う。Byte型またはInt型で宣言した変数はグローバル変数となり
プログラム中どこでも有効です。変数は','コンマで区切って複数宣言できる。配列は()内に数を指定する。
ただし使える変数、配列、内部スタックの合計はCPUが16F630の場合は、9バイト以下。プログラムサイズは127バイトまで。
※CPUが16F688の場合は、80バイト以下。プログラムサイズは255バイトまで。
※CPUが16F88の場合は、80バイト以下。プログラムサイズは2047バイトまで。
※プロシージャ、関数を呼出すとローカル変数の数だけ関数はさらに戻り値の1バイト分内部スタックを使います。
なおプロシージャ、関数から戻ると内部スタックは開放されます。
例:
Byte Abc,DD(3)  //変数AbcとDD(0)からDD(3)までの配列が使える

<プロシージャと関数>
プログラムで何回も同じ処理をすることがあります。この部分をプロシージャや関数としてまとめ
呼び出すようにするとプログラムが見やすくコンパクトになります。
また引数を設定して値を変えて呼び出すことで複雑な処理も可能になります。
関数は値を返すことができ<式>の中で使うことができます。
プロシージャはProc <プロシージャ名>() EndProc、関数はFunction <関数名>() EndFunctionの間に
処理を書きますが、そのままではなにも動作しません。呼び出しによって動作し処理の終わりとともに
呼ばれた場所に戻ります。また()内に変数を宣言するとローカル変数となります。
呼び出しはプロシージャ名、関数名で行いますが引数は省略できます。関数は引数を()で囲う。
ローカル変数は引数を値渡しで受け取ります。
関数は内部で値を関数名に代入することで外部に返します。
※呼び出し側の引数よりローカル変数を多く宣言した場合、多い部分は受け渡しの無いローカル変数として使えます。
※プロシージャ、関数内からプロシージャや関数の呼び出しはCPUが16F630の場合、深さ8レベルまで可能。
※CPUが16F688の場合、深さ20レベルまで可能。
※CPUが16F88の場合、深さ10レベルまで可能。
※ローカル変数や関数は内部スタックを使うため、深い呼び出しはスタックエラーとなります。
※ローカル変数は局所変数ともいい宣言したプロシージャ、関数内のみ有効な変数です。
呼び出し:    	<プロシージャ名> <式>,<式>,・・・
        	A=<関数名>(<式>,<式>,・・・)+1
        	If <関数名>(<式>,<式>,・・・)=1 Then

//プロシージャと関数の使用例:ポートAの0,1ビット(In2とIn3)の状態をブサーの回数で知らせる
Do
  BZ PAMASK() //プロシージャBZの呼び出し 引数に関数PAMASK()を使う
  Wait 10   //1秒のウエイト
Loop
Proc BZ(C)    //引数だけブザーを鳴らせる
  Do While C  //Cが0以外ならDo Loop間を繰り返す
    Buzzer 1 //ブザーを0.1秒鳴らす
    Wait 1
    --C    //C=C-1
  Loop
EndProc
Function PAMASK()  //プロシージャや関数は、引数の無い場合でも()で囲う
  PAMASK=PA AND 3 //ポートAの0,1ビットをマスクして戻り値とする
EndFunction

◆16進数、2進数やリテラル入力例
前進 &h0A    //16進入力 10進数の10と同じ
前進 B'1010'   //2進入力 10進数の10と同じ
前進 "@"     //リテラル入力 @の文字コードは64なので、前進 64 となる

<MYU BASICエラーについて>
MYU BASICではCOMPILEボタンを押した時、コンパイルと同時にエラーチェックを行います。
文法エラーがあった場合、ダイヤログが現れエラー部分が表示されコンパイルは中止されます。
正しくコンパイルされた場合、右下のボックスにコンパイルサイズやミュウロボ命令が表示されます。

◆PwerOnStartについて
PwerOnStart命令がプログラムの先頭に入っていると基板のスイッチONとともにプログラムがスタートします。
この状態で新しいプログラムを転送するには、一旦スイッチを切り、転送ケーブルを接続してから基盤のスイッチを
入れれば新しいプログラムを転送できます。
ところがパソコンの中には、この方法で転送できないものがあります。この対応についてはこちら

<ミュウロボ制御基板のエラーについて>
ミュウロボ制御基板では以下の場合、エラーとなり警告音を鳴らし続けます。
1、127バイト以上の転送。CPUがPIC16F688の場合は255バイト
2、深さ8レベル以上のプロシージャ、関数の呼び出し。CPUがPIC16F688の場合は20レベル
3、変数、配列、内部スタックの合計が9バイトを越えた場合。CPUがPIC16F688 88の場合は80バイト
4、16F630以外ででコンパイルしたものをPIC16F630に転送したとき。
※MYU BASIC側で正しくコンパイルされても127バイトを越えた転送はエラーとなります。
※エラーの場合は一旦電源を切りプログラムを修正してから再転送してください。
<MYU BASIC リファレンス>
※<式>のなかで使用できるものは、こちら!
命令その他 使用例および解説
// // 以下は次の行までなにも実行しない。注釈などを書く
DEFINE 定義名,<文> 第1引数の名前を定義して第2引数から次の行までの命令に置き換える
Byte 変数,変数,配列(定数)・・・ Byte ABC,D(2),XX Byte型の変数や配列をコンマで区切って宣言する
配列は()内に数を指定する。上の例ではD(0)からD(2)までの配列として使える
Int 変数,変数,配列(定数)・・・(16F688 88専用) Int ABC,D(2),XX Int型の変数や配列をコンマで区切って宣言する
配列は()内に数を指定する。上の例ではD(0)からD(2)までの配列として使える
PwerOnStart プログラムの先頭に置くと電源オンとともにプログラムが始まる
前進 <式> 前進 10+A 両輪を前転させた後、引数の値(0-255)x0.1秒だけ待つ
後退 <式> 後退 10 両輪を後転させた後、引数の値(0-255)x0.1秒だけ待つ
右回り <式> 右回り 10 左車輪を前転・右車輪を後転させた後、引数の値(0-255)x0.1秒だけ待つ
左回り <式> 左回り 10 右車輪を前転・左車輪を後転させた後、引数の値(0-255)x0.1秒だけ待つ
停止 <式> 停止 10 全モーターを停止させた後、引数の値(0-255)x0.1秒だけ待つ
左前 <式> 左前 10 左車輪を前転させた後、引数の値(0-255)x0.1秒だけ待つ
左後 <式> 左後 10 左車輪を後転させた後、引数の値(0-255)x0.1秒だけ待つ
右前 <式> 右前 10 右車輪を前転させた後、引数の値(0-255)x0.1秒だけ待つ
右後 <式> 右後 10 右車輪を後転させた後、引数の値(0-255)x0.1秒だけ待つ
モーター3左 <式> モーター3左 10 第3モーターを左回転させた後、引数の値(0-255)x0.1秒だけ待つ
モーター3右 <式> モーター3右 10 第3モーターを右回転させた後、引数の値(0-255)x0.1秒だけ待つ
モーター4左 <式> (16F88専用) モーター4左 10 第4モーターを左回転させた後、引数の値(0-255)x0.1秒だけ待つ
モーター4右 <式> (16F88専用) モーター4右 10 第4モーターを右回転させた後、引数の値(0-255)x0.1秒だけ待つ
Wait <式> Wait 10 引数の値(0-255)x0.1秒だけ前の状態を続ける
Buzzer <式> Buzzer 10 引数の値(0-255)x0.1秒だけブザーを鳴らす
WaitIn1 リミットスイッチ(In1)が押されるまで以前の状態を続ける
Servo <式>,<式> Servo 185,2 第1引数のパルス幅(30-255)を第2引数のサーボ(1-6)にセット
PulsOut <式>,<式> PulsOut 10,30 第1引数(1-255)x0.1秒だけ第2引数:パルス幅(1-255) の音を鳴らす
LoopProc プロシージャ名,定数 LoopProc BZ,3 第1引数のプロシージャを第2引数の回数(0-255)を繰り返す。回数が0の場合は無限に繰り返す
Delay <式> (16F688 88専用) Delay 1000 引数の値x0.001秒だけ待つ
Init (16F688 88専用) Init ポートを初期化する
StepIn (16F688 88専用) StepIn デバッグモードとなりレジスタの値をシリアルポートに出力。任意のシリアル入力でステップ動作となる
BreakP (16F688 88専用) BreakP プログラムポインタ:コマンドコード:AH.A.ARG2.ARG1.IXP.IX.IXM.FSR.INDFレジスタの内容をシリアルポートに出力し停止。任意のシリアル入力で次の命令から再実行
If <式1> Then
  <文1>
ElseIf <式2> Then
  <文2>
ElseIf <式3> Then
  <文3>
Else
  <文4>
EndIf
<式1>が0以外なら<文1>を実行

<式2>が0以外なら<文2>を実行:省略可

<式3>が0以外なら<文3>を実行:省略可

上の条件以外なら<文4>を実行:省略可

If In(1)=0 Then   //In1のスイッチがONなら
  左前
ElseIf In(2)=0 Then //In2のスイッチがONなら
  前進
ElseIf In(3)=0 Then //In3のスイッチがONなら
  停止
Else          //上の条件以外なら
  右前
EndIf

IfHi(1-4) Then
  <文1>
ElseIf <式> Then
  <文2>
Else
  <文3>
EndIf
入力ポートIn(1-4)がHighなら<文1>を実行

<式>が0以外なら<文2>を実行:省略可

上の条件以外なら<文3>を実行:省略可

IfHi(1) Then   //In1のスイッチがOFFなら
  左前
ElseIf In(2) Then //In2のスイッチがOFFなら
  前進
Else         //上の条件以外なら
  右前
EndIf

IfLo(1-4) Then
  <文1>
ElseIf <式> Then
  <文2>
Else
  <文3>
EndIf
入力ポートIn(1-4)がLowなら<文1>を実行

<式>が0以外なら<文2>を実行:省略可

上の条件以外なら<文3>を実行:省略可

IfLo(1) Then    //In1のスイッチがONなら
  左前
ElseIf In(2)=0 Then //In2のスイッチがONなら
  前進
Else          //上の条件以外なら
  右前
EndIf

Do
  <文>
Loop
Do Loop間を繰返し実行
Do
  前進 10
  右回り 5
Loop
Do While <式>
  <文>
Loop
<式>が0以外ならDo Loop間を繰返し実行
Do While In(1) //In1がOFFなら繰返し実行
  前進
Loop
Do
  <文>
Loop While <式>
Do
  前進
Loop While In(1) //In1がOFFなら繰返し実行

<式>が0以外ならDo Loop間を繰返し実行
ExitDo Do Loop間から抜け出す
Do
  前進
  IfLo(1) Then
    ExitDo //In1がONならDo Loopから抜け出す
  EndIf
Loop
For 変数=<式:初期値> To <式:最終値> Step <定数>
  <文>
Next
変数に初期値を代入、Step値が正の場合、変数<=最終値なら<文>を実行
Step値が負の場合、変数>=最終値なら<文>を実行
変数はStep値が加算され終了値以内ならFor Next間を繰返す
※Stepを省略した場合Step値は1となる
※MYU BASICで扱う値は全てバイト型(0-255)です。-1は255と同じです。
※For A=-1 To 1 はA=255 To 1と判断されFor Nextループを実行しません。
※またFor A=x To 255の場合、Aが255の次に0に戻る為、無限ループとなります。
※同様にFor A=x To 0 Step -1の場合、Aが0の次に255となる為、無限ループとなります。
For PC=1 To 32 //ポートCに1から32までを0.1秒間隔で出力
  Wait 1
Next
Proc <プロシージャ名>(<ローカル変数>,<ローカル変数>,・・)
  <文>
EndProc

Function <関数名>(<ローカル変数>,<ローカル変数>,・・)
  <文>
  <関数名>=<式:関数の戻り値>
EndFunction

プロシージャ、関数を宣言する時、()内に変数を宣言するとローカル変数となる
呼び出しはプロシージャ名、関数名で行うが引数は省略できる
関数は引数を()で囲う
ローカル変数は引数を値渡しで受け取る
関数は内部で値を関数名に代入することで外部に返す
//In2(RA0)とIn3(RA1)の状態をブサーの回数で知らせる
Do
  BZ PAMASK()
  Wait 10   //1秒のウエイト
Loop

Proc BZ(C)    //引数だけブザーを鳴らせる
  Do While C  //Cが0以外ならDo Loop間を繰り返す
    Buzzer 1 //ブザーを0.1秒鳴らす
    Wait 1
    --C    //C=C-1
  Loop
EndProc
Function PAMASK() //ポートAの0,1ビットをマスクする
  PAMASK=PA AND 3
EndFunction

ExitProc プロシージャから抜け出し呼ばれた場所に戻る
ExitFunction 関数から抜け出し呼ばれた場所に戻る
※myubasic.iniを編集(例えば、'前進'を'FF'に変える)すると命令をカスタマイズすることができます。
※モーター制御命令などの出力命令は、出力命令以外の命令の間も出力状態を維持します。前進の後、Buzzerを実行するとブザーを鳴らしながら前進します。
※Servo命令の詳しい使い方はこちら


●MYU BASICの入出力プログラム
ミュウロボ制御基板はPIC16F630を使って入出力をコントロールしています。ポートAはRA5以外入力用、ポートCは出力に設定されています。

<PIC16F630>
動作電圧 2.0V-5.5V
内部クロック 4MHz
タイマー1 125KHz
RA ポートA
RC ポートC

<入力ポート>
RA4 In1(リミットスイッチ)
RA3 シリアル信号入力用
RA2 In4
RA1 In3
RA0 In2

<出力ポート>
RA5 LEDと圧電ブザー用
RC5 S3,M2R
RC4 S2,M3L
RC3 S1,M3R
RC2 S6,M1L
RC1 S5,M1R
RC0 S4,M2L

<基板の入力ポート:In1-In4>
In1からIn4はセンサーなどを接続する入力ポートです。In1にはリミットスイッチが標準で接続されています。これらの入力ポートはプルアップされていて入力が無い状態ではHighとなっています。
入力の有無はPA(ポートA)を見ることで可能ですが、MYU BASICにはIn(1-4)やIfHi(1-4) Then、IfLo(1-4) Thenなどの命令が用意されています。下はリミットスイッチ(In1)が押されたときブザーを鳴らすプログラム例です。上の回路図からスイッチが押されるとIn1(RA4)がLowになることを理解してください。

//IfLo(1)を使う方法
Do
  IfLo(1) Then
    Buzzer 1
  EndIf
Loop
//In(1)を使う方法
Do
  If In(1)=0 Then
    Buzzer 1
  EndIf
Loop
//ポートAのビット4(RA4)をチェックする
Do
  If Not(PA AND &h10) Then
    Buzzer 1
  EndIf
Loop

これらのプログラムはどれも同じ動作をしますがコンパイルサイズは異なります。
ポートAのビット4(RA4)だけを調べる方法ですがビット4は16進表記で&h10、10進表記で16です。これとポートAとAND演算を行うことで可能です。このようにAND演算して特定のビットだけを選別することをマスクするといいます。

<基板の出力ポート:S1-S6>
S1からS6はRCサーボを制御するポートですが右図のように抵抗を介してLEDを光らせることもできます。またモータードライバー(SANYO LB1638)が接続されていてDCモーターの制御が可能です。
MYU BASICの出力命令には"前進","右回り","停止"などのモーター制御命令、ポート出力命令"PortOut"などがある他、PA(ポートA)やPC(ポートC)に直接値を代入する方法もあります。
※モーター制御命令などの出力命令は、出力命令以外の命令の間も出力状態を維持します。前進の後、Buzzerを実行するとブザーを鳴らしながら前進します。

PortOut <式>,<式> 第1引数(0-255)x0.1秒だけ第2引数のデータ(0-255)をポートに出力する

PortOut命令は、出力する時間とPIC16F630のポートCの下位6ビットとポートAの5ビット目を組み合わせた値を指定します。前進(5)とモーター左(16)を同時実行するには、それそれの値を加えた値(21)をポートに出力します。

PA=<式> PC=<式> PA(ポートA)やPC(ポートC)に直接値を代入する
Wait <式>   第1引数の時間(0-255) x 0.1秒だけ待つ

上の表を参考に PC=5 を実行すると前進します。次に Wait 10 と続けると 前進 10 と同じ動作となります。
また、2進表記を使うとビット操作が解りやすくなります。前進とモーター左を同時実行するには、RC0,RC2,RC4 のビットを 1 にすることなので PC=B'10101' と書くことで可能となります。

上の回路図を見るとポートAのビット5は出力に設定され基板のLEDと圧電ブザーに繋がっています。これを0.1秒ごとに反転するプログラムを作ってみました。ビットを反転するにはXORを使います。
//0.1秒ごとに基板のLEDを点滅
Do
  PA=PA XOR &h20 //ポートAのビット5を反転させる
  Wait 1 //0.1秒のウエイト
Loop

◆2進数と16進数
コンピュータデータの最小単位はビットです。1か0、ONかOFFかです。
これが8つ集まった単位がバイトとなります。
1バイトはB'00000000'からB'11111111'までの数、0から255までの数字を扱います。
16進数は4ビットを0からFの1文字で表しますから1バイトは上位4ビット、下位4ビットの2文字で表現します。
上の表から後退を2進数で表すとB'00100010'となり10進数では34となります。
これを16進では左表から&h22と表します。
ポート出力命令や下のLED制御ではビットごとのデータを扱うので2進数や16進数を使うと便利です。

MYU BASICの16進表記
・&h10 または H'10' (10進数の16)

MYU BASICの2進表記
・B'10000' (10進数の16)


●ブレッドボードを使ったLEDの制御
ブレッドボードを使うと電子回路の実験が簡単にできます。ミュウロボ制御基板側には電子部品店で売られているシングルピンソケット(メス)を半田付けしてありブレッドボードのLEDとはジャンパー線を使って上右図の配線をしてあります。
基板で使われているPIC16F630はポートCが出力にセットされていて抵抗を介してLEDを直接点灯させることができます。

<PortOut命令を使ってLEDを光らせる>
ポート出力命令は、出力する時間とPIC16F630のポートCの下位6ビット(RC0-RC5)とポートAの5ビット目を組み合わせた値を指定します。
※右上図の配線の場合、各LEDはポートCの値によって光ったり消えたりします。

PortOut m,n    //第1引数m(0-255)x0.1秒だけ 第2引数のデータn(0-255)をポートに出力する

◆2進数を理解する
右図は、10進数と2進数の比較表です。2進数の'1'はLEDの点灯、'0'は消灯となります。
PortOut命令の第2引数を'5'とした場合、右表から2進数では'0101'となりますからLEDは1つおきに光ります。
逆に'1010'と光らせるには、ポート出力命令の第2引数を10進数の'10'と指定します。
下のプログラムは0.1秒ごとLEDを交互に光らせたものです。

//LEDを1つおき交互に光らせる
Do
  PortOut 1,B'0101'   //ポートCにB'0101'(5)を0.1秒間出力
  PortOut 1,B'1010'   //ポートCにB'1010'(10)を0.1秒間出力
Loop

◆2進数・16進数の表記方法
B'1010'と書くと2進数を表記できます。これは右表から10進数の10です。16進表記では &HA または H'A'となります。

※上のプログラムはLED4個を交互に光らせているものです。値を変えることでLED6個の制御ができます。

<ポートCに直接値をセットしてLEDを光らせる>
ポートC(PC)に値を入力後、時間命令(wait)を実行することでLEDを光らせることができます。

PC=n    //ポートCにn(0-255)を出力、m(0-255)x0.1秒だけ待つ
Wait m

下のプログラムは0.1秒ごとLEDの2進数を1づつ増やすというものです。ポートCの値を1づつ増やしています。

//0.1秒ごとにポートCの値を1づつ増やす
Do
  ++PC     //ポートCの値を1増やす
  Wait 1    //0.1秒の待ち時間
Loop

MYUROBO-1基板には入力ポートを4個持っています。In1には標準でリミットスイッチが接続されています。下のプログラムはリミットスイッチを押した時、ポートCの値を1減らし離すと1増やすよう上のプログラムを改良したものです。

//リミットスイッチを押した時、ポートCの値を1減らし離すと1増やす
Do
  IfLo(1) Then  //リミットスイッチ(入力ポート1)が押されたら
    --PC     //ポートCの値を1減らす
  Else
    ++PC     //ポートCの値を1増やす
  EndIf
  Wait 1    //0.1秒の待ち時間
Loop

下のプログラムはシフト命令を利用してリミットスイッチを押している間LEDが下か上へ、離している間上から下へ点灯するようにしてあります。

//LED Shift リミットスイッチを押している間LEDが下か上へ離している間上から下へ点灯する
PC=1        //ポートCに1を出力
Do
  Wait 1     //0.1秒のウエイト
  IfHi(1) Then  //リミットスイッチOffで左シフト
    If PC=32 Then
      PC=1
    Else
      PC=<<PC //ポートCを左シフト
    EndIf
  Else      //リミットスイッチOnで右シフト
    If PC=1 Then
      PC=32
    Else
      PC=>>PC //ポートCを右シフト
    EndIf
  EndIf
Loop


<サンプルプログラム> 使用例1(myubasic1.mbs) このプログラムの動画(456KB)はこちら //渦巻き旋回(0.5秒ごとに回転半径を大きくする) Byte TIME TIME=1 T1H=0 Do 前進 0 WT TIME 左前 0 WT 10 If 244<T1H Then //0.5秒ごとに++TIME T1H=0 ++TIME EndIf Loop While TIME<30 Proc WT(C) Do While --C //WAIT Loop EndProc 使用例2(myubasic2.mbs) //二分木 動作イメージはこちら TREE 16 Buzzer 2 Proc TREE(X) 前進 X 停止 5 If X>=8 Then 左回り 3 停止 5 TREE >>X //Xを1/2にして再帰呼出 右回り 5 停止 5 TREE >>X //Xを1/2にして再帰呼出 左回り 3 停止 5 EndIf 後退 X 停止 5 EndProc 使用例3(myubasic3.mbs) //リミットスイッチを使った迷路脱出ロボット PwerOnStart Do IfLo(1) Then //前方が壁なら 後退 1 停止 5 Buzzer 5 後退 2 停止 10 右回り 9 停止 10 後退 3 停止 5 Do While In(2) //横壁まで 停止 0 左回り 0 Loop EndIf IfLo(2) Then //横壁なら 左前 0 Else 右前 0 EndIf Loop