Skip to content

Commit 3aabe31

Browse files
authored
feat(thermocycler-gen2): add plate lift wiggling (#440)
* Change minimum hardware RPM * Wiggle plate during plate lift * Fixed tests for plate wiggling
1 parent cff6451 commit 3aabe31

File tree

4 files changed

+125
-34
lines changed

4 files changed

+125
-34
lines changed

stm32-modules/include/thermocycler-gen2/thermocycler-gen2/motor_task.hpp

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,21 @@ struct LidStepperState {
112112
// for this movement.
113113
constexpr static double CLOSE_OVERDRIVE_DEGREES =
114114
motor_util::LidStepper::angle_to_microsteps(-5);
115+
constexpr static double PLATE_LIFT_NUDGE_START_DEGREES =
116+
motor_util::LidStepper::angle_to_microsteps(11);
117+
constexpr static double PLATE_LIFT_NUDGE_FINAL_DEGREES =
118+
motor_util::LidStepper::angle_to_microsteps(15);
119+
constexpr static double PLATE_LIFT_NUDGE_INCREMENT =
120+
motor_util::LidStepper::angle_to_microsteps(0.5);
121+
constexpr static double PLATE_LIFT_RETURN_DEGREES =
122+
motor_util::LidStepper::angle_to_microsteps(5);
115123
constexpr static double PLATE_LIFT_RAISE_DEGREES =
116124
motor_util::LidStepper::angle_to_microsteps(20);
117125
constexpr static double PLATE_LIFT_LOWER_DEGREES =
118-
motor_util::LidStepper::angle_to_microsteps(-30);
126+
motor_util::LidStepper::angle_to_microsteps(-23);
119127
// Velocity for plate lift actions. This provides a smoother lifting
120128
// action than the default open/close velocity.
121-
constexpr static double PLATE_LIFT_VELOCITY_RPM = 80.0F;
129+
constexpr static double PLATE_LIFT_VELOCITY_RPM = 40.0F;
122130
// Velocity for all lid movements other than plate lift
123131
constexpr static double LID_DEFAULT_VELOCITY_RPM = 125.0F;
124132
// States for lid stepper
@@ -129,6 +137,8 @@ struct LidStepperState {
129137
OPEN_OVERDRIVE, /**< Close from switch back to 90º position.*/
130138
CLOSE_TO_SWITCH, /**< Close lid until it hits the switch.*/
131139
CLOSE_OVERDRIVE, /**< Close lid a few degrees into the switch.*/
140+
LIFT_NUDGE, /**< Nudge the plate up with one pin.*/
141+
LIFT_NUDGE_DOWN, /**< Move back to the "open" position after nudging.*/
132142
LIFT_RAISE, /**< Open lid to raise the plate lift.*/
133143
LIFT_LOWER, /**< Close lid to lower the plate lift.*/
134144
};
@@ -267,6 +277,7 @@ class MotorTask {
267277
motor_util::MovementType::OpenLoop, 0),
268278
_seal_velocity(SealStepperState::DEFAULT_VELOCITY),
269279
_seal_acceleration(SealStepperState::DEFAULT_ACCEL),
280+
_nudge_degrees(0),
270281
_seal_position(motor_util::SealStepper::Status::UNKNOWN) {}
271282
MotorTask(const MotorTask& other) = delete;
272283
auto operator=(const MotorTask& other) -> MotorTask& = delete;
@@ -996,11 +1007,11 @@ class MotorTask {
9961007
std::ignore = policy.lid_stepper_set_rpm(
9971008
LidStepperState::PLATE_LIFT_VELOCITY_RPM);
9981009
// Now start a lid motor movement to closed position
1010+
_nudge_degrees = LidStepperState::PLATE_LIFT_NUDGE_START_DEGREES;
9991011
policy.lid_stepper_set_dac(LID_STEPPER_RUN_CURRENT);
1000-
policy.lid_stepper_start(LidStepperState::PLATE_LIFT_RAISE_DEGREES,
1001-
true);
1012+
policy.lid_stepper_start(_nudge_degrees, true);
10021013
// Store the new state, as well as the response ID
1003-
_lid_stepper_state.status = LidStepperState::Status::LIFT_RAISE;
1014+
_lid_stepper_state.status = LidStepperState::Status::LIFT_NUDGE;
10041015
_lid_stepper_state.position = motor_util::LidStepper::Position::BETWEEN;
10051016
_lid_stepper_state.response_id = response_id;
10061017
return true;
@@ -1281,7 +1292,39 @@ class MotorTask {
12811292
// TODO(Frank, Mar-7-2022) check if the lid didn't make it in
12821293
// all the way
12831294
break;
1295+
case LidStepperState::Status::LIFT_NUDGE:
1296+
policy.lid_stepper_start(
1297+
-1 * LidStepperState::PLATE_LIFT_RETURN_DEGREES, true);
1298+
_lid_stepper_state.status =
1299+
LidStepperState::Status::LIFT_NUDGE_DOWN;
1300+
break;
1301+
case LidStepperState::Status::LIFT_NUDGE_DOWN:
1302+
// Slow speed for both repeat nudge and for final lift
1303+
std::ignore = policy.lid_stepper_set_rpm(
1304+
LidStepperState::PLATE_LIFT_VELOCITY_RPM);
1305+
if (_nudge_degrees <
1306+
LidStepperState::PLATE_LIFT_NUDGE_FINAL_DEGREES) {
1307+
_nudge_degrees +=
1308+
LidStepperState::PLATE_LIFT_NUDGE_INCREMENT;
1309+
policy.lid_stepper_start(
1310+
LidStepperState::PLATE_LIFT_RETURN_DEGREES +
1311+
LidStepperState::PLATE_LIFT_NUDGE_INCREMENT,
1312+
true);
1313+
_lid_stepper_state.status =
1314+
LidStepperState::Status::LIFT_NUDGE;
1315+
} else {
1316+
policy.lid_stepper_start(
1317+
LidStepperState::PLATE_LIFT_RAISE_DEGREES +
1318+
LidStepperState::PLATE_LIFT_RETURN_DEGREES -
1319+
_nudge_degrees,
1320+
true);
1321+
_lid_stepper_state.status =
1322+
LidStepperState::Status::LIFT_RAISE;
1323+
}
1324+
break;
12841325
case LidStepperState::Status::LIFT_RAISE:
1326+
std::ignore = policy.lid_stepper_set_rpm(
1327+
LidStepperState::LID_DEFAULT_VELOCITY_RPM);
12851328
// Lower the plate lift mechanism and move the lid far enough
12861329
// that it will go PAST the switch.
12871330
policy.lid_stepper_start(
@@ -1315,6 +1358,13 @@ class MotorTask {
13151358
motor_util::MovementProfile _seal_profile;
13161359
double _seal_velocity;
13171360
double _seal_acceleration;
1361+
/**
1362+
* When performing a plate lift, a "nudge" is used to dislodge the plate
1363+
* while avoiding a sudden pop off the plate. The nudge increases in
1364+
* amplitude over multiple iterations; this variable tracks the current
1365+
* distance being set.
1366+
*/
1367+
double _nudge_degrees;
13181368
/**
13191369
* @brief We need to cache the position of the seal motor in addition to
13201370
* the state in _seal_stepper_state due to the lack of limit switches.

stm32-modules/thermocycler-gen2/firmware/motor_task/motor_hardware.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ extern "C" {
104104
/** Above this speed, will get skipping */
105105
#define LID_RPM_MAX (125)
106106
/** Below this speed reduces torque */
107-
#define LID_RPM_MIN (75)
107+
#define LID_RPM_MIN (10)
108108

109109
// ----------------------------------------------------------------------------
110110
// Local typedefs
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from test_utils import *
2+
3+
4+
if __name__ == '__main__':
5+
ser = build_serial()
6+
ser.write('dfu\n'.encode())
7+
exit(0)

stm32-modules/thermocycler-gen2/tests/test_motor_task.cpp

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -918,34 +918,68 @@ SCENARIO("motor task lid state machine") {
918918
test_motor_state_machine(tasks, steps);
919919
}
920920
WHEN("sending plate lift command") {
921-
std::vector<MotorStep> steps = {
922-
// First open past the switch
923-
{.msg = messages::PlateLiftMessage{.id = 123},
924-
.lid_angle_increased = true,
925-
.lid_overdrive = true,
926-
.motor_state = MotorStep::MotorState::PLATE_LIFT,
927-
.lid_rpm =
928-
motor_task::LidStepperState::PLATE_LIFT_VELOCITY_RPM},
929-
// Now close back below the switch
930-
{.msg = messages::LidStepperComplete(),
931-
.lid_angle_decreased = true,
932-
.lid_overdrive = true},
933-
// Now open back to the switch
934-
{.msg = messages::LidStepperComplete(),
935-
.lid_angle_increased = true,
936-
.lid_overdrive = false},
937-
// Now overdrive into the switch
938-
{.msg = messages::LidStepperComplete(),
939-
.lid_angle_decreased = true,
940-
.lid_overdrive = true},
941-
// Should send ACK now
942-
{.msg = messages::LidStepperComplete(),
943-
.motor_state = MotorStep::MotorState::IDLE,
944-
.ack =
945-
messages::AcknowledgePrevious{
946-
.responding_to_id = 123,
947-
.with_error = errors::ErrorCode::NO_ERROR}},
948-
};
921+
std::vector<MotorStep> steps;
922+
for (auto angle = motor_task::LidStepperState::
923+
PLATE_LIFT_NUDGE_START_DEGREES;
924+
angle <
925+
motor_task::LidStepperState::PLATE_LIFT_NUDGE_FINAL_DEGREES +
926+
motor_task::LidStepperState::PLATE_LIFT_NUDGE_INCREMENT;
927+
angle +=
928+
motor_task::LidStepperState::PLATE_LIFT_NUDGE_INCREMENT) {
929+
// Incremental nudging
930+
steps.push_back(MotorStep{
931+
.msg = messages::LidStepperComplete(),
932+
.lid_angle_increased = true,
933+
.lid_overdrive = true,
934+
.lid_rpm =
935+
motor_task::LidStepperState::PLATE_LIFT_VELOCITY_RPM,
936+
});
937+
steps.push_back(MotorStep{
938+
.msg = messages::LidStepperComplete(),
939+
.lid_angle_decreased = true,
940+
.lid_overdrive = true,
941+
.lid_rpm =
942+
motor_task::LidStepperState::PLATE_LIFT_VELOCITY_RPM,
943+
});
944+
}
945+
// Final open - all the way to the limit
946+
steps.push_back(MotorStep{
947+
.msg = messages::LidStepperComplete(),
948+
.lid_angle_increased = true,
949+
.lid_overdrive = true,
950+
.lid_rpm =
951+
motor_task::LidStepperState::PLATE_LIFT_VELOCITY_RPM});
952+
// Return below switch
953+
steps.push_back(MotorStep{
954+
.msg = messages::LidStepperComplete(),
955+
.lid_angle_increased = false,
956+
.lid_angle_decreased = true,
957+
.lid_overdrive = true,
958+
.lid_rpm =
959+
motor_task::LidStepperState::LID_DEFAULT_VELOCITY_RPM});
960+
// Return to the switch
961+
steps.push_back(MotorStep{
962+
.msg = messages::LidStepperComplete(),
963+
.lid_angle_increased = true,
964+
.lid_overdrive = false,
965+
.lid_rpm =
966+
motor_task::LidStepperState::LID_DEFAULT_VELOCITY_RPM});
967+
// Now BACK OUT of the switch
968+
steps.push_back(MotorStep{
969+
.msg = messages::LidStepperComplete(),
970+
.lid_angle_increased = false,
971+
.lid_angle_decreased = true,
972+
.lid_overdrive = true,
973+
.lid_rpm =
974+
motor_task::LidStepperState::LID_DEFAULT_VELOCITY_RPM});
975+
steps.push_back(
976+
MotorStep{.msg = messages::LidStepperComplete(),
977+
.motor_state = MotorStep::MotorState::IDLE,
978+
.ack = messages::AcknowledgePrevious{
979+
.responding_to_id = 123,
980+
.with_error = errors::ErrorCode::NO_ERROR}});
981+
steps[0].msg = messages::PlateLiftMessage{.id = 123};
982+
steps[0].motor_state = MotorStep::MotorState::PLATE_LIFT;
949983
test_motor_state_machine(tasks, steps);
950984
}
951985
GIVEN("seal retraction switch is triggered") {

0 commit comments

Comments
 (0)