{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# QCoDeS Example with Keysight B2200 Series Femto Leakage Switch Matrix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Instrument Short info\n", "The Keysight B2200 Switch Matrix has 14 rows and up to 48 columns. In the terminology of the Keysight B2200, the *Rows* are called *Inputs* and the *Columns* are called *Outputs*. In this example Notebook I will use the *Input/Output* terminology.\n", "\n", " **Note: Technically the Inputs could also be used as Outputs and vice versa.**\n", "\n", "The inputs are subdivided into\n", " - 8 triaxial BNC input ports labeled \"SMU Input\" with number 1 to 8\n", " - 6 normal BNC input ports labeled \"AUX Input\" with number 9 to 14\n", "\n", "The output ports are split into 4 modules with 12 ports each, hence a Switch matrix can support 12, 24, 36 or 48 output ports. The Instrument can either address the Modules individually (*Normal Config Mode*) or treat all installed modules as one (*Auto Config Mode*). In *Auto Config Mode* the output channels are numbered 1 to 48 (or whatever the maximum number of channels is if not all 4 modules are installed).\n", "\n", " **Note: The Qcodes driver only suports Auto Config Mode**" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import qcodes as qc\n", "\n", "from qcodes.instrument_drivers.Keysight.keysight_b220x import KeysightB220X\n", "from pyvisa.errors import VisaIOError\n", "\n", "from IPython.display import display, Markdown" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "using physical instrument\n" ] }, { "data": { "text/plain": [ "'switch_matrix'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a station to hold all the instruments\n", "\n", "station = qc.Station()\n", "\n", "# instantiate the Switch Matrix and add it to the station\n", "try:\n", " switch_matrix = KeysightB220X('switch_matrix',\n", " address='TCPIP::192.168.111.100::gpib0,22::INSTR')\n", " print(\"using physical instrument\")\n", "except (ValueError, VisaIOError):\n", " # Either there is no VISA lib installed or there was no real instrument found at the\n", " # specified address => use simulated instrument\n", " import qcodes.instrument.sims as sims\n", " path_to_yaml = sims.__file__.replace('__init__.py', 'keysight_b220x.yaml')\n", "\n", " switch_matrix = KeysightB220X('switch_matrix',\n", " address='GPIB::1::INSTR',\n", " visalib=path_to_yaml + '@sim'\n", " )\n", " display(Markdown(\"\"\"**Note: using simulated instrument.**\n", "\n", "Due to limitations in pyvisa-sim the behavior will be different. Especially\n", " - the default values are not recovered when calling `switch_matrix.reset()` method\n", " - commands will simply overwrite the current state (e.g. when calling `switch_matrix.gnd_enabled_inputs([3, 4])` and after that `switch_matrix.gnd_enabled_inputs([5, 6])`, the real instrument would return `[3,4,5,6]` when calling `switch_matrix.gnd_enabled_inputs()`, but the simulated instrument will only return `[5,6]`)\"\"\"))\n", "\n", "station.add_component(switch_matrix)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Switch control\n", "\n", "Any of the 14 Input ports can be connected to any of the 48 output ports" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] } ], "source": [ "switch_matrix.reset()\n", "\n", "print(switch_matrix.connections()) # {None}" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(2, 48)}\n" ] } ], "source": [ "switch_matrix.connect(2, 48) # connect input 2 to output 48\n", "\n", "print(switch_matrix.connections()) # {(2, 48)}" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(14, 3), (2, 48)}\n" ] } ], "source": [ "switch_matrix.connect(14, 3) # connect input 14 to output 3\n", "\n", "print(switch_matrix.connections()) # {(2, 48), (14, 3)}" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(2, 48)}\n" ] } ], "source": [ "switch_matrix.disconnect(14, 3) # disconnect input 14 from output 3\n", "\n", "print(switch_matrix.connections()) # {(2, 48)}" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] } ], "source": [ "switch_matrix.disconnect_all() # opens all switches\n", "\n", "print(switch_matrix.connections()) # {None}" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(11, 9), (3, 45)}\n" ] } ], "source": [ "# To connect multiple input->output pairs it is faster\n", "# to use the connect_paths method instead of calling connect in a loop\n", "switch_matrix.connect_paths({(3, 45), (11, 9)})\n", "\n", "print(switch_matrix.connections()) # {(11, 9), (3, 45)}" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] } ], "source": [ "# Multiple switches can be disconnected with the disconnect_paths method\n", "switch_matrix.disconnect_paths({(3, 45), (11, 9)})\n", "\n", "print(switch_matrix.connections()) # {None}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Advanced Switch Control\n", "---\n", "\n", "### Connection Rule\n", "The Switch matrix has two *connection rules*:\n", " - in *free route* mode (**Default** after reset):\n", " - each input port can be connected to multiple output ports\n", " - and each output port can be connected to multiple input ports.\n", " - **Caution: If the Free connection rule has been specified, ensure multiple input ports are not connected to the same output port. Such configurations can cause damage**\n", " - in *single route* mode:\n", " - each input port can be connected to only one output port\n", " - and each output port can be connected to only one input port.\n", " - existing connection to a port will be disconnected when a new connection is made.\n", " \n", "**Note: when switching from *free* to *single* mode, 1-to-multiple connections will not be changed until the connection is changed!!**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Free Route Mode" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] } ], "source": [ "switch_matrix.reset()\n", "\n", "print(switch_matrix.connections()) # {None}" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(2, 33)}\n" ] } ], "source": [ "switch_matrix.connect(2, 33)\n", "\n", "print(switch_matrix.connections()) # {(2, 33)}" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(2, 12), (2, 33)}\n" ] } ], "source": [ "switch_matrix.connect(2, 12) # Input 2 is connected to multiple outputs\n", "\n", "print(switch_matrix.connections()) # {(2, 33), (2, 12)}" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n", "Skipped `Connecting multiple inputs to the same output` example.\n" ] } ], "source": [ "# ! DANGER ZONE !\n", "# Connecting multiple inputs to the same output: This can cause damage if there\n", "# two sources on the input pins as they will be short circuited\n", "# \n", "# Uncomment and set to `True` if you know what you're doing:\n", "# I_know_what_I_am_doing = False\n", "# I_have_checked_there_are_no_two_sources_on_Input_5_and_6 = False\n", "switch_matrix.reset()\n", "print(switch_matrix.connections()) # {None}\n", "\n", "try:\n", " assert I_know_what_I_am_doing\n", " assert I_have_checked_there_are_no_two_sources_on_Input_5_and_6\n", " \n", " switch_matrix.connect(5, 14)\n", " print(switch_matrix.connections()) # {(5, 14)}\n", " \n", " switch_matrix.connect(6, 14) # Input 5 and 6 are now both connected to Output 14\n", " print(switch_matrix.connections()) # {(5, 14), (6, 14)}\n", "\n", "except (AssertionError, NameError):\n", " print(\"Skipped `Connecting multiple inputs to the same output` example.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Single Route mode" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "c:\\users\\administrator\\pycharmprojects\\venvs\\qcodes_runtime\\lib\\site-packages\\qcodes\\instrument_drivers\\Keysight\\keysight_b220x.py:300: UserWarning: When going from *free* to *single* mode existing connections are not released.\n", " warnings.warn('When going from *free* to *single* mode existing '\n" ] } ], "source": [ "switch_matrix.disconnect_all()\n", "print(switch_matrix.connections()) # {None}\n", "\n", "# Single route mode is activated like so:\n", "switch_matrix.connection_rule('single')" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(2, 48)}\n", "{(2, 48), (5, 9)}\n", "{(5, 9), (2, 12)}\n" ] } ], "source": [ "switch_matrix.connect(2, 48)\n", "print(switch_matrix.connections()) # {(2, 48)}\n", "\n", "switch_matrix.connect(5, 9)\n", "print(switch_matrix.connections()) # {(2, 48), (5, 9)}\n", "\n", "# The following command will implicitly release the 2->48 connection because \n", "# input 2 will be used to connect to output 48\n", "switch_matrix.connect(2, 12)\n", "print(switch_matrix.connections()) # {(2, 12), (5, 9)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note that even though a connection like {2->33, 2->12} or {5->14, 6->14} would be impossible \n", "to *create* in *Single Route* Mode it can still exist if it was created previously in *Free Route* mode!**\n", "\n", "The reason is if the connection was made in *Free Route* mode and after that *Single Route* was activated the connections will **persist**. The following example illustrates this:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n", "{(2, 45), (2, 44), (2, 18)}\n", "{(5, 45), (2, 44), (2, 18)}\n" ] } ], "source": [ "# Example:\n", "switch_matrix.reset() # After reset *free route* mode is active\n", "print(switch_matrix.connections()) # {None}\n", "\n", "switch_matrix.connect(2,18) # Connections: {(2, 18)}\n", "switch_matrix.connect(2,44) # Connections: {(2, 18), (2, 44)}\n", "switch_matrix.connect(2,45) # Connections: {(2, 18), (2, 44), (2, 45)}\n", "\n", "switch_matrix.connection_rule('single') # *Single Route* Mode is activated\n", "# Still multiple Outputs connected to Input 2! \n", "print(switch_matrix.connections()) # Connections: {(2, 18), (2, 44), (2, 45)}\n", "\n", "# The following command will only implcitly release the 2->45 connection:\n", "switch_matrix.connect(5,45) # Still multiple Outputs connected to Input 2!\n", "print(switch_matrix.connections()) # Connections: {(2, 18), (2, 44), (5, 45)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "### Connection Sequence\n", "As explained above in **Single Route** Mode the switch matrix implicitly disconnects the previous path when a new connection is made.\n", "\n", "There are options for how exactly this is done:\n", " - Break Before Make (`'bbm'`) (**Default** after reset):\n", " 1. Disconnect previous route.\n", " 2. Wait for relays to open.\n", " 3. Connect new route.\n", " - Make Before Break (`'mbb'`):\n", " 1. Connect new route.\n", " 2. Wait for relays to close.\n", " 3. Disconnect previous route.\n", " - No Sequence (`'none'`)\n", " 1. Disconnect previous route.\n", " 2. Connect new route." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connection Sequence after Reset: bbm\n" ] } ], "source": [ "switch_matrix.reset()\n", "\n", "# After Reset the switch matrix is in *Free Route* Mode\n", "# Although setting a Connection Sequence can also be done in *Free Route* mode,\n", "# it **only has effect in Single Route Mode** (because in Free Route mode no connections are implicitely opened)\n", "switch_matrix.connection_rule('single')\n", "\n", "# *Break Before Make* is Default after Reset\n", "print('Connection Sequence after Reset: ', switch_matrix.connection_sequence() )\n", "\n", "# Change connection sequence to *Make Before Break*\n", "switch_matrix.connection_sequence('mbb')\n", "\n", "# Change connection sequence to *No Sequence*\n", "switch_matrix.connection_sequence('none')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "### Ground Mode\n", "The Switch Matrix can automatically connect unused inputs and/or outputs to a designated Ground input. When the ground mode is *ON*, the input ground port is connected to\n", " - to *ground enabled* output ports that are not connected to any other input ports.\n", " - all inputs that are specified as *unused*\n", "\n", "**Note: Connection sequence (to connect input ground port to output ports) is always Break-Before-Make.**\n", "\n", "In principle the Ground Input Port can be chosen freely, however it is advisable to use the default ground input (AUX 12) as I will explain below.\n", "\n", "**Note: The port that is selected as *Ground Input Port* cannot be used in normal `connect`/`disconnect` commands**\n", "\n", "**Note: Ground mode cannot be set to ON when the bias mode is ON**\n", "\n", "To make use of the Ground mode several things have to be done:\n", " - specify which *outputs* should be *ground enabled*\n", " - specify which *inputs* will be unused and should be *ground enabled*\n", " - (most often not necessary (see above)) specify which input port should be the ground input\n", " - Set Ground mode *ON*\n", "\n", "The following will explain these steps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Specifying which outputs should be *ground enabled*\n", "\n", "There are two possibilities to specify which *outputs* should be *ground enabled*:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# Either only enable specific output ports\n", "switch_matrix.gnd_enable_output(33)\n", "switch_matrix.gnd_enable_output(11)\n", "\n", "# Or Ground enable all output ports:\n", "switch_matrix.gnd_enable_all_outputs()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Specifying which inputs are unused\n", "Input ports that are marked as *unused* cannot be used in `connect`/`disconnect` commands" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ground enabled inputs: [5, 6, 7, 8]\n" ] } ], "source": [ "# Specify unused inputs with a list\n", "switch_matrix.unused_inputs([5, 6, 7, 8])\n", "\n", "print(\"Ground enabled inputs: \", switch_matrix.unused_inputs())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note: Everytime `unused_inputs()` is called, the previous setting is overwritten!**" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before: [5, 6, 7, 8]\n", "After: [3]\n" ] } ], "source": [ "print(\"Before: \", switch_matrix.unused_inputs())\n", "\n", "switch_matrix.unused_inputs([3]) # when marking single inputs as unused they must also be wrapped in a list!\n", "\n", "print(\"After: \", switch_matrix.unused_inputs())\n", "\n", "# Calling `set_unused_input([3])` overwrote the previous setting ([5,6,7,8])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This means if you want to use all inputs again, simply call `unused_inputs()` with an empty list" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ground enabled inputs: []\n" ] } ], "source": [ "switch_matrix.unused_inputs([])\n", "print(\"Ground enabled inputs: \", switch_matrix.unused_inputs())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (Optional) Specifying which *input port* should be the *ground input*\n", "In general designating an input port as *ground input* **does not automatically connect the inner conductor to GND**! So typically a BNC Short Circuit Connector Cap is required to connect the port to GND.\n", "\n", "The **exception to this are input 12 and 13**, both have special internal circuitry. If *ground mode* is set to *ON* and\n", " - If Input 12 is selected as *ground input*, then the inner conductor of the BNC connector is **left floating** and the **internal inner conductor is connected to GND**\n", " - If Input 13 is selected as *ground input*, then the **inner conductor of the BNC connector AND the internal inner conductor is connected to GND**\n", " \n", "So for both Input 12 and 13 no external Short Circuit Connector Cap is required. \n", "\n", "**Note: For Input 13 care must be taken that no source is connected to the input as otherwise it will be shorted to GND which might cause damage**." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The Ground Input Port is: 12\n" ] } ], "source": [ "# The default *ground input* port is input AUX 12.\n", "print(\"The Ground Input Port is: \", switch_matrix.gnd_input_port())" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before executing this make sure that there is no source connected to input 13 as otherwise it will be grounded.\n", "\n", " Then set I_have_made_sure_that_there_is_no_source_connected_to_input_13 = True\n" ] } ], "source": [ "# I_have_made_sure_that_there_is_no_source_connected_to_input_13 = False\n", "try:\n", " assert I_have_made_sure_that_there_is_no_source_connected_to_input_13\n", " \n", " # Changing the ground input port can be done so:\n", " switch_matrix.gnd_input_port(13)\n", "except:\n", " print('Before executing this make sure that there is no source connected to input 13',\n", " 'as otherwise it will be grounded.\\n\\n',\n", " 'Then set I_have_made_sure_that_there_is_no_source_connected_to_input_13 = True')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Set Ground mode ON\n", "The last step to use Ground Mode is to switch it on" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "switch_matrix.gnd_mode(True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Caveats\n", "The port that is selected as *Ground Input Port* cannot be used in normal `connect`/`disconnect` commands\n", "\n", "Note: Using the port anyway **will fail** and simply not make the connection. The (dis)connect commands and most (but not all) automatically try to query the status byte and will warn the user if an error occured.\n", "\n", "Example:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "switch_matrix.reset()\n", "switch_matrix.gnd_mode(True)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\users\\administrator\\pycharmprojects\\venvs\\qcodes_runtime\\lib\\site-packages\\ipykernel_launcher.py:1: UserWarning: Instrument status byte indicates an error occured (value of STB was: 8)! Use `get_error` method to poll error message.\n", " \"\"\"Entry point for launching an IPython kernel.\n" ] } ], "source": [ "switch_matrix.connect(12, 22) # 12 is the gnd input port\n", "# A warning should be printed below notifying the user that an error occured" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+3022,\"Cannot directory specify Auto Ground Port channel\"\n" ] } ], "source": [ "# The detailed error message can be retrieved using the `get_error` method:\n", "\n", "print(switch_matrix.get_error()) # +3022,\"Cannot directory specify Auto Ground Port channel\"\n", "\n", "# Fun fact: `directory` is a typo in the instrument firmware. It should be \"Cannot *directly* ...\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ground Mode complete example" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "switch_matrix.reset()\n", "# After reset:\n", "# - All connections are disconnected,\n", "# - Ground input port is port AUX 12.\n", "# - No inputs or outputs are ground enabled\n", "# - Ground mode is off\n", "# The last two points mean that all inputs and outputs are floating!" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "switch_matrix.unused_inputs([5, 6, 7, 8])\n", "switch_matrix.gnd_enable_output(12)\n", "switch_matrix.gnd_enable_output(33)\n", "# Now\n", "# - Ground enabled inputs are [5,6,7,8]\n", "# - Ground enabled Outputs are [12, 33]\n", "# \n", "# They are not connected to ground yet because Ground Mode is still OFF!" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(12, 12), (12, 33)}\n" ] } ], "source": [ "switch_matrix.gnd_mode(True)\n", "\n", "# Now Inputs [5,6,7,8], and Outputs [12, 13] are connected to ground\n", "# (because they are not connected to anything else)\n", "# \n", "# All other inputs and outputs are still floating\n", "\n", "print(switch_matrix.connections()) # {(12, 12), (12, 33)} # (Only lists connections of output ports!)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(12, 12), (4, 33)}\n" ] } ], "source": [ "switch_matrix.connect(4, 33) # Now Output 33 is connected to Input 4 => Output 33 *not* connected to GND\n", "\n", "print(switch_matrix.connections()) # {(12, 12), (4, 33)}" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(12, 12), (12, 33)}\n" ] } ], "source": [ "switch_matrix.disconnect(4,33)\n", "# Output 33 is automatically connected to GND again when the connection is opened again!\n", "\n", "print(switch_matrix.connections()) # {(12, 12), (12, 33)}" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(12, 33)}\n" ] } ], "source": [ "# Ground enabled output ports can also be *Ground disabled* again\n", "# This will disconnect them from GND if they were connected to GND\n", "switch_matrix.gnd_disable_output(12)\n", "\n", "print(switch_matrix.connections()) # {(12, 33)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "### Bias Mode\n", "The Bias Mode is very similar to the previously described Ground Mode, so make sure to read the Ground Mode description above.\n", "\n", "The main difference to Ground Mode is that\n", " - instead of connecting ports to GND potential, in Bias Mode unused Outputs are connected to a Bias Potential which is supplied to the designated *Bias Input Port*.\n", " - The **default *Bias input Port* is AUX 10**\n", " - **By default all output ports are *Bias enabled***\n", "\n", "Other differences compared to GND mode are:\n", "\n", " - Bias Mode **always requires an external source** to supply the Bias potential (there is no internal circuitry)\n", " - Only *Output* Ports can be *Bias Enabled* (In Ground mode also Inputs could be *Ground enabled*)\n", "\n", "**Note: Bias mode cannot be set to ON when the ground mode is ON.**\n", "\n", "**Note: You cannot use the Bias port in `connect`/`disconnect` commands to make explicit connections to the Bias port.**\n", "\n", "The other steps are similar to Ground mode so I will jump directly to the complete example:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Bias Mode complete Example" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] } ], "source": [ "switch_matrix.reset()\n", "# After reset:\n", "# - All connections are disconnected,\n", "# - Bias input port is port AUX 10.\n", "# - No inputs or outputs are Bias enabled\n", "# - Bias mode is off\n", "# The last two points mean that all inputs and outputs are floating!\n", "print(switch_matrix.connections()) # {None}" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "# By default all ports are bias enabled!\n", "# For demonstration we'll bias-disable two ports:\n", "switch_matrix.bias_disable_output(15)\n", "switch_matrix.bias_disable_output(17)\n", "# - Bias disabled Outputs are [15, 17]\n", "# They are not connected to bias input yet because bias Mode is still OFF!" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n" ] } ], "source": [ "print(switch_matrix.connections())" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(10, 37), (10, 11), (10, 42), (10, 48), (10, 6), (10, 21), (10, 46), (10, 26), (10, 3), (10, 34), (10, 8), (10, 30), (10, 43), (10, 7), (10, 38), (10, 12), (10, 18), (10, 47), (10, 27), (10, 22), (10, 35), (10, 9), (10, 31), (10, 40), (10, 4), (10, 39), (10, 13), (10, 19), (10, 44), (10, 24), (10, 1), (10, 23), (10, 32), (10, 28), (10, 41), (10, 5), (10, 36), (10, 10), (10, 16), (10, 45), (10, 25), (10, 14), (10, 20), (10, 33), (10, 29), (10, 2)}\n", "False\n", "False\n" ] } ], "source": [ "switch_matrix.bias_mode(True)\n", "# Now all outputs besides Outputs [15, 17] are connected to bias input port (Port 10 by default)\n", "# \n", "# Only Outputs [15, 17] will be left floating\n", "print(switch_matrix.connections()) # {(10, 37), (10, 11), (10, 42), (10, 48), (10, 6), (10, 21), (10, 46), (10, 26), (10, 3), (10, 34), (10, 8), (10, 30), (10, 43), (10, 7), (10, 38), (10, 12), (10, 18), (10, 47), (10, 27), (10, 22), (10, 35), (10, 9), (10, 31), (10, 40), (10, 4), (10, 39), (10, 13), (10, 19), (10, 44), (10, 24), (10, 1), (10, 23), (10, 32), (10, 28), (10, 41), (10, 5), (10, 36), (10, 10), (10, 16), (10, 45), (10, 25), (10, 14), (10, 20), (10, 33), (10, 29), (10, 2)}\n", "\n", "print((10, 15) in switch_matrix.connections()) # bias-disabled output 15 was not connected to bias port 10\n", "print((10, 17) in switch_matrix.connections()) # bias-disabled output 17 was not connected to bias port 10" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n" ] } ], "source": [ "switch_matrix.connect(4, 11) # Now Output 11 is connected to Input 4 => Output 11 *not* connected to Bias Input\n", "\n", "print((10, 11) in switch_matrix.connections()) # False => bias port connection (10, 11) was implicitly opened\n", "print((4, 11) in switch_matrix.connections()) # True => connection (4, 11) was made\n" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n" ] } ], "source": [ "switch_matrix.disconnect(4, 11)\n", "# Output 11 is automatically connected to Bias Input Port again when the connection is opened again!\n", "# Input 4 is floating\n", "\n", "print((10, 11) in switch_matrix.connections()) # True => bias port connection (10, 11) was implicitly closed\n", "print((4, 11) in switch_matrix.connections()) # False => connection (4, 11) was opened" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\users\\administrator\\pycharmprojects\\venvs\\qcodes_runtime\\lib\\site-packages\\ipykernel_launcher.py:4: UserWarning: Instrument status byte indicates an error occured (value of STB was: 8)! Use `get_error` method to poll error message.\n", " after removing the cwd from sys.path.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+3014,\"Cannot directly specify Bias Port channel\"\n", "False\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "c:\\users\\administrator\\pycharmprojects\\venvs\\qcodes_runtime\\lib\\site-packages\\ipykernel_launcher.py:12: UserWarning: Instrument status byte indicates an error occured (value of STB was: 8)! Use `get_error` method to poll error message.\n", " if sys.path[0] == '':\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "+3014,\"Cannot directly specify Bias Port channel\"\n", "False\n" ] } ], "source": [ "# JUst as with GND mode, in bias mode you cannot use the bias input port in the \n", "# `connect`and `disconnect` commandsto make an explicit connection manually to the bias input:\n", "\n", "switch_matrix.connect(10, 17) # Try to make an connection to input port 10 with bias-disabled port 17\n", "\n", "print( switch_matrix.get_error() ) # +3014,\"Cannot directly specify Bias Port channel\"\n", "\n", "print((10, 17) in switch_matrix.connections()) # False\n", "\n", "\n", "# This statement is also valid for bias-enabled ports\n", "switch_matrix.connect(10, 23) # Try to make an connection to input port 10 with bias-enabled port 23\n", "\n", "print( switch_matrix.get_error() ) # +3014,\"Cannot directly specify Bias Port channel\"\n", "\n", "print((10, 17) in switch_matrix.connections()) # False\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "### Couple Mode\n", "\n", "In *Couple Mode*, pairs of input ports can be treated as one port. This is especially handy for Kelvin Measurement setups (=> *Force* and *Sense* lines), where you connect/disconnect *Force* and *Sense* at the same time from one output to the next.\n", "\n", "Couple mode will group subsequent channel numbers in pairs of two:\n", "\n", "`{(1,2), (3,4), (5,6), (7,8), (9,10), (11,12), (12,13)}`\n", "\n", "When making the connections always keep these rule in mind:\n", " - **Odd** *Input Ports* always connect to an **odd** *Output port*.\n", " - e.g. Input `3` will connect to `1`, `3`, or `17` and so on\n", " - Input `3` will never connect to `2`, `6`, `24` and so on\n", " - **Even** *Input Ports* always connect to an **even** *Output port*.\n", " - e.g. Input `6` will connect to `2`, `6`, or `34`\n", " - Input `6` will never connect to `1`, `9`, `21`\n", " - In a pair the **odd** port is always the lower port number.\n", " - When `(7,8)` are coupled and sending the command `switch_matrix.connect(7, 24)` the switch matrix \n", " - will make the following connection: `7->23`, `8->24`\n", " - It will **NOT** make `7->24`, `8->25` or `7->24`, `8->23` or \n", "\n", "Because of the above rules it us usually easiest if you always work with the **lower, odd number** in the commands. So for pair `(3,4)` use `3` in the commands.\n", "\n", "**Note: There are some limitations on using couple mode together with either Bias or GND mode. Refer to the manual for further information.**\n", "\n", "**Note: Couple Ports can also be automagically detected (see examples below)**\n", "\n", "**Note: Everytime `couple_ports` is called, the previous setting is overwritten!**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Enabling couple mode\n", "There are two steps to enabling couple mode:\n", " - *couple enabled* input ports have to be selected\n", " - *couple mode* has to be enabled\n", "\n", "You can also first enable couple mode and then select couple enabled ports" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "switch_matrix.reset()\n", "switch_matrix.couple_mode(True) # Enable couple mode\n", "\n", "switch_matrix.couple_ports([1]) # Enables couple mode for input pair (1,2)\n", "\n", "switch_matrix.couple_ports([1,3,5]) # Enables couple mode for input pairs {(1,2), (3,4), (5,6)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Everytime couple_ports is called, the previous setting is overwritten!" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before: [5]\n", "after: [1, 3]\n" ] } ], "source": [ "switch_matrix.couple_ports([5])\n", "\n", "print(\"before: \", switch_matrix.couple_ports())\n", "\n", "switch_matrix.couple_ports([1, 3])\n", "\n", "print(\"after: \", switch_matrix.couple_ports())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Making connections in couple mode\n", "Connections in couple mode are made just like in *non-couple* mode, by specifyin **one** input port and **one** output port to connect.\n", "\n", "The following examples assume couple mode is enabled for inputs `1`, `3` and `5`" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before: set()\n", "after connecting: {(4, 18), (3, 17)}\n", "after disconnecting: set()\n" ] } ], "source": [ "print(\"before: \", switch_matrix.connections()) # before: {None}\n", "\n", "switch_matrix.connect(3, 17)\n", "print(\"after connecting: \", switch_matrix.connections()) # after connecting: {(4, 18), (3, 17)}\n", "\n", "switch_matrix.disconnect(3, 17)\n", "print(\"after disconnecting: \", switch_matrix.connections()) # after disconnecting: {None}" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "after connecting: {(1, 11), (2, 12)}\n", "after connecting: {(1, 11), (2, 12)}\n" ] } ], "source": [ "# Watch out for the rules mentioned in the introduction to Couple mode above!\n", "\n", "switch_matrix.connect(2, 11) # Connections: {(1, 11), (2, 12)} and *NOT* {(2, 11), (1, 12)} or {(2, 11), (1, 10)}\n", "print(\"after connecting: \", switch_matrix.connections())\n", "\n", "switch_matrix.connect(1, 12) # Connections: {(1, 11), (2, 12)} and *NOT* {(1, 12), (2, 11)} or {(1, 12), (2, 13)}\n", "print(\"after connecting: \", switch_matrix.connections())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Autodetecting Couple Ports\n", "A very nice feature is that couple ports can also be autodetected. This assumes that an instrument with Kelvin connections is connected to the input ports.\n", "\n", "Setup: connect\n", " - `SMU +F` to input 3\n", " - `SMU +S` to input 4\n", " - `SMU -F` to input 7 \n", " - `SMU -S` to input 8 " ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "after autodetecting couple ports: set()\n" ] } ], "source": [ "switch_matrix.couple_port_autodetect() \n", "print(\"after autodetecting couple ports: \", switch_matrix.connections())\n", "# Will recognize SMU Kelvin connection on Port pairs (3,4) and (7,8) and enable couple mode for these ports." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When using Autodetection, watch out to make the connections correctly according to the *legal* pair numbers `(3,4)` is allowed, `(4,5)` not.\n", "\n", "Just for illustration a **bad example**: Connect the SMU as follows:\n", " - `SMU +F` to input 4 - **Switch matrix will not detect this**\n", " - `SMU +S` to input 5 - **Switch matrix will not detect this**\n", " - `SMU -F` to input 1 - **Switch matrix will not detect this**\n", " - `SMU -S` to input 8 - **Switch matrix will not detect this**" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "after autodetecting couple ports: set()\n" ] } ], "source": [ "switch_matrix.couple_port_autodetect() \n", "print(\"after autodetecting couple ports: \", switch_matrix.connections())\n", "\n", "# Since the Kelvin pairs are not connected to pairs of couple ports, the Switch\n", "# matrix will not *couple enable* these inputs." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.1" } }, "nbformat": 4, "nbformat_minor": 2 }