Demo!
This commit is contained in:
@@ -20,6 +20,8 @@ static const float IDLE_CORRECTION_RATE_ALPHA = 0.0005;
|
||||
|
||||
|
||||
MotorTask::MotorTask(const uint8_t task_core, DisplayTask& display_task) : Task{"Motor", 8192, 1, task_core}, display_task_(display_task) {
|
||||
queue_ = xQueueCreate(1, sizeof(KnobConfig));
|
||||
assert(queue_ != NULL);
|
||||
}
|
||||
|
||||
MotorTask::~MotorTask() {}
|
||||
@@ -35,10 +37,7 @@ TlvSensor tlv = TlvSensor();
|
||||
Commander command = Commander(Serial);
|
||||
|
||||
|
||||
float detents = 36;
|
||||
|
||||
void doMotor(char* cmd) { command.motor(&motor, cmd); }
|
||||
void doDetents(char* cmd) { command.scalar(&detents, cmd); }
|
||||
|
||||
void MotorTask::run() {
|
||||
driver.voltage_power_supply = 5;
|
||||
@@ -63,32 +62,42 @@ void MotorTask::run() {
|
||||
motor.PID_velocity.limit = 10;
|
||||
|
||||
|
||||
// motor.useMonitoring(Serial);
|
||||
|
||||
motor.init();
|
||||
|
||||
tlv.update();
|
||||
delay(10);
|
||||
|
||||
motor.initFOC(-0.2, Direction::CW);
|
||||
motor.initFOC(6, Direction::CW);
|
||||
Serial.println(motor.zero_electric_angle);
|
||||
|
||||
command.add('M', &doMotor, "foo");
|
||||
command.add('D', &doDetents, "Detents");
|
||||
motor.useMonitoring(Serial);
|
||||
// command.add('D', &doDetents, "Detents");
|
||||
motor.monitor_downsample = 0; // disable monitor at first - optional
|
||||
|
||||
// disableCore0WDT();
|
||||
|
||||
float current_detent_center = motor.shaft_angle;
|
||||
|
||||
int min = 0;
|
||||
int max = 255;
|
||||
int value = 0;
|
||||
KnobConfig config = {
|
||||
.num_positions = 2,
|
||||
.position = 0,
|
||||
.position_width_radians = 60 * _PI / 180,
|
||||
.detent_strength_unit = 0,
|
||||
};
|
||||
|
||||
float idle_check_velocity_ewma = 0;
|
||||
uint32_t last_idle_start = 0;
|
||||
uint32_t last_debug = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
motor.loopFOC();
|
||||
|
||||
if (xQueueReceive(queue_, &config, 0) == pdTRUE) {
|
||||
Serial.println("Got new config");
|
||||
current_detent_center = motor.shaft_angle;
|
||||
}
|
||||
|
||||
idle_check_velocity_ewma = motor.shaft_velocity * IDLE_VELOCITY_EWMA_ALPHA + idle_check_velocity_ewma * (1 - IDLE_VELOCITY_EWMA_ALPHA);
|
||||
if (fabsf(idle_check_velocity_ewma) > IDLE_VELOCITY_RAD_PER_SEC) {
|
||||
last_idle_start = 0;
|
||||
@@ -101,48 +110,55 @@ void MotorTask::run() {
|
||||
// If we are not moving and we're close to the center (but not exactly there), slowly adjust the centerpoint to match the current position
|
||||
if (last_idle_start > 0 && millis() - last_idle_start > IDLE_CORRECTION_DELAY_MILLIS && fabsf(motor.shaft_angle - current_detent_center) < IDLE_CORRECTION_MAX_ANGLE_RAD) {
|
||||
current_detent_center = motor.shaft_angle * IDLE_CORRECTION_RATE_ALPHA + current_detent_center * (1 - IDLE_CORRECTION_RATE_ALPHA);
|
||||
if (millis() - last_debug > 100) {
|
||||
last_debug = millis();
|
||||
Serial.print("Moving detent center. ");
|
||||
Serial.print(current_detent_center);
|
||||
Serial.print(" ");
|
||||
Serial.println(motor.shaft_angle);
|
||||
}
|
||||
// if (millis() - last_debug > 100) {
|
||||
// last_debug = millis();
|
||||
// Serial.print("Moving detent center. ");
|
||||
// Serial.print(current_detent_center);
|
||||
// Serial.print(" ");
|
||||
// Serial.println(motor.shaft_angle);
|
||||
// }
|
||||
}
|
||||
|
||||
if (fabs(detents) < 0.01) {
|
||||
float angle_to_detent_center = motor.shaft_angle - current_detent_center;
|
||||
if (angle_to_detent_center > config.position_width_radians * 1.05 && (config.num_positions <= 0 || config.position > 0)) {
|
||||
current_detent_center += config.position_width_radians;
|
||||
angle_to_detent_center -= config.position_width_radians;
|
||||
config.position--;
|
||||
} else if (angle_to_detent_center < -config.position_width_radians * 1.05 && (config.num_positions <= 0 || config.position < config.num_positions - 1)) {
|
||||
current_detent_center -= config.position_width_radians;
|
||||
angle_to_detent_center += config.position_width_radians;
|
||||
config.position++;
|
||||
}
|
||||
|
||||
float dead_zone_adjustment = CLAMP(
|
||||
angle_to_detent_center,
|
||||
fmaxf(-config.position_width_radians*DEAD_ZONE_DETENT_PERCENT, -DEAD_ZONE_RAD),
|
||||
fminf(config.position_width_radians*DEAD_ZONE_DETENT_PERCENT, DEAD_ZONE_RAD));
|
||||
|
||||
bool out_of_bounds = config.num_positions > 0 && ((angle_to_detent_center > 0 && config.position == 0) || (angle_to_detent_center < 0 && config.position == config.num_positions - 1));
|
||||
motor.PID_velocity.limit = out_of_bounds ? 10 : 3;
|
||||
motor.PID_velocity.P = out_of_bounds ? 4 : config.detent_strength_unit * 4;
|
||||
motor.PID_velocity.D = config.detent_strength_unit * 0.04;
|
||||
|
||||
if (fabsf(motor.shaft_velocity) > 20) {
|
||||
// Don't apply torque if velocity is too high (helps avoid feedback loop)
|
||||
motor.move(0);
|
||||
display_task_.set_angle(motor.shaft_angle);
|
||||
current_detent_center = motor.shaft_angle;
|
||||
} else {
|
||||
float detent_width = 2*PI/detents;
|
||||
|
||||
float angle_to_detent_center = motor.shaft_angle - current_detent_center;
|
||||
if (angle_to_detent_center > detent_width * 1.2 && value > min) {
|
||||
current_detent_center += detent_width;
|
||||
angle_to_detent_center -= detent_width;
|
||||
value--;
|
||||
} else if (angle_to_detent_center < -detent_width * 1.2 && value < max) {
|
||||
current_detent_center -= detent_width;
|
||||
angle_to_detent_center += detent_width;
|
||||
value++;
|
||||
}
|
||||
|
||||
float dead_zone_adjustment = CLAMP(
|
||||
angle_to_detent_center,
|
||||
fmaxf(-detent_width*DEAD_ZONE_DETENT_PERCENT, -DEAD_ZONE_RAD),
|
||||
fminf(detent_width*DEAD_ZONE_DETENT_PERCENT, DEAD_ZONE_RAD));
|
||||
|
||||
if (fabsf(motor.shaft_velocity) > 20) {
|
||||
// Don't apply torque if velocity is too high (helps avoid feedback loop)
|
||||
motor.move(0);
|
||||
} else {
|
||||
motor.move(motor.PID_velocity(-angle_to_detent_center + dead_zone_adjustment));
|
||||
}
|
||||
|
||||
display_task_.set_angle(-value * PI / 180);
|
||||
motor.move(motor.PID_velocity(-angle_to_detent_center + dead_zone_adjustment));
|
||||
}
|
||||
|
||||
display_task_.setData({
|
||||
.num_positions = config.num_positions,
|
||||
.current_position = config.position,
|
||||
.sub_position_unit = -angle_to_detent_center / config.position_width_radians,
|
||||
.position_width_radians = config.position_width_radians,
|
||||
});
|
||||
|
||||
motor.monitor();
|
||||
command.run();
|
||||
// command.run();
|
||||
}
|
||||
}
|
||||
|
||||
void MotorTask::setConfig(const KnobConfig& config) {
|
||||
xQueueOverwrite(queue_, &config);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user