« TortoiseSVNでの変更ファイル等をcopyするバッチファイル | トップページ | subversionリポジトリを別のPC/サーバに移すときやること »

2009年10月21日 (水)

pySerial/pyWin32でシリアル通信、でも受信が…

TracLightningに入っているpython(2.5)を使ってシリアル通信のプログラムを
試してみました。
その際、pySerial(pyserial-2.5-rc1.win32.exe)やpyWin32(pywin32-214.win32-py2.5.exe)を
インストールして使いました。
以下がそのプログラム。

# -*- coding: shift_jis -*-

from serial import Serial
from struct import unpack,pack
import time
from array import array

cmd1 = pack('8B',0x08,0x11,0x01,0x00,0x00,0x00,0x02,0xE4)
cmd2 = pack('8B',0x08,0x11,0x01,0x00,0x00,0x00,0x1B,0xCB)
cmd_done = pack('4B',0x04,0x12,0x02,0xE8)

b_array = array('B')

"""
送信のフォーマット
1.コマンド
    (パケット最後までの個数) 0x04または0x08 data0 … checksum
    2番目のデータが0x08なら設定値書き換えコマンド、
    0x04なら設定値にあわせた設定を実行するコマンド

受信のフォーマット
1.メッセージ
    (パケット最後までの個数) 0x0d data0 … checksum
    最小パケットは(n,0x0d,0x00,checksum)で4byte
2.コマンドに対するack
    0x03 0x0c 0xf1
"""
def checksum(num):
    global b_array
    csum = 0
    for i in range(num):
        csum += b_array[i]
    csum = csum % 256
    if csum==0:
        return True
    else:
        return False

def mParser():
    global b_array
    #len(b_array)>=numが前提
    num=b_array[0]
    if num > 4 and b_array[1]==0x0d and b_array[2]!=0 and checksum(num)==True: #メッセージの時だけ取り出し
        print b_array[:num]
    elif num == 4 and b_array[1]==0x0d and b_array[2]==0 and b_array[3]==0xef: #
        #なにもしない
        num =num #dummy
    elif b_array[0]==3 and b_array[1]==0x0c and b_array[2]==0xf1:#ack
        num = num #dummy
        #とりあえず何もやらない
    else:
        if num == 0 or checksum(num)==False:
            #print b_array
            #ここにくるものはほとんどごみ(なぜごみが出るか不明)…
            b_array=b_array[1:] #1個削る
            return
    b_array=b_array[num:] #1パケット分を削る

def bParser():
    global b_array
    while True:
        if len(b_array):
            num = b_array[0]
            if num == 0:
                num = 1
            if len(b_array)>=num:
                num = b_array[0]
                mParser()
            else:
                break
        else:
            break

com = Serial(
  port=0,
  baudrate=115200,
  bytesize=8,
  parity='N',
  stopbits=1,
  timeout=0, #0ならread()はすぐ読み出し
  xonxoff=0,
  rtscts=0,
  writeTimeout=None,
  dsrdtr=None)

com.flushInput()
com.flushOutput()

print com.portstr

interval = 8 #[sec]
v=0
b_array = array('B') #arrayとして初期化

print 'start'
nexttime = time.time()
while True:
    if time.time() >= nexttime:
        nexttime = nexttime + interval
        #送信
        if v==0:
          #print 'CMD1' % n
          com.write(cmd1)
          v = 1
        else:
          #print 'CMD2' % n
          com.write(cmd2)
          v = 0
        time.sleep(0.05)
        com.write(cmd_done) #実際に実行させる
    else:
        #受信
        dlen = com.inWaiting() #受信バッファにたまってる数を確認
        if dlen > 0:
            d = com.read(dlen)
            b_array.extend(array('B',d)) #b_arrayの後ろから追加
            bParser()
        else:
            b_array = array('B') #arrayをクリア#いるかな?これがないとしてもごみでるけど
        time.sleep(0.05)
com.close() #結局ctrl+Cとかで止めるから意味がなくなってる

しかし、送信はいいのですが、受信に変なデータ(ごみ)が入ってきます。
必ずというわけでもないのですが。
とりあえず長さとチェックサムをチェックすることで
いまのところ何とかなってる(と思う)のですが、すっきりしません。
これがなければ、ackを確認してから次のコマンドが出るようにしたいのですけど。
コンソールだけでなく、修正してtkinterを使ったものにしてもごみが出てしまいます。

---
TracLightningのpythonでは
win用python関連(pySerialやpyWin32)のインストーラがpythonの場所を見つけられなくてインストールできないのを
TracLightningでpsycoを使うでの、1,2の内容、もしくは手作業でレジストリ書き替えが必要だと思います(私は以前やっていたので)。

|

« TortoiseSVNでの変更ファイル等をcopyするバッチファイル | トップページ | subversionリポジトリを別のPC/サーバに移すときやること »

python」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: pySerial/pyWin32でシリアル通信、でも受信が…:

« TortoiseSVNでの変更ファイル等をcopyするバッチファイル | トップページ | subversionリポジトリを別のPC/サーバに移すときやること »