Skip to content

Commit

Permalink
updating uc2configmanager
Browse files Browse the repository at this point in the history
  • Loading branch information
beniroquai committed Aug 11, 2023
1 parent 6472e40 commit 2254cc6
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 316 deletions.
4 changes: 3 additions & 1 deletion imswitch/imcontrol/controller/CommunicationChannel.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ class CommunicationChannel(SignalInterface):

sigScanFrameFinished = Signal() # TODO: emit this signal when a scanning frame finished, maybe in scanController if possible? Otherwise in APDManager for now, even if that is not general if you want to do camera-based experiments. Could also create a signal specifically for this from the scan curve generator perhaps, specifically for the rotation experiments, would that be smarter?

sigUpdateRotatorPosition = Signal(str) # (rotatorName)
sigUpdateRotatorPosition = Signal(str, str) # (rotatorName)

sigUpdateMotorPosition = Signal() # # TODO: Just forcely update the positoin in the GUI

sigSetSyncInMovementSettings = Signal(str, float) # (rotatorName, position)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ def __init__(self, *args, **kwargs):

# Connect CommunicationChannel signals
self._commChannel.sharedAttrs.sigAttributeSet.connect(self.attrChanged)
self._commChannel.sigUpdateMotorPosition.connect(self.updateAllPositionGUI) # force update position in GUI

# Connect PositionerWidget signals
self._widget.sigStepUpClicked.connect(self.stepUp)
self._widget.sigStepDownClicked.connect(self.stepDown)
self._widget.sigStepAbsoluteClicked.connect(self.moveAbsolute)
self._widget.sigHomeAxisClicked.connect(self.homeAxis)
self._widget.sigStopAxisClicked.connect(self.stopAxis)
self._commChannel.sigUpdateMotorPosition.connect(self.updateAllPositionGUI)

def closeEvent(self):
self._master.positionersManager.execOnAll(
Expand Down Expand Up @@ -95,6 +97,13 @@ def setSpeed(self, positionerName, axis, speed=(1000, 1000, 1000)):
self.setSharedAttr(positionerName, axis, _speedAttr, speed)
self._widget.setSpeedSize(positionerName, axis, speed)

def updateAllPositionGUI(self):
# update all positions for all axes in GUI
for positionerName in self._master.positionersManager.getAllDeviceNames():
for axis in self._master.positionersManager[positionerName].axes:
self.updatePosition(positionerName, axis)
self.updateSpeed(positionerName, axis)

def updatePosition(self, positionerName, axis):
if axis == "XY":
for axis in (("X", "Y")):
Expand Down
223 changes: 45 additions & 178 deletions imswitch/imcontrol/controller/controllers/UC2ConfigController.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,195 +15,62 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__logger = initLogger(self)


self.UC2ConfigDir = os.path.join(dirtools.UserFileDirs.Root, 'imcontrol_UC2Config')
if not os.path.exists(self.UC2ConfigDir):
os.makedirs(self.UC2ConfigDir)
# get Updatemanager
self.updater = self._master.UC2ConfigManager
# Connect buttons to the logic handlers
self._widget.setPositionsBtn.clicked.connect(self.set_positions)
self._widget.autoEnableBtn.clicked.connect(self.set_auto_enable)
self._widget.unsetAutoEnableBtn.clicked.connect(self.unset_auto_enable)
self._widget.reconnectButton.clicked.connect(self.reconnect)
self._widget.btpairingButton.clicked.connect(self.btpairing)

return
# 1. load config from device
self.mConfigDevice = self.loadConfigFromDevice()
# switch-back to old configuration
if len(self.mConfigDevice)<4:
self.mConfigDevice = self.loadDefaultConfig()
self._widget.controlPanel.updateFirmwareDeviceLabel.setText("Something's wrong with the \n device/firmware, please reflash/reconnect!")

'''TODO: Reimplement?
# 1b. load default config if device not valid -> E.G. after flashing
if "motorconfig" in self.mConfigDevice and self.mConfigDevice['motorconfig'][1]["enable"]==0: # the defaultconfig has not been written
try:
self.__logger.debug("Trying to load default config from file")
self.mConfigDevice = self.loadDefaultConfigFromFile()
self._master.UC2ConfigManager.setpinDef(self.mConfigDevice)
except Exception as e:
self.__logger.error(e)
else:
self.__logger.error("Device not connected?!")
# 2. display device configs in the GUI
self.displayConfig(config=self.mConfigDevice)
#here we should write the default pindef for uc2 standalone or esp32 standalone
'''
# save parameters on the disk
self.defaultPinDefFile = "pinDef.json"

if self._setupInfo.uc2Config is None:
self._widget.replaceWithError('UC2Config is not configured in your setup file.')
return

self._widget.controlPanel.saveButton.clicked.connect(self.saveParams)
self._widget.controlPanel.loadButton.clicked.connect(self.loadParams)
self._widget.controlPanel.updateFirmwareDeviceButton.clicked.connect(self.updateFirmware)
self._widget.applyChangesButton.clicked.connect(self.applyParams)

self.isFirmwareUpdating = False

def loadConfigFromDevice(self):
return self._master.UC2ConfigManager.loadPinDefDevice()

def loadDefaultConfig(self):
return self._master.UC2ConfigManager.loadDefaultConfig()

def loadConfigToDevice(self, config):
pass

def saveParams(self):
UC2Config_info_dict = self.getInfoDict(self._widget.UC2ConfigParameterTree.p,
self._widget.pinDefParameterTree.p)
with open(os.path.join(self.UC2ConfigDir, self.defaultPinDefFile), 'w') as f:
json.dump(UC2Config_info_dict, f, indent=4)

def getInfoDict(self, generalParams=None, pinDefParams=None):
state_general = None
state_pinDef = None

if generalParams is not None:
# create dict for general params
generalparamnames = ["radius", "sigma", "rotationAngle"]
state_general = {generalparamname: float(
generalParams.param("general").param(generalparamname).value()) for generalparamname
in generalparamnames}

if pinDefParams is not None:
# create dict for pinDefration params
pinDefparamnames = pinDefParams.childs[0].names
state_pinDef = {}
for key in pinDefparamnames:
state_pinDef[key] = int(pinDefParams.childs[0][key])

info_dict = {
"general": state_general,
"pinDef": state_pinDef
}
return info_dict

def loadParams(self, config=None):
if config is not None and config:
state_general = None # TODO: Implement
state_pinDef = config

else: # TODO: Enabling sideloading the configuration? But ESP will be offline anyway..
with open(os.path.join(self.UC2ConfigDir, self.defaultPinDefFile), 'rb') as f:
UC2Config_info_dict = json.load(f)
state_general = UC2Config_info_dict["general"]
state_pinDef = UC2Config_info_dict["pinDef"]
self.setParamTree(state_general=state_general, state_pinDef=state_pinDef)
#self._master.UC2ConfigManager.setGeneral(state_general)


self.stages = self._master.positionersManager[self._master.positionersManager.getAllDeviceNames()[0]]

def set_motor_positions(self, a, x, y, z):
# Add your logic to set motor positions here.
print(f"Setting motor positions: A={a}, X={x}, Y={y}, Z={z}")
# push the positions to the motor controller
self.stages.setPositionOnDevice(value=float(a), axis="A")
self.stages.setPositionOnDevice(value=float(x), axis="X")
self.stages.setPositionOnDevice(value=float(y), axis="Y")
self.stages.setPositionOnDevice(value=float(z), axis="Z")

# retrieve the positions from the motor controller
positions = self.stages.getPosition()
self._widget.reconnectDeviceLabel.setText("Motor positions: A="+str(positions["A"])+", X="+str(positions["X"])+", \n Y="+str(positions["Y"])+", Z="+str(positions["Z"]))
# update the GUI
self._commChannel.sigUpdateMotorPosition.emit()

def set_auto_enable(self):
# Add your logic to auto-enable the motors here.
# get motor controller
self.stages.enalbeMotors(enableauto=True)

def unset_auto_enable(self):
# Add your logic to unset auto-enable for the motors here.
self.stages.enalbeMotors(enableauto=False)

def set_positions(self):
a = self._widget.motorAEdit.text()
x = self._widget.motorXEdit.text()
y = self._widget.motorYEdit.text()
z = self._widget.motorZEdit.text()
self.set_motor_positions(a, x, y, z)

def reconnectThread(self):
self._master.UC2ConfigManager.initSerial()
self._widget.reconnectDeviceLabel.setText("We are connected: "+str(self._master.UC2ConfigManager.isConnected()))

def reconnect(self):
self._logger.debug('Reconnecting to ESP32 device.')
self._widget.controlPanel.updateFirmwareDeviceLabel.setText("Reconnecting to ESP32 device.")
mThread = threading.Thread(target=self._master.UC2ConfigManager.initSerial)
self._widget.reconnectDeviceLabel.setText("Reconnecting to ESP32 device.")
mThread = threading.Thread(target=self.reconnectThread)
mThread.start()
mThread.join()
self._widget.controlPanel.updateFirmwareDeviceLabel.setText("We are connected: "+str(self._master.UC2ConfigManager.isConnected()))

def btpairing(self):
self._logger.debug('Pairing BT device.')
mThread = threading.Thread(target=self._master.UC2ConfigManager.pairBT)
mThread.start()
mThread.join()
self._widget.controlPanel.updateFirmwareDeviceLabel.setText("Bring the PS controller into pairing mode")


def updateFirmware(self, filename=None):
if not(self.isFirmwareUpdating):
self._widget.controlPanel.updateFirmwareDeviceButton.setEnabled(False)
threading.Thread(target=self.updateFirmwareThread, args=(filename,)).start()
self.isFirmwareUpdating = True

def updateFirmwareThread(self, filename=None):
# 1. download firmware
self._widget.controlPanel.updateFirmwareDeviceLabel.setText('Downloading firmware...')
FWdownloaded = self._master.UC2ConfigManager.downloadFirmware(filename)

# 2.1 close serial connection

# 2.2 flash firmware
if FWdownloaded:
self._widget.controlPanel.updateFirmwareDeviceLabel.setText('Flashing firmware...')
FWflashed = self._master.UC2ConfigManager.flashFirmware()
else:
self._widget.controlPanel.updateFirmwareDeviceLabel.setText('Firmware not downloaded.')
return


# 3. delete firmware
if FWflashed:
self._widget.controlPanel.updateFirmwareDeviceLabel.setText('Deleting firmware...')
self._master.UC2ConfigManager.removeFirmware()
else:
self._master.UC2ConfigManager.removeFirmware()
self._widget.controlPanel.updateFirmwareDeviceLabel.setText('Firmware not flashed.')
return

self._widget.controlPanel.updateFirmwareDeviceLabel.setText('Firmware was flashed.')

# 4. reestablish serial connection
self._master.UC2ConfigManager.initSerial()
self.isFirmwareUpdating = False
self._widget.controlPanel.updateFirmwareDeviceButton.setEnabled(True)

def removeFirmware(self, firmwarePath):
return self.firmwareUpdater.removeFirmware()

def setParamTree(self, state_general, state_pinDef):
generalParams = self._widget.UC2ConfigParameterTree.p
pinDefParams = self._widget.pinDefParameterTree.p

if pinDefParams is not None:
# create dict for pinDefration params
pinDefparamnames = pinDefParams.childs[0].names
for key in pinDefparamnames:
try:
pinDefParams.childs[0].param(key).setValue(state_pinDef[key])
except KeyError:
pass


def applyParams(self):
UC2Config_info_dict = self.getInfoDict(generalParams=self._widget.UC2ConfigParameterTree.p,
pinDefParams=self._widget.pinDefParameterTree.p)
#self.applyGeneral(UC2Config_info_dict["general"])
self.mConfigOffline = UC2Config_info_dict["pinDef"]
self.applypinDef(self.mConfigOffline)

def applyGeneral(self, info_dict):
self._master.UC2ConfigManager.setGeneral(info_dict)
image = self._master.UC2ConfigManager.update(maskChange=True)
self.updateDisplayImage(image)
# self._logger.debug('Apply changes to general UC2Config mask parameters.')

def applypinDef(self, info_dict):
shared_items = self._master.UC2ConfigManager.setpinDef(info_dict)
self._widget.controlPanel.updateFirmwareDeviceLabel.setText("Udated items: "+str(len(shared_items))+"/"+str(len(info_dict)))
self._logger.debug('Apply changes to pinDef.')

self._widget.reconnectDeviceLabel.updateFirmwareDeviceLabel.setText("Bring the PS controller into pairing mode")


# Copyright (C) 2020-2021 ImSwitch developers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ def move(self, value=0, axis="X", is_absolute=False, is_blocking=True, accelerat
else: self._position[iaxis] = value[i]
else:
print('Wrong axis, has to be "X" "Y" or "Z".')




def measure(self, sensorID=0, NAvg=100):
return self._motor.read_sensor(sensorID=sensorID, NAvg=NAvg)
Expand Down Expand Up @@ -184,6 +187,10 @@ def setPosition(self, value, axis):
# print(f"setPosition - Axis: {axis} -> New Value: {value}")
self._position[axis] = value

def setPositionOnDevice(self, value, axis):
self.setPosition(value, axis)
self._motor.set_position(axis, value)

def closeEvent(self):
pass

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ def setPosition(self, position: float, axis: str):
def finalize(self) -> None:
""" Close/cleanup positioner. """
pass

def enableMotors(self, enable: bool=None, autoenable:bool=None) -> None:
""" Enable/disable motors. """
pass


# Copyright (C) 2020-2021 ImSwitch developers
Expand Down
2 changes: 2 additions & 0 deletions imswitch/imcontrol/view/widgets/PositionerWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def addPositioner(self, positionerName, axes, hasSpeed, hasHome=True, hasStop=Tr
)

self.numPositioners += 1



def getAbsPosition(self, positionerName, axis):
""" Returns the absolute position of the specified positioner axis in
Expand Down
Loading

0 comments on commit 2254cc6

Please sign in to comment.