From e79a6f28e68cecb9bb229e81261a0653aad4eb21 Mon Sep 17 00:00:00 2001
From: "S.Moeller" <samuel.moeller@rwth-aachen.de>
Date: Wed, 21 Nov 2018 17:22:00 +0100
Subject: [PATCH] ParallesSweepenSpeedundMehr

---
 DecaDAC/DecaDACLabberDriver.py | 113 +++++++++++++++++++++++++++++----
 DecaDAC/DecaDac.ini            |  20 ++++++
 2 files changed, 122 insertions(+), 11 deletions(-)

diff --git a/DecaDAC/DecaDACLabberDriver.py b/DecaDAC/DecaDACLabberDriver.py
index 2a67c37..bbe1975 100644
--- a/DecaDAC/DecaDACLabberDriver.py
+++ b/DecaDAC/DecaDACLabberDriver.py
@@ -2,6 +2,7 @@
 import SerialDriver
 from InstrumentConfig import InstrumentQuantity
 import numpy as np
+import time
 
 class Error(Exception):
     pass
@@ -12,6 +13,17 @@ class Driver(SerialDriver.SerialDriver):
     def performSetValue(self, quant, value, sweepRate=0.0, options={}):
         """Perform the Set Value instrument operation"""
 
+        self.log('sweep_rate')
+        self.log(sweepRate)
+
+        #For storing multiple sweep commands an simultaneous execution:
+        if self.isFirstCall(options):
+            self.log('FirstCall' + str(quant.name))
+            self.collect_sweep_cmds = {}
+            self.collect_sweep_params = {}
+            self.max_sweep_time = 0
+            self.sweep_end_time = 0
+
         #Range settings are virtual
         if "range" in quant.section.lower():
             if self.__captchaGenerator__("Switching ranges has to be done "
@@ -46,30 +58,55 @@ class Driver(SerialDriver.SerialDriver):
         else:
             binValue = value
 
+        #Sweeping
         if sweepRate == 0.0:
             return super(Driver, self).performSetValue(quant,
                         binValue, sweepRate, options)
         else:
             current_value = self.performGetValue(quant)
             voltage_diff = value - current_value
+            self.log('voltage_diff' + str(voltage_diff))
+
+
+            
+            bin_diff = self.__convertToBin__(value, quant.name) - self.__convertToBin__(current_value, quant.name)
+            #self.log('bin_diff ' + str(bin_diff))
+
+            if bin_diff == 0 :
+                if self.isFinalCall(options) and len(self.collect_sweep_cmds) > 0:
+                    self.log('FinalCall and sending' + str(quant.name))
+                    self.send_sweep_cmds()
+                return value
             
             timesteps = abs(voltage_diff/sweepRate*1000)
             if timesteps < 1:
-                return self.performSetValue(quant, binValue,
-                                            sweepRate=0.0, options=options)
+                raise InstrumentDriver.Error('SweepRate is too high!')
                 
-            upper_limit = value if voltage_diff>0 else current_value
+            upper_limit = value if voltage_diff > 0 else current_value
             lower_limit = current_value if voltage_diff>0 else value
             upper_limit = str(self.__convertToBin__(upper_limit, quant.name))
-            lower_limit = str(self.__convertToBin__(lower_limit, quant.name))
-           
-            voltage_steps = np.sign(voltage_diff) * self.__convertToBin__(np.abs(voltage_diff), quant.name)
-            slope = str(int(round(voltage_steps/timesteps*65536)))
+            lower_limit = str(self.__convertToBin__(lower_limit, quant.name))             
+
+
+            slope = str(int(round(bin_diff/timesteps*65536)))
+            
+
             cmd_str = quant.sweep_cmd.replace('<ll>',
                                               lower_limit).replace('<ul>',
                                                          upper_limit).replace('<sr>',slope)
-            self.writeAndLog(cmd_str)
-            return self.__convertToVoltage__(self.__convertToBin__(value, quant.name), quant.name)
+            self.log(cmd_str)
+                                              
+            self.collect_sweep_cmds[quant.name] = cmd_str
+            self.collect_sweep_params[quant.name] = [bin_diff, int(slope)]
+
+        if self.isFinalCall(options):
+            self.log('FinalCall')
+
+        if self.isFinalCall(options) and len(self.collect_sweep_cmds) > 0 :
+            self.log('FinalCall and sending' + str(quant.name))
+            self.send_sweep_cmds()
+        
+        return self.__convertToVoltage__(self.__convertToBin__(value, quant.name), quant.name)
         
     
     def performSafetyCheck(self, quantities, target_value=0):
@@ -77,23 +114,45 @@ class Driver(SerialDriver.SerialDriver):
             if not self.readValueFromOther(quant) == target_value:
                 return False
         return True
-    
+
+    def checkIfSweeping(self, quant, options={}):
+        self.log('CheckIfSweeping ' + quant.name)
+
+        #Check if enough time passed for sweep(s) to have ended
+        if time.time() > self.sweep_end_time :
+            still_sweeping = int(self.askAndLog(quant.sweep_check_cmd).split(b"!")[-2][1:])
+            
+            if still_sweeping:
+                return still_sweeping
+            else:
+                self.performStopSweep(quant, options={} ) #performStopSweep is executed in order to get the lower and upper Voltage limits back to default
+                return False
+        else:
+            self.log('Not enough time passed, still sweeping')
+            return True
+
+
     def performGetValue(self, quant, options={}):
         """Perform the Get Value instrument operation"""
+
         #Pure virtual range quantity
         if "range" in quant.section.lower():
             return quant.getValue()
+
         response = super(Driver, self).performGetValue(quant, options)
         
         if "m;" in quant.get_cmd:
             return bool(int(response))
+
         if "d;" in quant.get_cmd:
+            self.log('Voltage before readout, {}'.format(quant.name))
+            self.log(quant.getValue())
             return self.__convertToVoltage__(response, quant.name)
         else:
             return response
     
     def __captchaGenerator__(self, message):
-        rd1, rd2 = np.random.randint(10,50,size=(2))
+        rd1, rd2 = np.random.randint(0,10,size=(2))
         text = message + "\n"
         text += "To continue anyway, calculate {} + {} = ".format(rd1, rd2)
         uinput = self.getValueFromUserDialog(value=0,
@@ -122,6 +181,38 @@ class Driver(SerialDriver.SerialDriver):
         else:
             raise InstrumentDriver.CommunicationError("INVALID RANGE SETTINGS!")
         
+
+    def send_sweep_cmds(self):
+        for quant_name, sweep_cmd_str in self.collect_sweep_cmds.items():
+            self.log('Sent sweep command for {}'.format(quant_name))
+            self.writeAndLog(sweep_cmd_str)
+
+            #calculate Duration of sweep (Slope value is 32bit, slope is added to current value every ms (thus *65536 / 1000))
+            binDiff = self.collect_sweep_params[quant_name][0] 
+            sweep_slope = self.collect_sweep_params[quant_name][1]
+            
+
+            
+            sweep_time = abs(binDiff / sweep_slope * 65536 / 1000) #sweep time in seconds
+
+
+            if sweep_time > self.max_sweep_time:
+                self.max_sweep_time = sweep_time
+
+        self.sweep_end_time = self.max_sweep_time + time.time()
+
+
+
+
+
+    def performStopSweep(self, quant, options={}):
+        self.log('Sending Stop Command for Sweep of {}'.format(quant.name))
+
+        #Correcting the upper and lower limits of the channel in order to allow for the full range again
+        corret_limits_and_stop = quant.sweep_cmd.replace('<ll>',str(0)).replace('<ul>',str(65535)).replace('<sr>',str(0))
+        self.write(corret_limits_and_stop)   
+        return self.performGetValue(quant)
+
 if __name__ == '__main__':
     pass
 
diff --git a/DecaDAC/DecaDac.ini b/DecaDAC/DecaDac.ini
index 796268c..56ae8ff 100644
--- a/DecaDAC/DecaDac.ini
+++ b/DecaDAC/DecaDac.ini
@@ -64,6 +64,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B0;C0;D<*>;
 sweep_cmd: B0;C0;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B0;C0;s;
 stop_cmd: B0;C0;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -80,6 +81,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B0;C1;D<*>;
 sweep_cmd: B0;C1;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B0;C1;s;
 stop_cmd: B0;C1;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -96,6 +98,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B0;C2;D<*>;
 sweep_cmd: B0;C2;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B0;C2;s;
 stop_cmd: B0;C2;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -113,6 +116,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B0;C3;D<*>;
 sweep_cmd: B0;C3;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B0;C3;s;
 stop_cmd: B0;C3;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -136,6 +140,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B1;C0;D<*>;
 sweep_cmd: B1;C0;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B1;C0;s;
 stop_cmd: B1;C0;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -153,6 +158,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B1;C1;D<*>;
 sweep_cmd: B1;C1;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B1;C1;s;
 stop_cmd: B1;C1;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -169,6 +175,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B1;C2;D<*>;
 sweep_cmd: B1;C2;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B1;C2;s;
 stop_cmd: B1;C2;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -185,6 +192,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B1;C3;D<*>;
 sweep_cmd: B1;C3;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B1;C3;s;
 stop_cmd: B1;C3;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -208,6 +216,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B2;C0;D<*>;
 sweep_cmd: B2;C0;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B2;C0;s;
 stop_cmd: B2;C0;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -224,6 +233,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B2;C1;D<*>;
 sweep_cmd: B2;C1;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B2;C1;s;
 stop_cmd: B2;C1;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -240,6 +250,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B2;C2;D<*>;
 sweep_cmd: B2;C2;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B2;C2;s;
 stop_cmd: B2;C2;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -257,6 +268,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B2;C3;D<*>;
 sweep_cmd: B2;C3;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B2;C3;s;
 stop_cmd: B2;C3;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -280,6 +292,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B3;C0;D<*>;
 sweep_cmd: B3;C0;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B3;C0;s;
 stop_cmd: B3;C0;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -296,6 +309,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B3;C1;D<*>;
 sweep_cmd: B3;C1;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B3;C1;s;
 stop_cmd: B3;C1;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -312,6 +326,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B3;C2;D<*>;
 sweep_cmd: B3;C2;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B3;C2;s;
 stop_cmd: B3;C2;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -328,6 +343,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B3;C3;D<*>;
 sweep_cmd: B3;C3;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B3;C3;s;
 stop_cmd: B3;C3;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -351,6 +367,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B4;C0;D<*>;
 sweep_cmd: B4;C0;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B4;C1;s;
 stop_cmd: B4;C0;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -367,6 +384,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B4;C1;D<*>;
 sweep_cmd: B4;C1;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B4;C1;s;
 stop_cmd: B4;C1;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -383,6 +401,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B4;C2;D<*>;
 sweep_cmd: B4;C2;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B4;C2;s;
 stop_cmd: B4;C2;S0;
 sweep_res: 150e-6
 sweep_rate: 1
@@ -400,6 +419,7 @@ datatype: DOUBLE
 unit: V
 set_cmd: B4;C3;D<*>;
 sweep_cmd: B4;C3;U<ul>;L<ll>;S<sr>;
+sweep_check_cmd: B4;C3;s;
 stop_cmd: B4;C3;S0;
 sweep_res: 150e-6
 sweep_rate: 1
-- 
GitLab