Subject: [PATCH] If something claims to be backwards compatible, it should be. The gearchange acts exactly like the old one, unless you specify num_gears

From: Andy Pugh <[email-masked]>
Date: Thu, 27 Jan 2011 00:10:50 +0000

Signed-off-by: Andy <[email-masked]>
---
 src/hal/components/gearchange.comp |  114 +++++++++++++++++++++++------------
 1 files changed, 75 insertions(+), 39 deletions(-)

diff --git a/src/hal/components/gearchange.comp b/src/hal/components/gearchange.comp
index 2ca7250..c57ba1d 100644
--- a/src/hal/components/gearchange.comp
+++ b/src/hal/components/gearchange.comp
@@ -1,65 +1,88 @@
-component gearchange """Calculate the correct motor speed setpoint for a 
-machine with multiple gear ratios.""";
+component gearchange """Adjust motor speed command for geared spindles.
+Scales the input value to the output depending on selected gear.""";
 
 pin in float speed-in "Speed command input.";
 pin out float speed-out "Speed command to DAC/PWM";
-pin in bit gear-#-sel [32 : personality+1] """Gear selection by bit. Higher
+pin in bit gear-#-sel [32 : personality] """Gear selection by bit. Higher
 numbers take priority if more than one is set""";
-pin in bit sel "Alias for sel2 for compatibility with the previous version ";
 pin in bit dir_in "Direction input for absolute speed + dir modes";
 pin out bit dir-out "Direction output (will be reversed for negative scales)";
 pin out bit min-lim "Indicates that the minimum limitation is active";
 pin out bit max-lim "Indicates that the maximum limitation is active";
-pin in unsigned gear-number "Gear selection as a numeric";
+pin in signed gear-number =-1 if personality != 0  "Gear selection as a numeric";
 pin out float speed-filtered "Speed command to display, limited and absolute";
 pin out float accel-limit "Acceleration limit for the selected gear";
-param rw float min#[32: personality+1] = 0 
-    "Minimum allowed speed in gear range N";
-param rw float max#[32 : personality+1] = 100000 
-    "Maximum allowed speed in gear range N";
-param rw float acc#[32 : personality+1] = 0 
-    "Maximum Acceleration in rpm/s. 0 = no limit";
-param rw float scale#[32 : personality+1] = 1.0 "Ratio in gear range 1";
-param rw bit reverse "negates the value of scale2, for compatibility";
-
-option extra_setup;
-variable float old_speed = 0;
+pin out unsigned gear "The actual detected gear";
+param rw float min#[32: (personality==0)*3 + personality] = 0 
+"Minimum allowed speed in gear range N";
+param rw float max#[32 : (personality==0)*3 + personality] = 100000 
+"Maximum allowed speed in gear range N";
+param rw float acc#[32 : personality] = 0 
+"Maximum Acceleration in rpm/s. 0 = no limit";
+param rw float scale#[32 : (personality==0)*3 + personality] = 1.0 "Ratio in gear range 1";
+pin in bit sel if personality == 0 "For compatibility with the previous version ";
+param rw bit reverse if personality == 0 "negates the value of scale2, for compatibility";
 
 description """The output will be a  value scaled for the selected gear, and 
 clamped to the min/max values for that gear.
 
-This should work for up to 32 gears.
+This version should work for up to 32 gears.
 To load two instances, one with 5 gears and one with 6 use:
-loadrt gearchange count=2 personality=5,6
-For a single instance you can omit the count, eg with 11 gears you can use:
-loadrt gearchange personality=11
 
-It accepts negative speeds, negative outputs and negative scales to allow for 
-gear ranges that reverse the motion.
+loadrt gearchange num_gears=5,6
+
+Gears are numbered from zero, ie the count includes neutral, so typically the 
+modparam should be one more than the actual gear ratio count.
+
+If no num_gears parameter is given then the component defaults to be compatible
+with the prevous (2.4) version with two gears and one \\fBsel\\fR pin that 
+switches from gear 1 to 2. 
+
+The \\fBcount=\\fR parameter is no longer supported. 
+If it is necessary to create multiple instances of the old-style component then 
+this can be achieved by using num_gears=1,1,1 (for three instances).
 
-The scale is the ratio between input speed and output speed, so the same VFD 
-scale parameter will work for any gear. The output value is that motor speed 
-which would be required to give the requested output speed with a gear ratio of
-1. If gear 1 is the slowest gear then other ratios will probably need to be 
-fractional. If the highest numbered gear is the slowest then the scales will 
-probably need to be greater than one. 
+The Component accepts negative speeds, negative outputs and negative scales to 
+allow for gear ranges that reverse the motion.
+
+The scale is the ratio between output speed and input speed, so the same VFD 
+scale parameter (typically set by the PWM scale parameter) will work for any 
+gear. 
+The output value is that motor speed which would be required to give the 
+requested output speed with a gear ratio of 1 at the set PWM scale. For example 
+if gear 1 has a max speed of 1000rpm and requires 10V to the VFD to achieve 
+that, and gear 2 has a max speed of 4000rpm then gearchange.N.ratio2 should be 
+set to 4. Then a spindle speed of 1000rpm would give 10V output in gear 1 and 
+2.5V in gear 2. 
 
 The gear can be input either as a numeric value (possibly assembled from 
 \\fBweighted_sum\\fR components to convert the positions of several levers into 
-a gear) or as an individual select bit for each gear. """;
+a gear) or as an individual select bit for each gear.""";
+
+option count_function yes;
+option extra_setup yes;
+
+variable float old_speed = 0;
 
 function _;
 license "GPL";
 ;;
 #include <rtapi_math.h>
+#define MAX_INSTS 8
+static int num_gears[MAX_INSTS];
+
+RTAPI_MP_ARRAY_INT(num_gears, MAX_INSTS, "Gear count for each gearbox");
+
 FUNCTION(_) {
-    int gear;
     double speed_target;
     double delta;
     
-    if (sel) gear = 2; // Backwards compatibility
-    else if (gear_number) gear = gear_number;
-    else for (gear = personality ; gear > 0 && !gear_sel(gear) ; gear--) {}
+    if (personality==0){ // Backwards compatibility
+        if (sel) gear = 2;
+        else gear = 1;
+    }
+    else if (gear_number != -1) gear = gear_number;
+    else for (gear = personality-1 ; gear > 0 && !gear_sel(gear) ; gear--) {}
     
     speed_filtered = fabs(speed_in);
     if (speed_filtered > max(gear)) {
@@ -70,19 +93,32 @@ FUNCTION(_) {
         speed_filtered = min(gear);}
     else { min_lim = 0; max_lim = 0; }
     
-    speed_target =  speed_filtered * ((scale(gear) != 0)? scale(gear) : 1)
-    *((speed_in < 0)? -1 : 1) ;
+    if (scale(gear) == 0) {
+        speed_target = 0;}
+    else {
+        speed_target = speed_filtered / scale(gear) * ((speed_in < 0)? -1 : 1);}
+    
     delta = acc(gear) * fperiod * ((speed_target > old_speed)? 1 : -1);
     speed_out = 
-        ((acc(gear) != 0 && fabs(speed_target - old_speed) > fabs(delta))?
-        (old_speed += delta) : (old_speed = speed_target));
+    ((acc(gear) != 0 && fabs(speed_target - old_speed) > fabs(delta))?
+     (old_speed += delta) : (old_speed = speed_target));
     
     dir_out = ((scale(gear) < 0)? !dir_in : dir_in);
-    dir_out = ((reverse && gear == 2)? !dir_out : dir_out); // Backwards compat
+    if (personality == 0){ // Backwards compatibility
+        dir_out = ((reverse && gear == 2)? !dir_out : dir_out); 
+    }
     accel_limit = acc(gear);
 }
 
 EXTRA_SETUP( ) {
-    if (personality == 0) personality = 2;
+    if (num_gears[extra_arg] < 2) personality = 0;
+    else personality = num_gears[extra_arg];
     return 0;
 }
+
+int get_count(void){
+    int i;
+    for (i = 0; num_gears[i] != 0 && i < MAX_INSTS; i++){}
+    if (i == 0) return 1;
+    return i;
+}
-- 
1.7.0.4