Safely remove hardware
Closed this issue · 7 comments
I've noticed if we close a script using dino without calling remove_[digital|analog]_hardware, dino.ino continue sending data over serial connection, even there is no one listening for it. Why not adding a "destructor" to Dino::Board that detach all digital and analog hardware?
Yes, currently you need to manually call Board#remove_digital_hardware
or Board#remove_analog_hardware
, or as of version 0.12, Board#remove_component
, which replaces both.
Take a look at this line: https://github.com/austinbv/dino/blob/0.12.0-wip/examples/ssd/ssd.rb#L14
You could implement something like this in the TxRx::Base class. Trap the signal and send the reset command ("90\n" as of 0.12). Removing the components in Ruby will be unnecessary. When the thread dies, so will the board instance and all the component instances. Sending the reset command will reset the Arduino to defaults and stop it from writing to serial.
I have no idea how cross-platform compatible trapping "SIGINT" is. You might ned to play around.
oh wait. I'have not already seen the revolutionary 0.12 full of beautiful refactoring and enhancement ;) the misbehaviour has disappeared with this new version. I think a trap feature could be implemented only by the user in application logic (the dino scripts).. but I've another potential bug issue: I edited Dino::TxRx::Base#handshake as follow:
def handshake
puts "HANDSHAKE"
flush_read
10.times do
write Dino::Message.encode(command: 90)
line = gets(1)
puts "Line: #{line}"
if line && line.match(/ACK:/)
flush_read
return line.chop.split(/:/)[1]
end
end
end
And I get the corresponding output:
HANDSHAKE
Line: K:14
Line:
Line: A
Line: CK:1
Line: 4
Line: AC
Line: K:14
Line: ACK
Line: :14
Line: ACK:
This happens with a low baud mode. (9600 in this case). Possible solutions are:
- deprecating low baud modes.
- increment number of tries (> 10) to enhance probability to catch an aligned command.
- concat two or three lines of input, like that
line = 3.times.map { gets(1) }.join
in this casse the ouput is matched at first attempt.
I have not followed previus issues of 0.12.0 so i don't know if this is in conflict with other requirements or bonds.
I just tried this about 10 times at 9600 baud with an UNO and then again with a Leonardo. No problem at all. What board, OS and ruby version are you using?
It looks like the call to gets
on the serial port inside TxRx::Base#gets
is timing out and returning a partial line.
UNO board, linux 3.12.6 (Arch linux) and ruby 2.0.0 (despite travis.yml says..maybe the problem? ) When I build dino-0.12.0.gem I got:
WARNING: open-ended dependency on serialport (>= 0) is not recommended
if serialport is semantically versioned, use:
add_runtime_dependency 'serialport', '~> 0'
serialport gem version used is 1.3.0.
I repeated the test (incrementing gets attempts to 20.times
) and the result is the same, but now when the line match 'ACK:' Dino::Board#handshake
does not return any value for Dino::Board@analog_zero
Line:
Line:
Line: A
Line: CK:1
Line: 4
Line: AC
Line: K:14
Line:
Line: AC
Line: K:14
Line: ACK:
/home/minasmazar/workspace/dino/lib/dino/board.rb:108:in `analog_pin_to_i': undefined method `+' for nil:NilClass (NoMethodError)
This problem disappears with a baud rate >= 38400.
I'm on 2.0.0 as well. So that's not it.
Try replacing the single line in TxRx::Base#gets
with this and see what happens:
IO.select([io], nil, nil, timeout) && io.gets("\n")
It has no effect. I've tried different combination of timeouts for IO.select but nothing seems change..