ValveControl Scripting in Python

The Arduino driving the valves can run the supplied ValveControl Arduino Sketch. This example control program can apply either closed-loop or open-loop valve control. It be configured for the specific actuator, valve, and optional feedback sensor arrangement.

The sketch acts upon command messages received over the USB serial port. The simplest means of testing is to use a terminal program to directly issue commands to the controller. This could simply be the console within the Arduino IDE, or a separate terminal program such as minicom or CoolTerm.

The more flexible way to drive the system is to use a Python script on a separate computer to send commands to the embedded controller. A self-contained Python sample appears below. It does require a pySerial installation to communicate with the Arduino.

This example uses only open-loop ‘speed’ commands to set the fill and empty rate on the two pairs of valves. The primary building block function for the sequence is set_flow().

pneumatics_exercise.valve_sequence.set_flow(port, flow, extend=1, retract=2, pause=None, verbose=False)[source]

Issue an open-loop set of flow commands for a valve pair attached to an actuator. Returns immediately or after an optional delay. No return value.

Parameters:
  • port – serial port stream handle

  • flow – net flow from -100 full retraction rate to 100 full extension rate

  • extend – channel number for extension valve pair

  • retract – channel number for retract valve pair

  • pause – time in seconds to delay after issuing command

  • verbose – flag to enable printed debugging output

Returns:

None

The full script is below. It can also be directly downloaded from the Python source tree on the course site.

  1#!/usr/bin/env python
  2"""\
  3valve_sequence.py
  4
  5Play back a sequence of pneumatic valve activations using a serial port
  6connection to an Arduino running ValveControl.
  7
  8Copyright (c) 2015-2017, Garth Zeglin.  All rights reserved. Licensed under the
  9terms of the BSD 3-clause license.
 10
 11"""
 12################################################################
 13# Import standard Python 2.7 modules.
 14from __future__ import print_function
 15import os, sys, time, argparse
 16
 17# This module requires a pySerial installation.
 18#  Package details: https://pypi.python.org/pypi/pyserial,
 19#  Documentation: http://pythonhosted.org/pyserial/
 20import serial
 21
 22################################################################
 23def set_flow( port, flow, extend=1, retract=2, pause=None, verbose=False):
 24    """Issue an open-loop set of flow commands for a valve pair attached to an actuator.
 25    Returns immediately or after an optional delay.  No return value.
 26
 27    :param port: serial port stream handle
 28    :param flow: net flow from -100 full retraction rate to 100 full extension rate
 29    :param extend: channel number for extension valve pair
 30    :param retract: channel number for retract valve pair
 31    :param pause: time in seconds to delay after issuing command
 32    :param verbose: flag to enable printed debugging output
 33    :return: None
 34    """
 35
 36
 37    if flow > 0:
 38        ext_command  = "speed %d %d" % (extend, flow)
 39        ret_command = "speed %d %d" % (retract, -100)
 40    elif flow == 0:
 41        ext_command  = "speed %d %d" % (extend, 0)
 42        ret_command = "speed %d %d" % (retract, 0)
 43    else:
 44        ext_command  = "speed %d %d" % (extend, -100)
 45        ret_command = "speed %d %d" % (retract, -flow)
 46
 47    if verbose:
 48        print ("Issuing %s, %s" % (ext_command, ret_command))
 49
 50    port.write("%s\n%s\n" % (ext_command, ret_command))
 51
 52    if pause is not None:
 53        time.sleep(pause)
 54
 55    # ignore any sensor feedback
 56    port.flushInput()
 57
 58    return
 59
 60################################################################
 61# The following section is run when this is loaded as a script.
 62if __name__ == "__main__":
 63
 64    # Initialize the command parser.
 65    parser = argparse.ArgumentParser( description = """Scripted sequence of pneumatic valve activations using the ValveControl controller on an Arduino.""")
 66    parser.add_argument( '-v', '--verbose', action='store_true', help='Enable more detailed output.' )
 67    parser.add_argument( '--debug', action='store_true', help='Enable debugging output.' )
 68    parser.add_argument( '-p', '--port', default='/dev/tty.usbmodem1411', help='Specify the name of the Arduino serial port device (default is /dev/tty.usbmodem1411).')
 69
 70    # Parse the command line, returning a Namespace.
 71    args = parser.parse_args()
 72
 73    # Open the serial port, which should also reset the Arduino
 74    print("Connecting to Arduino.")
 75    port = serial.Serial( args.port, 115200, timeout=5 )
 76    if args.verbose:
 77        print("Opened serial port named", port.name)
 78
 79    print("Sleeping briefly while Arduino boots...")
 80    time.sleep(2.0)
 81
 82    # throw away any extraneous input
 83    print("Flushing Arduino input...")
 84    port.flushInput()
 85
 86    # Begin the motion sequence.  This may be safely interrupted by the user pressing Control-C.
 87    try:
 88        print("Beginning movement sequence.")
 89        set_flow(port,   50, pause=2.0, verbose=args.verbose)
 90        set_flow(port,    0, pause=2.0, verbose=args.verbose)
 91        set_flow(port,  -50, pause=2.0, verbose=args.verbose)
 92        set_flow(port,    0, pause=2.0, verbose=args.verbose)
 93        set_flow(port,  100, pause=2.0, verbose=args.verbose)
 94        set_flow(port,    0, pause=2.0, verbose=args.verbose)
 95        set_flow(port, -100, pause=2.0, verbose=args.verbose)
 96        print("Movement complete.")
 97
 98    except KeyboardInterrupt:
 99        print("User interrupted motion.")
100
101    # Close the serial port connection.
102    port.write("stop\n")
103    port.close()