Skip to content

Commit

Permalink
Merge pull request #13 from qt3uw/12-support-independent-channel-scal…
Browse files Browse the repository at this point in the history
…ing-and-offsets

support independent channel scaling and offsets
  • Loading branch information
gadamc authored Nov 18, 2023
2 parents e04c1a1 + 6ef3733 commit f063686
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 14 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "nipiezojenapy"
version = "1.0.2.dev0"
version = "1.0.3.dev0"

description = "A package for controlling Jena PiezoSystem NV40 3CLE amplifier vi NIDAQMX."
readme = "README.md"
Expand Down
23 changes: 19 additions & 4 deletions src/applications/tkcontrollerapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
parser.add_argument('--piezo-read-channels', metavar = '<ch0,ch1,ch2>', default = 'ai0,ai1,ai2', type=str,
help='List of analog input channels used to read the piezo position')
parser.add_argument('-s', '--settle-time', metavar = 'settle_time', default = 0.01, type=float,
help='Amount of time, in seconds, that are paused after moving to a new position. This allows for the device to "settle" into position.')
help='''Amount of time, in seconds, that are paused after moving to a new position.
This allows for the device to "settle" into position.''')
parser.add_argument('-q', '--quiet', action = 'store_true',
help='When true,logger level will be set to warning. Otherwise, set to "info".')
parser.add_argument('-t', '--test', action = 'store_true',
Expand All @@ -27,8 +28,11 @@
help='sets min allowed position on piezo controller.')
parser.add_argument('-pmax', '--piezo-max-position', metavar = 'microns', default = 80, type=float,
help='sets min allowed position on piezo controller.')
parser.add_argument('-pscale', '--piezo-scale-microns-per-volt', default = 8, type=float,
help='sets micron to volt scale for piezo controller.')
parser.add_argument('-pscale', '--piezo-scale-microns-per-volt', nargs = "*", default = [8], type=float,
help='sets micron to volt scale for piezo controller for all channels or each channel individually.')
parser.add_argument('-poffset', '--piezo-scale-volts-offset', nargs = "*", default = [0], type=float,
help='''sets volt offset value for piezo controller for all channels or each channel individually.
This is the applied voltage that defines the position x, y, z = 0, 0, 0.''')

args = parser.parse_args()

Expand Down Expand Up @@ -208,13 +212,24 @@ def build_controller():
if args.test:
controller = nipiezojenapy.BaseControl()
else:
if len(args.piezo_scale_microns_per_volt) == 1:
piezo_scale_microns_per_volt = args.piezo_scale_microns_per_volt * 3
else:
piezo_scale_microns_per_volt = args.piezo_scale_microns_per_volt

if len(args.piezo_scale_volts_offset) == 1:
piezo_scale_volts_offset = args.piezo_scale_volts_offset * 3
else:
piezo_scale_volts_offset = args.piezo_scale_volts_offset

controller = nipiezojenapy.PiezoControl(device_name = args.daq_name,
write_channels = args.piezo_write_channels.split(','),
read_channels = args.piezo_read_channels.split(','),
move_settle_time = args.settle_time,
min_position = args.piezo_min_position,
max_position = args.piezo_max_position,
scale_microns_per_volt = args.piezo_scale_microns_per_volt)
scale_microns_per_volt = piezo_scale_microns_per_volt,
zero_microns_volt_offset = piezo_scale_volts_offset)
return controller

def main():
Expand Down
34 changes: 25 additions & 9 deletions src/nipiezojenapy/controller.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import nidaqmx
import logging
import time
from typing import List
from typing import List, Union, Tuple

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -77,7 +77,8 @@ class PiezoControl(BaseControl):
def __init__(self, device_name: str,
write_channels: List[str] = ['ao0','ao1','ao2'],
read_channels: List[str] = None,
scale_microns_per_volt: float = 8,
scale_microns_per_volt: Union[float, Tuple[float, float, float]] = 8,
zero_microns_volt_offset: Union[float, Tuple[float, float, float]] = 0,
move_settle_time: float = 0.001,
min_position: float = 0.0,
max_position: float = 80.0) -> None:
Expand All @@ -86,17 +87,32 @@ def __init__(self, device_name: str,
self.device_name = device_name
self.write_channels = write_channels
self.read_channels = read_channels
self.scale_microns_per_volt = scale_microns_per_volt
if isinstance(scale_microns_per_volt, float):
self.scale_microns_per_volt = tuple([scale_microns_per_volt] * 3)
else:
self.scale_microns_per_volt = tuple(scale_microns_per_volt)

if len(self.scale_microns_per_volt) != 3:
raise ValueError('scale_microns_per_volt must be a float or a list of three floats.')

if isinstance(zero_microns_volt_offset, float):
self.zero_microns_volt_offset = tuple([zero_microns_volt_offset] * 3)
else:
self.zero_microns_volt_offset = tuple(zero_microns_volt_offset)

if len(self.zero_microns_volt_offset) != 3:
raise ValueError('zero_microns_volt_offset must be a float or a list of three floats.')

self.minimum_allowed_position = min_position
self.maximum_allowed_position = max_position
self.settling_time_in_seconds = move_settle_time #10 millisecond settle time
self.last_write_values = [None, None, None]

def _microns_to_volts(self, microns: float) -> float:
return microns / self.scale_microns_per_volt
def _microns_to_volts(self, microns: float, axis: int) -> float:
return microns / self.scale_microns_per_volt[axis] + self.zero_microns_volt_offset[axis]

def _volts_to_microns(self, volts: float) -> float:
return self.scale_microns_per_volt * volts
def _volts_to_microns(self, volts: float, axis: int) -> float:
return self.scale_microns_per_volt[axis] * (volts - self.zero_microns_volt_offset[axis])


def go_to_position(self, x: float = None,
Expand All @@ -115,7 +131,7 @@ def goto(val, idx):
self._validate_value(val)
with nidaqmx.Task() as task:
task.ao_channels.add_ao_voltage_chan(self.device_name + '/' + self.write_channels[idx])
task.write(self._microns_to_volts(val))
task.write(self._microns_to_volts(val, idx))
self.last_write_values[idx] = val

debug_string = []
Expand Down Expand Up @@ -167,4 +183,4 @@ def get_current_position(self) -> List[float]:
return self.last_write_values

else:
return [self._volts_to_microns(v) for v in self.get_current_voltage()]
return [self._volts_to_microns(v, i) for i, v in enumerate(self.get_current_voltage())]

0 comments on commit f063686

Please sign in to comment.