Skip to content
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

Newport 842-PE #13

Open
wants to merge 49 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e19ae4b
minimum working example for Princeton Trivista spectrometer
Sep 3, 2013
926dd15
trivista add query commands
Sep 4, 2013
efc2055
trivista: custom query
Sep 4, 2013
6bc407a
initial commit for Newport842PE
Sep 5, 2013
a8f77b4
remove contributions from trivista
Sep 5, 2013
a95253b
add commands
Sep 5, 2013
98ee243
add commands
Sep 5, 2013
8c5bbd5
correct some Action
Sep 5, 2013
4f3cf3d
fix buggy commands
Sep 5, 2013
b73bc86
add dsu and clk
Sep 5, 2013
3c0bb52
initial commit for Newport 842-PE
Sep 5, 2013
e77b39d
merge
Sep 5, 2013
5cc2985
correct code style
Sep 6, 2013
c41841b
pep8 & pyflakes OK
Sep 6, 2013
5fca00b
remove send_command
Sep 6, 2013
86c253d
remove send_command
Sep 6, 2013
430d40c
m
Sep 6, 2013
a3df82c
add warning for broken functions
Sep 6, 2013
e8eadbc
change functions name to human
Sep 8, 2013
e8878d3
sampling getter/setter work
Sep 8, 2013
d147399
new query status. Now put result in an internal variable for later re…
Sep 9, 2013
9171be8
how to fake a getter
Sep 10, 2013
6796e6c
in @Feat status, read directly in a dictionary
Sep 10, 2013
98a960a
convert some @Action to getter/setter pairs
Sep 10, 2013
3b89594
status: read a float instead of a int (fix for some heads)
Sep 11, 2013
ece508f
all possible getter/setter done
Sep 11, 2013
a1da7cf
add pint (units)
Sep 11, 2013
744103c
prevent energy_mode with photodiode, split multiplies in 2, same for …
Sep 11, 2013
1a3f847
add unit for returned current_value
Sep 11, 2013
10588b2
convert Actions->setters, add send_command()
Sep 12, 2013
d50bc70
comments + prevent dBm without a photodiode
Sep 12, 2013
6af8e52
add units to get_statistics()
Sep 12, 2013
001cb97
helper function new_scale()
Sep 12, 2013
7bb9242
add units to walength
Sep 12, 2013
d05c3aa
split DeviceStatus['Multiplier'] in two variables, same for DeviceSta…
Oct 1, 2013
d9b7422
clock uses struct_time format
Oct 9, 2013
579ca5f
fix for head 918D-UV-OD3
Oct 9, 2013
c3316dd
prevent setting scale out of range for the head + function to test th…
Oct 18, 2013
f82e4df
add more tests
Oct 18, 2013
742c026
add test for wavelength
Oct 18, 2013
6e0dedb
add tests for offsets and multipliers
Oct 18, 2013
a22b8ec
add test for trigger
Oct 18, 2013
07ba54a
new_scale (setter) -> change scale (action)
Oct 18, 2013
a05de94
recalculate available scales when we change energy mode
Oct 18, 2013
944a27f
add file for tests
Oct 22, 2013
02544b1
add test + corrections for sampling
Oct 22, 2013
5e7851a
new tests
Oct 22, 2013
db9323a
new tests
Oct 22, 2013
bc2a0d2
minor corrections
Mar 8, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
325 changes: 325 additions & 0 deletions lantz/drivers/newport/842PE.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
# -*- coding: utf-8 -*-
"""
lantz.drivers.newport.842PE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Newport 842-PE powermeter

:copyright: 2013 by Lantz Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
import time
from lantz import Action, Feat, DictFeat
from lantz.serial import SerialDriver

class Newport842PE(SerialDriver):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For drivers that start with numbers, we usually use just the initial of the brand N842PE

"""Newport 842-PE powermeter
"""

ENCODING = 'ascii'

RECV_DONE = 'ACK\r\n' #this string is return by the device when the action is done
RECV_TERMINATION = '\r\n'
SEND_TERMINATION = '\r\n'

BAUDRATE = 115200
BYTESIZE = 8
PARITY = 'none'
STOPBITS = 1

#Display commands
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be indented like STOPBITS


@Action(values={'real-time':0, 'histogram':1, 'statistic':2, 'needle':3, 'lineplot':4})
def sdu(self, value):
"""This command is used to change the device’s on-screen display mode.
"""
self.sendCommand('*sdu {}'.format(value))

@Action(values=set(('auto', '1p', '3p', '10p', '30p', '100p', '300p', '1n', '3n', '10n', '30n', '100n', '300n', '1u', '3u', '10u', '30u', '100u', '300u', '1m', '3m', '10m', '30m', '100m', '300m', '1', '3', '10', '30', '100', '300', '1k', '3k', '10k', '30k', '100k', '300k', '1M', '3M', '10M', '30M', '100M', '300M',)))
def ssa(self, value):
"""This command is used to force the display of the current data into a specific range.
"""
self.sendCommand('*ssa {}'.format(value))

@Action(values={True:1, False:0})
def dbu(self, value):
"""This command changes the on-screen display unit to dBm.
"""
self.sendCommand('*dbu {}'.format(value))

@Action(values={True:1, False:0})
def shl(self, value):
"""This command is used to add significant digits to the on-screen reading.
"""
self.sendCommand('*shl {}'.format(value))

#MEASUREMENT COMMANDS - DATA ACQUISITION
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent


@Feat()
def cvu(self):
"""This command is used to query the value that is currently being displayed on the device’s screen. The value is displayed in Watts or in Joules (not in dBm).
"""
result = self.query('*cvu')
return float(result.replace('Current Value:','').strip())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine but you can use parse_query that allows you to query and parse robustly in the same line.
See for example: https://github.com/hgrecco/lantz/blob/master/lantz/drivers/aeroflex/a2023a.py#L107

But the way. Is there a way to know is the output is in Watt or Joules, because in that case you can use units.


@Feat(values={False:'New Data Not Available', True:'New Data Available'})
def nvu(self):
"""This command is used to check whether a new value is available from the device. Though optional, its use is recommended when used with single pulse operations.
"""
return self.query('*nvu')

@Feat()
def vsu(self):
"""This command is used to read all the statistics data, provided that the device has previously been set into statistic mode.
"""
return self.query('*vsu')

@Action(values={'stop':0, 'start raw':1, 'start saving':2, 'save both':3,})
def Log(self, value):
"""This command is used to log data on the 842-PE meter’s EEPROM.
"""
self.sendCommand('*log {}'.format(value))

#Buggy
@Action()
def fdl(self, value):
"""This command is used to retrieve a logged file from the device.
"""
# return self.query('*fdl {}'.format(value))
return self.query('*fdl 0')

#Buggy
@Feat()
def cau(self):
"""This command is used to send data to the serial port according to the data sampling setting. The maximum transfer speed is 200Hz.
"""
return self.query('*cau')

#MEASUREMENT COMMANDS - SETUP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent


def swa(self):
"""This command is used to specify the wavelength being used on the detector.
"""
self.sendCommand('*swa {}'.format(value))

@Action(values={True:1, False:0})
def atu(self,value):
"""This command is used to adjust the processing of the meter with the readings of the detector, depending on whether the detector is using an external attenuator or not.
"""
self.sendCommand('*atu {}'.format(value))

@Action(values=(set((1,2,)), None))
def smu(self,value,multiplier):
"""This command is used to set the value of the multipliers.
"""
self.sendCommand('*smu {0} {1}'.format(value,multiplier))

@Action(values=(set((1,2,)), None))
def sou(self,value,multiplier):
"""This command is used to set the value of the offsets.
"""
self.sendCommand('*sou {0} {1}'.format(value,multiplier))

@Feat()
def rds(self):
"""This command is used to read the current data sampling settings.
"""
return self.query('*rds')

SampleRateUnit = {'second':0, 'minute':1, 'hour':2, 'day':3, '%':4}
SamplePeriodUnit = {'second':0, 'minute':1, 'hour':2, 'day':3, 'week':4, 'pulse':5}
TotalDurationUnit = {'sample':0, 'second':1, 'minute':2, 'hour':3, 'day':4, 'week':5, 'continuous':6, 'predefinded':7}
TimeStamp = {True:1, False:0}
@Action(values=(None, SampleRateUnit, None, SamplePeriodUnit, None, TotalDurationUnit, TimeStamp,))
def dsu(self, sampleRate, sampleRateUnit, samplePeriod, samplePeriodUnit, totalDuration, totalDurationUnit, timeStamp,):
"""
"""
self.sendCommand('*dsu {} {} {} {} {} {} {}'.format(sampleRate, sampleRateUnit, samplePeriod, samplePeriodUnit, totalDuration, totalDurationUnit, timeStamp,))

@Action()
def tla(self, value=True):
"""This command sets the internal trigger level when using the device in energy reading mode.
"""
self.sendCommand('*tla {}%'.format(value))

#MEASUREMENT COMMANDS - MEASUREMENT CONTROL
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent


@Action(values={'disable':0, 'enable':1, 'reset':2})
def esu(self, value=True):
"""This command is used start, stop and reset the statistics calculating process on the data currently being acquisitioned.
"""
self.sendCommand('*esu {}'.format(value))

@Action(values={True:1, False:0})
def sca(self,value):
"""
"""
self.sendCommand('*sca {}'.format(value))

@Action(values={True:1, False:0})
def eaa(self,value):
"""
"""
self.sendCommand('*eaa {}'.format(value))

@Action(values={'off':0, 'on':1, 'undo':2})
def eoa(self,value):
"""
"""
self.sendCommand('*eoa {}'.format(value))

#INSTRUMENT AND DETECTOR INFORMATION COMMANDS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent


@Feat()
def ver(self):
"""This command is used to query the device to get information about the firmware version and the device type.
"""
return self.query('*ver')

@Feat()
def hea(self):
"""Model of the current head
"""
return self.query('*hea')

#The device is a bit buggy for this one as it return the info with 3 \n\r. So the hack here repare it.
@Feat()
def sta(self):
"""This command is used to view data that is relevant to the current detector head.
"""
out = ''
out += self.query('*sta')
out += '\t{}'.format(self.recv())
out += '\t{}'.format(self.recv())
return out

@Feat()
def bat(self):
"""This command is used to query the device’s remaining battery power.
"""
return self.query('*bat')

day = set(range(1,32))
month = set(range(1,13))
year = set(range(1970,3000))
hour = set(range(24))
minute = set(range(59))
second = set(range(59))
AMPM = {'AM':0, 'PM':1}
@Action(values=(day, month, year, hour, minute, second, AMPM,))
def clk(self, Day, Month, Year, Hour, Minute, Second, aMPM,):
"""
"""
self.sendCommand('*clk {} {} {} {} {} {} {}'.format(Day, Month, Year, Hour, Minute, Second, aMPM,))

#INSTRUMENT CONTROL COMMANDS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent


@Action(values={True:1, False:0})
def bkl(self, value=True):
"""This command is used to turn the backlight of the device display on or off.
"""
self.sendCommand('*bkl {}'.format(value))

@Action(values={True:1, False:0})
def ano(self, value=True):
"""This command is used to enable or disable the output of the current value on the analog port of the meter.
"""
self.sendCommand('*ano {}'.format(value))

#COMMUNICATIONS COMMANDS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent


@Action(values=set((2400, 9600, 14400, 19200, 38400, 155200)))
def brs(self, value=True):
"""This command is used to change the current baud rate of the serial port of the device.
"""
self.sendCommand('*brs {}'.format(value))

def query(self, command, *, send_args=(None, None), recv_args=(None, None)):
answer = super().query(command, send_args=send_args, recv_args=recv_args)
if answer == 'ERROR':
raise InstrumentError
return answer

def sendCommand(self, s):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use pep8. send_command

self.send(s)
self.waitInstrumentDone()

def waitInstrumentDone(self, termination=None, encoding=None, recv_chunk=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use pep8. wait_instrument_done

"""Wait for command completion by instrument.

:param termination: termination character (overrides class default)
:type termination: str
:param encoding: encoding to transform bytes to string (overrides class default)
:param recv_chunk: number of bytes to receive (overrides class default)
:return: string encoded from received bytes
"""

termination = termination or self.RECV_DONE
encoding = encoding or self.ENCODING
recv_chunk = recv_chunk or self.RECV_CHUNK

if not termination:
return str(self.raw_recv(recv_chunk), encoding)

if self.TIMEOUT is None or self.TIMEOUT < 0:
stop = float('+inf')
else:
stop = time.time() + self.TIMEOUT

received = self._received
while not termination in received:
if time.time() > stop:
raise LantzTimeoutError
raw_received = self.raw_recv(recv_chunk)
received += str(raw_received, encoding)

self.log_debug('Received {!r} (len={})', received, len(received))

if __name__ == '__main__':
import argparse
import lantz.log

parser = argparse.ArgumentParser(description='Newport 842-PE powermeter')
parser.add_argument('-i', '--interactive', action='store_true',
default=False, help='Show interactive GUI')
parser.add_argument('-p', '--port', type=str, default='17',
help='Serial port to connect to')

args = parser.parse_args()
lantz.log.log_to_screen(lantz.log.DEBUG)
with Newport842PE(args.port) as inst:
if args.interactive:
from lantz.ui.qtwidgets import start_test_app
start_test_app(inst)
else:
print('Non interactive mode')
inst.sdu('statistic')
print(inst.ver)
# inst.Log('save both')
# time.sleep(1)
# inst.Log('stop')
# print(inst.fdl(1))
# print(inst.cau)
# while 1:
# time.sleep(.1)
# print(inst.cvu)

dataAvailable = inst.nvu
if inst.nvu:
print(inst.cvu)
# print(inst.fdl) #buggy
# print(inst.cau) #buggy
inst.ssa('100m')
inst.bkl(1)
inst.dbu(False)
inst.shl(False)

# print(inst.sta)
print(inst.hea)
print(inst.bat)
# print(inst.sta)
inst.eoa('on')
#inst.sta
#inst.clk(5,9,2013,17,58,00,'PM')
#inst.dsu(1,'second', 10,'second', 1,'sample', True)
print(inst.rds)
19 changes: 19 additions & 0 deletions lantz/drivers/newport/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
"""
lantz.drivers.newport
~~~~~~~~~~~~~~~~~~~

:company: Newport
:description:
:website: http://www.newport.com

----

:copyright: 2013 by Lantz Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from .842PE import 842PE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the wrong import


__all__ = ['842PE',]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and the wrong usage

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should it be?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Giving that I'll rename my class N842PE.