如何使用ruby的serialport gem发送ACK?

时间:2012-03-06 14:00:15

标签: ruby macos serial-port osx-lion ruby-1.9

宝石

serialport(1.0.4)
作者:Guillaume Pierronnet,Alan Stern,Daniel E. Shipton,Tobin
Richard,Hector Parra,Ryan C. Payne 主页:http://github.com/hparra/ruby-serialport/
使用RS-232串口的库。

红宝石

ruby​​ 1.9.3p0(2011-10-30修订版33570)[x86_64-darwin11.2.0]
在rvm 1.10.2下运行


我在 Mac Lion 上使用此gem,我的设备规格如下。

  • 9600
  • 7位
  • 1站位
  • EVEN parity
  • RTS / CTS 用于发送/接收控制

我使用的驱动程序是md_PL2303_MacOSX10.6_dmg_v1.4.0.zip http://www.prolific.com.tw/eng/downloads.asp?id=31

收到数据后,我应该发回ACK,让设备知道数据是否正常。 这就是我目前的工作方式。

sp = SerialPort.new("/dev/serial-device", 9600, 7, 1, SerialPort::EVEN)
sp.flow_control = (SerialPort::SOFT | SerialPort::HARD)
loop do
  data = sp.gets
  p data
  while sp.cts() == 0; end #waiting for the device if it's ok to send
  sp.putc 0x06.chr #ACK
end

如果设备在我获取数据(data = sp.gets)后1秒内没有收到ACK,它将发送另一个相同的数据以确保我没问题。目前,虽然我试图像上面那样发送ACK,但我得到的是第二个相同的数据 *注意while sp.cts() == 0; end不需要1秒

老实说,我不确定我的代码是否正确发送ACK。如果有人能够指出我做错了什么,那将是一个很大的帮助 感谢


更新

  

http://ruby-doc.org/core-1.9.3/IO.html#method-i-putc
  putc(obj)

     

如果obj是Numeric,请编写代码为的字符   obj的最低有效字节,否则写入的第一个字节   obj到ios的字符串表示。注意:此方法不安全   使用多字节字符,因为它会截断它们。

所以事实证明,下面的4个中的任何一个都会输出相同的内容。这是我到目前为止所发现的,但设备尚未识别出ACK中的任何一个并向我发送第二个相同的数据...
我在想它可能是因为flow_control? (虽然我尝试过SOFT,HARD,NONE,SOFT | HARD)

~ $ irb
1.9.3p0 :001 >
1.9.3p0 :002 >   File.open('putc.txt', 'w') do |file|
1.9.3p0 :003 >     file.putc 0x06.chr
1.9.3p0 :004?>   file.putc 0x06.ord
1.9.3p0 :005?>   file.putc 0x06
1.9.3p0 :006?>   file.putc 6
1.9.3p0 :007?>   end
 => 6
1.9.3p0 :008 >
1.9.3p0 :009 >
1.9.3p0 :010 >   data = File.read('putc.txt')
 => "\x06\x06\x06\x06"
1.9.3p0 :011 > data.bytes.to_a
 => [6, 6, 6, 6]
1.9.3p0 :012 >
1.9.3p0 :013 >   exit
~ $
~ $ od -a putc.txt
0000000  ack ack ack ack
0000004
~ $

更新2

我试过tail -f / dev / serial-device但它没有显示,或者退出时出现“busy”错误。
 1.使用tty.usbserial发送&接收,拖尾tty.usbserial。两者都没有显示任何内容  2.使用cu.usbserial发送&接收,拖尾cu.usbserial。尾巴让我“忙”。

所以相反,我搜索了一下,发现了dtruss命令,看看幕后发生了什么。

Process.pid #find this PID
serial_port = SerialPort.new("/dev/tty.usbserial", 9600, 7, 1, SerialPort::EVEN)
serial_port.flow_control = (SerialPort::SOFT | SerialPort::HARD)
loop do 
  serial_port.gets
  while serial_port.cts() == 0; end
  p "before putc"
  serial_port.putc 0x06.chr
  p "after putc"
end

我在终端上运行了这个,并用sudo dtruss -a -p __PID_FROM_THE_RUBY_CODE__打开另一个,我得到了类似的东西

11812/0xfdd0:   5737859     772     11 read(0xB2, "0\0", 0x2000)         = 1 0
11812/0xfdd0:   5737866     208      0 sigprocmask(0x1, 0x0, 0x7FFF6FA7B340)         = 0x0 0
11812/0xfdd0:   5737869       5      0 sigaltstack(0x0, 0x7FFF6FA7B330, 0x0)         = 0 0
...
...
11812/0xfdd0:   5739675      16     11 write(0x1, "\"before putc\"\n\0", 0xE)        = 14 0
11812/0xfdd0:   5739685       4      0 sigprocmask(0x1, 0x0, 0x7FFF6FA7B150)         = 0x0 0
11812/0xfdd0:   5739686       4      0 sigaltstack(0x0, 0x7FFF6FA7B140, 0x0)         = 0 0
11812/0xfdd0:   5739694       9      6 write(0xB2, "\006\0", 0x1)        = 1 0
11812/0xfdd0:   5739709       5      0 sigprocmask(0x1, 0x0, 0x7FFF6FA7B1B0)         = 0x0 0
11812/0xfdd0:   5739710       3      0 sigaltstack(0x0, 0x7FFF6FA7B1A0, 0x0)         = 0 0
11812/0xfdd0:   5739716       8      4 write(0x1, "\"after putc\"\n\0", 0xD)         = 13 0

write(0xB2, "\006\0", 0x1)这似乎在写0x06。但我不知道怎么读这个...... 经过的时间5739694 - 5737859(接收数据gets - 发送ACK)= 1,835微秒,我相信。所以我想我会在1秒到期之前发送ACK ......

仍然没有线索为什么我得到第二个数据。 (除非在我发送ACK之前已经过了1秒......?)

1 个答案:

答案 0 :(得分:0)

你试过sp.puts 0x06.chr吗?看起来OSX Lion仍在运行Ruby 1.8.7作为库存,这应该可行。

在OSX Lion中,我能够做到这一点,第二个就是你想要的那个:

>> putc 0x06.chr
=> "\006"
>> puts 0x06.chr

=> nil

在Windows中,这将打印出一个时髦的角色......但您可以使用OSX Lion中的文件验证...

>> f = File.new('tmp.txt', 'w')
=> #<File:tmp.txt>
>> f.puts 0x06.chr
=> nil
>> f.close
=> nil
>> exit
narada:~ bcochran$ od -a tmp.txt 
0000000  ack  nl                                                        
0000002

<强>更新

你上面这样做的方式似乎也有效......

narada:~ bcochran$ irb
>> f = File.new('tmp.txt', 'w')
=> #<File:tmp.txt>
>> f.putc 0x06.chr
=> "\006"
>> f.close
=> nil
>> exit
narada:~ bcochran$ od -a tmp.txt 
0000000  ack                                                            
0000001