Как я могу отправить ACK, используя gem serialport? - PullRequest
1 голос
/ 06 марта 2012

камни

serialport (1.0.4)
Авторы: Гийом Пьерронне, Алан Стерн, Даниэль Э. Шиптон, Тобин
Ричард, Гектор Парра, Райан С. Пейн
Домашняя страница: http://github.com/hparra/ruby-serialport/
Библиотека для использования последовательных портов RS-232.

рубин

ruby ​​1.9.3p0 (2011-10-30, редакция 33570) [x86_64-darwin11.2.0]
работает под рвм 1.10.2


Я использую этот драгоценный камень на Mac Lion , и технические характеристики моего устройства следующие.

  • 9600
  • 7bits
  • 1 стоповый бит
  • ДАЖЕ паритет
  • 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

Если устройство не получит ACK в течение 1 секунды после получения данных (data = sp.gets), оно отправит другие те же данные, чтобы убедиться, что все получилось нормально. В настоящее время я получаю 2-ые те же данные, хотя пытаюсь отправить ACK, как указано выше.
* примечание while sp.cts() == 0; end не занимает 1 секунду

Если честно, я не уверен, верен ли мой код для отправки ACK. Если кто-нибудь может указать, где я делаю что-то не так, это очень поможет.
Спасибо


обновление

http://ruby -doc.org / ядро-1.9.3 / IO.html # метод-я-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, но он не отображался или вышел с ошибкой «занят».
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 мксек, я полагаю. так что я думаю, что посылаю ACK до истечения 1 секунды ...

до сих пор нет подсказок, почему я получаю 2-ые данные. (если в противном случае 1 секунда уже прошла, прежде чем я смогу отправить ACK ..?)

1 Ответ

0 голосов
/ 07 марта 2012

Вы пробовали 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
...