Esempio n. 1
0
 def range(self, val):
     rng = unit_scale(str(val))
     if not rng == round(rng, -int(floor(log10(rng)))):
         raise ParameterError()
     if str(rng)[0] != "2":
         raise ParameterError()
     if not 2000e-9 <= rng <= 200e6:
         raise ParameterError()
     self._range = val
     self._write("RANG {}".format(unit_convert(rng, 2, 2000)))
Esempio n. 2
0
    def __init__(self, instrument):
        """
        The self._ values indicate the user values as entered if valid.
        The self.__ values are the sanitised values used internally in the system to parse between functions

        Limitations:
        The function generator switches internal relays at certain thresholds. 
        Try to avoid these ranges in design if the function generator is loaded with a relatively low impedance
        Table of ranges on the same relay arrangement
        Min mVpp    Max mVpp
        4           60
        60.1        199.9
        200	        599.9
        600	        2000
        2001        6000
        6001        20000


        :param instrument:
        :return:
        """
        super().__init__(instrument)
        self.instrument.query_delay = 0.2
        self.instrument.timeout = 1000
        # Rigol Restrictions
        self.__restr_bandwidth = {
            "min": unit_scale("4uHz"),
            "max": unit_scale("20MHz")
        }
        self.__restr_phase = {"min": -180, "max": 180}
        self.__restr_amplitude = {
            "min": unit_scale("4mVpp"),
            "max": unit_scale("20Vpp")
        }
        self._amplitude = None
        self._store = {"ch1_duty": "50", "ch2_duty": "50"}
        self.api = [

            # WAVEFORM SELECTION:
            # Channel 1:
            (
                "channel1.waveform.sin",
                self.store_and_write,
                (
                    "FUNC SIN",  # base_str
                    {
                        "ch1_waveform_handler": None
                    })),  # handler
            ("channel1.waveform.square", self.store_and_write,
             ("FUNC SQU\r\nFUNC:SQU:DCYC {self._store[ch1_duty]}", {
                 "ch1_waveform_handler": "channel1.waveform.square"
             })),
            ("channel1.waveform.ramp", self.store_and_write, ("FUNC RAMP", {
                "ch1_waveform_handler":
                None
            })),
            ("channel1.waveform.pulse", self.store_and_write,
             ("FUNC PULS\r\nPULS:DCYC {self._store[ch1_duty]}", {
                 "ch1_waveform_handler": "channel1.waveform.pulse"
             })),
            ("channel1.waveform.arb", self.store_and_write, ("FUNC USER", {
                "ch1_waveform_handler":
                None
            })),
            ("channel1.waveform.triangle", self.store_and_write, ("FUNC TRI", {
                "ch1_waveform_handler":
                None
            })),
            ("channel1.waveform.noise", self.store_and_write, ("FUNC NOIS", {
                "ch1_waveform_handler":
                None
            })),
            ("channel1.waveform.dc", self.store_and_write, ("FUNC DC", {
                "ch1_waveform_handler":
                None
            })),
            # Channel 2:
            (
                "channel2.waveform.sin",
                self.store_and_write,
                (
                    "FUNC:CH2 SIN",  # base_str
                    {
                        "ch2_waveform_handler": None
                    })),  # handler
            ("channel2.waveform.square", self.store_and_write,
             ("FUNC:CH2 SQU\r\nFUNC:SQU:DCYC:CH2 {self._store[ch2_duty]}", {
                 "ch2_waveform_handler": "channel2.waveform.square"
             })),
            ("channel2.waveform.ramp", self.store_and_write,
             ("FUNC:CH2 RAMP", {
                 "ch2_waveform_handler": None
             })),
            ("channel2.waveform.pulse", self.store_and_write,
             ("FUNC:CH2 PULS\r\nPULS:DCYC {self._store[ch2_duty]}", {
                 "ch2_waveform_handler": "channel2.waveform.pulse"
             })),
            ("channel2.waveform.arb", self.store_and_write, ("FUNC:CH2 USER", {
                "ch2_waveform_handler":
                None
            })),
            ("channel2.waveform.triangle", self.store_and_write,
             ("FUNC:CH2 TRI", {
                 "ch2_waveform_handler": None
             })),
            ("channel2.waveform.noise", self.store_and_write,
             ("FUNC:CH2 NOIS", {
                 "ch2_waveform_handler": None
             })),
            ("channel2.waveform.dc", self.store_and_write, ("FUNC:CH2 DC", {
                "ch2_waveform_handler":
                None
            })),
            # CHANNEL CONFIGURATION:
            # Channel 1:
            ("channel1.vrms", self.write, "VOLT:UNIT VRMS\r\nVOLT {value}"),
            ("channel1.vpp", self.write, "VOLT:UNIT VPP\r\nVOLT {value}"),
            ("channel1.dbm", self.write, "VOLT:UNIT DBM\r\nVOLT {value}"),
            ("channel1.offset", self.write, "VOLT:OFFS {value}"),
            ("channel1.phase", self.write, "PHAS {value}"),
            ("channel1.duty", self.store_and_execute, ({
                "ch1_duty": "{value}"
            }, "ch1_waveform_handler")),
            ("channel1.frequency", self.write, "FREQ {value}"),
            # Channel 2:
            ("channel2.vrms", self.write, "VOLT:UNIT:CH2 VRMS\r\nVOLT {value}"
             ),
            ("channel2.vpp", self.write, "VOLT:UNIT:CH2 VPP\r\nVOLT {value}"),
            ("channel2.dbm", self.write, "VOLT:UNIT:CH2 DBM\r\nVOLT {value}"),
            ("channel2.offset", self.write, "VOLT:OFFS:CH2 {value}"),
            ("channel2.phase", self.write, "PHAS:CH2 {value}"),
            ("channel2.duty", self.store, {
                "ch2_duty": "{value}"
            }),
            ("channel2.frequency", self.write, "FREQ:CH2 {value}"),
            # CHANNEL ACTIVATION:
            ("channel1._call", self.write, "OUTP {value}"
             ),  # True won't work here needs to be ON or 1, OFF or 0
            ("channel2._call", self.write, "OUTP:CH2 {value}"
             ),  # True won't work here needs to be ON or 1, OFF or 0
            # SYNC CONFIGURATION:
            ("sync.polarity.normal", self.write, ""),
            ("sync.mode.normal", self.write, ""),
            ("sync.mode.source", self.write, ""),
            ("sync._call", self.write, "OUTP {value}"),
            # TRIGGER CONFIGURATION:
            ("trigger.immediate", self.write, "TRIG:SOUR IMM"),
            ("trigger.external._call", self.write, "TRIG:SOUR EXT"),
            ("trigger.external.rising", self.write,
             "TRIG:SOUR EXT\r\n TRIG1:SLOP POS"),
            ("trigger.external.falling", self.write,
             "TRIG:SOUR EXT\r\n TRIG1:SLOP NEG"),
            ("trigger.manual", self.write, "TRIG:SOUR BUS"),
            ("trigger.delay", self.write, "TRIG:DEL {seconds}"),
            ("trigger.out.off", self.write, "OUTP:TRIG OFF"),
            ("trigger.out._call", self.write, "OUTP:TRIG {output}"),
            ("trigger.out.rising", self.write, "OUTP:TRIG:SLOP POS"),
            ("trigger.out.falling", self.write, "OUTP:TRIG:SLOP NEG"),
            # Modulate
            # Channel 1:
            ("channel1.modulate.am._call", self.store, {
                "ch1_modulate_state": "AM",
                "ch1_modulate_setting": "FREQ"
            }),
            ("channel1.modulate.fm._call", self.store, {
                "ch1_modulate_state": "FM",
                "ch1_modulate_setting": "FREQ"
            }),
            ("channel1.modulate.pm._call", self.store, {
                "ch1_modulate_state": "PM",
                "ch1_modulate_setting": "FREQ"
            }),
            ("channel1.modulate.fsk._call", self.store, {
                "ch1_modulate_state": "FSK",
                "ch1_modulate_setting": "RATE"
            }),
            ("channel1.modulate.bpsk._call", self.store, {
                "ch1_modulate_state": "BPSK",
                "ch1_modulate_setting": "RATE"
            }),
            ("channel1.modulate.sum._call", self.store, {
                "ch1_modulate_state": "SUM",
                "ch1_modulate_setting": "RATE"
            }),
            # MODULATE SOURCES:
            ("channel1.modulate.source.internal._call", self.store_and_write,
             ("{self._store[ch1_modulate_state]}:SOUR INT", {
                 "ch1_modulate_source": "INT"
             })),
            ("channel1.modulate.source.external", self.store_and_write,
             ("{self._store[ch1_modulate_state]}:SOUR EXT", {
                 "ch1_modulate_source": "EXT"
             })),
            # MODULATE ACTIVATION:
            # Channel 1:
            ("channel1.modulate._call", self.write,
             "{self._store[ch1_modulate_state]}:STAT {value}\r\n{self._store[ch1_modulate_state]}:SOUR"
             "{self._store[ch1_modulate_source]}"),
            # MODULATE OPTIONS:
            # Channel 1:
            ("channel1.modulate.am.depth", self.write, "AM:DEPT {value}"),
            ("channel1.modulate.fm.freq_dev", self.write, "FM:DEV {value}"),
            ("channel1.modulate.pm.phase_dev", self.write, "PM:DEV{value}"),
            ("channel1.modulate.fsk.hop_freq", self.write, "FSK:FREQ {value}"),
            ("channel1.modulate.fsk.rate", self.write, "FSK:INT:RATE {value}"),
            # MODULATE SHAPES:
            # Channel 1:
            ("channel1.modulate.source.internal.shape.sin", self.write,
             "{self._store[ch1_modulate_state]}:INT:FUNC SIN"),
            ("channel1.modulate.source.internal.shape.square", self.write,
             "{self._store[ch1_modulate_state]}:INT:FUNC SQU"),
            ("channel1.modulate.source.internal.shape.triangle", self.write,
             "{self._store[ch1_modulate_state]}:INT:FUNC TRI"),
            ("channel1.modulate.source.internal.shape.up_ramp", self.write,
             "{self._store[ch1_modulate_state]}:INT:FUNC RAMP"),
            ("channel1.modulate.source.internal.shape.down_ramp", self.write,
             "{self._store[ch1_modulate_state]}:INT:FUNC NRAMP"),
            ("channel1.modulate.source.internal.shape.noise", self.write,
             "{self._store[ch1_modulate_state]}:INT:FUNC NOIS"),
            # BURST
            # Channel 1:
            ("channel1.burst.gated._call", self.write, "BURS:MODE GAT"),
            ("channel1.burst._call", self.write, "BURS:STAT {value}"),
            ("channel1.burst.ncycle._call", self.write, "BURS:MODE TRIG"),
            ("channel1.burst.ncycle.cycles._call", self.write,
             "BURS:NCYC {cycles}"),
            ("channel1.burst.ncycle.cycles.infinite", self.write,
             "BURS:NCYC INF"),
            ("channel1.burst.ncycle.burst_period", self.write,
             "BURS:INT:PER {seconds}"),
            ("channel1.burst.gated.positive", self.write,
             "BURS:GATE:POL NORM"),
            ("channel1.burst.gated.negative", self.write, "BURS:GATE:POL INV"),
            ("channel1.burst.phase", self.write, "BURS:PHAS {degrees}"),
            # Modulate Frequency
            ("channel1.modulate.source.internal.frequency", self.write,
             "{self._store[ch1_modulate_state]}:INT:{self._store[ch1_modulate_setting]} {value}"
             ),
            # LOAD:
            # channel1:
            ("channel1.load._call", self.write, "OUTP:LOAD {ohms}"),
            ("channel1.load.infinite", self.write, "OUTP:LOAD INF"),
            # channel2:
            ("channel2.load._call", self.write, "OUTP:LOAD:CH2 {ohms}"),
            ("channel2.load.infinite", self.write, "OUTP:LOAD:CH2 INF"),
        ]

        # -----------------------------------------------------------------------------------------------------------------------

        self.init_api()
Esempio n. 3
0
    def __init__(self, instrument):
        """
        The self._ values indicate the user values as entered if valid.
        The self.__ values are the sanitised values used internally in the system to parse between functions

        Limitations:
        The function generator switches internal relays at certain thresholds.
        Try to avoid these ranges in design if the function generator is loaded with a relatively low impedance
        Table of ranges on the same relay arrangement
        Min mVpp    Max mVpp
        4           60
        60.1        199.9
        200	        599.9
        600	        2000
        2001        6000
        6001        20000


        :param instrument:
        :return:
        """
        super().__init__(instrument)
        self.instrument.query_delay = 0.2
        self.instrument.timeout = 1000
        # Rigol Restrictions
        self.__restr_bandwidth = {
            "min": unit_scale("4uHz"),
            "max": unit_scale("20MHz")
        }
        self.__restr_phase = {"min": -180, "max": 180}
        self.__restr_amplitude = {
            "min": unit_scale("4mVpp"),
            "max": unit_scale("20Vpp"),
        }
        self._amplitude = None
        self._store = {
            "ch1_duty": "50",
            "ch2_duty": "50",
            "ch1_modulate_source": "INT"
        }

        self.api = [
            # waveform selection
            # Channel 1:
            (
                "channel1.waveform.sin",
                self.store_and_write,
                ("SOUR1:FUNC SIN", {
                    "ch1_waveform_handler": None
                }),
            ),
            (
                "channel1.waveform.square",
                self.store_and_write,
                (
                    "SOUR1:FUNC SQU\r\nSOUR1:FUNC:SQU:DCYC {self._store[ch1_duty]}",
                    {
                        "ch1_waveform_handler": "channel1.waveform.square"
                    },
                ),
            ),
            (
                "channel1.waveform.ramp",
                self.store_and_write,
                ("SOUR1:FUNC RAMP", {
                    "ch1_waveform_handler": None
                }),
            ),
            (
                "channel1.waveform.pulse",
                self.store_and_write,
                (
                    "SOUR1:FUNC PULS\r\nPULS:DCYC {self._store[ch1_duty]}",
                    {
                        "ch1_waveform_handler": "channel1.waveform.pulse"
                    },
                ),
            ),
            (
                "channel1.waveform.arb",
                self.store_and_write,
                ("SOUR1:FUNC  ARB", {
                    "ch1_waveform_handler": None
                }),
            ),
            (
                "channel1.waveform.triangle",
                self.store_and_write,
                ("SOUR1:FUNC TRI", {
                    "ch1_waveform_handler": None
                }),
            ),
            (
                "channel1.waveform.noise",
                self.store_and_write,
                ("SOUR1:FUNC NOIS", {
                    "ch1_waveform_handler": None
                }),
            ),
            (
                "channel1.waveform.dc",
                self.store_and_write,
                ("SOUR1:FUNC DC", {
                    "ch1_waveform_handler": None
                }),
            ),
            (
                "channel1.waveform.prbs",
                self.store_and_write,
                ("SOUR1:FUNC PRBS", {
                    "ch1_waveform_handler": None
                }),
            ),
            # Channel Configuration
            # Channel 1:
            ("channel1.vrms", self.write,
             "SOUR1:VOLT:UNIT VRMS\r\nVOLT {value}"),
            ("channel1.vpp", self.write,
             "SOUR1:VOLT:UNIT VPP\r\nVOLT {value}"),
            ("channel1.dbm", self.write,
             "SOUR1:VOLT:UNIT DBM\r\nVOLT {value}"),
            ("channel1.offset", self.write, "SOUR1:VOLT:OFFS {value}"),
            ("channel1.phase", self.write, "SOUR1:PHAS {value}"),
            (
                "channel1.duty",
                self.store_and_execute,
                ({
                    "ch1_duty": "{value}"
                }, "ch1_waveform_handler"),
            ),
            ("channel1.frequency", self.write, "SOUR1:FREQ {value}"),
            # Channel Activation
            ("channel1._call", self.write, "OUTP {value}"),
            # Sync Configuration
            ("sync.polarity.normal", self.write, ""),
            ("sync.mode.normal", self.write, ""),
            # Sync Mode source only works on one. Need to manually override so that only channel 1 being passed works
            ("sync.mode.source", self.write, ""),
            ("sync._call", self.write, "OUTP {value}"),
            # Trigger Configuration
            ("trigger.immediate", self.write, "TRIG1:SOUR IMM"),
            ("trigger.external._call", self.write, "TRIG1:SOUR EXT"),
            (
                "trigger.external.rising",
                self.write,
                "TRIG1:SOUR EXT\r\n TRIG1:SLOP POS",
            ),
            (
                "trigger.external.falling",
                self.write,
                "TRIG1:SOUR EXT\r\n TRIG1:SLOP NEG",
            ),
            ("trigger.manual._call", self.write, "TRIG1:SOUR BUS"),
            ("trigger.manual.initiate", self.write, "TRIG1:SOUR BUS"),
            ("trigger.timer", self.write,
             "TRIG:SOUR TIM\r\n TRIG1:TIM {seconds}"),
            ("trigger.delay", self.write, "TRIG1:DEL {seconds}"),
            ("trigger.out._call", self.write, "OUTP:TRIG"),
            ("trigger.out.off", self.write, "OUTP:TRIG OFF"),
            ("trigger.out.rising", self.write,
             "OUTP:TRIG ON\r\n OUTP:TRIG:SLOP POS"),
            ("trigger.out.falling", self.write,
             "OUTP:TRIG ON\r\n OUTP:TRIG:SLOP NEG"),
            # Modulate
            # Channel 1:
            (
                "channel1.modulate.am._call",
                self.store,
                {
                    "ch1_modulate_state": "AM",
                    "ch1_modulate_setting": "FREQ"
                },
            ),
            (
                "channel1.modulate.fm._call",
                self.store,
                {
                    "ch1_modulate_state": "FM",
                    "ch1_modulate_setting": "FREQ"
                },
            ),
            (
                "channel1.modulate.pm._call",
                self.store,
                {
                    "ch1_modulate_state": "PM",
                    "ch1_modulate_setting": "FREQ"
                },
            ),
            (
                "channel1.modulate.fsk._call",
                self.store,
                {
                    "ch1_modulate_state": "FSK",
                    "ch1_modulate_setting": "RATE"
                },
            ),
            (
                "channel1.modulate.bpsk._call",
                self.store,
                {
                    "ch1_modulate_state": "BPSK",
                    "ch1_modulate_setting": "RATE"
                },
            ),
            (
                "channel1.modulate.sum._call",
                self.store,
                {
                    "ch1_modulate_state": "SUM",
                    "ch1_modulate_setting": "FREQ"
                },
            ),
            # MODULATE SOURCES:
            (
                "channel1.modulate.source.internal._call",
                self.write,
                "SOUR1:{self._store[ch1_modulate_state]}:"
                "SOUR INT",
            ),
            (
                "channel1.modulate.source.external",
                self.write,
                "SOUR1:{self._store[ch1_modulate_state]}:SOUR EXT",
            ),
            # MODULATE ACTIVATION:
            # Channel 1:
            (
                "channel1.modulate._call",
                self.write,
                "{self._store[ch1_modulate_state]}:SOUR {self._store[ch1_modulate_source]}\r\n"
                "{self._store[ch1_modulate_state]}:STAT {value}",
            ),
            # MODULATE OPTIONS:
            # Channel 1:
            ("channel1.modulate.am.depth", self.write, "SOUR1:AM:DEPT {value}"
             ),
            ("channel1.modulate.am.dssc", self.write, "SOUR1:AM:DSSC ON"),
            ("channel1.modulate.fm.freq_dev", self.write,
             "SOUR1:FM:DEV {value}"),
            ("channel1.modulate.pm.phase_dev", self.write,
             "SOUR1:PM:DEV {value}"),
            ("channel1.modulate.fsk.hop_freq", self.write,
             "SOUR1:FSK:FREQ {value}"),
            ("channel1.modulate.fsk.rate", self.write,
             "SOUR1:FSK:INT:RATE {value}"),
            (
                "channel1.modulate.sum.modulate_percent",
                self.write,
                "SOUR1:SUM:AMPL {percent}",
            ),
            # Internal
            (
                "channel1.modulate.source.internal.shape.sin",
                self.write,
                "{self._store[ch1_modulate_state]}:INT:FUNC SIN",
            ),
            (
                "channel1.modulate.source.internal.shape.square",
                self.write,
                "{self._store[ch1_modulate_state]}:INT:FUNC SQU",
            ),
            (
                "channel1.modulate.source.internal.shape.triangle",
                self.write,
                "{self._store[ch1_modulate_state]}:INT:FUNC TRI",
            ),
            (
                "channel1.modulate.source.internal.shape.up_ramp",
                self.write,
                "{self._store[ch1_modulate_state]}:INT:FUNC RAMP",
            ),
            (
                "channel1.modulate.source.internal.shape.down_ramp",
                self.write,
                "{self._store[ch1_modulate_state]}:INT:FUNC NRAMP",
            ),
            (
                "channel1.modulate.source.internal.shape.noise",
                self.write,
                "{self._store[ch1_modulate_state]}:INT:FUNC NOIS",
            ),
            # Modulate Frequency
            (
                "channel1.modulate.source.internal.frequency",
                self.write,
                "SOUR1:{self._store[ch1_modulate_state]}:INT:{self._store[ch1_modulate_setting]} {value}",
            ),
            # LOAD:
            # channel1:
            ("channel1.load._call", self.write, "OUTP1:LOAD {ohms}"),
            ("channel1.load.infinite", self.write, "OUTP1:LOAD INF"),
            # BURST
            # Channel 1:
            ("channel1.burst.gated._call", self.write, "SOUR1:BURS:MODE GAT"),
            ("channel1.burst._call", self.write, "SOUR1:BURS:STAT {value}"),
            ("channel1.burst.ncycle._call", self.write,
             "SOUR1:BURS:MODE TRIG"),
            (
                "channel1.burst.ncycle.cycles._call",
                self.write,
                "SOUR1:BURS:NCYC {cycles}",
            ),
            (
                "channel1.burst.ncycle.cycles.infinite",
                self.write,
                "SOUR1:BURS:NCYC INF",
            ),
            (
                "channel1.burst.ncycle.burst_period",
                self.write,
                "SOUR1:BURS:INT:PER {seconds}",
            ),
            ("channel1.burst.gated.positive", self.write,
             "SOUR1:BURS:GATE:POL NORM"),
            ("channel1.burst.gated.negative", self.write,
             "SOUR1:BURS:GATE:POL INV"),
            ("channel1.burst.phase", self.write, "SOUR1:BURS:PHAS {degrees}"),
        ]

        # ----------------------------------------------------------------------------------------------------------------------

        self.init_api()
Esempio n. 4
0
 def test_none(self):
     self.assertEqual(unit_scale(None), None)
Esempio n. 5
0
 def test_mega_scale(self):
     self.assertAlmostEqual(unit_scale("10MV", ["V"]), 10e6)
Esempio n. 6
0
 def test_invalid_string(self):
     with self.assertRaises(InvalidScalarQuantityError):
         self.assertEqual(unit_scale("blah 4 uAsd", ["V"]), 10e0)
Esempio n. 7
0
 def test_milli_scale(self):
     self.assertAlmostEqual(unit_scale("10mV", ["V"]), 10e-3)
Esempio n. 8
0
 def test_number_invalid_unit(self):
     with self.assertRaises(InvalidScalarQuantityError):
         self.assertEqual(unit_scale("10kHz", ["V"]), 10e3)
Esempio n. 9
0
 def test_number_in_unit_set(self):
     self.assertEqual(unit_scale("10kHz", ["V", "Hz"]), 10e3)
Esempio n. 10
0
 def test_no_scale_no_units(self):
     self.assertEqual(unit_scale("10", ["V"]), 10e0)
Esempio n. 11
0
 def test_number_invalid_suffix(self):
     with self.assertRaises(InvalidScalarQuantityError):
         self.assertEqual(unit_scale("10 abcd", ["V"]), 10e0)
Esempio n. 12
0
 def test_giga_scale_no_units(self):
     self.assertAlmostEqual(unit_scale("10G", ["V"]), 10e9)
Esempio n. 13
0
 def test_nano_scale_no_units(self):
     self.assertAlmostEqual(unit_scale("10n", ["V"]), 10e-9)
Esempio n. 14
0
 def test_micro_scale_no_units(self):
     self.assertAlmostEqual(unit_scale("10u", ["V"]), 10e-6)
Esempio n. 15
0
 def test_kilo_scale_no_units(self):
     self.assertAlmostEqual(unit_scale("10k", ["V"]), 10e3)
Esempio n. 16
0
 def test_no_scale(self):
     self.assertEqual(unit_scale("10V", ["V"]), 10)