diff --git a/ADwinProII/labscript_devices_ADwin_modules.py b/ADwinProII/labscript_devices_ADwin_modules.py
index 46385ab1763d254182b8e575699dc8f8d443a805..60a86ecbf7946fef5e181302607bd42e9231a5fe 100644
--- a/ADwinProII/labscript_devices_ADwin_modules.py
+++ b/ADwinProII/labscript_devices_ADwin_modules.py
@@ -131,7 +131,7 @@ class ADwinAnalogOut(AnalogOut):
         self.PID_max = limits[1]
 
 
-    def set_PID(self,t,pid_no,start="last"):
+    def set_PID(self,t,pid_no,set_output=0):
         """(De-)activate PID for analog output, or change settings
         
         Parameters
@@ -141,25 +141,34 @@ class ADwinAnalogOut(AnalogOut):
         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".
+        set_value : float or "last"
+            When the PID is turned on, 'set_value' is the initially chosen output value,
+            'last' means that the I value from the previous PID is taken.
+            When the PID is turned off, 'set_value' is programmed as the new output/target value,
+            'last' means that the output from the PID loop is kept as 'set_target'.
         """
+        # Error check of bounds for set_output
+        if set_output!="last":
+            if set_output<self.PID_min or set_output>self.PID_max:
+                raise LabscriptError(
+                    f"{self.name}: PID 'set_output={set_output}' must be within ({self.PID_min},{self.PID_max})"
+                )
         
         # TURN OFF PID
         if pid_no is None:
             self.PID[t] = {
                 "PID_channel": 0,
-                "start": start,
+                "start": set_output,
             }
+            # If we don't keep the PID output, set the output to the set_value
+            if set_output!="last":
+                self.constant(t,set_output)
         # TURN ON PID
         elif (isinstance(pid_no,AnalogIn) and isinstance(pid_no.parent_device,_ADwinCard)) \
                 or isinstance(pid_no,int):
             self.PID[t] = {
                 "PID_channel": pid_no,
-                "start": start,
+                "start": set_output,
             }
             # TODO: Do we need scale factors for setting a PID with integer?
         else:
@@ -203,19 +212,17 @@ class ADwinAnalogOut(AnalogOut):
 
     def add_instruction(self,time,instruction,units=None):
         # Overwrite Output.add_instruction without limit check, becasue the value can be off-limits when this is the target value of the PID
-        # TODO / WARNING: THIS IS QUITE HACKY AND COULD LEAD TO OFF-LIMIT VALUES NOT NOTICED
-        # (the actual limits are also checked in the ADwin, so the actual output should be always within limits!)
         limits_temp = self.limits
-        self.limits = (-10,10)
+        if hasattr(self,"pid_no"):
+            self.limits = (-10,10)
         super().add_instruction(time,instruction,units)
         self.limits = limits_temp
 
     def expand_timeseries(self,all_times,flat_all_times_len):
         # Overwrite Output.add_instruction without limit check, becasue the value can be off-limits when this is the target value of the PID
-        # TODO / WARNING: THIS IS QUITE HACKY AND COULD LEAD TO OFF-LIMIT VALUES NOT NOTICED
-        # (the actual limits are also checked in the ADwin, so the actual output should be always within limits!)
         limits_temp = self.limits
-        self.limits = (-10,10)
+        if hasattr(self,"pid_no"):
+            self.limits = (-10,10)
         super().expand_timeseries(all_times,flat_all_times_len)
         self.limits = limits_temp
 
@@ -353,6 +360,38 @@ class ADwinAO8(_ADwinCard):
                     raise LabscriptError(
                         f"The ramp sample rate ({rate_kHz:.0f}kHz) of {output.name} must not be faster than ADwin ({ADwin_rate_kHz:.0f}kHz)."
                     )
+
+            # Check limits of output, but only when PID is NOT enabled (becasue then the target can be out of limits)
+            # Get all times when PID is not enabled
+            PID = output.PID.copy()
+            if 0 not in PID:
+                # Because 'np.digitize' determines the bins, we also have to make sure t=0 is included.
+                # If output.PID does not have the key t=0, then the PID is disabled in the beginning.
+                PID[0] = {"PID_channel":0,"start":0}
+            PID_times = np.array(list(PID.keys()))
+            PID_times.sort()
+            PID_off_times = []
+            # For each output value, digitize gets the next highest time in  PID_times.
+            # Using '-1' to get next lowest time.
+            for i_out,i_PID in enumerate(np.digitize(output.all_times, PID_times)-1):
+                t = PID_times[i_PID]
+                if PID[t]["PID_channel"]==0:
+                    # When we turn the PID off but keep the last output, we make sure that
+                    #  - at least once in the end the output is (re)set, otherwise the get_final_values() in the Worker is wrong,
+                    #  - don't try to also set the target value at the same time, as this would overwrite the target in the ADwin with the PID output.
+                    if PID[t]["start"]=="last":
+                        if i_out+1==len(output.all_times):
+                            raise LabscriptError(f"{output.name}: You must set the output at the end after turning off PID with 'last'.")
+                        elif output.all_times[i_out] == t:
+                            raise LabscriptError(f"{output.name}: Don't turn off PID with persitent value ('last') and also set new value.")
+                    PID_off_times.append(i_out)
+            PID_off_outputs = output.raw_output[PID_off_times]
+            if np.any(PID_off_outputs < output.limits[0]) or np.any(PID_off_outputs > output.limits[1]):
+                raise LabscriptError(
+                    f"Limits of {output.name} (when PID is off) must be in {output.limits}, " +
+                    f"you try to set ({PID_off_outputs.min()},{PID_off_outputs.max()}) " +
+                    f"or turning off the PID with target value beyond limits.")
+            
         # Check if the PID channel is allowed
         if np.any(self.PID_table["PID_channel"] > PIDNO):
             raise LabscriptError(f"ADwin: Setting the PID channel to more than {PIDNO} is not possible!")
@@ -406,14 +445,6 @@ class ADwinAO8(_ADwinCard):
                         output.raw_output[indices==i+1] *= output.PID[t]['PID_channel'].scale_factor
                     elif isinstance(output.PID[t]['PID_channel'],int):
                         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)
                     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.