2008年3月17日

+GAINER by Python構想 その6

あー、そうか、たいした長さのプログラムでもないから、Blogにそのまま転記しちゃえばいいかな?
ちょっとながいですが、以下、記します。(バグがあったらお許しを、Pythonは不慣れなので突っ込んでくださいね。)
あと、これはPySerialが必要ですので、"easy_install pyserial"とか、PySerialとかからダウンロード願います。

---- ここから ----

#!/usr/bin/env python

from serial import Serial

class Gainer:
def __init_(self):
self.ser = None
self.continuous_mode = 0

def open(self, port, config=None):
self.continuous_mode = 0
try:
self.ser = Serial(port)
except:
print "Can't open port!"
return -1
if config:
if config.has_key('baudrate'):
self.ser.baudrate = config['baudrate']
if config.has_key('bytesize'):
self.ser.bytesize = config['bytesize']
if config.has_key('parity'):
self.ser.parity = config['parity']
if config.has_key('stopbits'):
self.ser.stipbits = config['stopbits']
if config.has_key('timeout'):
self.ser.timeout = config['timeout']
if config.has_key('xonxoff'):
self.ser.xonxoff = config['xonxoff']
if config.has_key('rtscts'):
self.ser.rtscts = config['rtscts']
else:
self.ser.baudrate = 38400
self.ser.timeout = 5
return 0

def close(self):
if self.ser.isOpen() == False:
return -1
else:
self.continuous_mode = 0
self.ser.close()
return 0

def send_command(self, cmd):
if self.ser.isOpen() == False:
print "port is not opened."
return -1
self.ser.write(cmd)
return 0

def receive_result(self):
if self.ser.isOpen() == False:
print "port is not opened."
return ""
result = ""
while True:
char = self.ser.read()
#print char
result += char
if char == "*":
return result

def set_to_gainer(self, cmd):
print cmd
self.send_command(cmd)
result = self.receive_result()
print result
if cmd == result:
return True
else:
return False

def get_from_gainer_str(self, cmd):
print cmd
self.send_command(cmd)
result = self.receive_result()
length = len(result)
if (result[0:1] == cmd[0:1]
and result[length-1:length] == "*"):
print result
return result[1:length-1]
else:
return ""

def get_from_gainer_value(self, cmd):
print cmd
self.send_command(cmd)
result = self.receive_result()
length = len(result)
print result
if (result[0:1] == cmd[0:1]
and result[length-1:length] == "*"):
return int("0x"+result[1:length-1], 16)
else:
return 0

def get_from_gainer_value_continuous_mode(self, cmd):
if self.continuous_mode == 0:
self.continuous_mode = 1
print cmd
self.send_command(cmd)
result = self.receive_result()
length = len(result)
print result
if (result[0:1] == cmd[0:1]
and result[length-1:length] == "*"):
return int("0x"+result[1:length-1], 16)
else:
return 0


def reset(self):
return self.set_to_gainer("Q*")

def version(self):
return self.get_from_gainer_str("?*")

def configuration(self, mode):
if mode >= 1 and mode <= 8:
return self.set_to_gainer("KONFIGURATION_%1d*" % mode)
return False

def set_all_digital_output(self, output):
return self.set_to_gainer("D%04X*" % output)

def set_specified_digital_output_high(self, port):
return self.set_to_gainer("H%1d*" % port)

def set_specified_digital_output_low(self, port):
return self.set_to_gainer("L%1d*" % port)

def get_all_digital_inputs(self):
return self.get_from_gainer_value("R*")

def get_all_digital_inputs_continuous_mode(self):
return self.get_from_gainer_value_continuous_mode("r*")

def exit_continuous_mode(self):
cmd = "E*"
print cmd
self.send_command(cmd)
count = 0
while True:
result = self.receive_result()
print result
if cmd == result:
break
else:
count += 1
if count > 10:
return False
self.continuous_mode = 0
return True

def set_sensitivity_for_capacitive_sensing_inputs(self, setting):
return self.set_to_gainer("T%1d*" % setting)

def set_all_analog_outputs(self, value):
return self.set_to_gainer("A%08X*" % value)

def set_specified_analog_output_port(self, port, value):
return self.set_to_gainer("a%1d%02X*" % (port, value))

def set_specified_analog_output_row(self, row, value):
return self.set_to_gainer("a%1d%04X*" % (row, value))

def get_all_analog_inputs(self):
return self.get_from_gainer_value("I*")

def get_all_analog_inputs_continuous_mode(self):
return self.get_from_gainer_value_continuous_mode("i*")

def get_specified_analog_input(self, value):
return self.get_from_gainer_value("S%1d*" % value)

def set_ain_sampling_mode(self, value):
return self.set_to_gainer("M%1d*" % value)

def get_button_state(self):
result = self.receive_result()
print result
if result == "N*":
return 1
else:
return 0

def set_onboard_led(self, value):
if value == 1:
return self.set_to_gainer("h*")
else:
return self.set_to_gainer("l*")

def set_pga_gain_reference(self, gain, referense):
return self.set_to_gainer("G%1d%1d*" % (gain, referense))

---- ここまで ----

ちなみに、非同期受信は出来ていませんので、悪しからず。もう少し待ってくださいね。
以下は、デバッグに使ったテストツールです。
ご参考までに。

---- ここから ----

#!/usr/bin/env python

import Gainer
from time import sleep

g = Gainer.Gainer()
config = { 'baudrate' : 38400, 'timeout' : 5 }
if g.open("/dev/tty.usbserial-A2002mmD", config) == 0:
if g.reset() == True:
print "RESET"
else:
print "ERROR"
sleep(0.1)
g.version()
g.configuration(1)
sleep(0.1)

g.set_onboard_led(1)

sleep(2)
g.get_all_digital_inputs_continuous_mode()
g.exit_continuous_mode()

g.set_all_digital_output(0xffff)
sleep(2)

if False:
#for i in range(16):
g.set_specified_digital_output_high(i)
sleep(1)
g.set_specified_digital_output_low(i)
sleep(1)

print "0x%04X" % g.get_all_digital_inputs()

# for i in range(0x00, 0x100, 0x10):
# g.set_all_analog_outputs(i)
# sleep(0.1)
# for i in range(0x100, 0x00, -0x10):
# g.set_all_analog_outputs(i-1)
# sleep(0.1)
# g.set_all_analog_outputs(0)

for i in range(0x00, 0x100, 0x10):
g.set_specified_analog_output_port(3, i)
sleep(0.1)
g.set_specified_analog_output_port(3, 0)

# for i in range(0x00, 0x10):
# g.set_specified_analog_output_row(9, i)
# sleep(0.1)
# g.set_specified_analog_output_row(9, 0)

for i in range(1000):
#while True:
print "0x%08X" % g.get_all_analog_inputs_continuous_mode()
g.exit_continuous_mode()

g.set_onboard_led(0)

g.close()

---- ここまで ----

以上です。

7 コメント:

dada.yamada さんのコメント...

preタグでソースは表示すればいいのだそうです。これだから素人は困るよ。。。
ありがとうございました、kinofumiさん!

亀鶴 さんのコメント...

campでお世話になりましたkameiこと亀鶴です。
gainer.pyで早速遊んでおります。

バグ報告なのですが
set_pga_gain_referenceで呼ばれている、set_to_gainerの引数の数が違うようです。

既にお気づきかも知れませんが、念のため。

dada.yamada さんのコメント...

鶴亀さん、早速のコメントありがとうございます。
ある程度動いているんですかねー?
ご指摘いただいたバグは、

def set_pga_gain_reference(self, gain, referense):
return self.set_to_gainer("G%1d%1d*" % gain, referense)

のreturn文の中の引数に括弧がついていない話ですか?

def set_pga_gain_reference(self, gain, referense):
return self.set_to_gainer("G%1d%1d*" % (gain, referense))
でいいでしょうか?
この関数はノーデバッグでした。
ちょっとこれから確かめてみますが、動作がちゃんと確認できるかどうか・・・。

亀鶴 さんのコメント...

それでOKだと思います。
実はそのメソッドを使ったわけではなく、pycheckerを使ったら発見しただけで、特に今すぐ使いたい!というわけではなかったりします。
それなのに動作確認に時間を取らせてしまっているようで、すみません。
こちらでも確認してみます。

綴り間違いや、括弧の対応ミスなどの発見にはpycheckerやpylintが便利です。
#私はほぼ無意識に使うようになっています

dada.yamada さんのコメント...

とりあえず、鶴亀さんご指摘のバグを修正しておきました。

Ouch!Ouch!Ouch! さんのコメント...

亀鶴さんによると、
get_all_analog_inputs_continuous_mode関数でset_to_gainer()をコールしていてうまく動かない、というお話でしたが、ちゃんとget_from_gainer_value_continuous_mode関数を呼んでいるようです。
なんか、このブログでpreタグ処理にバグがあるのか、結構改行処理がうまく行っていないことがあるので、そのせいかなぁ。。。

Ouch!Ouch!Ouch! さんのコメント...

再度、亀鶴さんから不具合ご指摘をいただいたので修正しました。

変更内容:
get_specified_analog_value_continuous_modeの関数名をget_specified_analog_valueに変更し、内部でコールしているset_to_gainer関数をget_from_gainer_value関数に修正。

ちなみに、仕様書には上記関数のSコマンドはcontinuous modeと書いてあるが、実際は単発応答である。