diff --git a/imswitch/imcontrol/controller/controllers/FocusLockController.py b/imswitch/imcontrol/controller/controllers/FocusLockController.py index 1a36d4ede..145ac1f83 100644 --- a/imswitch/imcontrol/controller/controllers/FocusLockController.py +++ b/imswitch/imcontrol/controller/controllers/FocusLockController.py @@ -34,10 +34,6 @@ def __init__(self, *args, **kwargs): return self.camera = self._setupInfo.focusLock.camera - if self.camera == "ESP32": - self.isESP32 = True - else: - self.isESP32 = False self.positioner = self._setupInfo.focusLock.positioner self.updateFreq = self._setupInfo.focusLock.updateFreq self.cropFrame = (self._setupInfo.focusLock.frameCropx, @@ -45,14 +41,8 @@ def __init__(self, *args, **kwargs): self._setupInfo.focusLock.frameCropw, self._setupInfo.focusLock.frameCroph) - if self.isESP32: - # Create an instance of the ESP32CameraThread class - self.ESP32Camera = ESP32CameraThread('Espressif') - # Start the thread - self.ESP32Camera.startStreaming() - else: - self._master.detectorsManager[self.camera].crop(*self.cropFrame) + self._master.detectorsManager[self.camera].crop(*self.cropFrame) self._widget.setKp(self._setupInfo.focusLock.piKp) self._widget.setKi(self._setupInfo.focusLock.piKi) @@ -89,7 +79,7 @@ def __init__(self, *args, **kwargs): self.setPointData = np.zeros(self.buffer) self.timeData = np.zeros(self.buffer) - if not self.isESP32: self._master.detectorsManager[self.camera].startAcquisition() + self._master.detectorsManager[self.camera].startAcquisition() self.__processDataThread = ProcessDataThread(self) self.__focusCalibThread = FocusCalibThread(self) @@ -234,16 +224,8 @@ def __init__(self, controller, *args, **kwargs): def grabCameraFrame(self): - if not self._controller.isESP32: - detectorManager = self._controller._master.detectorsManager[self._controller.camera] - self.latestimg = detectorManager.getLatestFrame() - else: - try: - self.latestimg = self._controller.ESP32Camera.grabLatestFrame() - except: - self.latestimg = np.zeros((self._controller.ESP32Camera.Ny,self._controller.ESP32Camera.Nx)) - - + detectorManager = self._controller._master.detectorsManager[self._controller.camera] + self.latestimg = detectorManager.getLatestFrame() # 1.5 swap axes of frame (depending on setup, make this a variable in the json) if self._controller._setupInfo.focusLock.swapImageAxes: @@ -252,7 +234,7 @@ def grabCameraFrame(self): def update(self, twoFociVar): - if self._controller.isESP32: + if self._controller._master.detectorsManager[self._controller.camera].model == "ESP32SerialCamera": imagearraygf = ndi.filters.gaussian_filter(self.latestimg, 5) # mBackground = np.mean(mStack, (0)) #np.ones(mStack.shape[1:])# mBackground = ndi.filters.gaussian_filter(self.latestimg,15) @@ -407,108 +389,6 @@ def ki(self, value): -class ESP32CameraThread(object): - # attention a threading class won't work in windows!!! #FIXME: - def __init__(self, manufacturer): - self.manufacturer = manufacturer - self.serialdevice = None - self.Nx, self.Ny = 320,240 - self.frame = np.zeros((self.Ny,self.Nx)) - - # string to send data to camera - self.newCommand = "" - self.exposureTime = -1 - self.gain = -1 - - def setExposureTime(self, exposureTime): - self.newCommand = "t"+str(exposureTime) - self.exposureTime = exposureTime - - def setGain(self, gain): - self.newCommand = "g"+str(gain) - self.gain = gain - - def connect_to_usb_device(self): - ports = serial.tools.list_ports.comports() - for port in ports: - if port.manufacturer == self.manufacturer or port.manufacturer=="Microsoft": - try: - ser = serial.Serial(port.device, baudrate=2000000, timeout=1) - ser.write_timeout=.5 - print(f"Connected to device: {port.description}") - return ser - except serial.SerialException: - print(f"Failed to connect to device: {port.description}") - print("No matching USB device found.") - return None - - def startStreaming(self): - self.isRunning = True - self.mThread = threading.Thread(target=self.startStreamingThread) - self.mThread.start() - - def stopStreaming(self): - self.isRunning = False - self.mThread.join() - try:self.serialdevice.close() - except:pass - - def startStreamingThread(self): - self.serialdevice = self.connect_to_usb_device() - nFrame = 0 - nTrial = 0 - while self.isRunning: - try: - - # send new comamand to change camera settings, reset command - if not self.newCommand == "": - self.serialdevice.write((self.newCommand+' \n').encode()) - self.newCommand = "" - - # request new image - self.serialdevice.write((' \n').encode()) - - # don't read to early - time.sleep(.05) - # readline of camera - imageB64 = self.serialdevice.readline() - - # decode byte stream - image = np.array(Image.open(io.BytesIO(base64.b64decode(imageB64.decode())))) - self.frame = np.mean(image,-1) - - nFrame += 1 - - except Exception as e: - # try to reconnect - #print(e) # most of the time "incorrect padding of the bytes " - nFrame = 0 - nTrial+=1 - try: - self.serialdevice.flushInput() - self.serialdevice.flushOutput() - except: - pass - if nTrial > 10 and type(e)==serial.serialutil.SerialException: - try: - # close the device - similar to hard reset - self.serialdevice.setDTR(False) - self.serialdevice.setRTS(True) - time.sleep(.1) - self.serialdevice.setDTR(False) - self.serialdevice.setRTS(False) - time.sleep(.5) - #self.serialdevice.close() - except: pass - self.serialdevice = self.connect_to_usb_device() - nTrial = 0 - - - def grabLatestFrame(self): - return self.frame - - - # Copyright (C) 2020-2021 ImSwitch developers # This file is part of ImSwitch. diff --git a/imswitch/imcontrol/controller/controllers/MCTController.py b/imswitch/imcontrol/controller/controllers/MCTController.py index c959d1743..6f5c8c077 100644 --- a/imswitch/imcontrol/controller/controllers/MCTController.py +++ b/imswitch/imcontrol/controller/controllers/MCTController.py @@ -317,7 +317,7 @@ def takeTimelapseThread(self, tperiod = 1): self.stages.setSpeed(speed=1000, axis="Z") # ensure motors are enabled - self.stages.enalbeMotors(enable=True) + #self.stages.enalbeMotors(enable=True) try: # want to do autofocus? @@ -413,10 +413,10 @@ def acquireScan(self, timestamp=0): # in case something is not connected we want to reconnect! # TODO: This should go into some function outside the MCT!!! - if not ("IDENTIFIER_NAME" in self._master.UC2ConfigManager.ESP32.state.get_state() and self._master.UC2ConfigManager.ESP32.state.get_state()["IDENTIFIER_NAME"] == "uc2-esp"): - mThread = threading.Thread(target=self._master.UC2ConfigManager.initSerial) - mThread.start() - mThread.join() + #if not ("IDENTIFIER_NAME" in self._master.UC2ConfigManager.ESP32.state.get_state() and self._master.UC2ConfigManager.ESP32.state.get_state()["IDENTIFIER_NAME"] == "uc2-esp"): + # mThread = threading.Thread(target=self._master.UC2ConfigManager.initSerial) + # mThread.start() + # mThread.join() # initialize xyz coordinates if self.xyScanEnabled: diff --git a/imswitch/imcontrol/model/interfaces/CameraESP32CamSerial.py b/imswitch/imcontrol/model/interfaces/CameraESP32CamSerial.py index f92436e19..76248c7b6 100644 --- a/imswitch/imcontrol/model/interfaces/CameraESP32CamSerial.py +++ b/imswitch/imcontrol/model/interfaces/CameraESP32CamSerial.py @@ -16,6 +16,8 @@ def __init__(self): self.model = "ESP32Camera" self.shape = (0, 0) + self.isConnected = False + # camera parameters self.framesize = 100 self.exposure_time = 0 @@ -25,8 +27,8 @@ def __init__(self): self.SensorHeight = 240 self.manufacturer = 'Espressif' - self.serialdevice = None - self.frame = np.zeros((self.SensorHeight,self.SensorWidth)) + + self.frame = np.ones((self.SensorHeight,self.SensorWidth)) self.isRunning = False # string to send data to camera @@ -34,6 +36,8 @@ def __init__(self): self.exposureTime = -1 self.gain = -1 + self.serialdevice = self.connect_to_usb_device() + def connect_to_usb_device(self): ports = serial.tools.list_ports.comports() for port in ports: @@ -107,7 +111,9 @@ def getLast(self): return self.frame def startStreamingThread(self): - self.serialdevice = self.connect_to_usb_device() + # if we have never connected anything we should return and not always try to reconnecnt + if self.serialdevice is None: + return nFrame = 0 nTrial = 0 while self.isRunning: diff --git a/imswitch/imcontrol/model/managers/detectors/ESP32SerialCamManager.py b/imswitch/imcontrol/model/managers/detectors/ESP32SerialCamManager.py index 6fc5f4a12..099e5e64c 100644 --- a/imswitch/imcontrol/model/managers/detectors/ESP32SerialCamManager.py +++ b/imswitch/imcontrol/model/managers/detectors/ESP32SerialCamManager.py @@ -69,7 +69,7 @@ def getParameter(self, name): def getChunk(self): - pass + return np.expand_dims(self._camera.getLastChunk(),0) def flushBuffers(self): pass diff --git a/imswitch/imcontrol/model/managers/positioners/ESP32StageManager.py b/imswitch/imcontrol/model/managers/positioners/ESP32StageManager.py index 99f418e12..1042aafcf 100644 --- a/imswitch/imcontrol/model/managers/positioners/ESP32StageManager.py +++ b/imswitch/imcontrol/model/managers/positioners/ESP32StageManager.py @@ -3,7 +3,9 @@ import time import numpy as np from imswitch.imcommon.model import APIExport, generateAPI, initLogger - +import threading + + PHYS_FACTOR = 1 gTIMEOUT = 100 class ESP32StageManager(PositionerManager): @@ -218,35 +220,23 @@ def move(self, value=0, axis="X", is_absolute=False, is_blocking=True, accelerat if axis == 'X': self._motor.move_x(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout) - if not is_absolute: self._position[axis] = self._position[axis] + value - else: self._position[axis] = value elif axis == 'Y': self._motor.move_y(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout) - if not is_absolute: self._position[axis] = self._position[axis] + value - else: self._position[axis] = value elif axis == 'Z': self._motor.move_z(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout) - if not is_absolute: self._position[axis] = self._position[axis] + value - else: self._position[axis] = value elif axis == 'T': self._motor.move_t(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout) - if not is_absolute: self._position[axis] = self._position[axis] + value - else: self._position[axis] = value elif axis == 'XY': self._motor.move_xy(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout) - for i, iaxis in enumerate(("X", "Y")): - if not is_absolute: - self._position[iaxis] = self._position[iaxis] + value[i] - else: - self._position[iaxis] = value[i] elif axis == 'XYZ': self._motor.move_xyz(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout) - for i, iaxis in enumerate(("X", "Y")): - if not is_absolute: self._position[iaxis] = self._position[iaxis] + value[i] - else: self._position[iaxis] = value[i] else: print('Wrong axis, has to be "X" "Y" or "Z".') + # finally update positions + threading.Thread(target=self.getPosition).start() + + def measure(self, sensorID=0, NAvg=100): return self._motor.read_sensor(sensorID=sensorID, NAvg=NAvg) @@ -271,9 +261,6 @@ def setSpeed(self, speed, axis=None): self._speed[axis] = speed def setPosition(self, value, axis): - # if value: value += 1 # TODO: Firmware weirdness - # self._motor.set_position(axis=axis, position=value) # TODO: this line does nothing - # self._motor.set_motor_currentPosition(axis=axis, currentPosition=value) # axis, currentPosition # print(f"setPosition - Axis: {axis} -> New Value: {value}") self._position[axis] = value @@ -281,13 +268,17 @@ def closeEvent(self): pass def getPosition(self): + # load position from device + # t,x,y,z try: time.sleep(0.5) allPositions = self._motor.get_position() except: allPositions = [0,0,0,0] - - return {"X": allPositions[1], "Y": allPositions[2], "Z": allPositions[3], "T": allPositions[0]} + allPositionsDict={"X": allPositions[1], "Y": allPositions[2], "Z": allPositions[3], "T": allPositions[0]} + for iPosAxis, iPosVal in allPositionsDict.items(): + self.setPosition(iPosVal,iPosAxis) + return allPositionsDict def forceStop(self, axis): if axis=="X": @@ -330,12 +321,10 @@ def doHome(self, axis, isBlocking=False): def home_x(self, isBlocking): self._homeModule.home_x(speed=self.homeSpeedX, direction=self.homeDirectionX, isBlocking=isBlocking) self.setPosition(axis="X", value=0) - # self._position["X"] = 0 def home_y(self,isBlocking): self._homeModule.home_y(speed=self.homeSpeedY, direction=self.homeDirectionY, isBlocking=isBlocking) self.setPosition(axis="Y", value=0) - # self._position["Y"] = 0 def home_z(self,isBlocking): self._homeModule.home_z(speed=self.homeSpeedZ, direction=self.homeDirectionZ, isBlocking=isBlocking)