@@ -63,22 +63,17 @@ def configure_instruments(self, current_ma, compliance_v):
6363 self .k2400 .measure_voltage ()
6464 self .k2400 .enable_source ()
6565
66- def stabilize_at_start (self , start_temp , stability_log_callback ):
67- while True :
68- current_temp = float (self .lakeshore .query ('KRDG? A' ).strip ())
69- if current_temp > start_temp + 0.2 :
70- stability_log_callback (f"Cooling... Current: { current_temp :.4f} K > Target: { start_temp } K" )
71- self .lakeshore .write ('RANGE 1,0' ) # Heater Off
72- else :
73- stability_log_callback (f"Heating... Current: { current_temp :.4f} K <= Target: { start_temp } K" )
74- self .lakeshore .write ('RANGE 1,4' ) # Heater Medium
75- self .lakeshore .write (f'SETP 1,{ start_temp } ' )
76-
77- if abs (current_temp - start_temp ) < 0.1 :
78- stability_log_callback (f"Stabilized at { current_temp :.4f} K. Waiting 5s before ramp." )
79- time .sleep (5 )
80- return
81- time .sleep (2 )
66+ def get_temperature (self ):
67+ if not self .lakeshore : return 0.0
68+ return float (self .lakeshore .query ('KRDG? A' ).strip ())
69+
70+ def set_heater_range (self , output , heater_range ):
71+ range_map = {'off' : 0 , 'low' : 2 , 'medium' : 4 , 'high' : 5 }
72+ range_code = range_map .get (heater_range .lower ())
73+ if range_code is None : raise ValueError ("Invalid heater range." )
74+ self .lakeshore .write (f'RANGE { output } ,{ range_code } ' )
75+ def set_setpoint (self , output , temperature_k ):
76+ self .lakeshore .write (f'SETP { output } ,{ temperature_k } ' )
8277
8378 def start_ramp (self , end_temp , rate_k_min ):
8479 self .lakeshore .write (f'SETP 1,{ end_temp } ' )
@@ -138,9 +133,13 @@ def create_widgets(self):
138133 header = tk .Frame (self .root , bg = self .CLR_HEADER ); header .pack (side = 'top' , fill = 'x' )
139134 ttk .Label (header , text = f"Active R-T Sweep (K2400) v{ self .PROGRAM_VERSION } " , style = 'Header.TLabel' , font = self .FONT_TITLE ).pack (side = 'left' , padx = 20 , pady = 10 )
140135 main_pane = ttk .PanedWindow (self .root , orient = 'horizontal' ); main_pane .pack (fill = 'both' , expand = True , padx = 10 , pady = 10 )
141- left_panel = self ._create_left_panel (main_pane ); main_pane .add (left_panel , weight = 2 )
142- right_panel = self ._create_right_panel (main_pane ); main_pane .add (right_panel , weight = 3 )
143-
136+
137+ # --- FIX: Create both panels first, then add them to the PanedWindow ---
138+ left_panel = self ._create_left_panel (main_pane )
139+ right_panel = self ._create_right_panel (main_pane )
140+ main_pane .add (left_panel , weight = 2 )
141+ main_pane .add (right_panel , weight = 3 )
142+
144143 def _create_left_panel (self , parent ):
145144 panel = ttk .Frame (parent , padding = 5 ); panel .grid_columnconfigure (0 , weight = 1 ); panel .grid_rowconfigure (3 , weight = 1 )
146145 self ._create_info_panel (panel , 0 )
@@ -235,16 +234,44 @@ def stop_experiment(self, reason=""):
235234 self .ax_main .set_title ("Experiment stopped." ); self .canvas .draw ()
236235 if reason : messagebox .showinfo ("Experiment Finished" , f"Reason: { reason } " )
237236
237+ # --- NON-BLOCKING HEATER LOGIC (from 6517B scripts) ---
238+ def _stabilization_loop (self ):
239+ if self .experiment_state != 'stabilizing' : return
240+ try :
241+ current_temp = self .backend .get_temperature ()
242+ start_temp = self .params ['start_temp' ]
243+
244+ if current_temp > start_temp + 0.2 :
245+ self .log (f"Cooling... Current: { current_temp :.4f} K > Target: { start_temp } K" )
246+ self .backend .set_heater_range (1 , 'off' )
247+ else :
248+ self .log (f"Heating... Current: { current_temp :.4f} K <= Target: { start_temp } K" )
249+ self .backend .set_heater_range (1 , 'medium' )
250+ self .backend .set_setpoint (1 , start_temp )
251+
252+ if abs (current_temp - start_temp ) < 0.1 :
253+ self .log (f"Stabilized at { current_temp :.4f} K. Waiting 5s before starting ramp..." )
254+ self .experiment_state = 'ramping_setup'
255+ self .root .after (5000 , self ._experiment_loop ) # Transition to next state
256+ else :
257+ self .root .after (2000 , self ._stabilization_loop ) # Continue stabilizing
258+ except Exception as e :
259+ self .log (f"ERROR during stabilization: { e } " ); self .stop_experiment ("Stabilization Error" )
260+
238261 def _experiment_loop (self ):
239262 if self .experiment_state == 'idle' : return
240263 try :
241264 if self .experiment_state == 'stabilizing' :
242- self .backend .stabilize_at_start (self .params ['start_temp' ], self .log )
265+ self ._stabilization_loop ()
266+ return # Let the after() calls manage the flow
267+
268+ elif self .experiment_state == 'ramping_setup' :
243269 self .backend .start_ramp (self .params ['end_temp' ], self .params ['rate' ])
244270 self .log (f"Ramp started towards { self .params ['end_temp' ]} K." )
245271 self .experiment_state = 'ramping' ; self .start_time = time .time ()
246- self .root .after (100 , self ._experiment_loop )
247-
272+ self .root .after (100 , self ._experiment_loop ) # Transition to measurement
273+ return
274+
248275 elif self .experiment_state == 'ramping' :
249276 temp , voltage = self .backend .get_measurement ()
250277 resistance = voltage / (self .params ['current_ma' ] * 1e-3 ) if self .params ['current_ma' ] != 0 else float ('inf' )
@@ -256,9 +283,11 @@ def _experiment_loop(self):
256283 self .line_main .set_data (self .data_storage ['temperature' ], self .data_storage ['resistance' ])
257284 self .ax_main .relim (); self .ax_main .autoscale_view (); self .figure .tight_layout (); self .canvas .draw ()
258285
286+ # Check end conditions
259287 if temp >= self .params ['cutoff' ]:
260288 self .stop_experiment (f"Safety cutoff reached at { temp :.2f} K." )
261- elif temp >= self .params ['end_temp' ]:
289+ elif (self .params ['rate' ] > 0 and temp >= self .params ['end_temp' ]) or \
290+ (self .params ['rate' ] < 0 and temp <= self .params ['end_temp' ]):
262291 self .stop_experiment ("End temperature reached." )
263292 else :
264293 self .root .after (int (self .params ['delay_s' ] * 1000 ), self ._experiment_loop )
@@ -275,7 +304,10 @@ def _validate_and_get_params(self):
275304 'compliance_v' : float (self .entries ["Compliance (V)" ].get ()), 'delay_s' : float (self .entries ["Logging Delay (s)" ].get ()),
276305 'k2400_visa' : self .k2400_cb .get ()}
277306 if not all ([p for k , p in params .items () if k not in ['rate' , 'cutoff' ]]): raise ValueError ("A required field is empty." )
278- if not (params ['start_temp' ] < params ['end_temp' ] < params ['cutoff' ]): raise ValueError ("Temperatures must be in order: start < end < cutoff." )
307+ if params ['rate' ] > 0 and not (params ['start_temp' ] < params ['end_temp' ] < params ['cutoff' ]):
308+ raise ValueError ("For heating, temperatures must be in order: start < end < cutoff." )
309+ if params ['rate' ] < 0 and not (params ['start_temp' ] > params ['end_temp' ] > params ['cutoff' ]):
310+ raise ValueError ("For cooling, temperatures must be in order: start > end > cutoff." )
279311 return params
280312 except Exception as e : raise ValueError (f"Invalid parameter input: { e } " )
281313
0 commit comments