Fixed bug where movement of steppers in quick succession didn't yield confirmation by the atm.

This commit is contained in:
jupfi 2023-12-11 09:04:26 +01:00
parent 039e9fe2d9
commit a6ce0a7588
2 changed files with 88 additions and 35 deletions

View file

@ -1,4 +1,5 @@
import logging import logging
import time
import numpy as np import numpy as np
import json import json
import time import time
@ -29,6 +30,7 @@ class AutoTMController(ModuleController):
self.module.model.serial_data_received.connect(self.process_calibration_data) self.module.model.serial_data_received.connect(self.process_calibration_data)
self.module.model.serial_data_received.connect(self.print_info) self.module.model.serial_data_received.connect(self.print_info)
self.module.model.serial_data_received.connect(self.read_position_data) self.module.model.serial_data_received.connect(self.read_position_data)
self.module.model.serial_data_received.connect(self.process_reflection_data)
@pyqtSlot(str, object) @pyqtSlot(str, object)
def process_signals(self, key: str, value: object) -> None: def process_signals(self, key: str, value: object) -> None:
@ -299,9 +301,6 @@ class AutoTMController(ModuleController):
def on_ready_read(self) -> None: def on_ready_read(self) -> None:
"""This method is called when data is received from the serial connection.""" """This method is called when data is received from the serial connection."""
serial = self.module.model.serial serial = self.module.model.serial
if self.module.model.waiting_for_reflection:
logger.debug("Waiting for reflection data")
return
while serial.canReadLine(): while serial.canReadLine():
text = serial.readLine().data().decode().rstrip("\r\n") text = serial.readLine().data().decode().rstrip("\r\n")
@ -309,6 +308,7 @@ class AutoTMController(ModuleController):
self.module.model.serial_data_received.emit(text) self.module.model.serial_data_received.emit(text)
@pyqtSlot(str)
def process_reflection_data(self, text): def process_reflection_data(self, text):
"""This method is called when data is received from the serial connection. """This method is called when data is received from the serial connection.
It processes the data and adds it to the model. It processes the data and adds it to the model.
@ -316,6 +316,7 @@ class AutoTMController(ModuleController):
Args: Args:
text (str): The data received from the serial connection. text (str): The data received from the serial connection.
""" """
if text.startswith("m"):
text = text[1:] text = text[1:]
return_loss, phase = map(float, text.split("p")) return_loss, phase = map(float, text.split("p"))
self.module.model.last_reflection = (return_loss, phase) self.module.model.last_reflection = (return_loss, phase)
@ -724,25 +725,49 @@ class AutoTMController(ModuleController):
confirmation = self.send_command(command) confirmation = self.send_command(command)
return confirmation return confirmation
def on_relative_move(self, steps: str, stepper : Stepper = None ) -> None: def on_relative_move(self, steps: str, stepper: Stepper = None) -> None:
"""This method is called when the relative move button is pressed.""" """This method is called when the relative move button is pressed."""
timeout_duration = 15 # timeout in seconds
start_time = time.time()
if stepper is None: if stepper is None:
stepper = self.module.model.active_stepper stepper = self.module.model.active_stepper
stepper_position = stepper.position
future_position = stepper.position + int(steps) future_position = stepper.position + int(steps)
if self.validate_position(future_position, stepper): if self.validate_position(future_position, stepper):
confirmation = self.send_stepper_command(int(steps), stepper) # Convert the steps string to an integer confirmation = self.send_stepper_command(int(steps), stepper) # Convert the steps string to an integer
while stepper_position == stepper.position:
QApplication.processEvents()
# Check for timeout
if time.time() - start_time > timeout_duration:
logger.error("Relative move timed out")
break # or handle timeout differently
return confirmation return confirmation
def on_absolute_move(self, steps: str, stepper : Stepper = None ) -> None: def on_absolute_move(self, steps: str, stepper: Stepper = None) -> None:
"""This method is called when the absolute move button is pressed.""" """This method is called when the absolute move button is pressed."""
timeout_duration = 15 # timeout in seconds
start_time = time.time()
if stepper is None: if stepper is None:
stepper = self.module.model.active_stepper stepper = self.module.model.active_stepper
stepper_position = stepper.position
future_position = int(steps) future_position = int(steps)
if self.validate_position(future_position, stepper): if self.validate_position(future_position, stepper):
actual_steps = self.calculate_steps_for_absolute_move(future_position, stepper) actual_steps = self.calculate_steps_for_absolute_move(future_position, stepper)
confirmation = self.send_stepper_command(actual_steps, stepper) confirmation = self.send_stepper_command(actual_steps, stepper)
while stepper_position == stepper.position:
QApplication.processEvents()
# Check for timeout
if time.time() - start_time > timeout_duration:
logger.error("Absolute move timed out")
break # or handle timeout differently
return confirmation return confirmation
### Position Saving and Loading ### ### Position Saving and Loading ###
@ -877,50 +902,78 @@ class AutoTMController(ModuleController):
LUT.started_frequency = next_frequency LUT.started_frequency = next_frequency
logger.debug("Starting next mechanical tuning and matching:") logger.debug("Starting next mechanical tuning and matching:")
def get_magnitude(reflection):
CENTER_POINT_MAGNITUDE = 900 # mV
MAGNITUDE_SLOPE = 30 # dB/mV
return (reflection[0] - CENTER_POINT_MAGNITUDE) / MAGNITUDE_SLOPE
# Now we vary the tuning capacitor position and matching capacitor position # Now we vary the tuning capacitor position and matching capacitor position
# Step size tuner: # Step size tuner:
TUNER_STEP_SIZE = 10 TUNER_STEP_SIZE = 20
# Step size matcher: # Step size matcher:
MATCHER_STEP_SIZE = 50 MATCHER_STEP_SIZE = 5
# We read the first reflection # We read the first reflection
reflection = self.read_reflection(next_frequency) last_reflection = self.read_reflection(next_frequency)
logger.debug("Reflection: %s", reflection) last_magnitude = get_magnitude(last_reflection)
def read_reflection(self, frequency): # Now we tune and match our probe coil for every frequency
"""Read the reflection at the specified frequency.""" stepper = self.module.model.tuning_stepper
new_magnitude = 1e6 # Big
while new_magnitude > last_magnitude:
# We move the stepper
last_magnitude = new_magnitude
self.on_relative_move(TUNER_STEP_SIZE, stepper)
# We read the reflection
new_magnitude = get_magnitude(self.read_reflection(next_frequency))
# We move the stepper back
self.on_relative_move(-TUNER_STEP_SIZE, stepper)
logger.debug("Tuning capacitor position: %s", stepper.position)
def read_reflection(self, frequency) -> tuple:
"""Starts a reflection measurement and reads the reflection at the specified frequency."""
# We send the command to the atm system # We send the command to the atm system
self.module.model.waiting_for_reflection = True
command = f"r{frequency}" command = f"r{frequency}"
try: try:
confirmation = self.send_command(command) confirmation = self.send_command(command)
if confirmation: if confirmation:
if self.module.model.serial.waitForReadyRead(1000): reflection = self.module.model.last_reflection
#if self.module.model.serial.canReadLine():
text = self.module.model.serial.readLine().data().decode("utf-8") # Set the timeout duration (e.g., 5 seconds)
if text: timeout_duration = 5
logger.debug("Received reflection: %s", text) # Record the start time
#self.module.model.waiting_for_reflection = False start_time = time.time()
#return text
#else: # Wait for reflection data until the timeout is reached
time.sleep(0.1) while reflection is None:
# Check if the timeout has been reached
if time.time() - start_time > timeout_duration:
logger.error("Reading reflection timed out after %d seconds", timeout_duration)
self.module.view.add_error_text(f"Could not read reflection. Timed out after {timeout_duration} seconds")
return None
# Refresh the reflection data
reflection = self.module.model.last_reflection
QApplication.processEvents()
# Reset the reflection cache
self.module.model.last_reflection = None
return reflection
else: else:
logger.error("Could not read reflection. No confirmation received") logger.error("Could not read reflection. No confirmation received")
self.module.view.add_error_text("Could not read reflection. No confirmation received") self.module.view.add_error_text("Could not read reflection. No confirmation received")
self.module.model.waiting_for_reflection = False
return None return None
except Exception as e: except Exception as e:
logger.error("Could not read reflection. %s", e) logger.error("Could not read reflection. %s", e)
self.module.view.add_error_text("Could not read reflection. %s" % e) self.module.view.add_error_text(f"Could not read reflection. {e}")
self.module.model.waiting_for_reflection = False
return None return None

View file

@ -380,7 +380,7 @@ class AutoTMModel(ModuleModel):
self.el_lut = None self.el_lut = None
self.mech_lut = None self.mech_lut = None
self.waiting_for_reflection = False self.last_reflection = None
@property @property
def available_devices(self): def available_devices(self):