-
Notifications
You must be signed in to change notification settings - Fork 85
adding mc1 #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
adding mc1 #145
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
35f7a0f
adding mc1
CatherineH c3849bf
changing units to milliseconds on most mc1 unitless properties
CatherineH 2685ee4
adding division import to mc1
CatherineH e12032d
Qubitekk MC1 - Add instrument to docs
scasagrande f474064
Qubitekk MC1 - Formatting and refactoring properties in init
scasagrande 87f462d
fixed format string on properties
CatherineH 64bf3ca
Qubitekk MC1 - Change is_centering to return boolean
scasagrande e66c6b6
added more to docstring on mc1 output setting
CatherineH File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #!/usr/bin/python | ||
| # Qubitekk Motor controller example | ||
| from time import sleep | ||
|
|
||
| from instruments.qubitekk import MC1 | ||
| import quantities as pq | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
|
|
||
| mc1 = MC1.open_serial(vid=1027, pid=24577, baud=9600, timeout=1) | ||
| mc1.step_size = 25*pq.ms | ||
| mc1.inertia = 10*pq.ms | ||
| print("step size:", mc1.step_size) | ||
| print("inertial force: ", mc1.inertia) | ||
|
|
||
| print("Firmware", mc1.firmware) | ||
| print("Motor controller type: ", mc1.controller) | ||
| print("centering") | ||
|
|
||
| mc1.center() | ||
| while mc1.is_centering(): | ||
| print(str(mc1.metric_position)+" "+str(mc1.direction)) | ||
| pass | ||
|
|
||
| print("Stage Centered") | ||
| # for the motor in the mechanical delay line, the travel is limited from | ||
| # the full range of travel. Here's how to set the limits. | ||
| mc1.lower_limit = -260*pq.ms | ||
| mc1.upper_limit = 300*pq.ms | ||
| mc1.increment = 5*pq.ms | ||
| x_pos = mc1.lower_limit | ||
| while x_pos <= mc1.upper_limit: | ||
| print(str(mc1.metric_position)+" "+str(mc1.direction)) | ||
| mc1.move(x_pos) | ||
| while mc1.move_timeout > 0: | ||
| sleep(0.5) | ||
| sleep(1) | ||
| x_pos += mc1.increment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,3 +7,4 @@ | |
| from __future__ import absolute_import | ||
|
|
||
| from .cc1 import CC1 | ||
| from .mc1 import MC1 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,255 @@ | ||
| #!/usr/bin/env python | ||
| # -*- coding: utf-8 -*- | ||
| """ | ||
| Provides support for the Qubitekk MC1 Motor Controller. | ||
|
|
||
| MC1 Class originally contributed by Catherine Holloway. | ||
| """ | ||
|
|
||
| # IMPORTS ##################################################################### | ||
|
|
||
| from __future__ import absolute_import, division | ||
|
|
||
| from builtins import range, map | ||
| from enum import Enum | ||
|
|
||
| import quantities as pq | ||
|
|
||
| from instruments.abstract_instruments import Instrument | ||
| from instruments.util_fns import ( | ||
| int_property, enum_property, unitful_property, assume_units | ||
| ) | ||
|
|
||
| # CLASSES ##################################################################### | ||
|
|
||
|
|
||
| class MC1(Instrument): | ||
| """ | ||
| The MC1 is a controller for the qubitekk motor controller. Used with a | ||
| linear actuator to perform a HOM dip. | ||
| """ | ||
| def __init__(self, filelike): | ||
| super(MC1, self).__init__(filelike) | ||
| self.terminator = "\r" | ||
| self._increment = 1*pq.ms | ||
| self._lower_limit = -300*pq.ms | ||
| self._upper_limit = 300*pq.ms | ||
| self._firmware = None | ||
| self._controller = None | ||
|
|
||
| # ENUMS # | ||
|
|
||
| class MotorType(Enum): | ||
| """ | ||
| Enum for the motor types for the MC1 | ||
| """ | ||
| radio = "Radio" | ||
| relay = "Relay" | ||
|
|
||
| # PROPERTIES # | ||
|
|
||
| @property | ||
| def increment(self): | ||
| """ | ||
| Gets/sets the stepping increment value of the motor controller | ||
|
|
||
| :units: As specified, or assumed to be of units milliseconds | ||
| :type: `~quantities.Quantity` | ||
| """ | ||
| return self._increment | ||
|
|
||
| @increment.setter | ||
| def increment(self, newval): | ||
| self._increment = assume_units(newval, pq.ms).rescale(pq.ms) | ||
|
|
||
| @property | ||
| def lower_limit(self): | ||
| """ | ||
| Gets/sets the stepping lower limit value of the motor controller | ||
|
|
||
| :units: As specified, or assumed to be of units milliseconds | ||
| :type: `~quantities.Quantity` | ||
| """ | ||
| return self._lower_limit | ||
|
|
||
| @lower_limit.setter | ||
| def lower_limit(self, newval): | ||
| self._lower_limit = assume_units(newval, pq.ms).rescale(pq.ms) | ||
|
|
||
| @property | ||
| def upper_limit(self): | ||
| """ | ||
| Gets/sets the stepping upper limit value of the motor controller | ||
|
|
||
| :units: As specified, or assumed to be of units milliseconds | ||
| :type: `~quantities.Quantity` | ||
| """ | ||
| return self._upper_limit | ||
|
|
||
| @upper_limit.setter | ||
| def upper_limit(self, newval): | ||
| self._upper_limit = assume_units(newval, pq.ms).rescale(pq.ms) | ||
|
|
||
| direction = unitful_property( | ||
| name="DIRE", | ||
| doc=""" | ||
| Get the internal direction variable, which is a function of how far | ||
| the motor needs to go. | ||
|
|
||
| :type: `~quantities.Quantity` | ||
| :units: milliseconds | ||
| """, | ||
| units=pq.ms, | ||
| readonly=True | ||
| ) | ||
|
|
||
| inertia = unitful_property( | ||
| name="INER", | ||
| doc=""" | ||
| Gets/Sets the amount of force required to overcome static inertia. Must | ||
| be between 0 and 100 milliseconds. | ||
|
|
||
| :type: `~quantities.Quantity` | ||
| :units: milliseconds | ||
| """, | ||
| format_code='{:.0f}', | ||
| units=pq.ms, | ||
| valid_range=(0*pq.ms, 100*pq.ms), | ||
| set_fmt=":{} {}" | ||
| ) | ||
|
|
||
| @property | ||
| def internal_position(self): | ||
| """ | ||
| Get the internal motor state position, which is equivalent to the total | ||
| number of milliseconds that voltage has been applied to the motor in | ||
| the positive direction minus the number of milliseconds that voltage | ||
| has been applied to the motor in the negative direction. | ||
|
|
||
| :type: `~quantities.Quantity` | ||
| :units: milliseconds | ||
| """ | ||
| response = int(self.query("POSI?"))*self.step_size | ||
| return response | ||
|
|
||
| metric_position = unitful_property( | ||
| name="METR", | ||
| doc=""" | ||
| Get the estimated motor position, in millimeters. | ||
|
|
||
| :type: `~quantities.Quantity` | ||
| :units: millimeters | ||
| """, | ||
| units=pq.mm, | ||
| readonly=True | ||
| ) | ||
|
|
||
| setting = int_property( | ||
| name="OUTP", | ||
| doc=""" | ||
| Gets/sets the output port of the optical switch. 0 means input 1 is | ||
| directed to output 1, and input 2 is directed to output 2. 1 means that | ||
| input 1 is directed to output 2 and input 2 is directed to output 1. | ||
|
|
||
| :type: `int` | ||
| """, | ||
| valid_set=range(2), | ||
| set_fmt=":{} {}" | ||
| ) | ||
|
|
||
| step_size = unitful_property( | ||
| name="STEP", | ||
| doc=""" | ||
| Gets/Sets the number of milliseconds per step. Must be between 1 | ||
| and 100 milliseconds. | ||
|
|
||
| :type: `~quantities.Quantity` | ||
| :units: milliseconds | ||
| """, | ||
| format_code='{:.0f}', | ||
| units=pq.ms, | ||
| valid_range=(1*pq.ms, 100*pq.ms), | ||
| set_fmt=":{} {}" | ||
| ) | ||
|
|
||
| @property | ||
| def firmware(self): | ||
| """ | ||
| Gets the firmware version | ||
|
|
||
| :rtype: `tuple`(Major:`int`, Minor:`int`, Patch`int`) | ||
| """ | ||
| # the firmware is assumed not to change while the device is active | ||
| # firmware is stored locally as it will be gotten often | ||
| # pylint: disable=no-member | ||
| if self._firmware is None: | ||
| while self._firmware is None: | ||
| self._firmware = self.query("FIRM?") | ||
| value = self._firmware.split(".") | ||
| if len(value) < 3: | ||
| for _ in range(3-len(value)): | ||
| value.append(0) | ||
| value = tuple(map(int, value)) | ||
| self._firmware = value | ||
| return self._firmware | ||
|
|
||
| controller = enum_property( | ||
| 'MOTO', | ||
| MotorType, | ||
| doc=""" | ||
| Get the motor controller type. | ||
| """, | ||
| readonly=True | ||
| ) | ||
|
|
||
| @property | ||
| def move_timeout(self): | ||
| """ | ||
| Get the motor's timeout value, which indicates the number of | ||
| milliseconds before the motor can start moving again. | ||
|
|
||
| :type: `~quantities.Quantity` | ||
| :units: milliseconds | ||
| """ | ||
| response = int(self.query("TIME?")) | ||
| return response*self.step_size | ||
|
|
||
| # METHODS # | ||
|
|
||
| def is_centering(self): | ||
| """ | ||
| Query whether the motor is in its centering phase | ||
|
|
||
| :return: False if not centering, True if centering | ||
| :rtype: `bool` | ||
| """ | ||
| response = self.query("CENT?") | ||
| return True if int(response) == 1 else False | ||
|
|
||
| def center(self): | ||
| """ | ||
| Commands the motor to go to the center of its travel range | ||
| """ | ||
| self.sendcmd(":CENT") | ||
|
|
||
| def reset(self): | ||
| """ | ||
| Sends the stage to the limit of one of its travel ranges | ||
| """ | ||
| self.sendcmd(":RESE") | ||
|
|
||
| def move(self, new_position): | ||
| """ | ||
| Move to a specified location. Position is unitless and is defined as | ||
| the number of motor steps. It varies between motors. | ||
|
|
||
| :param new_position: the location | ||
| :type new_position: `~quantities.Quantity` | ||
| """ | ||
| if self.lower_limit <= new_position <= self.upper_limit: | ||
| new_position = assume_units(new_position, pq.ms).rescale(pq.ms) | ||
| clock_cycles = new_position/self.step_size | ||
| cmd = ":MOVE "+str(int(clock_cycles)) | ||
| self.sendcmd(cmd) | ||
| else: | ||
| raise ValueError("Location out of range") | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pq.mmis millimeters, not microns.