We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
bug: decadac getting and setting voltages fails unpredictably
### Steps to reproduce
1. start Harvard Decadac and  import a qcodes instrument instrument:

```
from qcodes.instrument_drivers.Harvard.Decadac import Decadac
sl0 = Decadac('dec_slot_0', port=5, slot=0)
```

2. run 

`sl0.ch1_voltage(0)`

3. fail as below, seems like its something to do with the mode (which is set in the init but somehow that isn't reliable), It is also not super reliable to fix by setting the mode to 1 but seems to work if I set it to 0 and back to 1 a few times...

### Expected behaviour
should set the voltage

### Actual behaviour
```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-18-e543db036233> in <module>()
----> 1 sl0.ch1_voltage(0)

a:\qcodes\qcodes\instrument\parameter.py in __call__(self, *args)
    133         else:
    134             if self.has_set:
--> 135                 self.set(*args)
    136             else:
    137                 raise NotImplementedError('no set cmd found in' +

a:\qcodes\qcodes\instrument\parameter.py in _validate_and_sweep(self, value)
    945             e.args = e.args + (
    946                 'setting {} to {}'.format(self.full_name, repr(value)),)
--> 947             raise e
    948 
    949     def set_step(self, step, max_val_age=None):

a:\qcodes\qcodes\instrument\parameter.py in _validate_and_sweep(self, value)
    929             step_clock = time.perf_counter()
    930 
--> 931             for step_val in self._sweep_steps(value):
    932                 self._set(step_val)
    933                 self._save_val(step_val)

a:\qcodes\qcodes\instrument\parameter.py in _sweep_steps(self, value)
    891         state = self._latest()
    892         if state['ts'] is None or state['ts'] < oldest_ok_val:
--> 893             start_value = self.get()
    894         else:
    895             start_value = state['value']

a:\qcodes\qcodes\instrument\parameter.py in get(self)
    826         except Exception as e:
    827             e.args = e.args + ('getting {}'.format(self.full_name),)
--> 828             raise e
    829 
    830     def _valmapping_get_parser(self, val):

a:\qcodes\qcodes\instrument\parameter.py in get(self)
    821     def get(self):
    822         try:
--> 823             value = self._get()
    824             self._save_val(value)
    825             return value

a:\qcodes\qcodes\utils\command.py in __call__(self, *args)
    175             raise TypeError(
    176                 'command takes exactly {} args'.format(self.arg_count))
--> 177         return self.exec_function(*args)

a:\qcodes\qcodes\instrument_drivers\Harvard\Decadac.py in _getvoltage(self, channel)
    129         response = temp[::-1]
    130 
--> 131         rawvoltage = self._code2voltage(response, channel)
    132         actualvoltage = rawvoltage - self._offsets[channel]
    133 

a:\qcodes\qcodes\instrument_drivers\Harvard\Decadac.py in _code2voltage(self, code, channel)
    232         """
    233 
--> 234         code = float(code)
    235         translationdict = {1: lambda x: (x+1)*20/2**16-10,
    236                            2: lambda x: (x+1)*10/2**16,

ValueError: ("could not convert string to float: '0! M 0'", 'getting dec_slot_0_ch1_voltage', 'setting dec_slot_0_ch1_voltage to 0')
```

@WilliamHPNielsen @giulioungaretti 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `qcodes/instrument_drivers/Harvard/Decadac.py`
Content:
```
1 import logging
2 from time import sleep
3 from functools import partial
4 from qcodes.instrument.visa import VisaInstrument
5 from qcodes.utils import validators as vals
6 
7 log = logging.getLogger(__name__)
8 
9 
10 class Decadac(VisaInstrument):
11     """
12     The qcodes driver for the Decadac.
13     Each slot on the Deacadac is to be treated as a seperate
14     four-channel instrument.
15 
16     Tested with a Decadec firmware revion number 14081 (Decadac 139).
17 
18     The message strategy is the following: always keep the queue empty, so
19     that self.visa_handle.ask(XXX) will return the answer to XXX and not
20     some previous event.
21 
22 
23     Attributes:
24 
25         _ramp_state (bool): If True, ramp state is ON. Default False.
26 
27         _ramp_time (int): The ramp time in ms. Default 100 ms.
28     """
29 
30     def __init__(self, name, port, slot, timeout=2, baudrate=9600,
31                  bytesize=8, **kwargs):
32 
33         """
34 
35         Creates an instance of the Decadac instrument corresponding to one slot
36         on the physical instrument.
37 
38         Args:
39             name (str): What this instrument is called locally.
40 
41             port (number): The number (only) of the COM port to connect to.
42 
43             slot (int): The slot to use.
44 
45             timeout (number): Seconds to wait for message response.
46             Default 0.3.
47 
48             baudrate (number): The connection baudrate. Default 9600.
49 
50             bytesize (number): The connection bytesize. Default 8.
51         """
52 
53         address = 'ASRL{:d}::INSTR'.format(port)
54         self.slot = slot
55 
56         super().__init__(name, address, timeout=timeout, **kwargs)
57 
58         # set instrument operation state variables
59         self._ramp_state = False
60         self._ramp_time = 100
61         self._voltranges = [1, 1, 1, 1]
62         self._offsets = [0, 0, 0, 0]
63 
64         # channels
65         for channelno in range(4):
66             self.add_parameter('ch{}_voltage'.format(channelno),
67                                get_cmd=partial(self._getvoltage,
68                                                channel=channelno),
69                                set_cmd=partial(self._setvoltage,
70                                                channel=channelno),
71                                label='Voltage',
72                                unit='V')
73 
74             self.add_parameter('ch{}_voltrange'.format(channelno),
75                                get_cmd=partial(self._getvoltrange, channelno),
76                                set_cmd=partial(self._setvoltrange, channelno),
77                                vals=vals.Enum(1, 2, 3))
78 
79             self.add_parameter('ch{}_offset'.format(channelno),
80                                get_cmd=partial(self._getoffset, channelno),
81                                set_cmd=partial(self._setoffset, channelno),
82                                label='Channel {} offset'.format(channelno),
83                                unit='V',
84                                docstring="""
85                                          The offset is applied to the channel.
86                                          E.g. if ch1_offset = 1 and ch_voltage
87                                          is set to 1, the instrument is told to
88                                          output 2 volts.
89                                          """)
90 
91         self.add_parameter('mode',
92                            label='Output mode',
93                            set_cmd='B {}; M {};'.format(self.slot, '{}'),
94                            vals=vals.Enum(0, 1),
95                            docstring="""
96                                      The operational mode of the slot.
97                                      0: output off, 1: output on.
98                                      """)
99 
100         # initialise hardware settings
101         self.mode.set(1)
102 
103     def _getoffset(self, n):
104         return self._offsets[n]
105 
106     def _setoffset(self, n, val):
107         self._offsets[n] = val
108 
109     def _getvoltrange(self, n):
110         return self._voltranges[n]
111 
112     def _setvoltrange(self, n, val):
113         self._voltranges[n] = val
114 
115     def _getvoltage(self, channel):
116         """
117         Function to query the voltage. Flushes the message queue in that
118         process.
119         """
120 
121         # set the relevant channel and slot to query
122         mssg = 'B {:d}; C {:d};'.format(self.slot, channel)
123         mssg += 'd;'
124 
125         # a bit of string juggling to extract the voltage
126         rawresponse = self.visa_handle.ask(mssg)
127         temp = rawresponse[::-1]
128         temp = temp[3:temp.upper().find('D')-1]
129         response = temp[::-1]
130 
131         rawvoltage = self._code2voltage(response, channel)
132         actualvoltage = rawvoltage - self._offsets[channel]
133 
134         return actualvoltage
135 
136     def _setvoltage(self, voltage, channel):
137         """
138         Function to set the voltage. Depending on whether self._ramp_state is
139         True or False, this function either ramps from the current voltage to
140         the specified voltage or directly makes the voltage jump there.
141 
142         Args:
143             voltage (number): the set voltage.
144         """
145 
146         actualvoltage = voltage + self._offsets[channel]
147         code = self._voltage2code(actualvoltage, channel)
148 
149         mssg = 'B {:d}; C {:d};'.format(self.slot, channel)
150 
151         if not self._ramp_state:
152             mssg += 'D ' + code + ';'
153 
154             self.visa_handle.write(mssg)
155 
156             # due to a quirk of the Decadac, we spare the user of an error
157             # sometimes encountered on first run
158             try:
159                 self.visa_handle.read()
160             except UnicodeDecodeError:
161                 log.warning(" Decadac returned nothing and possibly did nothing. " +
162                             "Please re-run the command")
163                 pass
164 
165         if self._ramp_state:
166             currentcode = self._voltage2code(self._getvoltage(channel),
167                                              channel)
168             slope = int((float(code)-float(currentcode)) /
169                         (10*self._ramp_time)*2**16)
170             if slope < 0:
171                 limit = 'L'
172             else:
173                 limit = 'U'
174 
175             script = ['{',
176                       '*1:',
177                       'M2;',
178                       'T 100;',  # 1 timestep: 100 micro s
179                       limit + code + ';',
180                       'S' + str(slope) + ';',
181                       'X0;',
182                       '}']
183             runcmd = 'X 1;'
184             mssg += ''.join(script) + runcmd
185             self.visa_handle.write(mssg)
186             sleep(0.0015*self._ramp_time)  # Required sleep.
187             self.visa_handle.read()
188 
189             # reset channel voltage ranges
190             if slope < 0:
191                 self.visa_handle.write('L 0;')
192                 self.visa_handle.read()
193             else:
194                 self.visa_handle.write('U 65535;')
195                 self.visa_handle.read()
196 
197     def set_ramping(self, state, time=None):
198         """
199         Function to set _ramp_state and _ramp_time.
200 
201         Args:
202             state (bool): True sets ramping ON.
203 
204             time (Optiona[int]): the ramp time in ms
205         """
206         self._ramp_state = state
207         if time is not None:
208             self._ramp_time = time
209 
210     def get_ramping(self):
211         """
212         Queries the value of self._ramp_state and self._ramp_time.
213 
214         Returns:
215             str: ramp state information
216         """
217         switch = {True: 'ON',
218                   False: 'OFF'}
219         mssg = 'Ramp state: ' + switch[self._ramp_state]
220         mssg += '. Ramp time: {:d} ms.'.format(int(self._ramp_time))
221         return mssg
222 
223     def _code2voltage(self, code, channel):
224         """
225         Helper function translating a 32 bit code used internally by
226         the Decadac into a voltage.
227 
228         Args:
229             code (str): The code string from the instrument.
230 
231             channel (int): The relevant channel.
232         """
233 
234         code = float(code)
235         translationdict = {1: lambda x: (x+1)*20/2**16-10,
236                            2: lambda x: (x+1)*10/2**16,
237                            3: lambda x: (x+1)*10/2**16-10}
238 
239         return translationdict[self._voltranges[channel]](code)
240 
241     def _voltage2code(self, voltage, channel):
242         """
243         Helper function translating a voltage in V into a 32 bit code used
244         internally by the Decadac.
245 
246         Args:
247             voltage (float): The physical voltage.
248 
249             channel (int): The relevant channel.
250 
251         Returns:
252             code (str): The corresponding voltage code.
253         """
254         translationdict = {1: lambda x: 2**16/20*(x-2**-16+10),
255                            2: lambda x: 2**16/10*(x-2**-16),
256                            3: lambda x: 2**16/10*(x-2**-16+10)}
257         voltage_float = translationdict[self._voltranges[channel]](voltage)
258         return str(int(voltage_float))
259 
260
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/qcodes/instrument_drivers/Harvard/Decadac.py b/qcodes/instrument_drivers/Harvard/Decadac.py
--- a/qcodes/instrument_drivers/Harvard/Decadac.py
+++ b/qcodes/instrument_drivers/Harvard/Decadac.py
@@ -90,15 +90,23 @@
 
         self.add_parameter('mode',
                            label='Output mode',
-                           set_cmd='B {}; M {};'.format(self.slot, '{}'),
-                           vals=vals.Enum(0, 1),
+                           set_cmd=partial(self._setmode, self.slot),
+                           vals=vals.Enum(0, 2),
                            docstring="""
                                      The operational mode of the slot.
-                                     0: output off, 1: output on.
+                                     0: output off,
+                                     2: 4-channel (low res) mode.
                                      """)
 
         # initialise hardware settings
-        self.mode.set(1)
+        self.mode.set(2)
+
+    def _setmode(slot, mode):
+        """
+        set_cmd for the mode parameter
+        """
+        self.visa_handle.write('B {}; M {};'.format(slot, mode)
+        self.visa_handle.read()
 
     def _getoffset(self, n):
         return self._offsets[n]
@@ -256,4 +264,3 @@
                            3: lambda x: 2**16/10*(x-2**-16+10)}
         voltage_float = translationdict[self._voltranges[channel]](voltage)
         return str(int(voltage_float))
-

{"golden_diff": "diff --git a/qcodes/instrument_drivers/Harvard/Decadac.py b/qcodes/instrument_drivers/Harvard/Decadac.py\n--- a/qcodes/instrument_drivers/Harvard/Decadac.py\n+++ b/qcodes/instrument_drivers/Harvard/Decadac.py\n@@ -90,15 +90,23 @@\n \n         self.add_parameter('mode',\n                            label='Output mode',\n-                           set_cmd='B {}; M {};'.format(self.slot, '{}'),\n-                           vals=vals.Enum(0, 1),\n+                           set_cmd=partial(self._setmode, self.slot),\n+                           vals=vals.Enum(0, 2),\n                            docstring=\"\"\"\n                                      The operational mode of the slot.\n-                                     0: output off, 1: output on.\n+                                     0: output off,\n+                                     2: 4-channel (low res) mode.\n                                      \"\"\")\n \n         # initialise hardware settings\n-        self.mode.set(1)\n+        self.mode.set(2)\n+\n+    def _setmode(slot, mode):\n+        \"\"\"\n+        set_cmd for the mode parameter\n+        \"\"\"\n+        self.visa_handle.write('B {}; M {};'.format(slot, mode)\n+        self.visa_handle.read()\n \n     def _getoffset(self, n):\n         return self._offsets[n]\n@@ -256,4 +264,3 @@\n                            3: lambda x: 2**16/10*(x-2**-16+10)}\n         voltage_float = translationdict[self._voltranges[channel]](voltage)\n         return str(int(voltage_float))\n-\n", "issue": "bug: decadac getting and setting voltages fails unpredictably\n### Steps to reproduce\r\n1. start Harvard Decadac and  import a qcodes instrument instrument:\r\n\r\n```\r\nfrom qcodes.instrument_drivers.Harvard.Decadac import Decadac\r\nsl0 = Decadac('dec_slot_0', port=5, slot=0)\r\n```\r\n\r\n2. run \r\n\r\n`sl0.ch1_voltage(0)`\r\n\r\n3. fail as below, seems like its something to do with the mode (which is set in the init but somehow that isn't reliable), It is also not super reliable to fix by setting the mode to 1 but seems to work if I set it to 0 and back to 1 a few times...\r\n\r\n### Expected behaviour\r\nshould set the voltage\r\n\r\n### Actual behaviour\r\n```\r\n---------------------------------------------------------------------------\r\nValueError                                Traceback (most recent call last)\r\n<ipython-input-18-e543db036233> in <module>()\r\n----> 1 sl0.ch1_voltage(0)\r\n\r\na:\\qcodes\\qcodes\\instrument\\parameter.py in __call__(self, *args)\r\n    133         else:\r\n    134             if self.has_set:\r\n--> 135                 self.set(*args)\r\n    136             else:\r\n    137                 raise NotImplementedError('no set cmd found in' +\r\n\r\na:\\qcodes\\qcodes\\instrument\\parameter.py in _validate_and_sweep(self, value)\r\n    945             e.args = e.args + (\r\n    946                 'setting {} to {}'.format(self.full_name, repr(value)),)\r\n--> 947             raise e\r\n    948 \r\n    949     def set_step(self, step, max_val_age=None):\r\n\r\na:\\qcodes\\qcodes\\instrument\\parameter.py in _validate_and_sweep(self, value)\r\n    929             step_clock = time.perf_counter()\r\n    930 \r\n--> 931             for step_val in self._sweep_steps(value):\r\n    932                 self._set(step_val)\r\n    933                 self._save_val(step_val)\r\n\r\na:\\qcodes\\qcodes\\instrument\\parameter.py in _sweep_steps(self, value)\r\n    891         state = self._latest()\r\n    892         if state['ts'] is None or state['ts'] < oldest_ok_val:\r\n--> 893             start_value = self.get()\r\n    894         else:\r\n    895             start_value = state['value']\r\n\r\na:\\qcodes\\qcodes\\instrument\\parameter.py in get(self)\r\n    826         except Exception as e:\r\n    827             e.args = e.args + ('getting {}'.format(self.full_name),)\r\n--> 828             raise e\r\n    829 \r\n    830     def _valmapping_get_parser(self, val):\r\n\r\na:\\qcodes\\qcodes\\instrument\\parameter.py in get(self)\r\n    821     def get(self):\r\n    822         try:\r\n--> 823             value = self._get()\r\n    824             self._save_val(value)\r\n    825             return value\r\n\r\na:\\qcodes\\qcodes\\utils\\command.py in __call__(self, *args)\r\n    175             raise TypeError(\r\n    176                 'command takes exactly {} args'.format(self.arg_count))\r\n--> 177         return self.exec_function(*args)\r\n\r\na:\\qcodes\\qcodes\\instrument_drivers\\Harvard\\Decadac.py in _getvoltage(self, channel)\r\n    129         response = temp[::-1]\r\n    130 \r\n--> 131         rawvoltage = self._code2voltage(response, channel)\r\n    132         actualvoltage = rawvoltage - self._offsets[channel]\r\n    133 \r\n\r\na:\\qcodes\\qcodes\\instrument_drivers\\Harvard\\Decadac.py in _code2voltage(self, code, channel)\r\n    232         \"\"\"\r\n    233 \r\n--> 234         code = float(code)\r\n    235         translationdict = {1: lambda x: (x+1)*20/2**16-10,\r\n    236                            2: lambda x: (x+1)*10/2**16,\r\n\r\nValueError: (\"could not convert string to float: '0! M 0'\", 'getting dec_slot_0_ch1_voltage', 'setting dec_slot_0_ch1_voltage to 0')\r\n```\r\n\r\n@WilliamHPNielsen @giulioungaretti \n", "before_files": [{"content": "import logging\nfrom time import sleep\nfrom functools import partial\nfrom qcodes.instrument.visa import VisaInstrument\nfrom qcodes.utils import validators as vals\n\nlog = logging.getLogger(__name__)\n\n\nclass Decadac(VisaInstrument):\n    \"\"\"\n    The qcodes driver for the Decadac.\n    Each slot on the Deacadac is to be treated as a seperate\n    four-channel instrument.\n\n    Tested with a Decadec firmware revion number 14081 (Decadac 139).\n\n    The message strategy is the following: always keep the queue empty, so\n    that self.visa_handle.ask(XXX) will return the answer to XXX and not\n    some previous event.\n\n\n    Attributes:\n\n        _ramp_state (bool): If True, ramp state is ON. Default False.\n\n        _ramp_time (int): The ramp time in ms. Default 100 ms.\n    \"\"\"\n\n    def __init__(self, name, port, slot, timeout=2, baudrate=9600,\n                 bytesize=8, **kwargs):\n\n        \"\"\"\n\n        Creates an instance of the Decadac instrument corresponding to one slot\n        on the physical instrument.\n\n        Args:\n            name (str): What this instrument is called locally.\n\n            port (number): The number (only) of the COM port to connect to.\n\n            slot (int): The slot to use.\n\n            timeout (number): Seconds to wait for message response.\n            Default 0.3.\n\n            baudrate (number): The connection baudrate. Default 9600.\n\n            bytesize (number): The connection bytesize. Default 8.\n        \"\"\"\n\n        address = 'ASRL{:d}::INSTR'.format(port)\n        self.slot = slot\n\n        super().__init__(name, address, timeout=timeout, **kwargs)\n\n        # set instrument operation state variables\n        self._ramp_state = False\n        self._ramp_time = 100\n        self._voltranges = [1, 1, 1, 1]\n        self._offsets = [0, 0, 0, 0]\n\n        # channels\n        for channelno in range(4):\n            self.add_parameter('ch{}_voltage'.format(channelno),\n                               get_cmd=partial(self._getvoltage,\n                                               channel=channelno),\n                               set_cmd=partial(self._setvoltage,\n                                               channel=channelno),\n                               label='Voltage',\n                               unit='V')\n\n            self.add_parameter('ch{}_voltrange'.format(channelno),\n                               get_cmd=partial(self._getvoltrange, channelno),\n                               set_cmd=partial(self._setvoltrange, channelno),\n                               vals=vals.Enum(1, 2, 3))\n\n            self.add_parameter('ch{}_offset'.format(channelno),\n                               get_cmd=partial(self._getoffset, channelno),\n                               set_cmd=partial(self._setoffset, channelno),\n                               label='Channel {} offset'.format(channelno),\n                               unit='V',\n                               docstring=\"\"\"\n                                         The offset is applied to the channel.\n                                         E.g. if ch1_offset = 1 and ch_voltage\n                                         is set to 1, the instrument is told to\n                                         output 2 volts.\n                                         \"\"\")\n\n        self.add_parameter('mode',\n                           label='Output mode',\n                           set_cmd='B {}; M {};'.format(self.slot, '{}'),\n                           vals=vals.Enum(0, 1),\n                           docstring=\"\"\"\n                                     The operational mode of the slot.\n                                     0: output off, 1: output on.\n                                     \"\"\")\n\n        # initialise hardware settings\n        self.mode.set(1)\n\n    def _getoffset(self, n):\n        return self._offsets[n]\n\n    def _setoffset(self, n, val):\n        self._offsets[n] = val\n\n    def _getvoltrange(self, n):\n        return self._voltranges[n]\n\n    def _setvoltrange(self, n, val):\n        self._voltranges[n] = val\n\n    def _getvoltage(self, channel):\n        \"\"\"\n        Function to query the voltage. Flushes the message queue in that\n        process.\n        \"\"\"\n\n        # set the relevant channel and slot to query\n        mssg = 'B {:d}; C {:d};'.format(self.slot, channel)\n        mssg += 'd;'\n\n        # a bit of string juggling to extract the voltage\n        rawresponse = self.visa_handle.ask(mssg)\n        temp = rawresponse[::-1]\n        temp = temp[3:temp.upper().find('D')-1]\n        response = temp[::-1]\n\n        rawvoltage = self._code2voltage(response, channel)\n        actualvoltage = rawvoltage - self._offsets[channel]\n\n        return actualvoltage\n\n    def _setvoltage(self, voltage, channel):\n        \"\"\"\n        Function to set the voltage. Depending on whether self._ramp_state is\n        True or False, this function either ramps from the current voltage to\n        the specified voltage or directly makes the voltage jump there.\n\n        Args:\n            voltage (number): the set voltage.\n        \"\"\"\n\n        actualvoltage = voltage + self._offsets[channel]\n        code = self._voltage2code(actualvoltage, channel)\n\n        mssg = 'B {:d}; C {:d};'.format(self.slot, channel)\n\n        if not self._ramp_state:\n            mssg += 'D ' + code + ';'\n\n            self.visa_handle.write(mssg)\n\n            # due to a quirk of the Decadac, we spare the user of an error\n            # sometimes encountered on first run\n            try:\n                self.visa_handle.read()\n            except UnicodeDecodeError:\n                log.warning(\" Decadac returned nothing and possibly did nothing. \" +\n                            \"Please re-run the command\")\n                pass\n\n        if self._ramp_state:\n            currentcode = self._voltage2code(self._getvoltage(channel),\n                                             channel)\n            slope = int((float(code)-float(currentcode)) /\n                        (10*self._ramp_time)*2**16)\n            if slope < 0:\n                limit = 'L'\n            else:\n                limit = 'U'\n\n            script = ['{',\n                      '*1:',\n                      'M2;',\n                      'T 100;',  # 1 timestep: 100 micro s\n                      limit + code + ';',\n                      'S' + str(slope) + ';',\n                      'X0;',\n                      '}']\n            runcmd = 'X 1;'\n            mssg += ''.join(script) + runcmd\n            self.visa_handle.write(mssg)\n            sleep(0.0015*self._ramp_time)  # Required sleep.\n            self.visa_handle.read()\n\n            # reset channel voltage ranges\n            if slope < 0:\n                self.visa_handle.write('L 0;')\n                self.visa_handle.read()\n            else:\n                self.visa_handle.write('U 65535;')\n                self.visa_handle.read()\n\n    def set_ramping(self, state, time=None):\n        \"\"\"\n        Function to set _ramp_state and _ramp_time.\n\n        Args:\n            state (bool): True sets ramping ON.\n\n            time (Optiona[int]): the ramp time in ms\n        \"\"\"\n        self._ramp_state = state\n        if time is not None:\n            self._ramp_time = time\n\n    def get_ramping(self):\n        \"\"\"\n        Queries the value of self._ramp_state and self._ramp_time.\n\n        Returns:\n            str: ramp state information\n        \"\"\"\n        switch = {True: 'ON',\n                  False: 'OFF'}\n        mssg = 'Ramp state: ' + switch[self._ramp_state]\n        mssg += '. Ramp time: {:d} ms.'.format(int(self._ramp_time))\n        return mssg\n\n    def _code2voltage(self, code, channel):\n        \"\"\"\n        Helper function translating a 32 bit code used internally by\n        the Decadac into a voltage.\n\n        Args:\n            code (str): The code string from the instrument.\n\n            channel (int): The relevant channel.\n        \"\"\"\n\n        code = float(code)\n        translationdict = {1: lambda x: (x+1)*20/2**16-10,\n                           2: lambda x: (x+1)*10/2**16,\n                           3: lambda x: (x+1)*10/2**16-10}\n\n        return translationdict[self._voltranges[channel]](code)\n\n    def _voltage2code(self, voltage, channel):\n        \"\"\"\n        Helper function translating a voltage in V into a 32 bit code used\n        internally by the Decadac.\n\n        Args:\n            voltage (float): The physical voltage.\n\n            channel (int): The relevant channel.\n\n        Returns:\n            code (str): The corresponding voltage code.\n        \"\"\"\n        translationdict = {1: lambda x: 2**16/20*(x-2**-16+10),\n                           2: lambda x: 2**16/10*(x-2**-16),\n                           3: lambda x: 2**16/10*(x-2**-16+10)}\n        voltage_float = translationdict[self._voltranges[channel]](voltage)\n        return str(int(voltage_float))\n\n", "path": "qcodes/instrument_drivers/Harvard/Decadac.py"}], "after_files": [{"content": "import logging\nfrom time import sleep\nfrom functools import partial\nfrom qcodes.instrument.visa import VisaInstrument\nfrom qcodes.utils import validators as vals\n\nlog = logging.getLogger(__name__)\n\n\nclass Decadac(VisaInstrument):\n    \"\"\"\n    The qcodes driver for the Decadac.\n    Each slot on the Deacadac is to be treated as a seperate\n    four-channel instrument.\n\n    Tested with a Decadec firmware revion number 14081 (Decadac 139).\n\n    The message strategy is the following: always keep the queue empty, so\n    that self.visa_handle.ask(XXX) will return the answer to XXX and not\n    some previous event.\n\n\n    Attributes:\n\n        _ramp_state (bool): If True, ramp state is ON. Default False.\n\n        _ramp_time (int): The ramp time in ms. Default 100 ms.\n    \"\"\"\n\n    def __init__(self, name, port, slot, timeout=2, baudrate=9600,\n                 bytesize=8, **kwargs):\n\n        \"\"\"\n\n        Creates an instance of the Decadac instrument corresponding to one slot\n        on the physical instrument.\n\n        Args:\n            name (str): What this instrument is called locally.\n\n            port (number): The number (only) of the COM port to connect to.\n\n            slot (int): The slot to use.\n\n            timeout (number): Seconds to wait for message response.\n            Default 0.3.\n\n            baudrate (number): The connection baudrate. Default 9600.\n\n            bytesize (number): The connection bytesize. Default 8.\n        \"\"\"\n\n        address = 'ASRL{:d}::INSTR'.format(port)\n        self.slot = slot\n\n        super().__init__(name, address, timeout=timeout, **kwargs)\n\n        # set instrument operation state variables\n        self._ramp_state = False\n        self._ramp_time = 100\n        self._voltranges = [1, 1, 1, 1]\n        self._offsets = [0, 0, 0, 0]\n\n        # channels\n        for channelno in range(4):\n            self.add_parameter('ch{}_voltage'.format(channelno),\n                               get_cmd=partial(self._getvoltage,\n                                               channel=channelno),\n                               set_cmd=partial(self._setvoltage,\n                                               channel=channelno),\n                               label='Voltage',\n                               unit='V')\n\n            self.add_parameter('ch{}_voltrange'.format(channelno),\n                               get_cmd=partial(self._getvoltrange, channelno),\n                               set_cmd=partial(self._setvoltrange, channelno),\n                               vals=vals.Enum(1, 2, 3))\n\n            self.add_parameter('ch{}_offset'.format(channelno),\n                               get_cmd=partial(self._getoffset, channelno),\n                               set_cmd=partial(self._setoffset, channelno),\n                               label='Channel {} offset'.format(channelno),\n                               unit='V',\n                               docstring=\"\"\"\n                                         The offset is applied to the channel.\n                                         E.g. if ch1_offset = 1 and ch_voltage\n                                         is set to 1, the instrument is told to\n                                         output 2 volts.\n                                         \"\"\")\n\n        self.add_parameter('mode',\n                           label='Output mode',\n                           set_cmd=partial(self._setmode, self.slot),\n                           vals=vals.Enum(0, 2),\n                           docstring=\"\"\"\n                                     The operational mode of the slot.\n                                     0: output off,\n                                     2: 4-channel (low res) mode.\n                                     \"\"\")\n\n        # initialise hardware settings\n        self.mode.set(2)\n\n    def _setmode(slot, mode):\n        \"\"\"\n        set_cmd for the mode parameter\n        \"\"\"\n        self.visa_handle.write('B {}; M {};'.format(slot, mode)\n        self.visa_handle.read()\n\n    def _getoffset(self, n):\n        return self._offsets[n]\n\n    def _setoffset(self, n, val):\n        self._offsets[n] = val\n\n    def _getvoltrange(self, n):\n        return self._voltranges[n]\n\n    def _setvoltrange(self, n, val):\n        self._voltranges[n] = val\n\n    def _getvoltage(self, channel):\n        \"\"\"\n        Function to query the voltage. Flushes the message queue in that\n        process.\n        \"\"\"\n\n        # set the relevant channel and slot to query\n        mssg = 'B {:d}; C {:d};'.format(self.slot, channel)\n        mssg += 'd;'\n\n        # a bit of string juggling to extract the voltage\n        rawresponse = self.visa_handle.ask(mssg)\n        temp = rawresponse[::-1]\n        temp = temp[3:temp.upper().find('D')-1]\n        response = temp[::-1]\n\n        rawvoltage = self._code2voltage(response, channel)\n        actualvoltage = rawvoltage - self._offsets[channel]\n\n        return actualvoltage\n\n    def _setvoltage(self, voltage, channel):\n        \"\"\"\n        Function to set the voltage. Depending on whether self._ramp_state is\n        True or False, this function either ramps from the current voltage to\n        the specified voltage or directly makes the voltage jump there.\n\n        Args:\n            voltage (number): the set voltage.\n        \"\"\"\n\n        actualvoltage = voltage + self._offsets[channel]\n        code = self._voltage2code(actualvoltage, channel)\n\n        mssg = 'B {:d}; C {:d};'.format(self.slot, channel)\n\n        if not self._ramp_state:\n            mssg += 'D ' + code + ';'\n\n            self.visa_handle.write(mssg)\n\n            # due to a quirk of the Decadac, we spare the user of an error\n            # sometimes encountered on first run\n            try:\n                self.visa_handle.read()\n            except UnicodeDecodeError:\n                log.warning(\" Decadac returned nothing and possibly did nothing. \" +\n                            \"Please re-run the command\")\n                pass\n\n        if self._ramp_state:\n            currentcode = self._voltage2code(self._getvoltage(channel),\n                                             channel)\n            slope = int((float(code)-float(currentcode)) /\n                        (10*self._ramp_time)*2**16)\n            if slope < 0:\n                limit = 'L'\n            else:\n                limit = 'U'\n\n            script = ['{',\n                      '*1:',\n                      'M2;',\n                      'T 100;',  # 1 timestep: 100 micro s\n                      limit + code + ';',\n                      'S' + str(slope) + ';',\n                      'X0;',\n                      '}']\n            runcmd = 'X 1;'\n            mssg += ''.join(script) + runcmd\n            self.visa_handle.write(mssg)\n            sleep(0.0015*self._ramp_time)  # Required sleep.\n            self.visa_handle.read()\n\n            # reset channel voltage ranges\n            if slope < 0:\n                self.visa_handle.write('L 0;')\n                self.visa_handle.read()\n            else:\n                self.visa_handle.write('U 65535;')\n                self.visa_handle.read()\n\n    def set_ramping(self, state, time=None):\n        \"\"\"\n        Function to set _ramp_state and _ramp_time.\n\n        Args:\n            state (bool): True sets ramping ON.\n\n            time (Optiona[int]): the ramp time in ms\n        \"\"\"\n        self._ramp_state = state\n        if time is not None:\n            self._ramp_time = time\n\n    def get_ramping(self):\n        \"\"\"\n        Queries the value of self._ramp_state and self._ramp_time.\n\n        Returns:\n            str: ramp state information\n        \"\"\"\n        switch = {True: 'ON',\n                  False: 'OFF'}\n        mssg = 'Ramp state: ' + switch[self._ramp_state]\n        mssg += '. Ramp time: {:d} ms.'.format(int(self._ramp_time))\n        return mssg\n\n    def _code2voltage(self, code, channel):\n        \"\"\"\n        Helper function translating a 32 bit code used internally by\n        the Decadac into a voltage.\n\n        Args:\n            code (str): The code string from the instrument.\n\n            channel (int): The relevant channel.\n        \"\"\"\n\n        code = float(code)\n        translationdict = {1: lambda x: (x+1)*20/2**16-10,\n                           2: lambda x: (x+1)*10/2**16,\n                           3: lambda x: (x+1)*10/2**16-10}\n\n        return translationdict[self._voltranges[channel]](code)\n\n    def _voltage2code(self, voltage, channel):\n        \"\"\"\n        Helper function translating a voltage in V into a 32 bit code used\n        internally by the Decadac.\n\n        Args:\n            voltage (float): The physical voltage.\n\n            channel (int): The relevant channel.\n\n        Returns:\n            code (str): The corresponding voltage code.\n        \"\"\"\n        translationdict = {1: lambda x: 2**16/20*(x-2**-16+10),\n                           2: lambda x: 2**16/10*(x-2**-16),\n                           3: lambda x: 2**16/10*(x-2**-16+10)}\n        voltage_float = translationdict[self._voltranges[channel]](voltage)\n        return str(int(voltage_float))\n", "path": "qcodes/instrument_drivers/Harvard/Decadac.py"}]}