diff --git a/docs/Cli.md b/docs/Cli.md index 43bb269df..b8b9c9880 100644 --- a/docs/Cli.md +++ b/docs/Cli.md @@ -92,7 +92,7 @@ Re-apply any new defaults as desired. | `play_sound` | index, or none for next | | `profile` | index (0 to 2) | | `rateprofile` | index (0 to 2) | -| `rccal` | Set R/C channel calibration (stick end points) | +| `rxrange` | configure rx channel ranges (end-points) | | `save` | save and reboot | | `set` | name=value or blank or * for list | | `status` | show system status | diff --git a/docs/Rx.md b/docs/Rx.md index 3c8d299a7..2baf944f0 100644 --- a/docs/Rx.md +++ b/docs/Rx.md @@ -217,21 +217,23 @@ Set the RX for 'No Pulses'. Turn OFF TX and RX, Turn ON RX. Press and release Set failsafe on channels 1-4 set to OFF in the receiver settings (via transmitter menu). -## Receiver Calibration. +## Receiver Channel Range Configuration. If you have a transmitter/receiver, that output a non-standard pulse range (i.e. 1070-1930 as some Spektrum receivers) -you could use rc calibration to map actual range of your transmitter to 1000-2000 as expected by Cleanflight. +you could use rx channel range configuration to map actual range of your transmitter to 1000-2000 as expected by Cleanflight. -To do this you should figure out what range your transmitter outputs and feed these values to rc calibration control. +The low and high value of a channel range are often referred to as 'End-points'. e.g. 'End-point adjustments / EPA'. + +All attempts should be made to configure your transmitter/receiver to use the range 1000-2000 *before* using this feature +as you will have less preceise control if it is used. + +To do this you should figure out what range your transmitter outputs and use these values for rx range configuration. You can do this in a few simple steps: -If you have used rc calibration previously you should reset it to prevent it from altering rc input. Do so -by entering the following commands in CLI: +If you have used rc range configuration previously you should reset it to prevent it from altering rc input. Do so +by entering the following command in CLI: ``` -rccal 0 1000 2000 -rccal 1 1000 2000 -rccal 2 1000 2000 -rccal 3 1000 2000 +rxrange reset save ``` @@ -241,11 +243,11 @@ a time. Go to CLI and set the min and max values with the following command: ``` -rccal +rxrange ``` -For example, if you got 1070-1930 range for roll channel. Roll is `channel 0` so you should type `rccal 0 1070 1930` in +For example, if you have the range 1070-1930 for the first channel you should use `rxrange 0 1070 1930` in the CLI. Be sure to enter the `save` command to save the settings. -Use sub-trim on your transmitter to set the middle point of pitch, roll, yaw and throttle. +After configuring channel ranges use the sub-trim on your transmitter to set the middle point of pitch, roll, yaw and throttle. diff --git a/src/main/config/config.c b/src/main/config/config.c index 6bf9c93e9..46bf70e46 100644 --- a/src/main/config/config.c +++ b/src/main/config/config.c @@ -414,11 +414,7 @@ static void resetConf(void) masterConfig.rxConfig.rssi_scale = RSSI_SCALE_DEFAULT; masterConfig.rxConfig.rssi_ppm_invert = 0; - // set default calibration to full range and 1:1 mapping - for (i = 0; i < MAX_CALIBRATED_RX_CHANNELS; i++) { - masterConfig.rxConfig.calibration[i].minrc = PWM_RANGE_MIN; - masterConfig.rxConfig.calibration[i].maxrc = PWM_RANGE_MAX; - } + resetAllRxChannelRangeConfigurations(masterConfig.rxConfig.channelRanges); masterConfig.inputFilteringMode = INPUT_FILTERING_DISABLED; diff --git a/src/main/drivers/pwm_rx.c b/src/main/drivers/pwm_rx.c index 5d057a050..156fb6faa 100644 --- a/src/main/drivers/pwm_rx.c +++ b/src/main/drivers/pwm_rx.c @@ -106,7 +106,6 @@ ppmDevice_t ppmDev; #define PPM_STABLE_FRAMES_REQUIRED_COUNT 25 #define PPM_IN_MIN_NUM_CHANNELS 4 #define PPM_IN_MAX_NUM_CHANNELS PWM_PORTS_OR_PPM_CAPTURE_COUNT -#define PPM_RCVR_TIMEOUT 0 bool isPPMDataBeingReceived(void) diff --git a/src/main/drivers/pwm_rx.h b/src/main/drivers/pwm_rx.h index 4b1463b0d..a81727f3c 100644 --- a/src/main/drivers/pwm_rx.h +++ b/src/main/drivers/pwm_rx.h @@ -22,6 +22,9 @@ typedef enum { INPUT_FILTERING_ENABLED } inputFilteringMode_e; +#define PPM_RCVR_TIMEOUT 0 + + void ppmInConfig(const timerHardware_t *timerHardwarePtr); void ppmAvoidPWMTimerClash(const timerHardware_t *timerHardwarePtr, TIM_TypeDef *sharedPwmTimer); diff --git a/src/main/io/serial_cli.c b/src/main/io/serial_cli.c index 997a381bc..fef8db196 100644 --- a/src/main/io/serial_cli.c +++ b/src/main/io/serial_cli.c @@ -117,7 +117,7 @@ static void cliSet(char *cmdline); static void cliGet(char *cmdline); static void cliStatus(char *cmdline); static void cliVersion(char *cmdline); -static void cliRxCalibration(char *cmdline); +static void cliRxRange(char *cmdline); #ifdef GPS static void cliGpsPassthrough(char *cmdline); @@ -258,8 +258,8 @@ const clicmd_t cmdTable[] = { "[]", cliProfile), CLI_COMMAND_DEF("rateprofile", "change rate profile", "[]", cliRateProfile), + CLI_COMMAND_DEF("rxrange", "configure rx channel ranges", NULL, cliRxRange), CLI_COMMAND_DEF("rxfail", "show/set rx failsafe settings", NULL, cliRxFail), - CLI_COMMAND_DEF("rxcal", "rc calibration", NULL, cliRxCalibration), CLI_COMMAND_DEF("save", "save and reboot", NULL, cliSave), CLI_COMMAND_DEF("serial", "configure serial ports", NULL, cliSerial), #ifdef USE_SERVOS @@ -929,42 +929,47 @@ static void cliMotorMix(char *cmdline) #endif } -static void cliRxCalibration(char *cmdline) +static void cliRxRange(char *cmdline) { - int i, check = 0; + int i, validArgumentCount = 0; char *ptr; if (isEmpty(cmdline)) { - for (i = 0; i < MAX_CALIBRATED_RX_CHANNELS; i++) { - printf("rccal %u %u %u\r\n", i, masterConfig.rxConfig.calibration[i].minrc, masterConfig.rxConfig.calibration[i].maxrc); + for (i = 0; i < NON_AUX_CHANNEL_COUNT; i++) { + rxChannelRangeConfiguration_t *channelRangeConfiguration = &masterConfig.rxConfig.channelRanges[i]; + printf("rxrange %u %u %u\r\n", i, channelRangeConfiguration->min, channelRangeConfiguration->max); } + } else if (strcasecmp(cmdline, "reset") == 0) { + resetAllRxChannelRangeConfigurations(masterConfig.rxConfig.channelRanges); } else { ptr = cmdline; i = atoi(ptr); - if (i >= 0 && i < MAX_CALIBRATED_RX_CHANNELS) { - int minrc, maxrc; + if (i >= 0 && i < NON_AUX_CHANNEL_COUNT) { + int rangeMin, rangeMax; + ptr = strchr(ptr, ' '); if (ptr) { - minrc = atoi(++ptr); - check++; + rangeMin = atoi(++ptr); + validArgumentCount++; } + ptr = strchr(ptr, ' '); if (ptr) { - maxrc = atoi(++ptr); - check++; + rangeMax = atoi(++ptr); + validArgumentCount++; } - if (check != 2) { - printf("Wrong number of arguments, needs idx min max\r\n"); - } - else if (minrc < 750 || minrc > 2250 || maxrc < 750 || maxrc > 2250 || minrc >= maxrc) { - printf("Parameters error. Should be: 750 <= minrc < maxrc <= 2250\r\n"); - } - else { - masterConfig.rxConfig.calibration[i].minrc = minrc; - masterConfig.rxConfig.calibration[i].maxrc = maxrc; + + if (validArgumentCount != 2) { + cliShowParseError(); + } else if (rangeMin < PWM_PULSE_MIN || rangeMin > PWM_PULSE_MAX || rangeMax < PWM_PULSE_MIN || rangeMax > PWM_PULSE_MAX || rangeMin >= rangeMax) { + cliShowParseError(); + } else { + rxChannelRangeConfiguration_t *channelRangeConfiguration = &masterConfig.rxConfig.channelRanges[i]; + channelRangeConfiguration->min = rangeMin; + channelRangeConfiguration->max = rangeMax; } } else { - printf("Invalid R/C channel: must be > 0 and < %u\r\n", MAX_CALIBRATED_RX_CHANNELS); + cliShowArgumentRangeError("channel", 0, NON_AUX_CHANNEL_COUNT - 1); } } } @@ -1509,9 +1514,9 @@ static void cliDump(char *cmdline) cliAdjustmentRange(""); - printf("\r\n# rccal\r\n"); + printf("\r\n# rxrange\r\n"); - cliRxCalibration(""); + cliRxRange(""); cliPrint("\r\n# servo\r\n"); diff --git a/src/main/rx/rx.c b/src/main/rx/rx.c index 76587a247..6a5dc32e3 100644 --- a/src/main/rx/rx.c +++ b/src/main/rx/rx.c @@ -116,6 +116,14 @@ STATIC_UNIT_TESTED void rxUpdateFlightChannelStatus(uint8_t channel, uint16_t pu } } +void resetAllRxChannelRangeConfigurations(rxChannelRangeConfiguration_t *rxChannelRangeConfiguration) { + // set default calibration to full range and 1:1 mapping + for (int i = 0; i < NON_AUX_CHANNEL_COUNT; i++) { + rxChannelRangeConfiguration->min = PWM_RANGE_MIN; + rxChannelRangeConfiguration->max = PWM_RANGE_MAX; + rxChannelRangeConfiguration++; + } +} void rxInit(rxConfig_t *rxConfig) { @@ -339,14 +347,14 @@ static uint16_t getRxfailValue(uint8_t channel) } -STATIC_UNIT_TESTED uint16_t applyRxCalibration(int sample, int minrc, int maxrc) +STATIC_UNIT_TESTED uint16_t applyRxChannelRangeConfiguraton(int sample, rxChannelRangeConfiguration_t range) { - // Check special condition sample = PPM_RCVR_TIMEOUT, allow no signal value to avoid being corrupted by calibration - if (sample == 0) { - return 0; + // Avoid corruption of channel with a value of PPM_RCVR_TIMEOUT + if (sample == PPM_RCVR_TIMEOUT) { + return PPM_RCVR_TIMEOUT; } - sample = scaleRange(sample, minrc, maxrc, PWM_RANGE_MIN, PWM_RANGE_MAX); + sample = scaleRange(sample, range.min, range.max, PWM_RANGE_MIN, PWM_RANGE_MAX); sample = MIN(MAX(PWM_PULSE_MIN, sample), PWM_PULSE_MAX); return sample; @@ -375,8 +383,8 @@ void processRxChannels(void) uint16_t sample = rcReadRawFunc(&rxRuntimeConfig, rawChannel); // apply the rx calibration - if (chan < MAX_CALIBRATED_RX_CHANNELS) { - sample = applyRxCalibration(sample, rxConfig->calibration[chan].minrc, rxConfig->calibration[chan].maxrc); + if (chan < NON_AUX_CHANNEL_COUNT) { + sample = applyRxChannelRangeConfiguraton(sample, rxConfig->channelRanges[chan]); } rxUpdateFlightChannelStatus(chan, sample); diff --git a/src/main/rx/rx.h b/src/main/rx/rx.h index e9c4d81de..099f596ef 100644 --- a/src/main/rx/rx.h +++ b/src/main/rx/rx.h @@ -76,7 +76,6 @@ extern const char rcChannelLetters[]; extern int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT]; // interval [1000;2000] #define MAX_MAPPABLE_RX_INPUTS 8 -#define MAX_CALIBRATED_RX_CHANNELS NON_AUX_CHANNEL_COUNT #define RSSI_SCALE_MIN 1 #define RSSI_SCALE_MAX 255 @@ -92,10 +91,10 @@ typedef struct rxFailsafeChannelConfiguration_s { uint8_t step; } rxFailsafeChannelConfiguration_t; -typedef struct rxCalibration_s { - uint16_t minrc; - uint16_t maxrc; -} rxCalibration_t; +typedef struct rxChannelRangeConfiguration_s { + uint16_t min; + uint16_t max; +} rxChannelRangeConfiguration_t; typedef struct rxConfig_s { uint8_t rcmap[MAX_MAPPABLE_RX_INPUTS]; // mapping of radio channels to internal RPYTA+ order @@ -112,7 +111,7 @@ typedef struct rxConfig_s { uint16_t rx_max_usec; rxFailsafeChannelConfiguration_t failsafe_aux_channel_configurations[MAX_AUX_CHANNEL_COUNT]; - rxCalibration_t calibration[MAX_CALIBRATED_RX_CHANNELS]; + rxChannelRangeConfiguration_t channelRanges[NON_AUX_CHANNEL_COUNT]; } rxConfig_t; #define REMAPPABLE_CHANNEL_COUNT (sizeof(((rxConfig_t *)0)->rcmap) / sizeof(((rxConfig_t *)0)->rcmap[0])) @@ -137,3 +136,5 @@ void parseRcChannels(const char *input, rxConfig_t *rxConfig); uint8_t serialRxFrameStatus(rxConfig_t *rxConfig); void updateRSSI(uint32_t currentTime); +void resetAllRxChannelRangeConfigurations(rxChannelRangeConfiguration_t *rxChannelRangeConfiguration); + diff --git a/src/test/unit/rc_calibration_unittest.cc b/src/test/unit/rx_ranges_unittest.cc similarity index 51% rename from src/test/unit/rc_calibration_unittest.cc rename to src/test/unit/rx_ranges_unittest.cc index c4165cba8..16f56119d 100755 --- a/src/test/unit/rc_calibration_unittest.cc +++ b/src/test/unit/rx_ranges_unittest.cc @@ -32,52 +32,54 @@ extern "C" { #include "gtest/gtest.h" extern "C" { -extern uint16_t applyRxCalibration(int sample, int minrc, int maxrc); +extern uint16_t applyRxChannelRangeConfiguraton(int sample, rxChannelRangeConfiguration_t range); } -TEST(RcCalibrationUnittest, TestRcCalibration) +#define RANGE_CONFIGURATION(min, max) (rxChannelRangeConfiguration_t) {min, max} + +TEST(RxChannelRangeTest, TestRxChannelRanges) { // No signal, special condition - EXPECT_EQ(applyRxCalibration(0, 1000, 2000), 0); - EXPECT_EQ(applyRxCalibration(0, 1300, 1700), 0); - EXPECT_EQ(applyRxCalibration(0, 900, 2100), 0); + EXPECT_EQ(applyRxChannelRangeConfiguraton(0, RANGE_CONFIGURATION(1000, 2000)), 0); + EXPECT_EQ(applyRxChannelRangeConfiguraton(0, RANGE_CONFIGURATION(1300, 1700)), 0); + EXPECT_EQ(applyRxChannelRangeConfiguraton(0, RANGE_CONFIGURATION(900, 2100)), 0); // Exact mapping - EXPECT_EQ(applyRxCalibration(1000, 1000, 2000), 1000); - EXPECT_EQ(applyRxCalibration(1500, 1000, 2000), 1500); - EXPECT_EQ(applyRxCalibration(2000, 1000, 2000), 2000); - EXPECT_EQ(applyRxCalibration(700, 1000, 2000), 750); - EXPECT_EQ(applyRxCalibration(2500, 1000, 2000), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1000, RANGE_CONFIGURATION(1000, 2000)), 1000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1500, RANGE_CONFIGURATION(1000, 2000)), 1500); + EXPECT_EQ(applyRxChannelRangeConfiguraton(2000, RANGE_CONFIGURATION(1000, 2000)), 2000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(700, RANGE_CONFIGURATION(1000, 2000)), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(2500, RANGE_CONFIGURATION(1000, 2000)), 2250); // Shifted range - EXPECT_EQ(applyRxCalibration(900, 900, 1900), 1000); - EXPECT_EQ(applyRxCalibration(1400, 900, 1900), 1500); - EXPECT_EQ(applyRxCalibration(1900, 900, 1900), 2000); - EXPECT_EQ(applyRxCalibration(600, 900, 1900), 750); - EXPECT_EQ(applyRxCalibration(2500, 900, 1900), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(900, RANGE_CONFIGURATION(900, 1900)), 1000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1400, RANGE_CONFIGURATION(900, 1900)), 1500); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1900, RANGE_CONFIGURATION(900, 1900)), 2000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(600, RANGE_CONFIGURATION(900, 1900)), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(2500, RANGE_CONFIGURATION(900, 1900)), 2250); // Narrower range than expected - EXPECT_EQ(applyRxCalibration(1300, 1300, 1700), 1000); - EXPECT_EQ(applyRxCalibration(1500, 1300, 1700), 1500); - EXPECT_EQ(applyRxCalibration(1700, 1300, 1700), 2000); - EXPECT_EQ(applyRxCalibration(700, 1300, 1700), 750); - EXPECT_EQ(applyRxCalibration(2500, 1300, 1700), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1300, RANGE_CONFIGURATION(1300, 1700)), 1000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1500, RANGE_CONFIGURATION(1300, 1700)), 1500); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1700, RANGE_CONFIGURATION(1300, 1700)), 2000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(700, RANGE_CONFIGURATION(1300, 1700)), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(2500, RANGE_CONFIGURATION(1300, 1700)), 2250); // Wider range than expected - EXPECT_EQ(applyRxCalibration(900, 900, 2100), 1000); - EXPECT_EQ(applyRxCalibration(1500, 900, 2100), 1500); - EXPECT_EQ(applyRxCalibration(2100, 900, 2100), 2000); - EXPECT_EQ(applyRxCalibration(600, 900, 2100), 750); - EXPECT_EQ(applyRxCalibration(2700, 900, 2100), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(900, RANGE_CONFIGURATION(900, 2100)), 1000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1500, RANGE_CONFIGURATION(900, 2100)), 1500); + EXPECT_EQ(applyRxChannelRangeConfiguraton(2100, RANGE_CONFIGURATION(900, 2100)), 2000); + EXPECT_EQ(applyRxChannelRangeConfiguraton(600, RANGE_CONFIGURATION(900, 2100)), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(2700, RANGE_CONFIGURATION(900, 2100)), 2250); // extreme out of range - EXPECT_EQ(applyRxCalibration(1, 1000, 2000), 750); - EXPECT_EQ(applyRxCalibration(1, 1300, 1700), 750); - EXPECT_EQ(applyRxCalibration(1, 900, 2100), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1, RANGE_CONFIGURATION(1000, 2000)), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1, RANGE_CONFIGURATION(1300, 1700)), 750); + EXPECT_EQ(applyRxChannelRangeConfiguraton(1, RANGE_CONFIGURATION(900, 2100)), 750); - EXPECT_EQ(applyRxCalibration(10000, 1000, 2000), 2250); - EXPECT_EQ(applyRxCalibration(10000, 1300, 1700), 2250); - EXPECT_EQ(applyRxCalibration(10000, 900, 2100), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(10000, RANGE_CONFIGURATION(1000, 2000)), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(10000, RANGE_CONFIGURATION(1300, 1700)), 2250); + EXPECT_EQ(applyRxChannelRangeConfiguraton(10000, RANGE_CONFIGURATION(900, 2100)), 2250); }