From 36a1e49f2badc5dcf619112615bdea7b94ac21f9 Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Sun, 28 Aug 2016 10:40:37 -0700 Subject: [PATCH 1/8] added mhs5200 --- instruments/minghe/mhs5200a.py | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 instruments/minghe/mhs5200a.py diff --git a/instruments/minghe/mhs5200a.py b/instruments/minghe/mhs5200a.py new file mode 100644 index 000000000..d13f4dfe4 --- /dev/null +++ b/instruments/minghe/mhs5200a.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Provides the support for the MingHe low-cost function generator. + +Class originally contributed by Catherine Holloway. +""" + +# IMPORTS ##################################################################### + +from __future__ import absolute_import +from __future__ import division + +from builtins import range, map +from enum import IntEnum, Enum + +import quantities as pq + +from instruments.abstract_instruments import Instrument +from instruments.util_fns import convert_temperature +from instruments.util_fns import enum_property, unitful_property, int_property + +# CLASSES ##################################################################### + + +class MHS5200(Instrument): + """ + The MHS5200 is a low-cost, 2 channel function generator. + + There is no user manual, but Al Williams has reverse-engineered the + communications protocol: + https://github.com/wd5gnr/mhs5200a/blob/master/MHS5200AProtocol.pdf + """ + def __init__(self, filelike): + super(MHS5200, self).__init__(filelike) + + + From 2e2a64a3e0bb00416a98b65e44c8c18ab33cb64c Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Thu, 1 Sep 2016 11:55:42 -0700 Subject: [PATCH 2/8] added minghe function generator --- doc/examples/minghe/ex_minghe_mhs5200.py | 18 ++ instruments/__init__.py | 1 + instruments/minghe/__init__.py | 6 + instruments/minghe/mhs5200a.py | 196 ++++++++++++++++- .../tests/test_minghe/test_minghe_mhs5200a.py | 199 ++++++++++++++++++ 5 files changed, 415 insertions(+), 5 deletions(-) create mode 100644 doc/examples/minghe/ex_minghe_mhs5200.py create mode 100644 instruments/minghe/__init__.py create mode 100644 instruments/tests/test_minghe/test_minghe_mhs5200a.py diff --git a/doc/examples/minghe/ex_minghe_mhs5200.py b/doc/examples/minghe/ex_minghe_mhs5200.py new file mode 100644 index 000000000..287fb9519 --- /dev/null +++ b/doc/examples/minghe/ex_minghe_mhs5200.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +from instruments.minghe import MHS5200 +import quantities as pq + +mhs = MHS5200.open_serial(vid=6790, pid=29987, baud=57600) +print(mhs.serial_number) +mhs.channel[0].frequency = 3000000*pq.Hz +print(mhs.channel[0].frequency) +mhs.channel[0].wave_type = MHS5200.WaveType.sawtooth_down +print(mhs.channel[0].wave_type) +mhs.channel[0].amplitude = 9.0*pq.V +print(mhs.channel[0].amplitude) +mhs.channel[0].offset = -0.5 +print(mhs.channel[0].offset) +mhs.channel[0].phase = 90 +print(mhs.channel[0].phase) + +mhs.channel[1].wave_type = MHS5200.WaveType.sawtooth_up diff --git a/instruments/__init__.py b/instruments/__init__.py index 29b03f2ca..c913473af 100644 --- a/instruments/__init__.py +++ b/instruments/__init__.py @@ -17,6 +17,7 @@ from . import hp from . import keithley from . import lakeshore +from . import minghe from . import newport from . import oxford from . import phasematrix diff --git a/instruments/minghe/__init__.py b/instruments/minghe/__init__.py new file mode 100644 index 000000000..4b17756e1 --- /dev/null +++ b/instruments/minghe/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Module containing MingHe instruments +""" +from .mhs5200a import MHS5200 diff --git a/instruments/minghe/mhs5200a.py b/instruments/minghe/mhs5200a.py index d13f4dfe4..3caf010bf 100644 --- a/instruments/minghe/mhs5200a.py +++ b/instruments/minghe/mhs5200a.py @@ -11,14 +11,13 @@ from __future__ import absolute_import from __future__ import division -from builtins import range, map -from enum import IntEnum, Enum +from builtins import range +from enum import Enum import quantities as pq from instruments.abstract_instruments import Instrument -from instruments.util_fns import convert_temperature -from instruments.util_fns import enum_property, unitful_property, int_property +from instruments.util_fns import ProxyList, assume_units # CLASSES ##################################################################### @@ -31,8 +30,195 @@ class MHS5200(Instrument): communications protocol: https://github.com/wd5gnr/mhs5200a/blob/master/MHS5200AProtocol.pdf """ + # pylint: disable=unused-variable def __init__(self, filelike): super(MHS5200, self).__init__(filelike) + self._channel_count = 2 - + # INNER CLASSES # + class Channel(object): + """ + Class representing a channel on the MHS52000. + """ + + __CHANNEL_NAMES = { + 1: '1', + 2: '2' + } + + def __init__(self, mhs, idx): + self._mhs = mhs + # Use zero-based indexing for the external API, but one-based + # for talking to the instrument. + self._idx = idx + 1 + self._chan = self.__CHANNEL_NAMES[self._idx] + self._count = 0 + + @property + def amplitude(self): + """ + Gets/Sets the amplitude of this channel. + + :units: As specified (if a `~quantities.Quantity`) or assumed to be + of units volt. + :type: `~quantities.Quantity` + """ + query = ":r{0}a".format(self._chan) + response = self._mhs.query(query) + return float(response.replace(query, ""))/100.0*pq.V + + @amplitude.setter + def amplitude(self, new_val): + new_val = 100*assume_units(new_val, pq.V).rescale(pq.V).magnitude + query = ":s{0}a{1}".format(self._chan, int(new_val)) + response = self._mhs.query(query) + + @property + def duty_cycle(self): + """ + Gets/Sets the duty cycle of this channel. + + :units: As specified (if a `~quantities.Quantity`) or assumed to be + of units seconds. + :type: `~quantities.Quantity` + """ + query = ":r{0}d".format(self._chan) + response = self._mhs.query(query) + duty = float(response.replace(query, ""))*pq.s + return duty + + @duty_cycle.setter + def duty_cycle(self, new_val): + new_val = assume_units(new_val, pq.s).rescale(pq.s).magnitude + query = ":s{0}d{1}".format(self._chan, int(new_val)) + response = self._mhs.query(query) + + @property + def enable(self): + """ + Gets/Sets the enable state of this channel. + + :param bool new_val: the enable state + """ + query = ":r{0}b".format(self._chan) + return int(self._mhs.query(query).replace(query, "").replace("\r", "")) + + @enable.setter + def enable(self, new_val): + query = ":s{0}b{1}".format(self._chan, int(new_val)) + response = self._mhs.query(query) + + @property + def frequency(self): + """ + Gets/Sets the frequency of this channel. + + :units: As specified (if a `~quantities.Quantity`) or assumed to be + of units hertz. + :type: `~quantities.Quantity` + """ + query = ":r{0}f".format(self._chan) + response = self._mhs.query(query) + freq = float(response.replace(query, ""))*pq.Hz + return freq + + @frequency.setter + def frequency(self, new_val): + new_val = assume_units(new_val, pq.Hz).rescale(pq.Hz).magnitude + query = ":s{0}f{1}".format(self._chan, int(new_val)) + response = self._mhs.query(query) + + @property + def offset(self): + """ + Gets/Sets the offset of this channel. + + :units: As specified (if a `~quantities.Quantity`) or assumed to be + of fraction. + :type: `~quantities.Quantity` + """ + # need to convert + query = ":r{0}o".format(self._chan) + response = self._mhs.query(query) + return int(response.replace(query, ""))/100.0-1.20 + + @offset.setter + def offset(self, new_val): + new_val = int(new_val*100)+120 + query = ":s{0}o{1}".format(self._chan, new_val) + response = self._mhs.query(query) + + @property + def phase(self): + """ + Gets/Sets the phase of this channel. + + :units: As specified (if a `~quantities.Quantity`) or assumed to be + of degrees. + :type: `~quantities.Quantity` + """ + # need to convert + query = ":r{0}p".format(self._chan) + response = self._mhs.query(query) + return int(response.replace(query, "")) + + @phase.setter + def phase(self, new_val): + query = ":s{0}p{1}".format(self._chan, int(new_val)) + response = self._mhs.query(query) + + @property + def wave_type(self): + """ + Gets/Sets the wave type of this channel. + + :type: `MHS5200.WaveType` + """ + query = ":r{0}w".format(self._chan) + response = self._mhs.query(query).replace(query, "") + return self._mhs.WaveType(int(response)) + + @wave_type.setter + def wave_type(self, new_val): + query = ":s{0}w{1}".format(self._chan, + self._mhs.WaveType(new_val).value) + response = self._mhs.query(query) + + class WaveType(Enum): + """ + Enum containing valid wave modes for + """ + sine = 0 + square = 1 + triangular = 2 + sawtooth_up = 3 + sawtooth_down = 4 + + @property + def channel(self): + """ + Gets a specific channel object. The desired channel is specified like + one would access a list. + + For instance, this would print the counts of the first channel:: + + >>> mhs = ik.minghe.MHS5200.open_serial(vid=1027, pid=24577, + baud=19200, timeout=1) + >>> print(mhs.channel[0].frequency) + + :rtype: `CC1.Channel` + """ + return ProxyList(self, MHS5200.Channel, range(self._channel_count)) + + @property + def serial_number(self): + """ + Get the serial number, as an int + + :rtype: int + """ + query = ":r0c" + response = self.query(query) + response = response.replace(query, "").replace("\r", "") + return response diff --git a/instruments/tests/test_minghe/test_minghe_mhs5200a.py b/instruments/tests/test_minghe/test_minghe_mhs5200a.py new file mode 100644 index 000000000..cb71da3f2 --- /dev/null +++ b/instruments/tests/test_minghe/test_minghe_mhs5200a.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Module containing tests for the MingHe MHS52000a +""" + +# IMPORTS #################################################################### + +from __future__ import absolute_import + +from nose.tools import raises +import quantities as pq + +import instruments as ik +from instruments.tests import expected_protocol, unit_eq + + +# TESTS ###################################################################### + + +def test_mhs_amplitude(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1a", + ":r2a", + ":s1a660", + ":s2a800" + ], + [ + ":r1a330", + ":r2a500", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].amplitude == 3.3*pq.V + assert mhs.channel[1].amplitude == 5.0*pq.V + mhs.channel[0].amplitude = 6.6*pq.V + mhs.channel[1].amplitude = 8.0*pq.V + + +def test_mhs_duty_cycle(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1d", + ":r2d", + ":s1d6", + ":s2d8" + + ], + [ + ":r1d330", + ":r2d500", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].duty_cycle == 330.0*pq.s + assert mhs.channel[1].duty_cycle == 500.0*pq.s + mhs.channel[0].duty_cycle = 6*pq.s + mhs.channel[1].duty_cycle = 8*pq.s + + +def test_mhs_enable(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1b", + ":r2b", + ":s1b0", + ":s2b1" + ], + [ + ":r1b1", + ":r2b0", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].enable + assert not mhs.channel[1].enable + mhs.channel[0].enable = False + mhs.channel[1].enable = True + + +def test_mhs_frequency(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1f", + ":r2f", + ":s1f6000", + ":s2f8000" + + ], + [ + ":r1f33000", + ":r2f500000", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].frequency == 33.0*pq.kHz + assert mhs.channel[1].frequency == 500.0*pq.kHz + mhs.channel[0].frequency = 6*pq.kHz + mhs.channel[1].frequency = 8*pq.kHz + + +def test_mhs_offset(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1o", + ":r2o", + ":s1o60", + ":s2o180" + + ], + [ + ":r1o120", + ":r2o0", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].offset == 0 + assert mhs.channel[1].offset == -1.2 + mhs.channel[0].offset = -0.6 + mhs.channel[1].offset = 0.6 + + +def test_mhs_phase(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1p", + ":r2p", + ":s1p60", + ":s2p180" + + ], + [ + ":r1p120", + ":r2p0", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].phase == 120 + assert mhs.channel[1].phase == 0 + mhs.channel[0].phase = 60 + mhs.channel[1].phase = 180 + + +def test_mhs_wave_type(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r1w", + ":r2w", + ":s1w2", + ":s2w3" + + ], + [ + ":r1w0", + ":r2w1", + "ok", + "ok" + ], + sep="\n" + ) as mhs: + assert mhs.channel[0].wave_type == mhs.WaveType.sine + assert mhs.channel[1].wave_type == mhs.WaveType.square + mhs.channel[0].wave_type = mhs.WaveType.triangular + mhs.channel[1].wave_type = mhs.WaveType.sawtooth_up + + +def test_mhs_serial_number(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":r0c" + + ], + [ + ":r0c5225A1", + ], + sep="\n" + ) as mhs: + assert mhs.serial_number == "5225A1" \ No newline at end of file From f1865ddd5637abe4b687bffd15ab2562a773bd14 Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Thu, 1 Sep 2016 12:04:24 -0700 Subject: [PATCH 3/8] added absolute_import --- instruments/minghe/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/instruments/minghe/__init__.py b/instruments/minghe/__init__.py index 4b17756e1..997950f6c 100644 --- a/instruments/minghe/__init__.py +++ b/instruments/minghe/__init__.py @@ -3,4 +3,5 @@ """ Module containing MingHe instruments """ +from __future__ import absolute_import from .mhs5200a import MHS5200 From 0f7eff430cc403c382b02b6550f23a3a7a2edf70 Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Thu, 15 Sep 2016 14:25:12 -0700 Subject: [PATCH 4/8] fixed scaling on frequency --- instruments/minghe/mhs5200a.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/instruments/minghe/mhs5200a.py b/instruments/minghe/mhs5200a.py index 3caf010bf..78b1535ad 100644 --- a/instruments/minghe/mhs5200a.py +++ b/instruments/minghe/mhs5200a.py @@ -102,7 +102,8 @@ def enable(self): :param bool new_val: the enable state """ query = ":r{0}b".format(self._chan) - return int(self._mhs.query(query).replace(query, "").replace("\r", "")) + return int(self._mhs.query(query).replace(query, ""). + replace("\r", "")) @enable.setter def enable(self, new_val): @@ -121,11 +122,12 @@ def frequency(self): query = ":r{0}f".format(self._chan) response = self._mhs.query(query) freq = float(response.replace(query, ""))*pq.Hz - return freq + return freq/100.0 @frequency.setter def frequency(self, new_val): - new_val = assume_units(new_val, pq.Hz).rescale(pq.Hz).magnitude + new_val = assume_units(new_val, pq.Hz).rescale(pq.Hz).\ + magnitude*100.0 query = ":s{0}f{1}".format(self._chan, int(new_val)) response = self._mhs.query(query) From 84da64c45ba2ec10efd154a741422c2a43a41aeb Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Sat, 17 Sep 2016 08:27:55 -0700 Subject: [PATCH 5/8] switched to abstract instrument class --- doc/examples/minghe/ex_minghe_mhs5200.py | 6 +- instruments/minghe/mhs5200a.py | 63 ++++++++++--------- .../tests/test_minghe/test_minghe_mhs5200a.py | 35 ++++++++--- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/doc/examples/minghe/ex_minghe_mhs5200.py b/doc/examples/minghe/ex_minghe_mhs5200.py index 287fb9519..55f929875 100644 --- a/doc/examples/minghe/ex_minghe_mhs5200.py +++ b/doc/examples/minghe/ex_minghe_mhs5200.py @@ -6,13 +6,13 @@ print(mhs.serial_number) mhs.channel[0].frequency = 3000000*pq.Hz print(mhs.channel[0].frequency) -mhs.channel[0].wave_type = MHS5200.WaveType.sawtooth_down +mhs.channel[0].function = MHS5200.Function.sawtooth_down print(mhs.channel[0].wave_type) -mhs.channel[0].amplitude = 9.0*pq.V +mhs.channel[0].amplitude[0] = 9.0*pq.V print(mhs.channel[0].amplitude) mhs.channel[0].offset = -0.5 print(mhs.channel[0].offset) mhs.channel[0].phase = 90 print(mhs.channel[0].phase) -mhs.channel[1].wave_type = MHS5200.WaveType.sawtooth_up +mhs.channel[1].wave_type = MHS5200.Function.sawtooth_up diff --git a/instruments/minghe/mhs5200a.py b/instruments/minghe/mhs5200a.py index 78b1535ad..b458d0696 100644 --- a/instruments/minghe/mhs5200a.py +++ b/instruments/minghe/mhs5200a.py @@ -15,8 +15,7 @@ from enum import Enum import quantities as pq - -from instruments.abstract_instruments import Instrument +from instruments.abstract_instruments import Instrument, FunctionGenerator from instruments.util_fns import ProxyList, assume_units # CLASSES ##################################################################### @@ -30,17 +29,17 @@ class MHS5200(Instrument): communications protocol: https://github.com/wd5gnr/mhs5200a/blob/master/MHS5200AProtocol.pdf """ - # pylint: disable=unused-variable def __init__(self, filelike): super(MHS5200, self).__init__(filelike) self._channel_count = 2 # INNER CLASSES # - class Channel(object): + class Channel(FunctionGenerator): """ Class representing a channel on the MHS52000. """ + # pylint: disable=protected-access __CHANNEL_NAMES = { 1: '1', @@ -49,14 +48,14 @@ class Channel(object): def __init__(self, mhs, idx): self._mhs = mhs + super(MHS5200.Channel, self).__init__(self._mhs._file) # Use zero-based indexing for the external API, but one-based # for talking to the instrument. self._idx = idx + 1 self._chan = self.__CHANNEL_NAMES[self._idx] self._count = 0 - @property - def amplitude(self): + def _get_amplitude_(self): """ Gets/Sets the amplitude of this channel. @@ -66,13 +65,17 @@ def amplitude(self): """ query = ":r{0}a".format(self._chan) response = self._mhs.query(query) - return float(response.replace(query, ""))/100.0*pq.V - - @amplitude.setter - def amplitude(self, new_val): - new_val = 100*assume_units(new_val, pq.V).rescale(pq.V).magnitude + return float(response.replace(query, ""))/100.0, self.VoltageMode.rms + + def _set_amplitude_(self, new_val, units): + if units == self.VoltageMode.peak_to_peak or \ + units == self.VoltageMode.rms: + new_val = assume_units(new_val, "V").rescale(pq.V).magnitude + elif units == self.VoltageMode.dBm: + raise NotImplementedError("Decibel units are not supported.") + new_val *= 100 query = ":s{0}a{1}".format(self._chan, int(new_val)) - response = self._mhs.query(query) + self._mhs.sendcmd(query) @property def duty_cycle(self): @@ -92,14 +95,15 @@ def duty_cycle(self): def duty_cycle(self, new_val): new_val = assume_units(new_val, pq.s).rescale(pq.s).magnitude query = ":s{0}d{1}".format(self._chan, int(new_val)) - response = self._mhs.query(query) + self._mhs.sendcmd(query) @property def enable(self): """ Gets/Sets the enable state of this channel. - :param bool new_val: the enable state + :param new_val: the enable state + :type: `bool` """ query = ":r{0}b".format(self._chan) return int(self._mhs.query(query).replace(query, ""). @@ -108,7 +112,7 @@ def enable(self): @enable.setter def enable(self, new_val): query = ":s{0}b{1}".format(self._chan, int(new_val)) - response = self._mhs.query(query) + self._mhs.sendcmd(query) @property def frequency(self): @@ -129,16 +133,16 @@ def frequency(self, new_val): new_val = assume_units(new_val, pq.Hz).rescale(pq.Hz).\ magnitude*100.0 query = ":s{0}f{1}".format(self._chan, int(new_val)) - response = self._mhs.query(query) + self._mhs.sendcmd(query) @property def offset(self): """ Gets/Sets the offset of this channel. - :units: As specified (if a `~quantities.Quantity`) or assumed to be - of fraction. - :type: `~quantities.Quantity` + :param new_val: The fraction of the duty cycle to offset the + function by. + :type: `float` """ # need to convert query = ":r{0}o".format(self._chan) @@ -149,7 +153,7 @@ def offset(self): def offset(self, new_val): new_val = int(new_val*100)+120 query = ":s{0}o{1}".format(self._chan, new_val) - response = self._mhs.query(query) + self._mhs.sendcmd(query) @property def phase(self): @@ -163,15 +167,16 @@ def phase(self): # need to convert query = ":r{0}p".format(self._chan) response = self._mhs.query(query) - return int(response.replace(query, "")) + return int(response.replace(query, ""))*pq.deg @phase.setter def phase(self, new_val): + new_val = assume_units(new_val, pq.deg).rescale("deg").magnitude query = ":s{0}p{1}".format(self._chan, int(new_val)) - response = self._mhs.query(query) + self._mhs.sendcmd(query) @property - def wave_type(self): + def function(self): """ Gets/Sets the wave type of this channel. @@ -179,15 +184,15 @@ def wave_type(self): """ query = ":r{0}w".format(self._chan) response = self._mhs.query(query).replace(query, "") - return self._mhs.WaveType(int(response)) + return self._mhs.Function(int(response)) - @wave_type.setter - def wave_type(self, new_val): + @function.setter + def function(self, new_val): query = ":s{0}w{1}".format(self._chan, - self._mhs.WaveType(new_val).value) - response = self._mhs.query(query) + self._mhs.Function(new_val).value) + self._mhs.sendcmd(query) - class WaveType(Enum): + class Function(Enum): """ Enum containing valid wave modes for """ diff --git a/instruments/tests/test_minghe/test_minghe_mhs5200a.py b/instruments/tests/test_minghe/test_minghe_mhs5200a.py index cb71da3f2..cd7632fab 100644 --- a/instruments/tests/test_minghe/test_minghe_mhs5200a.py +++ b/instruments/tests/test_minghe/test_minghe_mhs5200a.py @@ -35,12 +35,27 @@ def test_mhs_amplitude(): ], sep="\n" ) as mhs: - assert mhs.channel[0].amplitude == 3.3*pq.V - assert mhs.channel[1].amplitude == 5.0*pq.V + assert mhs.channel[0].amplitude[0] == 3.3*pq.V + assert mhs.channel[1].amplitude[0] == 5.0*pq.V mhs.channel[0].amplitude = 6.6*pq.V mhs.channel[1].amplitude = 8.0*pq.V +@raises(NotImplementedError) +def test_mhs_amplitude_dbm_notimplemented(): + with expected_protocol( + ik.minghe.MHS5200, + [ + ":s1a660" + ], + [ + "ok" + ], + sep="\n" + ) as mhs: + mhs.channel[0].amplitude = 6.6*ik.units.dBm + + def test_mhs_duty_cycle(): with expected_protocol( ik.minghe.MHS5200, @@ -94,13 +109,13 @@ def test_mhs_frequency(): [ ":r1f", ":r2f", - ":s1f6000", - ":s2f8000" + ":s1f600000", + ":s2f800000" ], [ - ":r1f33000", - ":r2f500000", + ":r1f3300000", + ":r2f50000000", "ok", "ok" ], @@ -178,10 +193,10 @@ def test_mhs_wave_type(): ], sep="\n" ) as mhs: - assert mhs.channel[0].wave_type == mhs.WaveType.sine - assert mhs.channel[1].wave_type == mhs.WaveType.square - mhs.channel[0].wave_type = mhs.WaveType.triangular - mhs.channel[1].wave_type = mhs.WaveType.sawtooth_up + assert mhs.channel[0].function == mhs.Function.sine + assert mhs.channel[1].function == mhs.Function.square + mhs.channel[0].function = mhs.Function.triangular + mhs.channel[1].function = mhs.Function.sawtooth_up def test_mhs_serial_number(): From 07cf48aa808ab27020b23a4b6469c7f0a3bb4c57 Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Sat, 17 Sep 2016 08:33:23 -0700 Subject: [PATCH 6/8] fixed a few docstrings --- instruments/minghe/mhs5200a.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/instruments/minghe/mhs5200a.py b/instruments/minghe/mhs5200a.py index b458d0696..b64c31473 100644 --- a/instruments/minghe/mhs5200a.py +++ b/instruments/minghe/mhs5200a.py @@ -56,13 +56,6 @@ def __init__(self, mhs, idx): self._count = 0 def _get_amplitude_(self): - """ - Gets/Sets the amplitude of this channel. - - :units: As specified (if a `~quantities.Quantity`) or assumed to be - of units volt. - :type: `~quantities.Quantity` - """ query = ":r{0}a".format(self._chan) response = self._mhs.query(query) return float(response.replace(query, ""))/100.0, self.VoltageMode.rms @@ -180,7 +173,7 @@ def function(self): """ Gets/Sets the wave type of this channel. - :type: `MHS5200.WaveType` + :type: `MHS5200.Function` """ query = ":r{0}w".format(self._chan) response = self._mhs.query(query).replace(query, "") From ac6aa9dfcc1376650e284ef22dc384f9a72e151f Mon Sep 17 00:00:00 2001 From: Catherine Holloway Date: Sat, 17 Sep 2016 11:40:00 -0700 Subject: [PATCH 7/8] after testing with device --- doc/examples/minghe/ex_minghe_mhs5200.py | 16 +++++++++++++--- instruments/minghe/mhs5200a.py | 8 ++++++++ .../tests/test_minghe/test_minghe_mhs5200a.py | 18 +++++++++--------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/doc/examples/minghe/ex_minghe_mhs5200.py b/doc/examples/minghe/ex_minghe_mhs5200.py index 55f929875..60b69bedb 100644 --- a/doc/examples/minghe/ex_minghe_mhs5200.py +++ b/doc/examples/minghe/ex_minghe_mhs5200.py @@ -7,12 +7,22 @@ mhs.channel[0].frequency = 3000000*pq.Hz print(mhs.channel[0].frequency) mhs.channel[0].function = MHS5200.Function.sawtooth_down -print(mhs.channel[0].wave_type) -mhs.channel[0].amplitude[0] = 9.0*pq.V +print(mhs.channel[0].function) +mhs.channel[0].amplitude = 9.0*pq.V print(mhs.channel[0].amplitude) mhs.channel[0].offset = -0.5 print(mhs.channel[0].offset) mhs.channel[0].phase = 90 print(mhs.channel[0].phase) -mhs.channel[1].wave_type = MHS5200.Function.sawtooth_up +mhs.channel[1].frequency = 2000000*pq.Hz +print(mhs.channel[1].frequency) +mhs.channel[1].function = MHS5200.Function.square +print(mhs.channel[1].function) +mhs.channel[1].amplitude = 2.0*pq.V +print(mhs.channel[1].amplitude) +mhs.channel[1].offset = 0.0 +print(mhs.channel[1].offset) +mhs.channel[1].phase = 15 +print(mhs.channel[1].phase) + diff --git a/instruments/minghe/mhs5200a.py b/instruments/minghe/mhs5200a.py index b64c31473..1f2c035e2 100644 --- a/instruments/minghe/mhs5200a.py +++ b/instruments/minghe/mhs5200a.py @@ -32,6 +32,14 @@ class MHS5200(Instrument): def __init__(self, filelike): super(MHS5200, self).__init__(filelike) self._channel_count = 2 + self.terminator = "\r\n" + + def _ack_expected(self, msg=""): + if msg.find(":r") == 0: + return None + else: + # most commands res + return "ok" # INNER CLASSES # diff --git a/instruments/tests/test_minghe/test_minghe_mhs5200a.py b/instruments/tests/test_minghe/test_minghe_mhs5200a.py index cd7632fab..34dc2e3e8 100644 --- a/instruments/tests/test_minghe/test_minghe_mhs5200a.py +++ b/instruments/tests/test_minghe/test_minghe_mhs5200a.py @@ -33,7 +33,7 @@ def test_mhs_amplitude(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].amplitude[0] == 3.3*pq.V assert mhs.channel[1].amplitude[0] == 5.0*pq.V @@ -51,7 +51,7 @@ def test_mhs_amplitude_dbm_notimplemented(): [ "ok" ], - sep="\n" + sep="\r\n" ) as mhs: mhs.channel[0].amplitude = 6.6*ik.units.dBm @@ -72,7 +72,7 @@ def test_mhs_duty_cycle(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].duty_cycle == 330.0*pq.s assert mhs.channel[1].duty_cycle == 500.0*pq.s @@ -95,7 +95,7 @@ def test_mhs_enable(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].enable assert not mhs.channel[1].enable @@ -119,7 +119,7 @@ def test_mhs_frequency(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].frequency == 33.0*pq.kHz assert mhs.channel[1].frequency == 500.0*pq.kHz @@ -143,7 +143,7 @@ def test_mhs_offset(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].offset == 0 assert mhs.channel[1].offset == -1.2 @@ -167,7 +167,7 @@ def test_mhs_phase(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].phase == 120 assert mhs.channel[1].phase == 0 @@ -191,7 +191,7 @@ def test_mhs_wave_type(): "ok", "ok" ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.channel[0].function == mhs.Function.sine assert mhs.channel[1].function == mhs.Function.square @@ -209,6 +209,6 @@ def test_mhs_serial_number(): [ ":r0c5225A1", ], - sep="\n" + sep="\r\n" ) as mhs: assert mhs.serial_number == "5225A1" \ No newline at end of file From fa654cc83942eee07e6c19a888715e57eb936f79 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Tue, 27 Sep 2016 09:16:18 -0400 Subject: [PATCH 8/8] Minghe MHS5200 - Add instrument to docs --- doc/source/apiref/minghe.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 doc/source/apiref/minghe.rst diff --git a/doc/source/apiref/minghe.rst b/doc/source/apiref/minghe.rst new file mode 100644 index 000000000..6a1763039 --- /dev/null +++ b/doc/source/apiref/minghe.rst @@ -0,0 +1,15 @@ +.. + TODO: put documentation license header here. + +.. currentmodule:: instruments.minghe + +====== +Minghe +====== + +:class:`MHS5200` Function Generator +=================================== + +.. autoclass:: MHS5200 + :members: + :undoc-members: