-
Notifications
You must be signed in to change notification settings - Fork 47
a performance improvement for scanning #262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
53e3bbe
7f696ed
28f0684
860725f
9eb55fa
d3d0b32
c901147
c6fbcca
b7a9ce2
1c1f885
5cb40c7
c427919
3a1aa64
8ebcf2c
2f93b68
6a3c3ac
b5ee8a5
b1e393e
10e8ebe
a9acc9c
7d53cc3
68869a5
dd613bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,7 @@ | |
| // byte[2]: how many micro steps - upper 8 bits | ||
| // byte[3]: how many micro steps - lower 8 bits | ||
|
|
||
| static const int CMD_LENGTH = 8; | ||
| static const int CMD_LENGTH = 12; | ||
| static const int MSG_LENGTH = 24; | ||
| byte buffer_rx[512]; | ||
| byte buffer_tx[MSG_LENGTH]; | ||
|
|
@@ -67,6 +67,8 @@ static const int SET_PID_ARGUMENTS = 29; | |
| static const int SEND_HARDWARE_TRIGGER = 30; | ||
| static const int SET_STROBE_DELAY = 31; | ||
| static const int SET_AXIS_DISABLE_ENABLE = 32; | ||
| static const int MOVETO_XY = 34; | ||
| static const int SET_SRAMP_MOD = 36; | ||
| static const int SET_PIN_LEVEL = 41; | ||
| static const int INITFILTERWHEEL = 253; | ||
| static const int INITIALIZE = 254; | ||
|
|
@@ -301,12 +303,11 @@ uint16_t home_safety_margin[4] = {4, 4, 4, 4}; | |
| // IntervalTimer does not work on teensy with SPI, the below lines are to be removed | ||
| static const int TIMER_PERIOD = 500; // in us | ||
| volatile int counter_send_pos_update = 0; | ||
| volatile bool flag_send_pos_update = false; | ||
|
|
||
| static const int interval_send_pos_update = 10000; // in us | ||
| elapsedMicros us_since_last_pos_update; | ||
|
|
||
| static const int interval_check_position = 10000; // in us | ||
| static const int interval_check_position = 5000; // in us | ||
| elapsedMicros us_since_last_check_position; | ||
|
|
||
| static const int interval_send_joystick_update = 30000; // in us | ||
|
|
@@ -356,7 +357,7 @@ void onJoystickPacketReceived(const uint8_t* buffer, size_t size) | |
| } | ||
| else | ||
| { | ||
| focusPosition = focusPosition + (int32_t(uint32_t(buffer[0]) << 24 | uint32_t(buffer[1]) << 16 | uint32_t(buffer[2]) << 8 | uint32_t(buffer[3])) - focuswheel_pos); | ||
| focusPosition = focusPosition - (int32_t(uint32_t(buffer[0]) << 24 | uint32_t(buffer[1]) << 16 | uint32_t(buffer[2]) << 8 | uint32_t(buffer[3])) - focuswheel_pos); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't figure out why we switched the sign here. Can you help me understand how this is related to scanning performance, and what the sign switch does?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The knob is designed to increase with clockwise rotation and decrease with counterclockwise rotation. This modification aims to align with conventional intuition. |
||
| focuswheel_pos = int32_t(uint32_t(buffer[0]) << 24 | uint32_t(buffer[1]) << 16 | uint32_t(buffer[2]) << 8 | uint32_t(buffer[3])); | ||
| } | ||
|
|
||
|
|
@@ -911,6 +912,21 @@ void loop() { | |
| } | ||
| break; | ||
| } | ||
| case MOVETO_XY: | ||
| { | ||
| long x_absolute_position = int32_t(uint32_t(buffer_rx[2]) << 24 | uint32_t(buffer_rx[3]) << 16 | uint32_t(buffer_rx[4]) << 8 | uint32_t(buffer_rx[5])); | ||
| X_direction = sgn(x_absolute_position - tmc4361A_currentPosition(&tmc4361[x])); | ||
| X_commanded_target_position = x_absolute_position; | ||
| if (tmc4361A_moveTo(&tmc4361[x], X_commanded_target_position) == 0) | ||
| X_commanded_movement_in_progress = true; | ||
| long y_absolute_position = int32_t(uint32_t(buffer_rx[6]) << 24 | uint32_t(buffer_rx[7]) << 16 | uint32_t(buffer_rx[8]) << 8 | uint32_t(buffer_rx[9])); | ||
| Y_direction = sgn(y_absolute_position - tmc4361A_currentPosition(&tmc4361[y])); | ||
| Y_commanded_target_position = y_absolute_position; | ||
| if (tmc4361A_moveTo(&tmc4361[y], Y_commanded_target_position) == 0) | ||
| Y_commanded_movement_in_progress = true; | ||
| mcu_cmd_execution_in_progress = true; | ||
| break; | ||
| } | ||
| case MOVETO_Z: | ||
| { | ||
| long absolute_position = int32_t(uint32_t(buffer_rx[2]) << 24 | uint32_t(buffer_rx[3]) << 16 | uint32_t(buffer_rx[4]) << 8 | uint32_t(buffer_rx[5])); | ||
|
|
@@ -938,6 +954,21 @@ void loop() { | |
| } | ||
| break; | ||
| } | ||
| case SET_SRAMP_MOD: | ||
| { | ||
| uint8_t axis = buffer_rx[2]; | ||
| uint8_t mode = buffer_rx[3]; | ||
| // map to w axis, in the host w axis index is 5 | ||
| if (axis == AXIS_W) | ||
| axis = w; | ||
|
|
||
| // guard code | ||
| if (axis > STAGE_AXES) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it only okay to change the ramp mode for X, Y, and Z? It isn't okay to change them for THETA and W?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For safety reasons, I’ve only tested along the X, Y, and Z axes so far, so I’m keeping it in safe mode for now.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This just fails silently, though. If someone tries to use this command with
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we let all other commands fail silently, so I guess we can keep this. We really need to introduce a mechanism for communicating command failures, though. Failing silently shouldn't be an option! |
||
| return; | ||
|
|
||
| tmc4361[axis].ramp_mode = mode; | ||
| break; | ||
| } | ||
| case SET_LIM: | ||
| { | ||
| switch (buffer_rx[2]) | ||
|
|
@@ -2181,9 +2212,9 @@ void loop() { | |
| buffer_tx[18] &= ~ (1 << BIT_POS_JOYSTICK_BUTTON); // clear the joystick button bit | ||
| buffer_tx[18] = buffer_tx[18] | joystick_button_pressed << BIT_POS_JOYSTICK_BUTTON; | ||
|
|
||
| // Calculate and fill out the checksum. NOTE: This must be after all other buffer_tx modifications are done! | ||
| uint8_t checksum = crc8ccitt(buffer_tx, MSG_LENGTH - 1); | ||
| buffer_tx[MSG_LENGTH - 1] = checksum; | ||
| // Calculate and fill out the checksum. NOTE: This must be after all other buffer_tx modifications are done! | ||
| uint8_t checksum = crc8ccitt(buffer_tx, MSG_LENGTH - 1); | ||
| buffer_tx[MSG_LENGTH - 1] = checksum; | ||
|
|
||
| if(!DEBUG_MODE) | ||
| SerialUSB.write(buffer_tx,MSG_LENGTH); | ||
|
|
@@ -2201,8 +2232,6 @@ void loop() { | |
| SerialUSB.print(", PG:"); | ||
| SerialUSB.println(digitalRead(pin_PG)); | ||
| } | ||
| flag_send_pos_update = false; | ||
|
|
||
| } | ||
|
|
||
| // keep checking position process at suitable frequence | ||
|
|
@@ -2213,22 +2242,29 @@ void loop() { | |
| { | ||
| X_commanded_movement_in_progress = false; | ||
| mcu_cmd_execution_in_progress = false || Y_commanded_movement_in_progress || Z_commanded_movement_in_progress || W_commanded_movement_in_progress; | ||
| // It's important that we check positions next time around because | ||
| // once the axis reaches the target position, we need the PC to be notified instantly. | ||
| // Other axes are the same reason. | ||
| us_since_last_pos_update = interval_send_pos_update + 1; | ||
| } | ||
| if (Y_commanded_movement_in_progress && tmc4361A_currentPosition(&tmc4361[y]) == Y_commanded_target_position && !is_homing_Y && !tmc4361A_isRunning(&tmc4361[y], stage_PID_enabled[y])) | ||
| { | ||
| Y_commanded_movement_in_progress = false; | ||
| mcu_cmd_execution_in_progress = false || X_commanded_movement_in_progress || Z_commanded_movement_in_progress || W_commanded_movement_in_progress; | ||
| us_since_last_pos_update = interval_send_pos_update + 1; | ||
| } | ||
| if (Z_commanded_movement_in_progress && tmc4361A_currentPosition(&tmc4361[z]) == Z_commanded_target_position && !is_homing_Z && !tmc4361A_isRunning(&tmc4361[z], stage_PID_enabled[z])) | ||
| { | ||
| Z_commanded_movement_in_progress = false; | ||
| mcu_cmd_execution_in_progress = false || X_commanded_movement_in_progress || Y_commanded_movement_in_progress || W_commanded_movement_in_progress; | ||
| us_since_last_pos_update = interval_send_pos_update + 1; | ||
| } | ||
| if (enable_filterwheel == true) { | ||
| if (W_commanded_movement_in_progress && tmc4361A_currentPosition(&tmc4361[w]) == W_commanded_target_position && !is_homing_W && !tmc4361A_isRunning(&tmc4361[w], stage_PID_enabled[w])) | ||
| { | ||
| W_commanded_movement_in_progress = false; | ||
| mcu_cmd_execution_in_progress = false || X_commanded_movement_in_progress || Y_commanded_movement_in_progress || Z_commanded_movement_in_progress; | ||
| us_since_last_pos_update = interval_send_pos_update + 1; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -2270,28 +2306,6 @@ void loop() { | |
| } | ||
| } | ||
|
|
||
| /*************************************************** | ||
|
|
||
| timer interrupt | ||
|
|
||
| ***************************************************/ | ||
|
|
||
| // timer interrupt | ||
| /* | ||
| // IntervalTimer stops working after SPI.begin() | ||
| void timer_interruptHandler() | ||
| { | ||
| SerialUSB.println("timer event"); | ||
| counter_send_pos_update = counter_send_pos_update + 1; | ||
| if(counter_send_pos_update==interval_send_pos_update/TIMER_PERIOD) | ||
| { | ||
| flag_send_pos_update = true; | ||
| counter_send_pos_update = 0; | ||
| SerialUSB.println("send pos update"); | ||
| } | ||
| } | ||
| */ | ||
|
|
||
| /***************************************************************************************************/ | ||
| /********************************************* utils *********************************************/ | ||
| /***************************************************************************************************/ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -370,20 +370,17 @@ def update_coordinates_dataframe(self, region_id, z_level, pos: squid.abc.Pos, f | |
| self.coordinates_pd = pd.concat([self.coordinates_pd, new_row], ignore_index=True) | ||
|
|
||
| def move_to_coordinate(self, coordinate_mm): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe there's a reason I'm missing here, but this refactor duplicates code. Instead, I probably would do: This:
Also, since
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I would copy the code. |
||
| print("moving to coordinate", coordinate_mm) | ||
| x_mm = coordinate_mm[0] | ||
| self.stage.move_x_to(x_mm) | ||
| self._sleep(SCAN_STABILIZATION_TIME_MS_X / 1000) | ||
|
|
||
| y_mm = coordinate_mm[1] | ||
| self.stage.move_y_to(y_mm) | ||
| self._sleep(SCAN_STABILIZATION_TIME_MS_Y / 1000) | ||
| have_z = len(coordinate_mm) >= 3 | ||
| self.stage.move_xy_to(x_mm, y_mm, blocking=not have_z) | ||
|
|
||
| # check if z is included in the coordinate | ||
| if len(coordinate_mm) == 3: | ||
| if have_z: | ||
| z_mm = coordinate_mm[2] | ||
| self.move_to_z_level(z_mm) | ||
|
|
||
| self._sleep(SCAN_STABILIZATION_TIME_MS / 1000) | ||
|
|
||
| def move_to_z_level(self, z_mm): | ||
| print("moving z") | ||
| self.stage.move_z_to(z_mm) | ||
|
|
@@ -646,7 +643,6 @@ def acquire_camera_image( | |
| camera_illumination_time = self.camera.get_exposure_time() | ||
| if self.liveController.trigger_mode == TriggerMode.SOFTWARE: | ||
| self.liveController.turn_on_illumination() | ||
| self.wait_till_operation_is_completed() | ||
| camera_illumination_time = None | ||
| elif self.liveController.trigger_mode == TriggerMode.HARDWARE: | ||
| if "Fluorescence" in config.name and ENABLE_NL5 and NL5_USE_DOUT: | ||
|
|
@@ -719,7 +715,6 @@ def acquire_rgb_image(self, config, file_ID, current_path, current_round_images, | |
| if self.liveController.trigger_mode == TriggerMode.SOFTWARE: | ||
| # TODO(imo): use illum controller | ||
| self.liveController.turn_on_illumination() | ||
| self.wait_till_operation_is_completed() | ||
|
|
||
| # read camera frame | ||
| self.camera.send_trigger(illumination_time=self.camera.get_exposure_time()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -505,6 +505,10 @@ def __init__(self, serial_device: AbstractCephlaMicroSerial, reset_and_initializ | |
| self.log.debug("Resetting and initializing microcontroller.") | ||
| self.reset() | ||
| time.sleep(0.5) | ||
|
|
||
| # Need set the parameter before initialization | ||
| self.initizlize_sramp_of_axes() | ||
|
|
||
| if USE_SQUID_FILTERWHEEL: | ||
| self.init_filter_wheel() | ||
| time.sleep(0.5) | ||
|
|
@@ -561,6 +565,17 @@ def reset(self): | |
| # here. | ||
| self._cmd_id = 0 | ||
|
|
||
| def initizlize_sramp_of_axes(self): | ||
| # initialize axes sramp mode | ||
| self.set_sramp_mode(AXIS.X, X_AXIS_SRAMP_MODE) | ||
| self.wait_till_operation_is_completed() | ||
| self.set_sramp_mode(AXIS.Y, Y_AXIS_SRAMP_MODE) | ||
| self.wait_till_operation_is_completed() | ||
| self.set_sramp_mode(AXIS.Z, Z_AXIS_SRAMP_MODE) | ||
| self.wait_till_operation_is_completed() | ||
| self.set_sramp_mode(AXIS.W, W_AXIS_SRAMP_MODE) | ||
| self.wait_till_operation_is_completed() | ||
|
|
||
| def initialize_drivers(self): | ||
| self._cmd_id = 0 | ||
| cmd = bytearray(self.tx_buffer_length) | ||
|
|
@@ -684,6 +699,24 @@ def move_y_to_usteps(self, usteps): | |
| cmd[5] = payload & 0xFF | ||
| self.send_command(cmd) | ||
|
|
||
| def move_xy_to_usteps(self, xusteps, yusteps): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we also added a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I will temporarily remove MOVE_XY from the firmware. |
||
| xpayload = self._int_to_payload(xusteps, 4) | ||
| ypayload = self._int_to_payload(yusteps, 4) | ||
|
|
||
| cmd = bytearray(self.tx_buffer_length) | ||
| cmd[1] = CMD_SET.MOVETO_XY | ||
| cmd[2] = xpayload >> 24 | ||
| cmd[3] = (xpayload >> 16) & 0xFF | ||
| cmd[4] = (xpayload >> 8) & 0xFF | ||
| cmd[5] = xpayload & 0xFF | ||
|
|
||
| cmd[6] = ypayload >> 24 | ||
| cmd[7] = (ypayload >> 16) & 0xFF | ||
| cmd[8] = (ypayload >> 8) & 0xFF | ||
| cmd[9] = ypayload & 0xFF | ||
|
|
||
| self.send_command(cmd) | ||
|
|
||
| def move_z_usteps(self, usteps): | ||
| self._move_axis_usteps(usteps, CMD_SET.MOVE_Z) | ||
|
|
||
|
|
@@ -961,6 +994,9 @@ def configure_squidfilter(self): | |
| self.wait_till_operation_is_completed() | ||
| self.set_max_velocity_acceleration(AXIS.W, MAX_VELOCITY_W_mm, MAX_ACCELERATION_W_mm) | ||
| self.wait_till_operation_is_completed() | ||
| # initialize axes sramp mode | ||
| self.set_sramp_mode(AXIS.W, W_AXIS_SRAMP_MODE) | ||
| self.wait_till_operation_is_completed() | ||
|
|
||
| def ack_joystick_button_pressed(self): | ||
| cmd = bytearray(self.tx_buffer_length) | ||
|
|
@@ -994,6 +1030,13 @@ def set_pin_level(self, pin, level): | |
| cmd[3] = level | ||
| self.send_command(cmd) | ||
|
|
||
| def set_sramp_mode(self, axis, mode): | ||
| cmd = bytearray(self.tx_buffer_length) | ||
| cmd[1] = CMD_SET.SET_SRAMP_MOD | ||
| cmd[2] = axis | ||
| cmd[3] = mode | ||
| self.send_command(cmd) | ||
|
|
||
| def turn_on_AF_laser(self): | ||
| self.set_pin_level(MCU_PINS.AF_LASER, 1) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we don't initialize this in
tmc4361A_init, which means I think we default it to 0. To preserve the original behavior it'd be good to settmc4361a->ramp_mode = TMC4361_RAMP_SSHAPin the init.I know we set the ramp mode in our
.pyimplementation, but you generally don't want to assume other pieces of code will do the right thing.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I agree with you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@veerwang can you implement the suggested change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I would do it.