Ver Fonte

Add 'magnetic detent' demo, filter noisy hx711 data

Scott Bezek há 4 anos atrás
pai
commit
01ecb23df2

+ 27 - 5
firmware/src/interface_task.cpp

@@ -35,6 +35,8 @@ static PB_SmartKnobConfig configs[] = {
     // float endstop_strength_unit;
     // float snap_point;
     // char text[51];
+    // pb_size_t detent_positions_count;
+    // int32_t detent_positions[5];
 
     {
         0,
@@ -117,6 +119,17 @@ static PB_SmartKnobConfig configs[] = {
         1.1,
         "Coarse values\nWeak detents",
     },
+    {
+        32,
+        0,
+        7 * PI / 180,
+        2.5,
+        1,
+        0.7,
+        "Coarse values\nMagnetic detents",
+        4,
+        {2, 10, 21, 22},
+    },
 };
 
 InterfaceTask::InterfaceTask(const uint8_t task_core, MotorTask& motor_task, DisplayTask* display_task) : 
@@ -271,13 +284,22 @@ void InterfaceTask::updateHardware() {
                 press_value_unit = 1. * (value - lower) / (upper - lower);
 
                 static bool pressed;
+                static uint8_t press_count;
                 if (!pressed && press_value_unit > 0.75) {
-                    motor_task_.playHaptic(true);
-                    pressed = true;
-                    changeConfig(true);
+                    press_count++;
+                    if (press_count > 2) {
+                        motor_task_.playHaptic(true);
+                        pressed = true;
+                        changeConfig(true);
+                    }
                 } else if (pressed && press_value_unit < 0.25) {
-                    motor_task_.playHaptic(false);
-                    pressed = false;
+                    press_count++;
+                    if (press_count > 2) {
+                        motor_task_.playHaptic(false);
+                        pressed = false;
+                    }
+                } else {
+                    press_count = 0;
                 }
             }
         } else {

+ 21 - 2
firmware/src/motor_task.cpp

@@ -110,6 +110,10 @@ void MotorTask::run() {
                 case CommandType::CONFIG: {
                     // Change haptic input mode
                     config = command.data.config;
+                    if (config.position == INT32_MIN) {
+                        // INT32_MIN indicates no change to position, so restore from latest_config
+                        config.position = latest_config.position;
+                    }
                     latest_config = config;
                     log("Got new config");
                     current_detent_center = motor.shaft_angle;
@@ -130,7 +134,9 @@ void MotorTask::run() {
                     const float derivative_position_width_lower = radians(3);
                     const float derivative_position_width_upper = radians(8);
                     const float raw = derivative_lower_strength + (derivative_upper_strength - derivative_lower_strength)/(derivative_position_width_upper - derivative_position_width_lower)*(config.position_width_radians - derivative_position_width_lower);
-                    motor.PID_velocity.D = CLAMP(
+                    // When there are intermittent detents (set via detent_positions), disable derivative factor as this adds extra "clicks" when nearing
+                    // a detent.
+                    motor.PID_velocity.D = config.detent_positions_count > 0 ? 0 : CLAMP(
                         raw,
                         min(derivative_lower_strength, derivative_upper_strength),
                         max(derivative_lower_strength, derivative_upper_strength)
@@ -200,7 +206,20 @@ void MotorTask::run() {
             // Don't apply torque if velocity is too high (helps avoid positive feedback loop/runaway)
             motor.move(0);
         } else {
-            float torque = motor.PID_velocity(-angle_to_detent_center + dead_zone_adjustment);
+            float input = -angle_to_detent_center + dead_zone_adjustment;
+            if (!out_of_bounds && config.detent_positions_count > 0) {
+                bool in_detent = false;
+                for (uint8_t i = 0; i < config.detent_positions_count; i++) {
+                    if (config.detent_positions[i] == config.position) {
+                        in_detent = true;
+                        break;
+                    }
+                }
+                if (!in_detent) {
+                    input = 0;
+                }
+            }
+            float torque = motor.PID_velocity(input);
             #if SK_INVERT_ROTATION
                 torque = -torque;
             #endif

+ 10 - 6
firmware/src/proto_gen/smartknob.pb.h

@@ -30,6 +30,8 @@ typedef struct _PB_SmartKnobConfig {
     float endstop_strength_unit;
     float snap_point;
     char text[51];
+    pb_size_t detent_positions_count;
+    int32_t detent_positions[5];
 } PB_SmartKnobConfig;
 
 typedef struct _PB_SmartKnobState {
@@ -70,14 +72,14 @@ extern "C" {
 #define PB_Log_init_default                      {""}
 #define PB_SmartKnobState_init_default           {0, 0, false, PB_SmartKnobConfig_init_default}
 #define PB_ToSmartknob_init_default              {0, 0, {PB_RequestState_init_default}}
-#define PB_SmartKnobConfig_init_default          {0, 0, 0, 0, 0, 0, ""}
+#define PB_SmartKnobConfig_init_default          {0, 0, 0, 0, 0, 0, "", 0, {0, 0, 0, 0, 0}}
 #define PB_RequestState_init_default             {0}
 #define PB_FromSmartKnob_init_zero               {0, {PB_Ack_init_zero}}
 #define PB_Ack_init_zero                         {0}
 #define PB_Log_init_zero                         {""}
 #define PB_SmartKnobState_init_zero              {0, 0, false, PB_SmartKnobConfig_init_zero}
 #define PB_ToSmartknob_init_zero                 {0, 0, {PB_RequestState_init_zero}}
-#define PB_SmartKnobConfig_init_zero             {0, 0, 0, 0, 0, 0, ""}
+#define PB_SmartKnobConfig_init_zero             {0, 0, 0, 0, 0, 0, "", 0, {0, 0, 0, 0, 0}}
 #define PB_RequestState_init_zero                {0}
 
 /* Field tags (for use in manual encoding/decoding) */
@@ -90,6 +92,7 @@ extern "C" {
 #define PB_SmartKnobConfig_endstop_strength_unit_tag 5
 #define PB_SmartKnobConfig_snap_point_tag        6
 #define PB_SmartKnobConfig_text_tag              7
+#define PB_SmartKnobConfig_detent_positions_tag  8
 #define PB_SmartKnobState_current_position_tag   1
 #define PB_SmartKnobState_sub_position_unit_tag  2
 #define PB_SmartKnobState_config_tag             3
@@ -145,7 +148,8 @@ X(a, STATIC,   SINGULAR, FLOAT,    position_width_radians,   3) \
 X(a, STATIC,   SINGULAR, FLOAT,    detent_strength_unit,   4) \
 X(a, STATIC,   SINGULAR, FLOAT,    endstop_strength_unit,   5) \
 X(a, STATIC,   SINGULAR, FLOAT,    snap_point,        6) \
-X(a, STATIC,   SINGULAR, STRING,   text,              7)
+X(a, STATIC,   SINGULAR, STRING,   text,              7) \
+X(a, STATIC,   REPEATED, INT32,    detent_positions,   8)
 #define PB_SmartKnobConfig_CALLBACK NULL
 #define PB_SmartKnobConfig_DEFAULT NULL
 
@@ -176,9 +180,9 @@ extern const pb_msgdesc_t PB_RequestState_msg;
 #define PB_FromSmartKnob_size                    261
 #define PB_Log_size                              258
 #define PB_RequestState_size                     0
-#define PB_SmartKnobConfig_size                  94
-#define PB_SmartKnobState_size                   112
-#define PB_ToSmartknob_size                      102
+#define PB_SmartKnobConfig_size                  149
+#define PB_SmartKnobState_size                   168
+#define PB_ToSmartknob_size                      158
 
 #ifdef __cplusplus
 } /* extern "C" */

+ 1 - 0
proto/smartknob.proto

@@ -49,6 +49,7 @@ message SmartKnobConfig {
     float endstop_strength_unit = 5;
     float snap_point = 6;
     string text = 7 [(nanopb).max_length = 50];
+    repeated int32 detent_positions = 8 [(nanopb).max_count = 5];
 }
 
 message RequestState {}