class FB::Arduino
Software abstraction layer for the Arduino’s serial interface. Translates Ruby method calls into serial commands.
Constants
- Position
Attributes
commands[RW]
inbound_queue[RW]
inputs[RW]
logger[RW]
outbound_queue[RW]
serial_port[RW]
status[RW]
Public Class Methods
new(serial_port: DefaultSerialPort.new, logger: STDOUT)
click to toggle source
Initialize and provide a serial object, as well as an IO object to send log messages to. Default SerialPort is DefaultSerialPort
. Default logger is STDOUT
# File lib/arduino.rb, line 19 def initialize(serial_port: DefaultSerialPort.new, logger: STDOUT) @outbound_queue = [] # Pi -> Arduino Gcode @inbound_queue = EM::Channel.new # Pi <- Arduino @serial_port = serial_port @logger = logger @commands = FB::OutgoingHandler.new(self) @inputs = FB::IncomingHandler.new(self) @status = FB::Status.new start_event_listeners end
Public Instance Methods
can_execute?()
click to toggle source
# File lib/arduino.rb, line 76 def can_execute? # If the device is ready and commands are in the queue @outbound_queue.any? && status.ready? end
current_position()
click to toggle source
# File lib/arduino.rb, line 61 def current_position Position.new(status[:X], status[:Y], status[:Z]) end
disconnect()
click to toggle source
Handle loss of serial connection
# File lib/arduino.rb, line 56 def disconnect log "Connection to device lost" @onclose.call if @onclose end
execute_now(gcode)
click to toggle source
# File lib/arduino.rb, line 80 def execute_now(gcode) log "RPI MSG: #{gcode}" serial_port.puts gcode status[:last] = gcode.name status[:BUSY] = 1 # If not, pi will race arduino and "talk too fast" end
log(message)
click to toggle source
Log to screen/file/IO stream
# File lib/arduino.rb, line 33 def log(message) logger.puts(message) end
maybe_execute_command()
click to toggle source
# File lib/arduino.rb, line 69 def maybe_execute_command # This method smells procedural. Refactor? sleep 0.08 # Throttle CPU return unless can_execute? gcode = @outbound_queue.pop gcode.is_a?(FB::Gcode) ? execute_now(gcode) : reject_gcode(gcode) end
next_cmd()
click to toggle source
# File lib/arduino.rb, line 65 def next_cmd outbound_queue.first end
onchange(&blk)
click to toggle source
# File lib/arduino.rb, line 42 def onchange(&blk) @onchange = blk end
onclose(&blk)
click to toggle source
# File lib/arduino.rb, line 51 def onclose(&blk) @onclose = blk end
onmessage(&blk)
click to toggle source
Handle incoming text from arduino into pi
# File lib/arduino.rb, line 47 def onmessage(&blk) @onmessage = blk end
reject_gcode(gcode)
click to toggle source
# File lib/arduino.rb, line 87 def reject_gcode(gcode) log "Outbound messages must be GCode objects. Use of "\ "#{gcode.class}:#{gcode.inspect} is not permitted." end
start_event_listeners()
click to toggle source
# File lib/arduino.rb, line 92 def start_event_listeners EM.tick_loop { maybe_execute_command } status.onchange { |diff| @onchange.call(diff) if @onchange } inbound_queue.subscribe do |gcodes| Array(gcodes).each do |gcode| parse_incoming(gcode) @onmessage.call(gcode) if @onmessage end end end
write(gcode)
click to toggle source
Send outgoing test to arduino from pi
# File lib/arduino.rb, line 38 def write(gcode) @outbound_queue.unshift gcode end
Private Instance Methods
parse_incoming(gcode)
click to toggle source
Highest priority method for processing incoming Gcode
. Use for system level status changes.
# File lib/arduino.rb, line 107 def parse_incoming(gcode) inputs.execute(gcode) end