diff --git a/ADwinProII/blacs_workers.py b/ADwinProII/blacs_workers.py
index d69de1fd9aff044e8b601b4da5b5a16c68914c40..5b8cec38b65483230666a4bf5359c6cef99f04dc 100644
--- a/ADwinProII/blacs_workers.py
+++ b/ADwinProII/blacs_workers.py
@@ -29,7 +29,7 @@ class ADwinProIIWorker(Worker):
     def init(self):
         self.timing = None
         self.h5file = None
-        self.smart_cache = {"AOUT":None, "PIDs":None, "AIN":None}
+        self.smart_cache = {"AOUT":None, "PIDs":None, "PID_CONFIG":None, "AIN":None}
         self.smart_cache.update({DIO:None for DIO in self.DIO_ADwin_DataNo})
         self.process_number_buffered = int(self.process_buffered[-1])
         self.process_number_manual = int(self.process_manual[-1])
@@ -164,12 +164,19 @@ class ADwinProIIWorker(Worker):
                 self.adw.SetData_Long(PIDs["n_cycles"], 4, 1, PIDs.shape[0])
                 self.adw.SetData_Long(PIDs["AOUT_channel"], 5, 1, PIDs.shape[0])
                 self.adw.SetData_Long(PIDs["PID_channel"], 6, 1, PIDs.shape[0])
-                self.adw.SetData_Float(PIDs["PID_P"], 25, 1, PIDs.shape[0])
-                self.adw.SetData_Float(PIDs["PID_I"], 26, 1, PIDs.shape[0])
-                self.adw.SetData_Float(PIDs["PID_D"], 27, 1, PIDs.shape[0])
-                self.adw.SetData_Long(PIDs["PID_min"], 28, 1, PIDs.shape[0])
-                self.adw.SetData_Long(PIDs["PID_max"], 29, 1, PIDs.shape[0])
                 self.adw.SetData_Long(PIDs["PID_start"], 30, 1, PIDs.shape[0])
+            PID_config = group["ANALOG_OUT/PID_CONFIG"]
+            if fresh or not np.array_equal(PID_config[:],self.smart_cache["PID_CONFIG"]):
+                print("PID_CONFIG programmed.")
+                self.smart_cache["PID_CONFIG"] = PID_config[:]
+                n_PID = PID_config.shape[0]
+                self.adw.Set_Par(22,n_PID)
+                self.adw.SetData_Long(PID_config["PID_channel"], 24, 1, n_PID)
+                self.adw.SetData_Float(PID_config["PID_P"], 25, 1, n_PID)
+                self.adw.SetData_Float(PID_config["PID_I"], 26, 1, n_PID)
+                self.adw.SetData_Float(PID_config["PID_D"], 27, 1, n_PID)
+                self.adw.SetData_Long(PID_config["PID_min"], 28, 1, n_PID)
+                self.adw.SetData_Long(PID_config["PID_max"], 29, 1, n_PID)
             AIN = group["ANALOG_IN/TIMES"]
             if fresh or not np.array_equal(AIN[:],self.smart_cache["AIN"]):
                 print("AIN programmed.")
diff --git a/ADwinProII/labscript_devices.py b/ADwinProII/labscript_devices.py
index d1bee26ac79993ac01ba804af3866b9d46de0644..f74a85b4056302be67bca20f1bfae9040378ece7 100644
--- a/ADwinProII/labscript_devices.py
+++ b/ADwinProII/labscript_devices.py
@@ -232,12 +232,14 @@ class ADwinProII(PseudoclockDevice):
         # Lists to collect instructions of analog channels
         analog_output = []
         PID_channels = []
+        PID_config = []
         analog_input = []
  
         for device in self.modules: 
             if isinstance(device,ADwinAO8):
                 analog_output.append(device.outputs)
-                PID_channels.append(device.PID_channels)
+                PID_channels.append(device.PID_table)
+                PID_config.append(device.PID_config)
             elif isinstance(device,ADwinDIO32):
                 group.create_dataset("DIGITAL_OUT/"+device.name, data=device.digital_data)
             elif isinstance(device,ADwinAI8):
@@ -252,14 +254,17 @@ class ADwinProII(PseudoclockDevice):
         PID_channels.append(np.full(1,last_values,dtype=PID_channels[0].dtype))
         # Concatenate arrays
         PID_channels = np.concatenate(PID_channels)
+        PID_config = np.concatenate(PID_config)
         analog_output = np.concatenate(analog_output)
         analog_input = np.concatenate(analog_input)
         # Sort analog outputs and PID settings
         analog_output = np.sort(analog_output, axis=0, order="n_cycles")
         PID_channels = np.sort(PID_channels, axis=0, order="n_cycles")
+        PID_config = np.sort(PID_config, axis=0, order="PID_channel")
         # Save datasets
         AO_group.create_dataset('VALUES', compression=config.compression, data=analog_output)
         AO_group.create_dataset('PID_CHANNELS', compression=config.compression, data=PID_channels)
+        AO_group.create_dataset('PID_CONFIG', compression=config.compression, data=PID_config)
         AI_group.create_dataset('TIMES', data=analog_input)
 
         AI_datapoints = analog_input["stop_time"] - analog_input["start_time"]
diff --git a/ADwinProII/labscript_devices_ADwin_modules.py b/ADwinProII/labscript_devices_ADwin_modules.py
index 29ef0f9c183578751aca4498ac3728575ecac266..46385ab1763d254182b8e575699dc8f8d443a805 100644
--- a/ADwinProII/labscript_devices_ADwin_modules.py
+++ b/ADwinProII/labscript_devices_ADwin_modules.py
@@ -96,17 +96,13 @@ class ADwinAnalogOut(AnalogOut):
         )
         self.PID = {} # instructions for PID settings
 
-
-    def set_PID(self,t,PID_AnalogIn,P=0,I=0,D=0,limits=None, start="last"):
-        """(De-)activate PID for analog output, or change settings
+    def init_PID(self,pid_no,P=0,I=0,D=0,limits=None):
+        """Set parameters for PID once at beginning of shot.
         
         Parameters
         ----------
-        t : float
-            Time when to apply the PID settings
-        PID_AnalogIn : int or `AnalogIn` or None
+        pid_no : int or `AnalogIn`
             Channel of analog input for error siganl of PID feedback.
-            If `None` PID is deactivated.
         P : float
             Proportional parameter
         I : float
@@ -115,38 +111,54 @@ class ADwinAnalogOut(AnalogOut):
             Differential parameter
         limits : tuple of float, optional
             Limits for output voltage, defaults to output limits
-        start : float or "last"
-            Inital value of the output when the PID is turned on, assigned to the I part.
-            If start="last" when the PID is turned on, the I value from the PID earlier 
-            in the shot is kept. If start="last" when the PID is turned off, the last output
-            value is kept as "set_target".
         """
+        if hasattr(self,"pid_no"):
+            raise NotImplementedError("Only one set of PID parameters per channel is implemented.")
 
         if limits is None:
             # Use the Output limits if there are none specified here.
             limits = self.limits
         if limits[0]<self.limits[0] or limits[1]>self.limits[1]:
             raise LabscriptError(f"Limits of {self.name} with PID must not be larger than channel limits {self.limits}!")
+
+        if isinstance(pid_no,AnalogIn) and isinstance(pid_no.parent_device,_ADwinCard):
+            pid_no = int(pid_no.connection) + pid_no.parent_device.start_index
+        self.pid_no = pid_no
+        self.P = P
+        self.I = I
+        self.D = D
+        self.PID_min = limits[0]
+        self.PID_max = limits[1]
+
+
+    def set_PID(self,t,pid_no,start="last"):
+        """(De-)activate PID for analog output, or change settings
+        
+        Parameters
+        ----------
+        t : float
+            Time when to apply the PID settings
+        pid_no : int or `AnalogIn` or None
+            Channel of analog input for error siganl of PID feedback.
+            If `None` PID is deactivated.
+        start : float or "last"
+            Inital value of the output when the PID is turned on, assigned to the I part.
+            If start="last" when the PID is turned on, the I value from the PID earlier 
+            in the shot is kept. If start="last" when the PID is turned off, the last output
+            value is kept as "set_target".
+        """
         
         # TURN OFF PID
-        if PID_AnalogIn is None:
+        if pid_no is None:
             self.PID[t] = {
                 "PID_channel": 0,
-                "P": P,
-                "I": I,
-                "D": D,
-                "limits": limits,
                 "start": start,
             }
         # TURN ON PID
-        elif (isinstance(PID_AnalogIn,AnalogIn) and isinstance(PID_AnalogIn.parent_device,_ADwinCard)) \
-                or isinstance(PID_AnalogIn,int):
+        elif (isinstance(pid_no,AnalogIn) and isinstance(pid_no.parent_device,_ADwinCard)) \
+                or isinstance(pid_no,int):
             self.PID[t] = {
-                "PID_channel": PID_AnalogIn,
-                "P": P,
-                "I": I,
-                "D": D,
-                "limits": limits,
+                "PID_channel": pid_no,
                 "start": start,
             }
             # TODO: Do we need scale factors for setting a PID with integer?
@@ -321,6 +333,7 @@ class ADwinAO8(_ADwinCard):
     def __init__(self, name, parent_device, module_address, num_AO=8, **kwargs):
         self.num_AO = num_AO
         self.start_index = module_start_index[int(module_address)]
+
         super().__init__(name, parent_device, module_address, **kwargs)
 
 
@@ -341,10 +354,9 @@ class ADwinAO8(_ADwinCard):
                         f"The ramp sample rate ({rate_kHz:.0f}kHz) of {output.name} must not be faster than ADwin ({ADwin_rate_kHz:.0f}kHz)."
                     )
         # Check if the PID channel is allowed
-        if np.any(self.PID_channels["PID_channel"] > PIDNO):
-            max_PID_channel = self.PID_channels["PID_channel"].max()
+        if np.any(self.PID_table["PID_channel"] > PIDNO):
             raise LabscriptError(f"ADwin: Setting the PID channel to more than {PIDNO} is not possible!")
-        if np.any(self.PID_channels["PID_channel"] < 0):
+        if np.any(self.PID_table["PID_channel"] < 0):
             raise LabscriptError("ADwin: Setting the PID channel to less than 0 is not possible!")
 
     def generate_code(self,hdf5_file):
@@ -353,25 +365,36 @@ class ADwinAO8(_ADwinCard):
         pseudoclock = clockline.parent_device
 
         output_dtypes = [("n_cycles",np.int32),("channel",np.int32),("value",np.int32)]
-        PID_dtypes = [
-            ("n_cycles",np.int32),("AOUT_channel",np.int32),("PID_channel",np.int32),
-            ("PID_P",np.float64),("PID_I",np.float64),("PID_D",np.float64),("PID_min",np.int32),("PID_max",np.int32),("PID_start",np.int32)
+        PID_config_dtypes = [
+            ("PID_channel",np.int32),("PID_P",np.float64),("PID_I",np.float64),("PID_D",np.float64),("PID_min",np.int32),("PID_max",np.int32)
+        ]
+        PID_table_dtypes = [
+            ("n_cycles",np.int32),("AOUT_channel",np.int32),("PID_channel",np.int32),("PID_start",np.int32)
             ]
         outputs = []
-        PID_channels = []
+        PID_table = []
+        PID_config = []
 
         for output in sorted(self.child_devices, key=lambda dev:int(dev.connection)):
             output.expand_output()
 
             # Get input channels for PID, collect changed for time table and store bare channels as dataset
             if output.PID:
-                PID_array = np.zeros(len(output.PID),dtype=PID_dtypes)
+                # Get PID parameters
+                if not hasattr(output,"pid_no"):
+                    raise LabscriptError(f"For {self.name} you try to use a PID, but never set the parameters via {self.name}.init_PID().")
+                PID_config. append(
+                    np.array([
+                        (output.pid_no,output.P,output.I,output.D,ADC(output.PID_min,self.resolution_bits,self.min_V,self.max_V),ADC(output.PID_max,self.resolution_bits,self.min_V,self.max_V))
+                        ], dtype=PID_config_dtypes)
+                )
+                PID_array = np.zeros(len(output.PID),dtype=PID_table_dtypes)
                 PID_times = np.array(list(output.PID.keys()))
                 PID_times.sort()
                 PID_array["n_cycles"] = np.round(PID_times * pseudoclock.clock_limit)
                 # PID_array["PID_channel"] = list(output.PID_channel.values())
                 PID_array["AOUT_channel"] = int(output.connection) + self.start_index
-                PID_channels.append(PID_array)
+                PID_table.append(PID_array)
                 # If a PID is enabled, the set values are not the actual voltage values of the 
                 # Output, but those measured at the input. If the input has a gain enabled, the
                 # set values have the be scaled too, to have the PID stabilized to the right values.
@@ -385,12 +408,12 @@ class ADwinAO8(_ADwinCard):
                         PID_array["PID_channel"][i] = output.PID[t]['PID_channel']
                     # If PID_channel[t]=None, there are zeros in the PID_array
 
-                    PID_array["PID_P"][i] = output.PID[t]['P']
-                    PID_array["PID_I"][i] = output.PID[t]['I']
-                    PID_array["PID_D"][i] = output.PID[t]['D']
-                    limits = output.PID[t]['limits']
-                    PID_array["PID_min"][i] = ADC(limits[0],self.resolution_bits,self.min_V,self.max_V)
-                    PID_array["PID_max"][i] = ADC(limits[1],self.resolution_bits,self.min_V,self.max_V)
+                    # PID_array["PID_P"][i] = output.PID[t]['P']
+                    # PID_array["PID_I"][i] = output.PID[t]['I']
+                    # PID_array["PID_D"][i] = output.PID[t]['D']
+                    # limits = output.PID[t]['limits']
+                    # PID_array["PID_min"][i] = ADC(limits[0],self.resolution_bits,self.min_V,self.max_V)
+                    # PID_array["PID_max"][i] = ADC(limits[1],self.resolution_bits,self.min_V,self.max_V)
                     if output.PID[t]["start"]=="last":
                         # When we want to use the previous value during the shot,
                         # we use a value that's out of the 16 bit ADC range to identify.
@@ -406,7 +429,8 @@ class ADwinAO8(_ADwinCard):
             outputs.append(out)
 
         self.outputs = np.concatenate(outputs) if outputs else np.array([],dtype=output_dtypes)
-        self.PID_channels = np.concatenate(PID_channels) if PID_channels else np.array([],dtype=PID_dtypes)
+        self.PID_table = np.concatenate(PID_table) if PID_table else np.array([],dtype=PID_table_dtypes)
+        self.PID_config = np.concatenate(PID_config) if PID_config else np.array([],dtype=PID_config_dtypes)