# UserDefinedSerial

 Summary: Control arbitrary serial-based shutters and state devices Author: Mark Tsuchida License: BSD Platforms: All platforms (uses serial port) Serial port settings: Depends on device Since version: 1.4.19 (nightly 20140813)

The UserDefinedSerial device adapter will allow you to control any shutter or state device (turret, changer, switch, etc.) that uses the serial port for communication and operates using a simple serial protocol.

You will need to know the correct serial port settings for the device, as well as the command protocol for controlling the device.

## Configuration (Step 1: write-only communication)

There are quite a few properties that need to be set correctly, so it is simplest to first configure the device to move in response to commands. The device adapter will remember the last-set state (shutter open/close or state device position) in software, so things will stay in sync if the device is reliable (doesn’t encounter errors) and you don’t manually operate it. For devices that do not have commands to query state, this will be the only configuration step.

### Common settings

Start by setting these properties in the Hardware Configuration Wizard:

• Port - Set this to the correct serial port (COM port on Windows). Also, set the port settings to the correct values for the device.
• Command mode - The format of the commands to be sent. More on this below.
• Response detection - Leave at “Ignore responses”
• Initialize-command (optional) - If there is a command that needs to be executed to set up the device for use, enter it here. Otherwise, leave it blank.
• Shutdown-command (optional) - If there is a command that should be executed when finished using the device, enter it here. Typically, leave it blank.

#### Command mode

Usually, serial commands are short strings (made up of letters, numbers, and punctuation). The device manual should indicate how these commands are terminated: CR, LF, or CRLF. Select the corresponding ASCII mode.

ASCII-no-terminator can be used in unusual cases where the terminator is not one of the three provided options, or where a subset of commands need to be sent without a terminator. In such cases, the terminator must be included in every command string.

Some devices use binary commands, made up of raw byte values and no terminator. In such cases, select Binary.

#### How to enter commands

Special control characters and commas in commands need to be entered according to special rules. See the later section on “How to enter command and response strings”.

### UserDefinedShutter

• Open-command - Enter the command that opens the shutter.
• Close-command - Enter the command that closes the shutter.

The remaining properties can be left blank for now.

### UserDefinedStateDevice

• Number of positions - Set this to the number of positions. (E.g. 8 if you have an 8-position filter wheel.)

In addition, the commands for setting each position need to be set. To do so, first finish and save the hardware configuration; then open the Device Property Browser. Enter set the following properties:

• SetPosition-command-n (where n is a number) - Enter the command that tells the device to move to position n.

The remaining properties of UserDefinedStateDevice can be left blank for now.

Now, to cause the SetPosition commands to be remembered in your hardware configuration file, add (or append to) the System-Startup configuration preset (see Micro-Manager Configuration Guide). In this case, you will want to include all the SetPosition-command-n properties in the System configuration group’s Startup preset.

## Configuration (Step 2: checking device responses)

Most devices respond to commands with a specific acknowledgement. (Some devices don’t send anything back to the computer; if that is the case with your device, you are done configuring.)

It is useful to check the device’s response in case it indicates an error. UserDefinedSerial currently supports checking command responses against a fixed string; an error is reported if the device fails to respond or responds with a string that differs from the expected one.

### Choosing a response detection method

Devices that use an ASCII protocol typically terminate their responses with CR, LF, or CRLF, just like the commands (although the terminator is not necessarily the same one used for commands - check your device’s manual). Some devices return 1 or a few bytes in a fixed-length format, without a terminator. In the Hardware Configuration Wizard, set the Response detection property accordingly:

• Ignore responses - No responses are ever checked.
• Terminator-CR - Responses are expected to be terminated with a CR (carriage return).
• Terminator-CRLF - Responses are expected to be terminated with a CR followed by an LF (linefeed).
• Terminator-LF - Responses are expected to be terminated with an LF.
• Variable-length binary - Responses are binary bytes without a terminator. The expected number of bytes are read from the device.

### Common settings

• Initialize-response - Enter the expected response from the device after the initialization command is sent.
• Shutdown-response- Enter the expected response from the device after the shutdown command is sent.

You do not have to specify a response string for every command. Where a response string is left empty, the response is simply ignored (not checked for).

### UserDefinedShutter

• Open-response - The expected response to the open command.
• Close-response - The expected response to the close command.

### UserDefinedStateDevice

In the Device Property Browser:

• SetPosition-response-n (where n is a number) - The expected response to the SetPosition-command-n command.

(You will want to add these too to the System-Startup configuration preset.)

## Configuration (Step 3: setting up device state querying)

By default, UserDefinedSerial devices keep the device’s current state in sync with the software by remembering the state last set from Micro-Manager. The two can go out of sync if, for example, the user can manually switch the device without going through Micro-Manager.

If the device has commands to query its current state, you can set up UserDefinedSerial to use those commands instead of trusting the memorized last-set state.

### UserDefinedShutter

The shutter must support a command to query whether the shutter is open or closed, whose response is a fixed string for each case. Set the following properties in the Hardware Configuration Wizard:

• QueryState-command - The command to ask the shutter if it is open.
• QueryState-open-response - The response that means that the shutter is currently open.
• QueryState-close-response - The response that means that the shutter is currently closed.

### UserDefinedStateDevice

In the Device Property Browser, you can set the following properties:

• QueryPosition-command - The command to ask the device its current position.
• QueryPosition-response-n (where n is a number) - The response that means that the device is currently at position n.

(You will want to add these to the System-Startup configuration preset.)

## Synchronizing state at startup

If your device does not support querying its state, you might notice that Micro-Manager thinks that the device is in the wrong state until the first time you move the device from Micro-Manager.

This should not happen with shutters because UserDefinedShutter always closes the shutter at startup.

With UserDefinedStateDevice, one way to prevent this from happening is to set the Initialize-command property to a command that moves the device to position 0 (which is where UserDefinedStateDevice assumes the device to be until it knows otherwise), in addition to initializing the device. Make sure there is no danger with moving the device automatically during startup.

## Setting Delay

UserDefinedSerial devices do not (yet) support querying the device to detect the completion of motion. Instead, you can set fixed delays on the Delay page of the Hardware Configuration Wizard.

The Delay value should be the maximum time it takes the device to complete motion, measuring from the moment when the command is sent (or, if so configured, when the response is received).

So, if your device does not send a response until motion is complete, you can simply set up response checking and leave the Delay at 0 ms.

## How to enter command and response strings

In most cases, commands and responses consisting of letters, numbers, and punctuation can be entered literally.

If your Command mode setting specifies a terminator, command strings should NOT include the terminator. If your Response detection setting specifies a terminator, response strings should NOT include the terminator.

Special characters and non-letter bytes (any byte that is not a printable ASCII character) should be entered using the following escape sequences:

Escape Sequence Decimal Value Hexadecimal Value Remarks
\\ 92 0x5c Backslash
\’ 39 0x27 Single quote (escape not required)
\” 34 0x22 Double quote (escape not required)
\? 63 0x3f Question mark (escape not required)
\a 7 0x07 Bell
\b 8 0x08 Backspace
\f 12 0x0c Form Feed
\n 10 0x0a Line Feed
\r 13 0x0d Carriage Return
\t 9 0x09 Horizontal Tab
\v 11 0x0b Vertical Tab
\nnn     Octal value (nnn is up to 3 octal digits)
\x2c 44 2c Comma (,) (must be escaped because not allowed in property value)

These escape sequences are almost identical to the rules used for string literals in the C and C++ languages. There are three differences from the C specification:

• Unicode escapes (\uxxxx, \Uxxxx) are not supported.
• Hexadecimal escapes (\xhh) are terminated at 2 hex digits, even if the next character is a valid hex digit.
• Since quotes are not used to delimit the string, there is no need to escape single or double quote characters.

### Examples

If the command to move your state device to position 5 is MOVE A,5, then enter

   MOVE A\x2c5


for the SetPosition-command-5 property.

If your device uses a binary protocol with two-byte commands and responses, and the command to ask if the shutter is open is 0x0b00 (or 11 followed by 0 in decimal), you can set the QueryState-command property to any of the following equivalent strings:

   \x0b\x00
\013\000
\13\0
\v\0


(with Command mode set to Binary).

If the response to that command is 0x0b01 for “open” and 0x0b02 for “closed”, you will set the QueryState-open-response to e.g.

   \x0b\x01


and QueryState-closed-response to e.g.

   \x0b\x02


with Response detection set to Variable-length binary.

## How responses are checked

In all cases, the serial receive buffer is cleared before sending a command.

### “Ignore responses”

Responses are completely ignored, whether or not you enter strings for the *-response properties.

### “Terminator-CR”, “Terminator-CRLF”, and “Terminator-LF”

After sending a command, if the corresponding *-response property is not empty, a response is read, using the serial port’s timeout setting, until the terminator (CR, LF, or CRLF) is encountered. The response (excluding the terminator) is then checked against the expected string. If it does not match, an error is reported. If the *-response property is empty, the response is ignored (not read at all).

For query commands, the response string (again, excluding the terminator) is checked against each of the corresponding *-response properties. If no match is found, an error is reported. If any of the corresponding *-response properties are empty, the query is not performed in the first place.

### “Fixed-length binary”

After sending a command, if the corresponding *-response property is not empty, the same number of bytes as the value of that property are read, using the serial port’s timeout setting. If the expected number of bytes could not be read, or their values fail to match the expected string, an error is reported. If the *-response property is empty, the response is ignored (not read at all).

For query commands, the corresponding *-response properties must all contain strings of the same length (or an error is reported, unless one or more are empty). That many bytes are read from the device and compared to the candidates. If the expected number of bytes could not be read, or no match is found, an error is reported. If any of the corresponding *-response properties are empty, the query is not performed in the first place.