"""\
CncShieldGUI.py
GUI controller for the CNC_Shield_Server Arduino sketch.
Copyright (c) 2015, Garth Zeglin. All rights reserved. Licensed under the terms
of the BSD 3-clause license.
"""
from __future__ import print_function
import os, sys, argparse, math
# import the common GUI library over which this built
from ArduinoGUI.ArduinoConsole import ArduinoConsole
################################################################
[docs]class CncShieldGUIController(object):
"""Application-specific control object to manage the GUI for the
CNC_Shield_Server. This class creates a generic ArduinoConsole GUI, adds
application-specific GUI controls, and manages basic I/O using a protocol
object.
:param client: a protocol object to receive commands from the GUI
:param port: the name of the serial port device
:param kwargs: collect any unused keyword arguments
"""
def __init__(self, client, port = None, **kwargs ):
"""Initialize the application-specific GUI."""
# create the generic interface
self.window = ArduinoConsole()
# reroute printed output to the console window; this works because there is a write method defined
sys.stdout = self.window
# add custom interface elements.
self.window.addSlider("X", self.x_slider_moved)
self.window.addSlider("Y", self.y_slider_moved)
self.window.addSlider("Z", self.z_slider_moved)
self.window.addButton("Enable", self.enable_button_pressed)
self.window.addButton("Disable", self.disable_button_pressed)
self.window.addButton("Home", self.home_button_pressed)
self.window.addButton("Start", self.start_button_pressed)
self.window.addButton("Stop", self.stop_button_pressed)
# add a plot window
self.window.addScope()
self.window.addScopeChannel('x', color='red', duration=10)
self.window.addScopeChannel('y', color='green', duration=10)
self.window.addScopeChannel('z', color='blue', duration=10)
# set up the connect/disconnect control
self.window.attachConnectCallback( self._connect_disconnect )
# set up the command lin
self.window.attachCommandCallback( self._command_input)
self.client = client
self.input_monitor = None
# fill in the default text field for the Arduino port name if provided
if port is not None:
self.window.setArduinoPortName(port)
return
#=============================================================================
def _connect_disconnect(self, name, flag ):
if flag:
# connect
if self.client.is_connected():
print("Client already connected.")
else:
if name is not None and name != "":
self.client.set_serial_port_name(name)
print("Connecting to the Arduino.")
self.client.open_serial_port()
# set up an event after the Arduino has had time to boot
self.window.newSingleShotTimer( 2000, self._startup_delay_complete)
# create a monitor for the serial port device connected to the Arduino to indicate when data is ready
self.input_monitor = self.window.newInputMonitor( self.client.input.fileno(), self.port_data_ready )
else:
# disconnect
if self.client.is_connected():
self.input_monitor.setEnabled(False)
self.client.close_serial_port()
self.input_monitor = None
else:
print("Client not connected.")
return
def _command_input(self, command):
print( "User entered '%s'." % command)
self.client.send_command(command)
return
def _startup_delay_complete(self):
print("Arduino bootup delay complete.")
self.client.flush_serial_input()
self.window.resetPlotPressed()
#=============================================================================
#=============================================================================
# Note that the following functions have a hardcoded scaling from slider -> microsteps.
[docs] def x_slider_moved(self, value):
"""Callback function activated when the X slider is moved."""
# print("User moved X slider to %f." % value)
self.client.issue_move( [int(20000*value), self.client.target[1], self.client.target[2] ])
[docs] def y_slider_moved(self, value):
"""Callback function activated when the Y slider is moved."""
# print("User moved Y slider to %f." % value)
self.client.issue_move( [self.client.target[0], int(20000*value), self.client.target[2] ])
[docs] def z_slider_moved(self, value):
"""Callback function activated when the Z slider is moved."""
# print("User moved Z slider to %f." % value)
self.client.issue_move( [self.client.target[0], self.client.target[1], int(20000*value) ])
#=============================================================================
[docs] def port_data_ready(self, fd):
"""Callback function activated when data is received from the Arduino. This
just prints a message, but would usually process status messages as part
of a command protocol."""
# process the input
last_position_count = self.client.position_message_count
self.client.debug = self.window.isShowingRawData()
self.client.wait_for_input()
# if new position data was received, add it to the plot
if self.client.position_message_count > last_position_count:
t = [ 1e-6 * self.client.arduino_time]
x = [ self.client.position[0] ]
y = [ self.client.position[1] ]
z = [ self.client.position[2] ]
self.window.addScopeSamples('x', x, t)
self.window.addScopeSamples('y', y, t)
self.window.addScopeSamples('z', z, t)
self.window.replotScope()
return
################################################################