Getting started with the Python module

So you just received your shiny new qontrollers, and are ready to start programming? This note is for you! First, we’ll get you up and running, then show you some of the module’s features.

Setting up

Things to do before we get started:

  1. Make sure you have a working Python interpreter. Open a command prompt or terminal and type python or python3. If your Python is working, you’ll see details of your installation, such as your version. The Qontrol Python API has stopped support for Python 2 (which is now deprecated) but works with Python 3.6 and above. If you don’t have Python, install it.
  2. Install the latest Qontrol Python module either from Github (make sure you have pyserial 3.4 or greater) or using the Python package manager, with pip3 install qontrol (or pip install qontrol if your default Python is version 3).
  3. Find our example script, example.py installed with the module, or download it directly from here.
  4. Move example.py to your desktop (for now).
  5. Ensure your qontroller is connected to the PC, and that your experimental device is disconnected from the qontroller.
  6. Check that the USB device is recognised by your PC, and that virtual COM port drivers are installed. If not, these drivers can be downloaded from the FTDI website.
  7. Now plug in and switch on the qontroller’s power.

Great! If all that went to plan, you should now have a working system. Next, we’ll guide you through the example code.

Module basics

First, we read in the qontrol module. with an import call. This file needs to be in your Python PATH variable. The easiest way to achieve this is by installing it with pip, but if you’re debugging or modifying the module you can just keep it in the same directory as your application code (on the desktop, if you followed step 4).

import qontrol

To initialise an output device (or daisy-chain), like a Q8iv, first use a definition like

q = qontrol.QXOutput(serial_port_name = "COM1")

where q is our qontroller object, which stores information about the hardware, such as its device ID (q.device_id) and number of channels (q.n_chs), and handles all communications and commands. COM1 is an example of what the connected serial port name might be on Windows. Port numbers greater than 10 must be written like //./COM42. On MacOS or Linux, this will look something like /dev/tty.usbserial-FT123ABC. When your code is finished using the hardware, it’s good practice to close the connection with a call to

q.close()

Controlling outputs, and reading inputs is easy. Writing to the qontroller object’s v or i arrays (using standard Python array indexing) sets the output for channel with that index. Reading from those arrays reads the input values back from the hardware. For example, we can set the voltage on output channel 3 to 4.5V with the code

q.v[3] = 4.5

and read back the current (in mA) with

measured_current = q.i[3]

We can do bulk changes to channels using slices. The slice character in Python, :, means either “everything between two indices” (e.g. v[2:5]), “everything from the beginning until an index” (e.g. v[:5]), or “everything from an index until the end” (e.g. v[2:]). Many other channel-wise parameters can be modified in this way; use help(qontrol.QXOutput) to learn more.

Running the example code

To run our example.py script, we need two things:

  1. to have the qontrol module in our Python PATH variable (e.g. in the same place as example.py), and
  2. to point Python to the location of example.py.

On Linux and MacOS, in a terminal window (e.g. Terminal.app, on Mac), do something like this:

python3 ~/Desktop/example.py

On Windows 7, in the command prompt (cmd), an example command is:

CD %USERPROFILE%\Desktop; PYTHON example.py

If the example code runs successfully, the lights on your qontroller will flash as commands are transmitted, and output channels are energised. The qontroller’s device ID will be read out, as well as its number of channels, and other details. The voltage on each channel will be briefly set to the channel’s number (modulo 8), then return to zero (e.g. channel 3 is set to 3 V). The current of each channel will be read out.

Contents of example.py

import qontrol

# Setup Qontroller
serial_port_name = "/dev/tty.usbserial-FT06QAZ5"
q = qontrol.QXOutput(serial_port_name = serial_port_name, response_timeout = 0.1)

print ("Qontroller '{:}' initialised with firmware {:} and {:} channels".format(q.device_id, q.firmware, q.n_chs) )

# Set voltage on each channel to its index in volts, read voltage, current
for channel in range(q.n_chs):
	set_voltage = channel
	
	# Set voltage
	q.v[channel] = set_voltage
	
	# Measure voltage (Q8iv)
	measured_voltage = q.v[channel]
	
	# Measure current (Q8iv, Q8b, Q8)
	measured_current = q.i[channel]
	
	print ("Channel {:} set to {:} V, measured {:} V and {:} mA".format(channel, set_voltage, measured_voltage, measured_current) )


# Set all channels to zero
q.v[:] = 0

q.close()

Happy experimenting!

Now hack the example code into whatever shape you desire. Need help? Want more functionality? Just curious? We’d love to hear from you: leave a comment below, or email us at [email protected]. If you want to make things better, we warmly welcome Github push requests.