Parcourir la source

Basic working biased detents

Scott Bezek il y a 4 ans
Parent
commit
8de43b89e9

+ 54 - 3
firmware/src/interface_task.cpp

@@ -13,8 +13,6 @@
 #include "interface_task.h"
 #include "util.h"
 
-#define COUNT_OF(A) (sizeof(A) / sizeof(A[0]))
-
 #if SK_LEDS
 CRGB leds[NUM_LEDS];
 #endif
@@ -37,6 +35,8 @@ static PB_SmartKnobConfig configs[] = {
     // char text[51];
     // pb_size_t detent_positions_count;
     // int32_t detent_positions[5];
+    // float snap_point_bias;
+    // int32_t snap_point_bias_center_position;
 
     {
         0,
@@ -46,6 +46,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Unbounded\nNo detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         11,
@@ -55,6 +59,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Bounded 0-10\nNo detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         73,
@@ -64,6 +72,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Multi-rev\nNo detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         2,
@@ -73,6 +85,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         0.55, // Note the snap point is slightly past the midpoint (0.5); compare to normal detents which use a snap point *past* the next value (i.e. > 1)
         "On/off\nStrong detent",
+        0,
+        {},
+        0,
+        0,
     },
     {
         1,
@@ -82,6 +98,10 @@ static PB_SmartKnobConfig configs[] = {
         0.6,
         1.1,
         "Return-to-center",
+        0,
+        {},
+        0,
+        0,
     },
     {
         256,
@@ -91,6 +111,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Fine values\nNo detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         256,
@@ -100,6 +124,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Fine values\nWith detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         32,
@@ -109,6 +137,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Coarse values\nStrong detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         32,
@@ -118,6 +150,10 @@ static PB_SmartKnobConfig configs[] = {
         1,
         1.1,
         "Coarse values\nWeak detents",
+        0,
+        {},
+        0,
+        0,
     },
     {
         32,
@@ -126,9 +162,24 @@ static PB_SmartKnobConfig configs[] = {
         2.5,
         1,
         0.7,
-        "Coarse values\nMagnetic detents",
+        "Magnetic detents",
         4,
         {2, 10, 21, 22},
+        0,
+        0,
+    },
+    {
+        13,
+        6,
+        60 * PI / 180,
+        1,
+        1,
+        0.55,
+        "Return-to-center\nwith detents",
+        0,
+        {},
+        0.4,
+        6
     },
 };
 

+ 38 - 2
firmware/src/motor_task.cpp

@@ -108,6 +108,36 @@ void MotorTask::run() {
                     calibrate();
                     break;
                 case CommandType::CONFIG: {
+                    // Check new config for validity
+                    if (command.data.config.num_positions < 0) {
+                        log("Ignoring invalid config: num_positions cannot be negative");
+                        break;
+                    }
+                    if (command.data.config.detent_strength_unit < 0) {
+                        log("Ignoring invalid config: detent_strength_unit cannot be negative");
+                        break;
+                    }
+                    if (command.data.config.endstop_strength_unit < 0) {
+                        log("Ignoring invalid config: endstop_strength_unit cannot be negative");
+                        break;
+                    }
+                    if (command.data.config.snap_point < 0.5) {
+                        log("Ignoring invalid config: snap_point must be >= 0.5 for stability");
+                        break;
+                    }
+                    if (command.data.config.detent_positions_count > COUNT_OF(command.data.config.detent_positions)) {
+                        log("Ignoring invalid config: detent_positions_count is too large");
+                        break;
+                    }
+                    if (command.data.config.snap_point_bias < 0) {
+                        log("Ignoring invalid config: snap_point_bias cannot be negative or there is risk of instability");
+                        break;
+                    }
+                    if (command.data.config.snap_point_bias_center_position < 0 || command.data.config.snap_point_bias_center_position > command.data.config.num_positions || (command.data.config.num_positions > 0 && command.data.config.snap_point_bias_center_position == command.data.config.num_positions)) {
+                        log("Ignoring invalid config: snap_point_bias_center_position out of range");
+                        break;
+                    }
+
                     // Change haptic input mode
                     config = command.data.config;
                     if (config.position == INT32_MIN) {
@@ -181,11 +211,17 @@ void MotorTask::run() {
         #if SK_INVERT_ROTATION
             angle_to_detent_center = -motor.shaft_angle - current_detent_center;
         #endif
-        if (angle_to_detent_center > config.position_width_radians * config.snap_point && (config.num_positions <= 0 || config.position > 0)) {
+
+        float snap_point_radians = config.position_width_radians * config.snap_point;
+        float bias_radians = config.position_width_radians * config.snap_point_bias;
+        float snap_point_radians_decrease = snap_point_radians + (config.position <= config.snap_point_bias_center_position ? bias_radians : -bias_radians);
+        float snap_point_radians_increase = -snap_point_radians + (config.position >= config.snap_point_bias_center_position ? -bias_radians : bias_radians); 
+
+        if (angle_to_detent_center > snap_point_radians_decrease && (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 * config.snap_point && (config.num_positions <= 0 || config.position < config.num_positions - 1)) {
+        } else if (angle_to_detent_center < snap_point_radians_increase && (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++;

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

@@ -32,6 +32,8 @@ typedef struct _PB_SmartKnobConfig {
     char text[51];
     pb_size_t detent_positions_count;
     int32_t detent_positions[5];
+    float snap_point_bias;
+    int32_t snap_point_bias_center_position;
 } PB_SmartKnobConfig;
 
 typedef struct _PB_SmartKnobState {
@@ -72,14 +74,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, "", 0, {0, 0, 0, 0, 0}}
+#define PB_SmartKnobConfig_init_default          {0, 0, 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, "", 0, {0, 0, 0, 0, 0}}
+#define PB_SmartKnobConfig_init_zero             {0, 0, 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) */
@@ -93,6 +95,8 @@ extern "C" {
 #define PB_SmartKnobConfig_snap_point_tag        6
 #define PB_SmartKnobConfig_text_tag              7
 #define PB_SmartKnobConfig_detent_positions_tag  8
+#define PB_SmartKnobConfig_snap_point_bias_tag   9
+#define PB_SmartKnobConfig_snap_point_bias_center_position_tag 10
 #define PB_SmartKnobState_current_position_tag   1
 #define PB_SmartKnobState_sub_position_unit_tag  2
 #define PB_SmartKnobState_config_tag             3
@@ -149,7 +153,9 @@ 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,   REPEATED, INT32,    detent_positions,   8)
+X(a, STATIC,   REPEATED, INT32,    detent_positions,   8) \
+X(a, STATIC,   SINGULAR, FLOAT,    snap_point_bias,   9) \
+X(a, STATIC,   SINGULAR, INT32,    snap_point_bias_center_position,  10)
 #define PB_SmartKnobConfig_CALLBACK NULL
 #define PB_SmartKnobConfig_DEFAULT NULL
 
@@ -180,9 +186,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                  149
-#define PB_SmartKnobState_size                   168
-#define PB_ToSmartknob_size                      158
+#define PB_SmartKnobConfig_size                  165
+#define PB_SmartKnobState_size                   184
+#define PB_ToSmartknob_size                      174
 
 #ifdef __cplusplus
 } /* extern "C" */

+ 2 - 0
firmware/src/util.h

@@ -5,3 +5,5 @@ template <typename T> T CLAMP(const T& value, const T& low, const T& high)
 {
   return value < low ? low : (value > high ? high : value); 
 }
+
+#define COUNT_OF(A) (sizeof(A) / sizeof(A[0]))

+ 2 - 0
proto/smartknob.proto

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