|
[ruby-list:42173] Re: RS232Cによるパソコン間の通信の不具合(質問): msg#00204lang.ruby.japanese
PCと電子コンパスとの通信は、完璧に成功したと報告しましたが、実はいま一つ問題 があります。 スクリプトまで持ち出すと容量が増え迷惑でないかと心配し、簡易なスクリプトで内 容がわかる程度に留めてきました。 しかし、PC間の通信問題を越えて、電子コンパスとの通信問題に発展しております。 このために、スクリプトが複雑になりました。また、将来、RS232Cを利用される方 に、このやり取りが参考にもなることもあると思います。また、なかむらさんのご指 摘のように「小出しするつもり」では全くありせんので、言葉に甘えて、スクリプト を添付します。(電子コンパスとの通信は可能ですが、計測値3種 (roll,pitch,azimuth)を表示するだけに留めています。) 1 現状 スクリプトをrunさせて、port=.open(com4,"r+").binmodeで、電子コンパスに指 令を送り、計測を一回だけで終了し、port.closeする場合には、そのPCからの計測命 令の発出直後に計測データを表示し、スクリプトを終了します。毎回、runさせるな らば、これでも計測に利用可能です。 2 問題点 ところが、run後に任意の時間に、計測を繰り返し、計測値を表示記録させる目的 で、while〜endを利用して、繰り返し計測をしようとすると、問題が発生します。 chr = STDIN.getcによって、キー入力文字をchrで判定して、(例えばenterキーを押 したときのみ) 計測を行うようにしたところ、enterキーを押したときに、計測内 容は、古い計測値を示します。すなわち、数10回も以前に取得した計測値が、読み 込まれているらしく、これを表示するので、enterキーを押した直後の計測値を表示 しません。 これでは、使い物になりません。この原因は、bufferにデータが貯まるためと思わ れます。このとき、sysread(1)やport.flush等を入れても、効果がありません。 3 疑問点 1) port.flushの入れるスクリプト内の位置はどこが正しいでしょうか。 2) この現象は、Rubyのバッファーだけでなく、OS側もバッファーリングしている ために起こるのではないかと思いますが、如何でしょうか。 3) OSのバッファーリングを、ios.flushのように、system命令でWindows側をfl ushする命令はないのでしょうか。 面倒な内容ですが、よろしくご指導をお願いします。 矢幡 久 ================================ # 電子コンパス計測システム TruePoint 矢幡 2006年4月30日 #電子コンパスへのメッセージパケットID # Start/Stop Messages 開始/終了 reset=0x42 # request data:none, Reply data: Not applicable vrsn=0xC3 # Reply data: 12bytes Major 0-1, Minor 2-3, Options 4-5, Serial # number 6-9 Up Orentation 10, Forward orientation 11 power=0x44 # request data:none , Reply data: DPOWER Wakeup Message baud=0x47 # Diagnostic Messages 診断 test=0x48 # Request data none, Reply data 2bytes Results 0-1 stat=0x49 # Status Reply data: 6 bytes 温度0-1、Heading Kang 2-3, Reserved 4-5 # Initaialization Messages 初期化 inical=0x50 # Request data 9 bytes, Azimth offset 3-4,Roll offest 5-6,Pitch offset 7-8 imvar=0x54 # Initialize Magnetic Declination 3bytes wmm=0x55 # World Magnetic Model 15bytes, Day0 Month 1, Year 2,Lat3-6, Lon 7-10, Alt 11-14 # Reply data 23bytes, Status 0, Magnetic declination 1-2,Source, 3-22 orient=0x70 # Output data 18bytes: Roll 0-1, Pitch 2-3, Azimuth 4-5,rightwar acceleration 6-7 # forwar acc. 8-9, upward acc. 10-11, rightward magnetometer # 12-13, forward mag. 14-15, upward mag. 16-17 # Compensation Message 補償 mcal=0x72 # Request data 1 byte 0=No request, 1=Start compass # compensation 2=request 3=abort, 4=revert to default compensation values # Reply data 13 bytes: state 0, status code 1, bin 0 dat count 2, 〜 bin 7 data # computation competion count 10, quality 11-12 # Other Messages その他 sdflt =0x66 # Set start-up defaults SDFLT/DSDFLT 12bytes Req 0-1, MagDecl2-3, # Azimuth offset 4-5, Pitch offset 6-7, Roll 8-9, DORIENT Int 10-11 orrate=0x7F # dorient massage rate Request data 2 bytes DORIENT interval 0-1 # Reply 2 bytes, system "MODE COM4 BAUD=9600 PARITY=N DATA=8 STOP=1" port = open("com4", "r+b")#.binmode msgidd=[orient] # , inical, imvar] hel=0 msgidd.each {|msgid| aa=[] sop=[0x0D,0x0A,0x7E] # sbuffer=sop checksum=0 # msgid=orient # example msglength = 0 sbuffer[3]=msgid # メッセージID sbuffer[4]=msglength # dataの長さ (0..4+msglength).each {|i| dd=sbuffer[i] d3=sprintf("%2X", dd) p [i,sbuffer[i],dd,d3] aa << d3 checksum+=dd } p checksum # チェックサム p dd=checksum%256 d3=sprintf("%2X", dd) i=msglength+5 p [i,sbuffer[i],dd,d3] aa << d3 p aa p "============== 1 ==============" i=0 # status = timeout(1) { # Time Limit aa.each {|hel| # hel.each {|hel2| port.syswrite hel #hel #,"\r\n" # RS232C OUT print hel # => "0xa" } print "\n" } p "============== 2 ============" p chrt = "r" countnum=0 while (1) #(chrt != "s") # <=== whileの前に#をおき、これを潰すと、うまく 動作する。 print "key = " chr = STDIN.getc if chr!= "s" then # キー入力がs以外のときは計測する。 # port.syswrite hel #hel #,"\r\n" # RS232C OUT data=[] while c = port.sysread(1) # RS232C IN b=c[0] break if b==0x0D end while c = port.sysread(1) # RS232C IN b=c[0] break if b==0x0A end while c = port.sysread(1) # RS232C IN b=c[0] break if b==0x7E end c=port.sysread(1) msgid= sprintf("%02X",c[0]) # messageID #print "命令ID=",msgid,"\t" c=port.sysread(1) msglength = c[0].to_i # messageのデータ長 #print "データバイト数=",msglength ,"\n" data=[] msglength.times { c = port.sysread(1) data << c } # p data d=data.pack("a1a1a1a1a1a1") # data(バイナリー)をパックした文字列 を返す。 #p d dd=d.unpack("sss") # 2byteを符号付きshortとみなし、配列で返す。 # p dd dd.each {|ee| print sprintf("%3.1f\t",ee*360.0/65535) # 65536/360×角度として送 信されるので、角度に戻す } print "\n" port.flush # <=== flushの入れる位置はこれでよいか? $stdout.flush # <=== flushの入れる位置はこれでよいか? end end # <==== while に合わせて潰すend port.close
|
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | [ruby-list:42172] Re: ASR1.8.4.2 いただきました, conundrum / |
|---|---|
| Next by Date: | [ruby-list:42174] i18n Typo and Ruby-GetText, Masayoshi Takahashi |
| Previous by Thread: | [ruby-list:42171] Re: RS232Cによるパソコン間の通信の不具合(質問), yahata hisashi |
| Next by Thread: | [ruby-list:42175] Re: RS232Cによるパソコン間の通信の不具合(質問), AOKI Shigeru |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |