ブログの主のねこぽんは独学のみで趣味のプログラミングをしています。まちがった知識や用語、偏った部分も多分にあると思います。このブログでプログラミングに興味をもち、プログラミングの流れだけをつかんだら他のプログラミングの本や本格的なブログへステップアップしていってもらえたら、とおもいます。
UARTであそぼう!
プログラムはパズルだ!
今回はX-Basic回とPython回で使ったサンプルを少しパワーアップしてお互いUARTで通信できるようにするにゃよ!
どんな感じの予定か結果を先にみてみましょ。
X68000Zから操作中!
X68000Zから操作中!
X68000Zのキーボードで操作。あたり判定はラズパイで処理。
わかりやすいようにラズパイ側の表示もそのままにゃけど、これを応用すればラズパイ側の表示はしないで処理のみを徹底的にさせて結果だけをX68000Zに戻すということが出来ますにゃ!
今回あたりから、趣味のプログラミングの醍醐味、各所にパズル要素が出てきてるね。
障害物部分もそうだにゃ。X,Yを増減したあとに障害物を確認したら障害物があった場合に数値を戻さなきゃいけない、どうしよう みたいな。
やりかたは人それぞれでいいよね。効率よく組んで速度を求めるとかも楽しいかもだけど、まずは自分でわかりやすくがいいよね。
UART接続確認、ファイルの準備。
ここで物理的な接続方法を確認にゃよ。
接続確認したら今回のサンプルファイルをダウンロードして準備にゃ。
BasicN02_set.zip X68000Z用 HUMAN302(BasicN02).XDF / ラズパイ用 UART-(BasicN02).py
各ファイルをラズパイ、X68000ZmのSDをカードに移動。
UARTプログラミングで遊ぶためには config.sysで RSDRV.SYSが有効になってないとなので、起動すれば有効になるFDイメージを用意しています。
ラズパイ側準備
X68000Z側準備
いつもHDDから起動で遊んでて、あれ、FD起動できないぞ? の場合
BOOTのとこを、「2HD0」にします!2HD0を選択すると、起動時にSDカード入ってない場合はHDDを起動するからいつもこれでいいかも。
「RS232C」部分は19200にしないとなんだけど、起動時にRSDRV.SYSが有効になってないと19200にできないからここではさわらないにゃ!
今回のサンプル HUMAN302(BasicN02).XDF を 起動。
念のために再度SwitchでRS232Cを確認にゃ。
19200bpsになってなかったら変えてね。
Switch を終了させて Basic起動。
サンプルファイルBasicN02.basをロードするにゃよ。
X68000Z側 サンプルプログラムを確認
Switch を終了させて Basic起動。
サンプルファイルBasicN02.basをロードするにゃよ。
ブロック分けされてるとなんとなくメージわくねー。
1:まえおき
10 cls ※画面クリア
20 screen 1,2,1,1 ※画面設定(テキトーです)
30 int x=30,y=15,ai ※変数宣言(整数)
40 str a,sousin_word ※変数宣言(文字列)
50 ai=fopen("AUX","rw") ※こういうもんだと無心でコピペ
2:すでにX68000Zに転送されて溜まってる通信を捌かせる
60 while not ai=0
70 c=fgerc(ai)
80 endwhile
3:障害物を設置(見た目だけ)。キャラと座標を表示のサブルーチンへ
90 locate 10,10:print"#"
100 locate 38,20:print"#"
110 pri()
4:メインループ キー入力まちの永遠ループ
130 while not(a = "e")
140 a = inkey$(0)
150 if a = "4" then han(4)
160 if a = "6" then han(6)
170 if a = "5" then han(5)
180 if a = "8" then han(8)
190 endwhile:end
5:判定をラズパイに依頼ルーチン (詳細あり)
210 func han(k)
220 cx=x:cy=y:lp=0:c=0 ※サブルーチン内での変数設定
230 if k=4 then cx=cx-1
240 if k=6 then cx=cx+1
250 if k=5 then cy=cy+1
260 if k=8 then cy=cy-1
270 sousin_word =itoa(cx)+"*"+itoa(cy)
280 fwrites(sousin_word,ai)
290 fwrites(chr$(10),ai)
300 while lp=0
310 c=fgetc(ai):locate 10,2:print chr$(c)
320 if chr$(c)="Y" and k=4 then kesi():x=x-1:pri():lp=1
330 if chr$(c)="Y" and k=6 then kesi():x=x+1:pri():lp=1
340 if chr$(c)="Y" and k=5 then kesi():y=y+1:pri():lp=1
350 if chr$(c)="Y" and k=8 then kesi():y=y-1:pri():lp=1
360 if chr$(c)="N" then lp=1
370 endwhile
380 endfunc
さらなる詳細の説明。 ここを押してね。
一歩先の未来を仮で設定
230 if k=4 then cx=cx-1
240 if k=6 then cx=cx+1
250 if k=5 then cy=cy+1
260 if k=8 then cy=cy-1
一歩先の未来の座標を文字列としてラズパイに送信 (改行コードもセットで送信で一区切り)
270 sousin_word =itoa(cx)+"*"+itoa(cy) ※仮想移動は 「*」として送信
280 fwrites(sousin_word,ai)
290 fwrites(chr$(10),ai)
通信受信まち(310行) 進めるかどうかは Y/N で帰ってくる 障害物無いときは進む。
300 while lp=0
310 c=fgetc(ai):locate 10,2:print chr$(c)
320 if chr$(c)="Y" and k=4 then kesi():x=x-1:pri():lp=1
330 if chr$(c)="Y" and k=6 then kesi():x=x+1:pri():lp=1
340 if chr$(c)="Y" and k=5 then kesi():y=y+1:pri():lp=1
350 if chr$(c)="Y" and k=8 then kesi():y=y-1:pri():lp=1
360 if chr$(c)="N" then lp=1
370 endwhile
6:キャラを消す
400 func kesi()
410 locate x,y:print" "
420 endfunc
7:キャラと座標を表示 (詳細あり)
440 func pri()
450 locate x,y:print"O"
460 locate 2,2:print x
470 locate 5,2:print y
480 sousin_word =itoa(x)+"@"+itoa(y)
490 fwrites(sousin_word,ai)
500 fwrites(chr$(10),ai)
510 endfunc
さらなる詳細の説明。 ここを押してね。
キャラ表示時に今現在の座標をラズパイに送信
480 sousin_word =itoa(x)+"@"+itoa(y) ※実際の移動は 「@」として送信
490 fwrites(sousin_word,ai)
500 fwrites(chr$(10),ai)
ラズパイ側 サンプルプログラムを確認
Thonnyで開いた状態のプログラム見ていくにゃ。
tkinterはボタンとかキー入力のイベント待ちはできるけど、UARTの受信待ちはどうすればいいんだろって番長悩んでたの解決してるぽいね。
とりあえず時間でサブルーチン開始の命令あったからそれ使ったみたいにゃ。64行目のこの1行。 0.5秒後にサブルーチンへGO!
1:使用モジュールインポート
import serial #シリアルポート使用
import tkinter
2:UART通信の設定 こういうもんだと 無心でコピペ
ser = serial.Serial('/dev/ttyAMA0',19200,timeout=None)
X=360 #キャラ単位の移動だと12ぐらい X68000Z側 30 の 12倍
Y=180 #キャラ単位の移動だと12ぐらい X68000Z側 15 の 12倍
3:障害物位置をリスト化 ほんとはLabel数をリスト数から反映して増やせればいいんだけど今回はスキップ
SankakuList = ["10*10","38*20"]
4:キャラ位置表示(label位置再指定) サブルーチン
def print_Ichi():
label1.place(x=X,y=Y)
label2["text"] = str(int(X/12)) + "," + str(int(Y/12)) #こちらは12で割ってX68000Zと合わせる
5:メインループ (詳細あり)
def jyusin_loop():
global X
global Y
jyusinOK= False #ループ離脱用。True/False 2択の変数
while jyusinOK == False:
line = ser.readline()
Pri = str(line)
Pri= line.decode('ShiftJIS')
Pri = Pri.replace('\n', '')
if Pri.count("*") == 1:
hit=False
for num in SankakuList:
if num == Pri:
hit=True
break
if hit==False:
sousin="Y"
else:
sousin="N"
enc2 = sousin.encode()
#print ("x68へ送信:" + str(enc2))
ser.write(enc2)#X68に状態を送信
if Pri.count("@") == 1:
Plisplit = Pri.split("@")
X=(int(Plisplit[0]))*12
Y=(int(Plisplit[1]))*12
print_Ichi()
jyusinOK= True
root.after(1, jyusin_loop)
さらなる詳細の説明。 ここを押してね。
X68000Zから受け取ったデータの整理 こういうもんだセットとして使用で可
line = ser.readline()
Pri = str(line)
Pri= line.decode('ShiftJIS')
Pri = Pri.replace('\n', '')
X68000Zから受け取ったデータの種類判断
if Pri.count("*") == 1: # *が入ったデータは未来位置 もし未来位置を受け取ったら
#-----------------------------
if Pri.count("@") == 1: # @ が入ったデータは現在位置 もし現在位置を受け取ったら
未来位置に障害物があるかの判定
hit=False
for num in SankakuList: #障害物リストを全部ループ(2個入ってるから2回ループ)
if num == Pri: #num = 1回目 「10*10」 2回目 「38*20」 が入る
hit=True #一致したら 障害物があるということ
break #もう一致してるのにさらなるループは処理遅くなるので離脱
if hit==False:
sousin="Y" #障害物が無い場合は 行けるサインの「Y」
else:
sousin="N" #障害物がある場合は 行けないの「N」
enc2 = sousin.encode() # X68に結果を送信 こういうもんだセット
ser.write(enc2)
現在位置データが送られてきた場合の処理
Plisplit = Pri.split("@") #@を堺に文字列を分割。
X=(int(Plisplit[0]))*12 #文字列を整数に変換 12倍してラズパイ向けに合わせてます。
Y=(int(Plisplit[1]))*12 #文字列を整数に変換 12倍してラズパイ向けに合わせてます。
print_Ichi()
jyusinOK= True #UART受信ルーチン 一旦離脱。
root.after(1, jyusin_loop) 即受信ルーチンへ戻らせます。
6:ウインドウ作成
root = tkinter.Tk()
root.title("key")
root.geometry("744x348") #X68000Zで「A」上下左右移動させてカウントしたら 62×29 だったので その12倍
7:障害物設置 (見た目のみ)
label3 = tkinter.Label(root,text="■")
label3.place(x=10*12,y=10*12)
label4 = tkinter.Label(root,text="■")
label4.place(x=38*12,y=20*12)
8:キャラと現在位置用の label設置。UART受信ループへ。
label1 = tkinter.Label(root,text="◎")
label1.place(x=X,y=Y)
label2 = tkinter.Label(root,text="")
label2.place(x=0,y=0)
print_Ichi()
root.after(500, jyusin_loop) #0.5秒後にUART受信ループへGO
root.mainloop()
ラズパイ側 実行、X68000Z側 RUN
サンプルプログラムコードを眺めつつ 動かしてみるとなんとなくわかってくるかも。
障害物 あるなしを Y/N で返してるけど、 他のアルファベットで M だったら街に入った! とか応用できそうだねー。
あとは、今んとこ番長はTkinter初挑戦なのでlableの複製がプログラムから出来るかどうかわからないけど、せっかく障害物をリスト化してるからそのリストから障害物を描画する方向で他の方法を考えたりすると障害物簡単に増やせるにゃね。
全角文字列の送受信はお問い合わせにて。
全角文字列のやりとりについて気になる方は お問い合わせ から
お気軽に連絡くださいだダイガ!
・
・
・
- X68000Z UARTでなにができるの?
- X68000Zを動かしてみよう! X-Basic準備
- どのラズパイを選べばいいかな?
- ラズパイUART設定とケーブル接続
- ラズパイとのUART接続確認テスト
- MIDI再生専用FDを作成(mt32pi)
- MIDI再生専用FDを作成(ttymidi)
- mt32-piでラズパイをMIDI音源にする
- MIDIハード音源を試す
- DACとちびモニターを用意する
- X68uartRasModuleの製作 準備編
- X68uartRasModuleの製作 組立編
- アップデートとHDDの設定
- SX-Window HDDにインスト
- SX-Window MIDI演奏設定
- SX-Window MIDIハード音源設定
- プログラミング編 X-Basicになれてみる
- プログラミング編 Pythonに少し慣れてみる
- プログラミング編 UARTでX68kZからラズパイを操作!
- シェルスクリプトSW分岐とLチカ
- ちびモニタとLEDを制御する!
- ttymidiのUSBの関連付け自動
- Python実行形式にするPyInstaller
- Winkipedia/2chSC閲覧 X68k RasNet
- X68000Zの基本操作などのまとめ
- 番外編はTOPから!