diff --git a/flight/libraries/sanitycheck.c b/flight/libraries/sanitycheck.c index 61950cbd9..13bca13be 100644 --- a/flight/libraries/sanitycheck.c +++ b/flight/libraries/sanitycheck.c @@ -178,26 +178,26 @@ int32_t configuration_check() } } - uint8_t checks_disabled; - FlightModeSettingsDisableSanityChecksGet(&checks_disabled); - if (checks_disabled == FLIGHTMODESETTINGS_DISABLESANITYCHECKS_TRUE) { - severity = SYSTEMALARMS_ALARM_WARNING; - } - // query sanity check hooks - if (severity == SYSTEMALARMS_ALARM_OK) { + if (severity < SYSTEMALARMS_ALARM_CRITICAL) { SANITYCHECK_CustomHookInstance *instance = NULL; LL_FOREACH(hooks, instance) { if (instance->enabled) { alarmstatus = instance->hook(); if (alarmstatus != SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE) { - severity = SYSTEMALARMS_ALARM_WARNING; + severity = SYSTEMALARMS_ALARM_CRITICAL; break; } } } } + uint8_t checks_disabled; + FlightModeSettingsDisableSanityChecksGet(&checks_disabled); + if (checks_disabled == FLIGHTMODESETTINGS_DISABLESANITYCHECKS_TRUE) { + severity = SYSTEMALARMS_ALARM_WARNING; + } + if (severity != SYSTEMALARMS_ALARM_OK) { ExtendedAlarmsSet(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION, severity, alarmstatus, alarmsubstatus); } else { @@ -287,6 +287,17 @@ static bool check_stabilization_settings(int index, bool multirotor, bool copter return false; } + + // if cruise control, ensure rate or acro are not set + if (modes[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_CRUISECONTROL) { + for (uint32_t i = 0; i < FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_YAW; i++) { + if ((modes[i] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_RATE || + modes[i] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ACRO)) { + return false; + } + } + } + // Warning: This assumes that certain conditions in the XML file are met. That // FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_MANUAL has the same numeric value for each channel // and is the same for STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL @@ -304,7 +315,6 @@ FrameType_t GetCurrentFrameType() switch ((SystemSettingsAirframeTypeOptions)airframe_type) { case SYSTEMSETTINGS_AIRFRAMETYPE_QUADX: case SYSTEMSETTINGS_AIRFRAMETYPE_QUADP: - case SYSTEMSETTINGS_AIRFRAMETYPE_QUADH: case SYSTEMSETTINGS_AIRFRAMETYPE_HEXA: case SYSTEMSETTINGS_AIRFRAMETYPE_OCTO: case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOX: diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index 891537bd6..e8b75b645 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -806,7 +806,7 @@ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuator freq[i] = 100; // Value must be small enough so CCr isn't update until the PIOS_Servo_Update is triggered clock[i] = ACTUATOR_ONESHOT125_CLOCK; // Setup an 8MHz timer clock break; - case ACTUATORSETTINGS_BANKMODE_ONESHOT: + case ACTUATORSETTINGS_BANKMODE_PWMSYNC: freq[i] = 100; clock[i] = ACTUATOR_PWM_CLOCK; break; diff --git a/flight/modules/GPS/GPS.c b/flight/modules/GPS/GPS.c index 97151f2fb..8f78f9061 100644 --- a/flight/modules/GPS/GPS.c +++ b/flight/modules/GPS/GPS.c @@ -91,7 +91,12 @@ void updateGpsSettings(UAVObjEvent *ev); #else #if defined(PIOS_GPS_MINIMAL) #define GPS_READ_BUFFER 32 - #define STACK_SIZE_BYTES 500 + +#ifdef PIOS_INCLUDE_GPS_NMEA_PARSER + #define STACK_SIZE_BYTES 580 // NMEA +#else + #define STACK_SIZE_BYTES 440 // UBX +#endif // PIOS_INCLUDE_GPS_NMEA_PARSER #else #define STACK_SIZE_BYTES 650 #endif // PIOS_GPS_MINIMAL @@ -203,9 +208,11 @@ int32_t GPSInitialize(void) GPSSettingsInitialize(); GPSSettingsDataProtocolGet(&gpsProtocol); switch (gpsProtocol) { +#if defined(PIOS_INCLUDE_GPS_NMEA_PARSER) case GPSSETTINGS_DATAPROTOCOL_NMEA: gps_rx_buffer = pios_malloc(NMEA_MAX_PACKET_LENGTH); break; +#endif case GPSSETTINGS_DATAPROTOCOL_UBX: gps_rx_buffer = pios_malloc(sizeof(struct UBXPacket)); break; @@ -459,12 +466,12 @@ static void updateHwSettings() } } -#ifdef PIOS_INCLUDE_GPS_UBX_PARSER +#if defined(PIOS_INCLUDE_GPS_UBX_PARSER) && !defined(PIOS_GPS_MINIMAL) void AuxMagSettingsUpdatedCb(__attribute__((unused)) UAVObjEvent *ev) { load_mag_settings(); } -#if defined(PIOS_INCLUDE_GPS_UBX_PARSER) && !defined(PIOS_GPS_MINIMAL) + void updateGpsSettings(__attribute__((unused)) UAVObjEvent *ev) { uint8_t ubxAutoConfig; @@ -537,7 +544,6 @@ void updateGpsSettings(__attribute__((unused)) UAVObjEvent *ev) ubx_autoconfig_set(newconfig); } #endif /* if defined(PIOS_INCLUDE_GPS_UBX_PARSER) && !defined(PIOS_GPS_MINIMAL) */ -#endif /* ifdef PIOS_INCLUDE_GPS_UBX_PARSER */ /** * @} * @} diff --git a/flight/modules/GPS/NMEA.c b/flight/modules/GPS/NMEA.c index 34eba2f9f..7c33edf11 100644 --- a/flight/modules/GPS/NMEA.c +++ b/flight/modules/GPS/NMEA.c @@ -40,14 +40,13 @@ #include "GPS.h" // #define ENABLE_DEBUG_MSG ///< define to enable debug-messages -#define DEBUG_PORT PIOS_COM_TELEM_RF ///< defines which serial port is ued for debug-messages - +#define DEBUG_PORT PIOS_COM_TELEM_RF ///< defines which serial port is used for debug-messages // Debugging #ifdef ENABLE_DEBUG_MSG // #define DEBUG_MSG_IN ///< define to display the incoming NMEA messages // #define DEBUG_PARAMS ///< define to display the incoming NMEA messages split into its parameters -// #define DEBUG_MGSID_IN ///< define to display the the names of the incoming NMEA messages +// #define DEBUG_MSGID_IN ///< define to display the names of the incoming NMEA messages // #define NMEA_DEBUG_PKT ///< define to enable debug of all NMEA messages // #define NMEA_DEBUG_GGA ///< define to enable debug of GGA messages // #define NMEA_DEBUG_VTG ///< define to enable debug of VTG messages @@ -68,40 +67,40 @@ struct nmea_parser { bool (*handler)(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); }; -static bool nmeaProcessGPGGA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); -static bool nmeaProcessGPRMC(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); -static bool nmeaProcessGPVTG(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); -static bool nmeaProcessGPGSA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); +static bool nmeaProcessGxGGA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); +static bool nmeaProcessGxRMC(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); +static bool nmeaProcessGxVTG(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); +static bool nmeaProcessGxGSA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); #if !defined(PIOS_GPS_MINIMAL) -static bool nmeaProcessGPZDA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); -static bool nmeaProcessGPGSV(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); +static bool nmeaProcessGxZDA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); +static bool nmeaProcessGxGSV(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam); #endif // PIOS_GPS_MINIMAL static const struct nmea_parser nmea_parsers[] = { { - .prefix = "GPGGA", - .handler = nmeaProcessGPGGA, + .prefix = "GGA", + .handler = nmeaProcessGxGGA, }, { - .prefix = "GPVTG", - .handler = nmeaProcessGPVTG, + .prefix = "VTG", + .handler = nmeaProcessGxVTG, }, { - .prefix = "GPGSA", - .handler = nmeaProcessGPGSA, + .prefix = "GSA", + .handler = nmeaProcessGxGSA, }, { - .prefix = "GPRMC", - .handler = nmeaProcessGPRMC, + .prefix = "RMC", + .handler = nmeaProcessGxRMC, }, #if !defined(PIOS_GPS_MINIMAL) { - .prefix = "GPZDA", - .handler = nmeaProcessGPZDA, + .prefix = "ZDA", + .handler = nmeaProcessGxZDA, }, { - .prefix = "GPGSV", - .handler = nmeaProcessGPGSV, + .prefix = "GSV", + .handler = nmeaProcessGxGSV, }, #endif // PIOS_GPS_MINIMAL }; @@ -373,6 +372,8 @@ bool NMEA_update_position(char *nmea_sentence, GPSPositionSensorData *GpsData) // Sample NMEA message: "GPRMC,000131.736,V,,,,,0.00,0.00,060180,,,N*43" // The first parameter starts at the beginning of the message + // Skip first two character, allow GL, GN, GP... + p += 2; params[0] = p; nbParams = 1; while (*p != 0) { @@ -406,11 +407,13 @@ bool NMEA_update_position(char *nmea_sentence, GPSPositionSensorData *GpsData) parser = NMEA_find_parser_by_prefix(params[0]); if (!parser) { // No parser found + #ifdef DEBUG_MSGID_IN DEBUG_MSG(" NO PARSER (\"%s\")\n", params[0]); + #endif return false; } - #ifdef DEBUG_MGSID_IN + #ifdef DEBUG_MSGID_IN DEBUG_MSG("%s %d ", params[0]); #endif // Send the message to the parser and get it update the GpsData @@ -422,7 +425,9 @@ bool NMEA_update_position(char *nmea_sentence, GPSPositionSensorData *GpsData) if (!parser->handler(GpsData, &gpsDataUpdated, params, nbParams)) { // Parse failed + #ifdef DEBUG_MSGID_IN DEBUG_MSG("PARSE FAILED (\"%s\")\n", params[0]); + #endif if (gpsDataUpdated && (GpsData->Status == GPSPOSITIONSENSOR_STATUS_NOFIX)) { GPSPositionSensorSet(GpsData); } @@ -432,13 +437,13 @@ bool NMEA_update_position(char *nmea_sentence, GPSPositionSensorData *GpsData) // All is fine :) Update object if data has changed if (gpsDataUpdated) { - #ifdef DEBUG_MGSID_IN + #ifdef DEBUG_MSGID_IN DEBUG_MSG("U"); #endif GPSPositionSensorSet(GpsData); } - #ifdef DEBUG_MGSID_IN + #ifdef DEBUG_MSGID_IN DEBUG_MSG("\n"); #endif return true; @@ -446,11 +451,11 @@ bool NMEA_update_position(char *nmea_sentence, GPSPositionSensorData *GpsData) /** - * Parse an NMEA GPGGA sentence and update the given UAVObject + * Parse an NMEA GxGGA sentence and update the given UAVObject * \param[in] A pointer to a GPSPositionSensor UAVObject to be updated. * \param[in] An NMEA sentence with a valid checksum */ -static bool nmeaProcessGPGGA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) +static bool nmeaProcessGxGGA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) { if (nbParam != 15) { return false; @@ -499,11 +504,11 @@ static bool nmeaProcessGPGGA(GPSPositionSensorData *GpsData, bool *gpsDataUpdate } /** - * Parse an NMEA GPRMC sentence and update the given UAVObject + * Parse an NMEA GxRMC sentence and update the given UAVObject * \param[in] A pointer to a GPSPositionSensor UAVObject to be updated. * \param[in] An NMEA sentence with a valid checksum */ -static bool nmeaProcessGPRMC(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) +static bool nmeaProcessGxRMC(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) { if (nbParam != 13) { return false; @@ -567,11 +572,11 @@ static bool nmeaProcessGPRMC(GPSPositionSensorData *GpsData, bool *gpsDataUpdate } /** - * Parse an NMEA GPVTG sentence and update the given UAVObject + * Parse an NMEA GxVTG sentence and update the given UAVObject * \param[in] A pointer to a GPSPositionSensor UAVObject to be updated. * \param[in] An NMEA sentence with a valid checksum */ -static bool nmeaProcessGPVTG(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) +static bool nmeaProcessGxVTG(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) { if (nbParam != 9 && nbParam != 10 /*GTOP GPS seems to gemnerate an extra parameter...*/) { return false; @@ -592,11 +597,11 @@ static bool nmeaProcessGPVTG(GPSPositionSensorData *GpsData, bool *gpsDataUpdate #if !defined(PIOS_GPS_MINIMAL) /** - * Parse an NMEA GPZDA sentence and update the @ref GPSTime object + * Parse an NMEA GxZDA sentence and update the @ref GPSTime object * \param[in] A pointer to a GPSPositionSensor UAVObject to be updated (unused). * \param[in] An NMEA sentence with a valid checksum */ -static bool nmeaProcessGPZDA(__attribute__((unused)) GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) +static bool nmeaProcessGxZDA(__attribute__((unused)) GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) { if (nbParam != 7) { return false; @@ -636,7 +641,7 @@ static uint8_t gsv_processed_mask; static uint16_t gsv_incomplete_error; static uint16_t gsv_duplicate_error; -static bool nmeaProcessGPGSV(__attribute__((unused)) GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) +static bool nmeaProcessGxGSV(__attribute__((unused)) GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) { if (nbParam < 4) { return false; @@ -723,7 +728,7 @@ static bool nmeaProcessGPGSV(__attribute__((unused)) GPSPositionSensorData *GpsD * \param[in] A pointer to a GPSPositionSensor UAVObject to be updated. * \param[in] An NMEA sentence with a valid checksum */ -static bool nmeaProcessGPGSA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) +static bool nmeaProcessGxGSA(GPSPositionSensorData *GpsData, bool *gpsDataUpdated, char *param[], uint8_t nbParam) { if (nbParam != 18) { return false; diff --git a/flight/pios/stm32f10x/pios_servo.c b/flight/pios/stm32f10x/pios_servo.c index f0a11d8e2..76da3d33a 100644 --- a/flight/pios/stm32f10x/pios_servo.c +++ b/flight/pios/stm32f10x/pios_servo.c @@ -40,8 +40,10 @@ static const struct pios_servo_cfg *servo_cfg; // determine if the related timer will work in synchronous (or OneShot/OneShot125) One Pulse mode. -// static uint8_t pios_servo_bank_mode[PIOS_SERVO_BANKS] = { 0 }; - +static uint8_t pios_servo_bank_mode[PIOS_SERVO_BANKS] = { 0 }; +// used to skip updates when pulse length is higher than update cycle +static uint16_t pios_servo_bank_next_update[PIOS_SERVO_BANKS] = { 0 }; +static uint16_t pios_servo_bank_max_pulse[PIOS_SERVO_BANKS] = { 0 }; // timer associated to each bank static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; @@ -49,7 +51,7 @@ static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; static uint8_t *pios_servo_pin_bank; #define PIOS_SERVO_TIMER_CLOCK 1000000 - +#define PIOS_SERVO_SAFE_MARGIN 50 /** * Initialise Servos */ @@ -91,6 +93,12 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) pios_servo_pin_bank[j] = bank; } } + pios_servo_bank_timer[bank] = chan->timer; + + TIM_ARRPreloadConfig(chan->timer, ENABLE); + TIM_CtrlPWMOutputs(chan->timer, ENABLE); + TIM_Cmd(chan->timer, ENABLE); + bank++; } @@ -113,10 +121,6 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; } - - TIM_ARRPreloadConfig(chan->timer, ENABLE); - TIM_CtrlPWMOutputs(chan->timer, ENABLE); - TIM_Cmd(chan->timer, ENABLE); } return 0; @@ -166,37 +170,106 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) return; } + /* Update the position */ const struct pios_tim_channel *chan = &servo_cfg->channels[servo]; + uint16_t val = position; + uint16_t margin = chan->timer->ARR / 50; // Leave 2% of period as margin to prevent overlaps + if (val > (chan->timer->ARR - margin)) { + val = chan->timer->ARR - margin; + } + + uint8_t bank = pios_servo_pin_bank[servo]; + if (pios_servo_bank_max_pulse[bank] < val) { + pios_servo_bank_max_pulse[bank] = val; + } switch (chan->timer_chan) { case TIM_Channel_1: - TIM_SetCompare1(chan->timer, position); + TIM_SetCompare1(chan->timer, val); break; case TIM_Channel_2: - TIM_SetCompare2(chan->timer, position); + TIM_SetCompare2(chan->timer, val); break; case TIM_Channel_3: - TIM_SetCompare3(chan->timer, position); + TIM_SetCompare3(chan->timer, val); break; case TIM_Channel_4: - TIM_SetCompare4(chan->timer, position); + TIM_SetCompare4(chan->timer, val); break; } } void PIOS_Servo_Update() { - /* - for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { + for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { const TIM_TypeDef *timer = pios_servo_bank_timer[i]; - if (timer) { - TIM_Cmd((TIM_TypeDef *)timer, ENABLE); + if (timer && pios_servo_bank_mode[i] == PIOS_SERVO_BANK_MODE_SINGLE_PULSE) { + // a pulse to be generated is longer than cycle period. skip this update. + if (TIM_GetCounter((TIM_TypeDef *)timer) > (uint32_t)(pios_servo_bank_next_update[i] + PIOS_SERVO_SAFE_MARGIN)) { + TIM_GenerateEvent((TIM_TypeDef *)timer, TIM_EventSource_Update); + pios_servo_bank_next_update[i] = pios_servo_bank_max_pulse[i]; + } } - } - */ + pios_servo_bank_max_pulse[i] = 0; + } + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + uint8_t bank = pios_servo_pin_bank[i]; + uint8_t mode = pios_servo_bank_mode[bank]; + if (mode == PIOS_SERVO_BANK_MODE_SINGLE_PULSE) { + /* Update the position */ + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_SetCompare1(chan->timer, 0); + break; + case TIM_Channel_2: + TIM_SetCompare2(chan->timer, 0); + break; + case TIM_Channel_3: + TIM_SetCompare3(chan->timer, 0); + break; + case TIM_Channel_4: + TIM_SetCompare4(chan->timer, 0); + break; + } + } + } +} + +void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) +{ + PIOS_Assert(bank < PIOS_SERVO_BANKS); + pios_servo_bank_mode[bank] = mode; + + if (pios_servo_bank_timer[bank]) { + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + if (pios_servo_pin_bank[i] == bank) { + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + /* Set up for output compare function */ + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + case TIM_Channel_2: + TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + case TIM_Channel_3: + TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + case TIM_Channel_4: + TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + } + } + } + + // Setup the timer accordingly + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); + TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); + } } -void PIOS_Servo_SetBankMode(__attribute__((unused)) uint8_t bank, __attribute__((unused)) uint8_t mode) {} uint8_t PIOS_Servo_GetPinBank(uint8_t pin) { diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 7e66c09e2..84a450b7f 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -142,11 +142,7 @@ void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) } } } - if (mode != PIOS_SERVO_BANK_MODE_PWM) { - // TIM_UpdateDisableConfig(pios_servo_bank_timer[bank], ENABLE); - } else { - // TIM_UpdateDisableConfig(pios_servo_bank_timer[bank], DISABLE); - } + // Setup the timer accordingly TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); diff --git a/flight/targets/boards/coptercontrol/board_hw_defs.c b/flight/targets/boards/coptercontrol/board_hw_defs.c index 6463451b3..2a22cf78a 100644 --- a/flight/targets/boards/coptercontrol/board_hw_defs.c +++ b/flight/targets/boards/coptercontrol/board_hw_defs.c @@ -1247,6 +1247,18 @@ const struct pios_ppm_cfg pios_ppm_cfg = { .num_channels = 1, }; +const struct pios_ppm_cfg pios_ppm_pin6_cfg = { + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + }, + /* Use only the first channel for ppm */ + .channels = &pios_tim_rcvrport_all_channels[5], + .num_channels = 1, +}; + #endif /* PIOS_INCLUDE_PPM */ #if defined(PIOS_INCLUDE_PPM_FLEXI) diff --git a/flight/targets/boards/coptercontrol/firmware/Makefile b/flight/targets/boards/coptercontrol/firmware/Makefile index 799013726..d58b57e64 100644 --- a/flight/targets/boards/coptercontrol/firmware/Makefile +++ b/flight/targets/boards/coptercontrol/firmware/Makefile @@ -30,6 +30,12 @@ USE_DSP_LIB ?= NO # Set to YES to build a FW version that will erase data flash memory ERASE_FLASH ?= NO +# Set to yes to include Gcsreceiver module +GCSRECEIVER ?= NO + +# Enable Diag tasks ? +DIAG_TASKS ?= NO + # List of mandatory modules to include MODULES += Attitude MODULES += Stabilization @@ -103,7 +109,6 @@ ifndef TESTAPP SRC += $(OPUAVSYNTHDIR)/gyrostate.c SRC += $(OPUAVSYNTHDIR)/attitudestate.c SRC += $(OPUAVSYNTHDIR)/manualcontrolcommand.c - SRC += $(OPUAVSYNTHDIR)/i2cstats.c SRC += $(OPUAVSYNTHDIR)/watchdogstatus.c SRC += $(OPUAVSYNTHDIR)/manualcontrolsettings.c SRC += $(OPUAVSYNTHDIR)/flightmodesettings.c @@ -116,15 +121,23 @@ ifndef TESTAPP SRC += $(OPUAVSYNTHDIR)/gpsvelocitysensor.c SRC += $(OPUAVSYNTHDIR)/gpssettings.c SRC += $(OPUAVSYNTHDIR)/hwsettings.c - SRC += $(OPUAVSYNTHDIR)/gcsreceiver.c SRC += $(OPUAVSYNTHDIR)/receiveractivity.c - SRC += $(OPUAVSYNTHDIR)/taskinfo.c - SRC += $(OPUAVSYNTHDIR)/callbackinfo.c SRC += $(OPUAVSYNTHDIR)/mixerstatus.c SRC += $(OPUAVSYNTHDIR)/ratedesired.c SRC += $(OPUAVSYNTHDIR)/txpidsettings.c SRC += $(OPUAVSYNTHDIR)/mpu6000settings.c - SRC += $(OPUAVSYNTHDIR)/perfcounter.c + # Command line option for Gcsreceiver module + ifeq ($(GCSRECEIVER), YES) + SRC += $(OPUAVSYNTHDIR)/gcsreceiver.c + endif + # Enable Diag tasks and UAVOs needed + ifeq ($(DIAG_TASKS), YES) + CDEFS += -DDIAG_TASKS + SRC += $(OPUAVSYNTHDIR)/taskinfo.c + SRC += $(OPUAVSYNTHDIR)/callbackinfo.c + SRC += $(OPUAVSYNTHDIR)/perfcounter.c + SRC += $(OPUAVSYNTHDIR)/i2cstats.c + endif else ## Test Code SRC += $(OPTESTS)/test_common.c diff --git a/flight/targets/boards/coptercontrol/firmware/inc/pios_config.h b/flight/targets/boards/coptercontrol/firmware/inc/pios_config.h index 9450a6781..aabc651a7 100644 --- a/flight/targets/boards/coptercontrol/firmware/inc/pios_config.h +++ b/flight/targets/boards/coptercontrol/firmware/inc/pios_config.h @@ -97,10 +97,10 @@ /* PIOS receiver drivers */ #define PIOS_INCLUDE_PWM #define PIOS_INCLUDE_PPM -#define PIOS_INCLUDE_PPM_FLEXI +/* #define PIOS_INCLUDE_PPM_FLEXI */ #define PIOS_INCLUDE_DSM #define PIOS_INCLUDE_SBUS -#define PIOS_INCLUDE_GCSRCVR +/* #define PIOS_INCLUDE_GCSRCVR */ /* #define PIOS_INCLUDE_OPLINKRCVR */ /* PIOS abstract receiver interface */ @@ -142,7 +142,7 @@ /* #define PIOS_TELEM_PRIORITY_QUEUE */ #define PIOS_INCLUDE_GPS #define PIOS_GPS_MINIMAL -#define PIOS_INCLUDE_GPS_NMEA_PARSER +/* #define PIOS_INCLUDE_GPS_NMEA_PARSER */ #define PIOS_INCLUDE_GPS_UBX_PARSER /* #define PIOS_GPS_SETS_HOMELOCATION */ diff --git a/flight/targets/boards/coptercontrol/firmware/pios_board.c b/flight/targets/boards/coptercontrol/firmware/pios_board.c index 62232d832..444c9f772 100644 --- a/flight/targets/boards/coptercontrol/firmware/pios_board.c +++ b/flight/targets/boards/coptercontrol/firmware/pios_board.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #ifdef PIOS_INCLUDE_INSTRUMENTATION #include @@ -52,6 +54,9 @@ */ uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; +static SystemAlarmsExtendedAlarmStatusOptions CopterControlConfigHook(); +static void ActuatorSettingsUpdatedCb(UAVObjEvent *ev); + #define PIOS_COM_TELEM_RF_RX_BUF_LEN 32 #define PIOS_COM_TELEM_RF_TX_BUF_LEN 12 @@ -712,8 +717,8 @@ void PIOS_Board_Init(void) uint8_t hwsettings_rcvrport; HwSettingsCC_RcvrPortGet(&hwsettings_rcvrport); - switch (hwsettings_rcvrport) { - case HWSETTINGS_CC_RCVRPORT_DISABLED: + switch ((HwSettingsCC_RcvrPortOptions)hwsettings_rcvrport) { + case HWSETTINGS_CC_RCVRPORT_DISABLEDONESHOT: #if defined(PIOS_INCLUDE_HCSR04) { uint32_t pios_hcsr04_id; @@ -721,7 +726,7 @@ void PIOS_Board_Init(void) } #endif break; - case HWSETTINGS_CC_RCVRPORT_PWM: + case HWSETTINGS_CC_RCVRPORT_PWMNOONESHOT: #if defined(PIOS_INCLUDE_PWM) { uint32_t pios_pwm_id; @@ -735,12 +740,17 @@ void PIOS_Board_Init(void) } #endif /* PIOS_INCLUDE_PWM */ break; - case HWSETTINGS_CC_RCVRPORT_PPM: - case HWSETTINGS_CC_RCVRPORT_PPMOUTPUTS: + case HWSETTINGS_CC_RCVRPORT_PPMNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPMOUTPUTSNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPM_PIN6ONESHOT: #if defined(PIOS_INCLUDE_PPM) { uint32_t pios_ppm_id; - PIOS_PPM_Init(&pios_ppm_id, &pios_ppm_cfg); + if (hwsettings_rcvrport == HWSETTINGS_CC_RCVRPORT_PPM_PIN6ONESHOT) { + PIOS_PPM_Init(&pios_ppm_id, &pios_ppm_pin6_cfg); + } else { + PIOS_PPM_Init(&pios_ppm_id, &pios_ppm_cfg); + } uint32_t pios_ppm_rcvr_id; if (PIOS_RCVR_Init(&pios_ppm_rcvr_id, &pios_ppm_rcvr_driver, pios_ppm_id)) { @@ -750,7 +760,7 @@ void PIOS_Board_Init(void) } #endif /* PIOS_INCLUDE_PPM */ break; - case HWSETTINGS_CC_RCVRPORT_PPMPWM: + case HWSETTINGS_CC_RCVRPORT_PPMPWMNOONESHOT: /* This is a combination of PPM and PWM inputs */ #if defined(PIOS_INCLUDE_PPM) { @@ -777,6 +787,8 @@ void PIOS_Board_Init(void) } #endif /* PIOS_INCLUDE_PWM */ break; + case HWSETTINGS_CC_RCVRPORT_OUTPUTSONESHOT: + break; } #if defined(PIOS_INCLUDE_GCSRCVR) @@ -794,15 +806,16 @@ void PIOS_Board_Init(void) GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE); #ifndef PIOS_ENABLE_DEBUG_PINS - switch (hwsettings_rcvrport) { - case HWSETTINGS_CC_RCVRPORT_DISABLED: - case HWSETTINGS_CC_RCVRPORT_PWM: - case HWSETTINGS_CC_RCVRPORT_PPM: - case HWSETTINGS_CC_RCVRPORT_PPMPWM: + switch ((HwSettingsCC_RcvrPortOptions)hwsettings_rcvrport) { + case HWSETTINGS_CC_RCVRPORT_DISABLEDONESHOT: + case HWSETTINGS_CC_RCVRPORT_PWMNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPMNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPMPWMNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPM_PIN6ONESHOT: PIOS_Servo_Init(&pios_servo_cfg); break; - case HWSETTINGS_CC_RCVRPORT_PPMOUTPUTS: - case HWSETTINGS_CC_RCVRPORT_OUTPUTS: + case HWSETTINGS_CC_RCVRPORT_PPMOUTPUTSNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_OUTPUTSONESHOT: PIOS_Servo_Init(&pios_servo_rcvr_cfg); break; } @@ -841,6 +854,59 @@ void PIOS_Board_Init(void) /* Make sure we have at least one telemetry link configured or else fail initialization */ PIOS_Assert(pios_com_telem_rf_id || pios_com_telem_usb_id); + + // Attach the board config check hook + SANITYCHECK_AttachHook(&CopterControlConfigHook); + // trigger a config check if actuatorsettings are updated + ActuatorSettingsInitialize(); + ActuatorSettingsConnectCallback(ActuatorSettingsUpdatedCb); +} + +SystemAlarmsExtendedAlarmStatusOptions CopterControlConfigHook() +{ + // inhibit usage of oneshot for non supported RECEIVER port modes + uint8_t recmode; + + HwSettingsCC_RcvrPortGet(&recmode); + uint8_t flexiMode; + uint8_t modes[ACTUATORSETTINGS_BANKMODE_NUMELEM]; + ActuatorSettingsBankModeGet(modes); + HwSettingsCC_FlexiPortGet(&flexiMode); + + switch ((HwSettingsCC_RcvrPortOptions)recmode) { + // Those modes allows oneshot usage + case HWSETTINGS_CC_RCVRPORT_DISABLEDONESHOT: + case HWSETTINGS_CC_RCVRPORT_OUTPUTSONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPM_PIN6ONESHOT: + if ((recmode == HWSETTINGS_CC_RCVRPORT_PPM_PIN6ONESHOT || + flexiMode == HWSETTINGS_CC_FLEXIPORT_PPM) && + (modes[3] == ACTUATORSETTINGS_BANKMODE_PWMSYNC || + modes[3] == ACTUATORSETTINGS_BANKMODE_ONESHOT125)) { + return SYSTEMALARMS_EXTENDEDALARMSTATUS_UNSUPPORTEDCONFIG_ONESHOT; + } else { + return SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE; + } + + // inhibit oneshot for the following modes + case HWSETTINGS_CC_RCVRPORT_PPMNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPMOUTPUTSNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PPMPWMNOONESHOT: + case HWSETTINGS_CC_RCVRPORT_PWMNOONESHOT: + for (uint8_t i = 0; i < ACTUATORSETTINGS_BANKMODE_NUMELEM; i++) { + if (modes[i] == ACTUATORSETTINGS_BANKMODE_PWMSYNC || + modes[i] == ACTUATORSETTINGS_BANKMODE_ONESHOT125) { + return SYSTEMALARMS_EXTENDEDALARMSTATUS_UNSUPPORTEDCONFIG_ONESHOT;; + } + + return SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE; + } + } + return SYSTEMALARMS_EXTENDEDALARMSTATUS_UNSUPPORTEDCONFIG_ONESHOT;; +} +// trigger a configuration check if ActuatorSettings are changed. +void ActuatorSettingsUpdatedCb(__attribute__((unused)) UAVObjEvent *ev) +{ + configuration_check(); } /** diff --git a/flight/targets/boards/revoproto/firmware/inc/pios_config.h b/flight/targets/boards/revoproto/firmware/inc/pios_config.h index b7aed8375..5897732ad 100644 --- a/flight/targets/boards/revoproto/firmware/inc/pios_config.h +++ b/flight/targets/boards/revoproto/firmware/inc/pios_config.h @@ -108,8 +108,6 @@ #define PIOS_INCLUDE_IAP #define PIOS_INCLUDE_SERVO /* #define PIOS_INCLUDE_I2C_ESC */ -#define PIOS_INCLUDE_OVERO -#define PIOS_OVERO_SPI /* #define PIOS_INCLUDE_SDCARD */ /* #define LOG_FILENAME "startup.log" */ #define PIOS_INCLUDE_FLASH diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml index ee885f643..f8173c9ad 100644 --- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml +++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Panels.qml @@ -893,7 +893,7 @@ Item { Text { text: ["FixedWing", "FixedWingElevon", "FixedWingVtail", "VTOL", "HeliCP", "QuadX", "QuadP", - "QuadH", "Hexa+", "Octo+", "Custom", "HexaX", "HexaH", "OctoV", "OctoCoaxP", "OctoCoaxX", "OctoX", "HexaCoax", + "Hexa+", "Octo+", "Custom", "HexaX", "HexaH", "OctoV", "OctoCoaxP", "OctoCoaxX", "OctoX", "HexaCoax", "Tricopter", "GroundVehicleCar", "GroundVehicleDiff", "GroundVehicleMoto"][SystemSettings.AirframeType] anchors.right: parent.right color: "white" diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Warnings.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Warnings.qml index 8078a2854..8197fa42d 100644 --- a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Warnings.qml +++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Warnings.qml @@ -24,10 +24,10 @@ Item { property variant thrustmodeColors : ["green", "grey", "grey", "grey", "grey", "grey", "grey", "grey", "green", "green", "green", "cyan"] - // SystemSettings.AirframeType 3 - 18 : VtolPathFollower, check ThrustControl + // SystemSettings.AirframeType 3 - 17 : VtolPathFollower, check ThrustControl property var thrust_mode: FlightStatus.FlightMode < 7 ? StabilizationDesired.StabilizationMode_Thrust : - FlightStatus.FlightMode > 6 && SystemSettings.AirframeType > 2 && SystemSettings.AirframeType < 19 + FlightStatus.FlightMode > 6 && SystemSettings.AirframeType > 2 && SystemSettings.AirframeType < 18 && VtolPathFollowerSettings.ThrustControl == 1 ? 11 : FlightStatus.FlightMode > 6 && SystemSettings.AirframeType < 3 ? 11: 0 diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts index 1fa713f73..730541f42 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts @@ -6649,15 +6649,13 @@ Applique et Enregistre tous les paramètres sur la SD Sortie - Output Update Speed Bof... - Fréquence Mise à Jour Sorties + Fréquence Mise à Jour Sorties - Channel: - Canal : + Canal : @@ -6763,16 +6761,58 @@ Applique et Enregistre tous les paramètres sur la SD Test en Temps Réel - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - Configurer ici "RapidESC" : 490Hz est une valeur classique pour les multirotors. + Configurer ici "RapidESC" : 490Hz est une valeur classique pour les multirotors. 490 + + + Output configuration + + + + + Bank(Channels): + + + + + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + + + Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + + + + Mode: + Mode : + + + + Setup output mode. Use PWM or OneShot with Standard ESCs. +Several other ESCs like BLHeli 13+ can use the more advanced OneShot125. +When using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + Calibration status + Statut de l'étalonnage + outputChannelForm @@ -6786,20 +6826,14 @@ Applique et Enregistre tous les paramètres sur la SD Link Lien - - - # - - Channel Number Numéro Canal - Minimum PWM value, beware of not overdriving your servo. - Valeur minimum PWM, attention de respecter les limites de votre servo. + Valeur minimum PWM, attention de respecter les limites de votre servo. @@ -6832,9 +6866,8 @@ Applique et Enregistre tous les paramètres sur la SD Mode de sortie - Maximum PWM value, beware of not overdriving your servo. - Valeur maximum PWM, attention de respecter les limites de votre servo. + Valeur maximum PWM, attention de respecter les limites de votre servo. @@ -6843,13 +6876,40 @@ Applique et Enregistre tous les paramètres sur la SD - 0: + - - - - + # - Bank + + + + + Minimum PWM value, beware of not overdriving your servo. +Using OneShot125 a value of 1000(uS) here will produce a pulse of 125(uS). + + + + + 0 + 0 + + + + Bank number + + + + + 0 + + + + + Maximum value, beware of not overdriving your servo. +Using OneShot125 a value of 2000(uS) here will produce a pulse of 250(uS). + @@ -9609,19 +9669,32 @@ Veuillez sélectionner le type de multirotor désiré pour la configuration ci-d - - + + Start Démarrer - - + + + + + Output value : <b>%1</b> µs + Valeur de sortie : <b>%1</b> µs + + + + <html><head/><body><p><span style=" font-size:10pt;">To find </span><span style=" font-size:10pt; font-weight:600;">the neutral rate for this reversable motor</span><span style=" font-size:10pt;">, press the Start button below and slide the slider to the right or left until you find the value where the motor doesn't start. <br/><br/>When done press button again to stop.</span></p></body></html> + <html><head/><body><p><span style=" font-size:10pt;">Pour trouver </span><span style=" font-size:10pt; font-weight:600;">la valeur de neutre de ce moteur inversable</span><span style=" font-size:10pt;">, appuyez sur le bouton Démarrer et bouger le curseur à gauche ou à droite jusqu'à trouver la position centrale où le moteur ne démarre pas. <br/><br/>Lorsque c'est terminé, appuyer à nouveau sur le bouton pour arrêter.</span></p></body></html> + + + + Stop Arrêter - + The actuator module is in an error state. Please make sure the correct firmware version is used then restart the wizard and try again. If the problem persists please consult the openpilot.org support forum. @@ -9668,14 +9741,13 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">En fonction du véhicule que vous avez sélectionné, les moteurs pilotés par des variateurs et/ou les servos contrôlés directement par la carte OpenPilot devront-être calibrés. Les étapes suivantes vous guideront en toute sécurité dans ce processus. </span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">In this step we will set the neutral rate for the motor highlighted in the illustration to the right. <br />Please pay attention to the details and in particular the motors position and its rotation direction. Ensure the motors are spinning in the correct direction as shown in the diagram. Swap any 2 motor wires to change the direction of a motor. </span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To find </span><span style=" font-size:10pt; font-weight:600;">the neutral rate for this motor</span><span style=" font-size:10pt;">, press the Start button below and slide the slider to the right until the motor just starts to spin stable. <br /><br />When done press button again to stop.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> @@ -9698,6 +9770,29 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Cochez "Inverser" pour changer la direction de mouvement du servo.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">In this step we will set the neutral rate for the motor highlighted in the illustration to the right. <br />Please pay attention to the details and in particular the motors position and its rotation direction. Ensure the motors are spinning in the correct direction as shown in the diagram. Swap any 2 motor wires to change the direction of a motor. </span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A cette étapes nous allons ajuster le neutre du moteur mis en évidence dans l'illustration à droite. <br/>Veuillez faire attention aux détails et en particulier à la position et au sens de rotation du moteur concerné. Soyez certain que le moteur tourne dans le bon sens comme indiqué sur l'illustration ci-contre. Vous pouvez intervertir deux fils du moteur pour changer son sens de rotation. </span></p></body></html> + + + + <html><head/><body><p><span style=" font-size:10pt;">To find </span><span style=" font-size:10pt; font-weight:600;">the neutral rate for this motor</span><span style=" font-size:10pt;">, press the Start button below and slide the slider to the right until the motor just starts to spin stable. <br/><br/>When done press button again to stop.</span></p></body></html> + <html><head/><body><p><span style=" font-size:10pt;">Pour trouver </span><span style=" font-size:10pt; font-weight:600;">le neutre de ce moteur</span><span style=" font-size:10pt;">, appuyez sur le bouton "Démarrer" ci-dessous et bougez le curseur vers la droite jusqu'à ce que le moteur démarre et tourne de manière régulière. <br /><br />Lorsque c'est réglé, appuyez à nouveau sur le bouton pour arrêter.</span></p></body></html> + + + + Output value: 1000µs + Valeur de sortie : <b>1000</b> µs + RebootPage @@ -10529,7 +10624,7 @@ p, li { white-space: pre-wrap; } ConfigMultiRotorWidget - + Input Entrée @@ -10539,7 +10634,7 @@ p, li { white-space: pre-wrap; } Sortie - + @@ -10547,18 +10642,33 @@ p, li { white-space: pre-wrap; } - + Configuration OK Configuration OK - + <font color='red'>ERROR: Assign a Yaw channel</font> <font color='red'>ERREUR : Veuillez affecter le canal de Yaw</font> - + + Duplicate channel in motor outputs + Canaux en double dans le sorties moteur + + + + Channel already used + Canal déjà utilisé + + + + Select output channel for Accessory%1 RcInput + Sélectionnez le canal de sortie pour l'entrée RC Accessory%1 + + + <font color='red'>ERROR: Assign all %1 motor channels</font> <font color='red'>ERREUR : Veuillez affecter tous les %1 canaux moteurs</font> @@ -10645,7 +10755,7 @@ Voulez-vous toujours continuer ? Vous devrez reconfigurer manuellement les paramètres d'armement lorsque l'assistant sera terminé. Après la dernière étape de l'assistant, vous serez redirigé vers l'écran des Paramètres d'Armement. - + Next Suivant @@ -11522,7 +11632,7 @@ Double clic sur la légende ou le tracé pour afficher/cacher la légende.Écriture paramètres de stabilisation - + Writing mixer settings Écriture paramètres mixeur @@ -11734,7 +11844,7 @@ Double clic sur la légende ou le tracé pour afficher/cacher la légende. UploaderGadgetWidget - + Connected Device Périphérique Connecté @@ -11751,12 +11861,12 @@ Double clic sur la légende ou le tracé pour afficher/cacher la légende. - + Device Périphérique - + http://wiki.openpilot.org/display/Doc/Erase+board+settings @@ -11766,66 +11876,71 @@ Double clic sur la légende ou le tracé pour afficher/cacher la légende.En cours d'exécution - + Timed out while waiting for all boards to be disconnected! Bof Expiration du temps d'attente de la déconnexion de toutes les cartes ! - - + + Timed out while waiting for a board to be connected! Bof Expiration du temps dans l'attente d'une connexion de carte ! - + + To upgrade the OPLinkMini board please disconnect it from the USB port, press the Upgrade again button and follow instructions on screen. + Pour mettre à jour une carte OPLinkMini veuillez la déconnecterdu port USB, appuyez à nouveau sur le bouton de mise à jour et suivez les instructions à l'écran. + + + Timed out while waiting for a board to be fully connected! - Expiration du temps dans l'attente d'une connexion complète de carte ! + Expiration du temps dans l'attente d'une connexion complète de carte ! Failed to enter bootloader mode. - Échec du passage en mode bootloader. + Échec du passage en mode bootloader. Unknown board id '0x%1' - Carte inconnue id '0x%1' + Carte inconnue id '0x%1' Firmware image not found. - Image firmware non trouvée. + Image firmware non trouvée. Could not open firmware image for reading. - Impossible d'ouvrir l'image de firmware en lecture. + Impossible d'ouvrir l'image de firmware en lecture. Could not enter direct firmware upload mode. - Impossible de passer en mode DFU. + Impossible de passer en mode DFU. Firmware upload failed. - Échec du téléversement du firmware. + Échec du téléversement du firmware. Failed to upload firmware description. - Échec du téléversement de la description firmware. + Échec du téléversement de la description firmware. - + Timed out while booting. - Expiration du temps d'attente lors du démarrage. + Expiration du temps d'attente lors du démarrage. - + Please disconnect your OpenPilot board. Veuillez déconnecter votre carte OpenPilot. @@ -11848,7 +11963,7 @@ Double clic sur la légende ou le tracé pour afficher/cacher la légende.La carte doit être connectée à un port USB ! - + Waiting for all OpenPilot boards to be disconnected from USB. Attente de la déconnexion de toutes les cartes connectées en USB. @@ -11866,37 +11981,37 @@ Double clic sur la légende ou le tracé pour afficher/cacher la légende. Bringing the board into boot loader mode. Please wait. - Passage de la carte en mode bootloader. Veuillez patienter. + Passage de la carte en mode bootloader. Veuillez patienter. Step %1 - Étape %1 + Étape %1 Rebooting the board. Please wait. - Redémarrage de la carte. Veuillez patienter. + Redémarrage de la carte. Veuillez patienter. Rebooting and erasing the board. Please wait. - Redémarrage et effacement de la carte. Veuillez patienter. + Redémarrage et effacement de la carte. Veuillez patienter. Board was updated successfully. Press OK to finish. - La carte a été mise à jour avec succès. Appuyez sur OK pour terminer. + La carte a été mise à jour avec succès. Appuyez sur OK pour terminer. Something went wrong. - Quelque chose c'est mal passé. + Quelque chose c'est mal passé. Press OK to finish, you will have to manually upgrade the board. - Appuyez sur OK pour terminer, vous devrez mettre à jour votre carte manuellement. + Appuyez sur OK pour terminer, vous devrez mettre à jour votre carte manuellement. Bringing the board into boot loader mode. @@ -11986,7 +12101,7 @@ La carte sera redémarrée et tous les paramètres effacés. Veuillez vérifier que la carte n'est pas armée et appuyez à nouveau Réinitialiser pour continuer ou allumer/éteindre la carte pour forcer la réinitialisation. - + Annuler @@ -12428,12 +12543,12 @@ La carte sera redémarrée et tous les paramètres effacés. Source: - Source : + Source : The source of Curve 1 will always be Throttle - La source de la Courbe 1 est toujours Throttle + La source de la Courbe 1 est toujours Throttle @@ -12818,6 +12933,76 @@ Les valeurs classiques sont de 100% en configuration + et 50% en configuration X Select the Multirotor frame type Sélectionner ici le type de châssis Multirotor + + + Select output channel for Accessory0 RcInput + Sélectionnez le canal de sortie pour l'entrée RC Accessory0 + + + + Accessory1 + + + + + RcOutput channels + Canaux de sortie RC + + + + RC Output + Sorties RC + + + + Accessory0 + + + + + RC Input + Entrées RC + + + + Select output channel for Accessory2 RcInput + Sélectionnez le canal de sortie pour l'entrée RC Accessory2 + + + + Select output channel for Accessory1 RcInput + Sélectionnez le canal de sortie pour l'entrée RC Accessory1 + + + + Accessory2 + + + + + RcOutput curve + Courbe de sortie RC + + + + Curve + Courbe + + + + Select output curve for Accessory0 RcInput + Sélectionnez la courbe de mixage pour l'entrée RC Accessory0 + + + + Select output curve for Accessory1 RcInput + Sélectionnez la courbe de mixage pour l'entrée RC Accessory1 + + + + Select output curve for Accessory2 RcInput + Sélectionnez la courbe de mixage pour l'entrée RC Accessory2 + RevoHWWidget @@ -12909,7 +13094,7 @@ Méfiez-vous de ne pas vous verrouiller l'accès ! OPLinkWidget - + Form Formulaire @@ -13060,9 +13245,8 @@ Méfiez-vous de ne pas vous verrouiller l'accès ! Tx Perdus - TX Resent - TX Renvoyés + TX Renvoyés @@ -13209,14 +13393,12 @@ Méfiez-vous de ne pas vous verrouiller l'accès ! Canal Mini - Channel Set - Canal fixe + Canal fixe - Sets the random sequence of channels to use for frequency hopping. - Fixe une séquence aléatoire de canaux à utiliser pour les sauts de fréquence. + Fixe une séquence aléatoire de canaux à utiliser pour les sauts de fréquence. @@ -13261,17 +13443,17 @@ Méfiez-vous de ne pas vous verrouiller l'accès ! Channel 0 is 430 MHz, channel 250 is 440 MHz, and the channel spacing is 40 KHz. - Canal 0 correspond à 430Mhz, canal 249 à 440Mhz, et l'espacement des canaux est de 40KHz. {0 ?} {430 ?} {250 ?} {440 ?} {40 ?} + Canal 0 correspond à 430Mhz, canal 250 à 440Mhz, et l'espacement des canaux est de 40KHz. 440.000 (MHz) - + 430.000 (MHz) - + @@ -13445,7 +13627,7 @@ p, li { white-space: pre-wrap; } ConfigOutputWidget - + The actuator module is in an error state. This can also occur because there are no inputs. Please fix these before testing outputs. Le module actionneur est en erreur. Cela peut aussi arriver lorsque il n'y a pas d'entrées (Rx radiocommande). Veuillez corriger cela avant de tester les sorties. @@ -13455,10 +13637,23 @@ p, li { white-space: pre-wrap; } Cette option démarre vos moteurs avec la valeur sélectionnée sur les curseurs, indépendamment de l'émetteur. Il est recommandé d'enlever les hélices des moteurs. Êtes-vous sûr de vouloir faire ça ? - + + You may want to save your neutral settings. + Vous pouvez enregistrer vos changements des réglages de neutre. + + + http://wiki.openpilot.org/x/WIGf + + + OneShot only works with MainPort settings marked with "+OneShot" +Using "PPM_PIN6+OneShot" bank 4 (output 6) must be set to PWM + OneShot fonctionne uniquement avec les réglages de Mainport marqués avec "+OneShot" +En utilisant "PPM_PIN6+OneShot" la banque 4 (sortie 6) doit être réglée sur PWM + + ConfigRevoHWWidget @@ -14298,36 +14493,25 @@ Veuillez vérifier le fichier. ConfigPipXtremeWidget - - - - Unbind - Dissocier + Dissocier - - - - Bind - Associer + Associer - Unknown - Inconnu + Inconnu - Information - Information + Information - To apply the changes when binding/unbinding the board must be rebooted or power cycled. détachement ou dissociation ~ unbinding ? tr Bof - Pour appliquer les changements d'association/dissociation la carte doit être redémarrée ou débranchée/rebranchée. + Pour appliquer les changements d'association/dissociation la carte doit être redémarrée ou débranchée/rebranchée. @@ -14640,7 +14824,7 @@ et même conduire au crash. A utiliser avec prudence. Personnalisé - + http://wiki.openpilot.org/x/44Cf @@ -14813,7 +14997,7 @@ et même conduire au crash. A utiliser avec prudence. TimedDialog - + Cancel Annuler @@ -15587,7 +15771,7 @@ A noter : Pour le GPS OpenPilot v8, veuillez choisir l'option GPS U-Blox. - + %1 µs @@ -15762,22 +15946,56 @@ p, li { white-space: pre-wrap; } Reboot - Redémarrage + Redémarrage <html><head/><body><p>Please wait. Your controller is rebooting.<br/>This can take up to a minute.</p></body></html> - <html><head/><body><p>Veuillez patienter. Votre contrôleur redémarre<br/>Cela peut prendre jusqu'à une minute.</p></body></html> + <html><head/><body><p>Veuillez patienter. Votre contrôleur redémarre<br/>Cela peut prendre jusqu'à une minute.</p></body></html> Ok - Ok + Ok <font color='red'>Reboot failed!</font><p>Please perform a manual reboot by power cycling the board.<br>To power cycle the controller remove all batteries and the USB cable for at least 30 seconds.<br>After 30 seconds, plug in the board again and wait for it to connect, this can take a few seconds.<br>Then press Ok.</p> - <font color='red'>Le rédémarrage a échoué !</font><p>Veuillez effectuer un redémarrage manuel de la carte.<br>Pour redémarrer la carte contrôleur, envelez toutes les batteries ainsi que le câble USB pour au moins 30 secondes.<br>Après 30 secondes, connecter à nouveau la carte et attendez qu'elle soit connectée, cela peut prendre quelques secondes.<br>Ensuite cliquez sur Ok.</p> + <font color='red'>Le rédémarrage a échoué !</font><p>Veuillez effectuer un redémarrage manuel de la carte.<br>Pour redémarrer la carte contrôleur, envelez toutes les batteries ainsi que le câble USB pour au moins 30 secondes.<br>Après 30 secondes, connecter à nouveau la carte et attendez qu'elle soit connectée, cela peut prendre quelques secondes.<br>Cliquez ensuite sur Ok.</p> + + + + ConfigOPLinkWidget + + + + + + Unbind + Dissocier + + + + + + + Bind + Associer + + + + Unknown + Inconnu + + + + Information + Information + + + + To apply the changes when binding/unbinding the board must be rebooted or power cycled. + Pour appliquer les changements d'association/dissociation la carte doit être redémarrée ou débranchée/rebranchée. diff --git a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui index a96e1f7a6..e7c7ddf10 100644 --- a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui +++ b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui @@ -116,8 +116,8 @@ 0 0 - 622 - 519 + 624 + 510 @@ -309,18 +309,14 @@ - - - - - - - - - + + - + + + + USB HID Port @@ -330,49 +326,14 @@ - - - - - + + - - true - - - - - - - - MainPort - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - - - - FlexiPort - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - + USB VCP Port @@ -382,17 +343,40 @@ - - + + - RcvrPort + - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + false - + + + + Main Port + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + Flexi Port + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + Qt::Horizontal @@ -405,6 +389,22 @@ + + + + + + + + + + Receiver Port + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp index 87dc480f6..338dcc874 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configgroundvehiclewidget.cpp @@ -60,10 +60,10 @@ QStringList ConfigGroundVehicleWidget::getChannelDescriptions() channelDesc[configData.ground.GroundVehicleSteering2 - 1] = QString("GroundSteering2"); } if (configData.ground.GroundVehicleThrottle1 > 0) { - channelDesc[configData.ground.GroundVehicleThrottle1 - 1] = QString("GroundThrottle1"); + channelDesc[configData.ground.GroundVehicleThrottle1 - 1] = QString("GroundMotor1"); } if (configData.ground.GroundVehicleThrottle2 > 0) { - channelDesc[configData.ground.GroundVehicleThrottle2 - 1] = QString("GroundThrottle2"); + channelDesc[configData.ground.GroundVehicleThrottle2 - 1] = QString("GroundMotor2"); } return channelDesc; } @@ -116,6 +116,13 @@ void ConfigGroundVehicleWidget::setupUI(QString frameType) m_aircraft->gvThrottleCurve1GroupBox->setEnabled(true); m_aircraft->gvThrottleCurve2GroupBox->setEnabled(true); + // Default Curve2 range -1 -> +1, allow forward/reverse (Car and Tank) + m_aircraft->groundVehicleThrottle1->setMixerType(MixerCurve::MIXERCURVE_THROTTLE); + m_aircraft->groundVehicleThrottle2->setMixerType(MixerCurve::MIXERCURVE_PITCH); + + initMixerCurves(frameType); + + if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)") { // Tank m_vehicleImg->setElementId("tank"); @@ -159,9 +166,9 @@ void ConfigGroundVehicleWidget::setupUI(QString frameType) // Motorcycle m_vehicleImg->setElementId("motorbike"); setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Motorcycle")); - m_aircraft->gvMotor1ChannelBox->setEnabled(false); - m_aircraft->gvMotor2ChannelBox->setEnabled(true); - m_aircraft->gvThrottleCurve1GroupBox->setEnabled(false); + + m_aircraft->gvMotor1ChannelBox->setEnabled(true); + m_aircraft->gvMotor2ChannelBox->setEnabled(false); m_aircraft->gvMotor2Label->setText("Rear motor"); @@ -171,7 +178,11 @@ void ConfigGroundVehicleWidget::setupUI(QString frameType) m_aircraft->gvSteering1Label->setText("Front steering"); m_aircraft->gvSteering2Label->setText("Balancing"); - m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve"); + // Curve1 for Motorcyle + m_aircraft->gvThrottleCurve1GroupBox->setTitle("Rear throttle curve"); + m_aircraft->gvThrottleCurve1GroupBox->setEnabled(true); + m_aircraft->gvThrottleCurve2GroupBox->setTitle(""); + m_aircraft->gvThrottleCurve2GroupBox->setEnabled(false); // Curve range 0 -> +1 (no reverse) m_aircraft->groundVehicleThrottle2->setMixerType(MixerCurve::MIXERCURVE_THROTTLE); @@ -201,19 +212,24 @@ void ConfigGroundVehicleWidget::setupUI(QString frameType) m_aircraft->gvSteering1Label->setText("Front steering"); m_aircraft->gvSteering2Label->setText("Rear steering"); - m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve"); - m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve"); + // Curve2 for Car + m_aircraft->gvThrottleCurve2GroupBox->setTitle("Throttle curve"); + m_aircraft->gvThrottleCurve2GroupBox->setEnabled(true); + m_aircraft->gvThrottleCurve1GroupBox->setTitle(""); + m_aircraft->gvThrottleCurve1GroupBox->setEnabled(false); - m_aircraft->groundVehicleThrottle2->setMixerType(MixerCurve::MIXERCURVE_THROTTLE); + m_aircraft->groundVehicleThrottle2->setMixerType(MixerCurve::MIXERCURVE_PITCH); m_aircraft->groundVehicleThrottle1->setMixerType(MixerCurve::MIXERCURVE_THROTTLE); initMixerCurves(frameType); // If new setup, set curves values if (frameTypeSaved->getValue().toString() != "GroundVehicleCar") { - // Curve range 0 -> +1 (no reverse) m_aircraft->groundVehicleThrottle1->initLinearCurve(5, 1.0); - m_aircraft->groundVehicleThrottle2->initLinearCurve(5, 1.0); + // Set curve2 range from -0.926 to 1 (forward / reverse) + // Take in account 4% offset in Throttle input after calibration + // 0.5 / 0.54 = 0.926 + m_aircraft->groundVehicleThrottle2->initLinearCurve(5, 1.0, -0.926); } } @@ -321,6 +337,8 @@ void ConfigGroundVehicleWidget::initMixerCurves(QString frameType) // no, init a straight curve if (frameType == "GroundVehicleDifferential") { m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 0.8, -0.8); + } else if (frameType == "GroundVehicleCar") { + m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0, -1.0); } else { m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0); } @@ -388,7 +406,7 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeTyp // motor int channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1; - setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR); + setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); @@ -495,7 +513,7 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType) channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1; setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR); - setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); + setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1; setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR); diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp index 6681a5b17..9823d81c7 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp @@ -154,7 +154,7 @@ ConfigMultiRotorWidget::ConfigMultiRotorWidget(QWidget *parent) : m_aircraft->quadShape->setScene(scene); QStringList multiRotorTypes; - multiRotorTypes << "Tricopter Y" << "Quad +" << "Quad X" << "Quad H" << "Hexacopter" << "Hexacopter X" << "Hexacopter H" + multiRotorTypes << "Tricopter Y" << "Quad +" << "Quad X" << "Hexacopter" << "Hexacopter X" << "Hexacopter H" << "Hexacopter Y6" << "Octocopter" << "Octocopter X" << "Octocopter V" << "Octo Coax +" << "Octo Coax X"; m_aircraft->multirotorFrameType->addItems(multiRotorTypes); @@ -195,12 +195,6 @@ void ConfigMultiRotorWidget::setupUI(QString frameType) m_aircraft->mrRollMixLevel->setValue(50); m_aircraft->mrPitchMixLevel->setValue(50); setYawMixLevel(50); - } else if (frameType == "QuadH" || frameType == "Quad H") { - setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad H")); - - m_aircraft->mrRollMixLevel->setValue(50); - m_aircraft->mrPitchMixLevel->setValue(70); - setYawMixLevel(50); } else if (frameType == "QuadP" || frameType == "Quad +") { setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad +")); @@ -296,8 +290,6 @@ void ConfigMultiRotorWidget::setupEnabledControls(QString frameType) enableComboBoxes(this, CHANNELBOXNAME, 4, true); } else if (frameType == "QuadP" || frameType == "Quad +") { enableComboBoxes(this, CHANNELBOXNAME, 4, true); - } else if (frameType == "QuadH" || frameType == "Quad H") { - enableComboBoxes(this, CHANNELBOXNAME, 4, true); } else if (frameType == "Hexa" || frameType == "Hexacopter") { enableComboBoxes(this, CHANNELBOXNAME, 6, true); } else if (frameType == "HexaX" || frameType == "Hexacopter X") { @@ -445,12 +437,6 @@ void ConfigMultiRotorWidget::refreshWidgetsValues(QString frameType) setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE); setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE); setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSW); - } else if (frameType == "QuadH") { - // Motors 1/2/3/4 are: NW / NE / SE / SW - setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW); - setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE); - setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE); - setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSW); } else if (frameType == "Hexa") { // Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN); @@ -564,9 +550,6 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() } else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") { airframeType = "QuadX"; setupQuad(false); - } else if (m_aircraft->multirotorFrameType->currentText() == "Quad H") { - airframeType = "QuadH"; - setupQuad(false); } else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") { airframeType = "Hexa"; setupHexa(true); @@ -840,8 +823,6 @@ void ConfigMultiRotorWidget::updateAirframe(QString frameType) elementId = "quad-x"; } else if (frameType == "QuadP" || frameType == "Quad +") { elementId = "quad-plus"; - } else if (frameType == "QuadH" || frameType == "Quad H") { - elementId = "quad-h"; } else if (frameType == "Hexa" || frameType == "Hexacopter") { elementId = "quad-hexa"; } else if (frameType == "HexaX" || frameType == "Hexacopter X") { diff --git a/ground/openpilotgcs/src/plugins/config/configgadget.qrc b/ground/openpilotgcs/src/plugins/config/configgadget.qrc index 01984a553..d89ac5bca 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadget.qrc +++ b/ground/openpilotgcs/src/plugins/config/configgadget.qrc @@ -54,5 +54,6 @@ images/calibration/plane-swd.png images/calibration/board-swd.png images/gear.png + images/error.svg diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index f43d63eb2..826e2ca8b 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -1698,12 +1698,31 @@ void ConfigInputWidget::resetChannelSettings() void ConfigInputWidget::resetActuatorSettings() { actuatorSettingsData = actuatorSettingsObj->getData(); - // Clear all output data : Min, max, neutral = 1500 - // 1500 = servo middle, can be applied to all outputs because board is 'Alwaysdisarmed' + + UAVDataObject *mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + QString mixerType; + + // Clear all output data : Min, max, neutral at same value + // 1000 for motors and 1500 for all others (Reversable motor included) for (unsigned int output = 0; output < 12; output++) { - actuatorSettingsData.ChannelMax[output] = 1500; - actuatorSettingsData.ChannelMin[output] = 1000; - actuatorSettingsData.ChannelNeutral[output] = 1500; + QString mixerNumType = QString("Mixer%1Type").arg(output + 1); + UAVObjectField *field = mixer->getField(mixerNumType); + Q_ASSERT(field); + + if (field) { + mixerType = field->getValue().toString(); + } + if ((mixerType == "Motor") || (mixerType == "Disabled")) { + actuatorSettingsData.ChannelMax[output] = 1000; + actuatorSettingsData.ChannelMin[output] = 1000; + actuatorSettingsData.ChannelNeutral[output] = 1000; + } else { + actuatorSettingsData.ChannelMax[output] = 1500; + actuatorSettingsData.ChannelMin[output] = 1500; + actuatorSettingsData.ChannelNeutral[output] = 1500; + } actuatorSettingsObj->setData(actuatorSettingsData); } } diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.h b/ground/openpilotgcs/src/plugins/config/configinputwidget.h index 913d55f70..49902c07c 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.h @@ -40,6 +40,7 @@ #include "manualcontrolcommand.h" #include "manualcontrolsettings.h" #include "actuatorsettings.h" +#include "mixersettings.h" #include "flightmodesettings.h" #include "receiveractivity.h" #include diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 330911bf4..b2a2e1edd 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -32,7 +32,6 @@ #include "mixersettings.h" #include "actuatorcommand.h" #include "actuatorsettings.h" -#include "systemalarms.h" #include "systemsettings.h" #include "uavsettingsimportexport/uavsettingsimportexportfactory.h" #include @@ -53,6 +52,8 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren ui = new Ui_OutputWidget(); ui->setupUi(this); + ui->gvFrame->setVisible(false); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); Core::Internal::GeneralSettings *settings = pm->getObject(); if (!settings->useExpertMode()) { @@ -105,6 +106,9 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode5, 4, 0, true); addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode6, 5, 0, true); + SystemAlarms *systemAlarmsObj = SystemAlarms::GetInstance(getObjectManager()); + connect(systemAlarmsObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(updateWarnings(UAVObject *))); + disconnect(this, SLOT(refreshWidgetsValues(UAVObject *))); populateWidgets(); @@ -115,6 +119,9 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren ConfigOutputWidget::~ConfigOutputWidget() { + SystemAlarms *systemAlarmsObj = SystemAlarms::GetInstance(getObjectManager()); + + disconnect(systemAlarmsObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(updateWarnings(UAVObject *))); // Do nothing } @@ -196,6 +203,15 @@ void ConfigOutputWidget::runChannelTests(bool state) if (state) { sendAllChannelTests(); } + + // Add info at end + if (!state && isDirty()) { + QMessageBox mbox; + mbox.setText(QString(tr("You may want to save your neutral settings."))); + mbox.setStandardButtons(QMessageBox::Ok); + mbox.setIcon(QMessageBox::Information); + mbox.exec(); + } } OutputChannelForm *ConfigOutputWidget::getOutputChannelForm(const int index) const @@ -436,3 +452,27 @@ void ConfigOutputWidget::stopTests() { ui->channelOutTest->setChecked(false); } + +void ConfigOutputWidget::updateWarnings(UAVObject *) +{ + SystemAlarms *systemAlarmsObj = SystemAlarms::GetInstance(getObjectManager()); + SystemAlarms::DataFields systemAlarms = systemAlarmsObj->getData(); + + if (systemAlarms.Alarm[SystemAlarms::ALARM_SYSTEMCONFIGURATION] > SystemAlarms::ALARM_WARNING) { + switch (systemAlarms.ExtendedAlarmStatus[SystemAlarms::EXTENDEDALARMSTATUS_SYSTEMCONFIGURATION]) { + case SystemAlarms::EXTENDEDALARMSTATUS_UNSUPPORTEDCONFIG_ONESHOT: + setWarning(tr("OneShot only works with Receiver Port settings marked with '+OneShot'
" + "When using Receiver Port setting 'PPM_PIN6+OneShot' " + "Bank 4 (output 6,9-10) must be set to PWM")); + return; + } + } + setWarning(NULL); +} + +void ConfigOutputWidget::setWarning(QString message) +{ + ui->gvFrame->setVisible(!message.isNull()); + ui->picWarning->setPixmap(message.isNull() ? QPixmap() : QPixmap(":/configgadget/images/error.svg")); + ui->txtWarning->setText(message); +} diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h index 3b25fed69..2478ca902 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h @@ -37,6 +37,8 @@ #include #include +#include "systemalarms.h" + class Ui_OutputWidget; class OutputChannelForm; @@ -50,11 +52,11 @@ public: protected: void enableControls(bool enable); + void setWarning(QString message); private: Ui_OutputWidget *ui; QList sliders; - void updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, QCheckBox *rev, int value); void assignOutputChannel(UAVDataObject *obj, QString &str); @@ -70,6 +72,7 @@ private: UAVObject::Metadata accInitialData; private slots: + void updateWarnings(UAVObject *); void stopTests(); virtual void refreshWidgetsValues(UAVObject *obj = NULL); void updateObjectsFromWidgets(); diff --git a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp index 198753877..00d3d3811 100644 --- a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp @@ -85,7 +85,6 @@ QStringList ConfigVehicleTypeWidget::getChannelDescriptions() case SystemSettings::AIRFRAMETYPE_TRI: case SystemSettings::AIRFRAMETYPE_QUADX: case SystemSettings::AIRFRAMETYPE_QUADP: - case SystemSettings::AIRFRAMETYPE_QUADH: case SystemSettings::AIRFRAMETYPE_OCTOV: case SystemSettings::AIRFRAMETYPE_OCTOCOAXX: case SystemSettings::AIRFRAMETYPE_OCTOCOAXP: @@ -316,8 +315,7 @@ int ConfigVehicleTypeWidget::frameCategory(QString frameType) || frameType == "Elevon" || frameType == "FixedWingVtail" || frameType == "Vtail") { return ConfigVehicleTypeWidget::FIXED_WING; } else if (frameType == "Tri" || frameType == "Tricopter Y" || frameType == "QuadX" || frameType == "Quad X" - || frameType == "QuadP" || frameType == "Quad +" || frameType == "Quad H" || frameType == "QuadH" - || frameType == "Hexa" || frameType == "Hexacopter" + || frameType == "QuadP" || frameType == "Quad +" || frameType == "Hexa" || frameType == "Hexacopter" || frameType == "HexaX" || frameType == "Hexacopter X" || frameType == "HexaCoax" || frameType == "HexaH" || frameType == "Hexacopter H" || frameType == "Hexacopter Y6" || frameType == "Octo" || frameType == "Octocopter" diff --git a/ground/openpilotgcs/src/plugins/config/images/error.svg b/ground/openpilotgcs/src/plugins/config/images/error.svg new file mode 100644 index 000000000..8de454769 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/images/error.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index f804aab1d..61c88a66f 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -6,7 +6,7 @@ 0 0 - 698 + 765 754 @@ -122,11 +122,11 @@ 0 0 - 680 - 672 + 743 + 668 - + 6 @@ -143,735 +143,871 @@ 12 - - - - 0 - 0 - - - - - 0 - 0 - - + - Output configuration + GroupBox - - - - - - + + + 9 + + + 9 + + + 9 + + + 9 + + + + + QFrame::NoFrame - - Qt::AlignCenter + + QFrame::Raised + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Bank(Channels): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + Update rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + Mode: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + - + + + Qt::AlignCenter + + + + + + + - + + + Qt::AlignCenter + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup PWM rate here: usual value is 490 Hz for multirotor airframes.<br/>PWMSync and OneShot125 does not use this value.</p></body></html> + + + + + + + 50 + + + + + 60 + + + + + 125 + + + + + 165 + + + + + 270 + + + + + 330 + + + + + 400 + + + + + 490 + + + + + + + + + + + Qt::AlignCenter + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup PWM rate here: usual value is 490 Hz for multirotor airframes.<br/>PWMSync and OneShot125 does not use this value.</p></body></html> + + + + + + + 50 + + + + + 60 + + + + + 125 + + + + + 165 + + + + + 270 + + + + + 330 + + + + + 400 + + + + + 490 + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup PWM rate here: usual value is 490 Hz for multirotor airframes.<br/>PWMSync and OneShot125 does not use this value.</p></body></html> + + + + + + + 50 + + + + + 60 + + + + + 125 + + + + + 165 + + + + + 270 + + + + + 330 + + + + + 400 + + + + + 490 + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup PWM rate here: usual value is 490 Hz for multirotor airframes.<br/>PWMSync and OneShot125 does not use this value.</p></body></html> + + + + + + + 50 + + + + + 60 + + + + + 125 + + + + + 165 + + + + + 270 + + + + + 330 + + + + + 400 + + + + + 490 + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup output mode. Use PWM or PWMSync with Standard ESCs.<br/>Several other ESCs like BLHeli 13+ can use the more advanced OneShot125.<br/>When using OneShot125 all values set in min/max and idle are divided by <br/>eight before being sent to esc (i.e. 1000 = 125, 2000 = 250).</p></body></html> + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup output mode. Use PWM or PWMSync with Standard ESCs.<br/>Several other ESCs like BLHeli 13+ can use the more advanced OneShot125.<br/>When using OneShot125 all values set in min/max and idle are divided by <br/>eight before being sent to esc (i.e. 1000 = 125, 2000 = 250).</p></body></html> + + + + + + + - + + + Qt::AlignCenter + + + + + + + - + + + Qt::AlignCenter + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup PWM rate here: usual value is 490 Hz for multirotor airframes.<br/>PWMSync and OneShot125 does not use this value.</p></body></html> + + + false + + + + + + + 50 + + + + + 60 + + + + + 125 + + + + + 165 + + + + + 270 + + + + + 330 + + + + + 400 + + + + + 490 + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup output mode. Use PWM or PWMSync with Standard ESCs.<br/>Several other ESCs like BLHeli 13+ can use the more advanced OneShot125.<br/>When using OneShot125 all values set in min/max and idle are divided by <br/>eight before being sent to esc (i.e. 1000 = 125, 2000 = 250).</p></body></html> + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup output mode. Use PWM or PWMSync with Standard ESCs.<br/>Several other ESCs like BLHeli 13+ can use the more advanced OneShot125.<br/>When using OneShot125 all values set in min/max and idle are divided by <br/>eight before being sent to esc (i.e. 1000 = 125, 2000 = 250).</p></body></html> + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup output mode. Use PWM or PWMSync with Standard ESCs.<br/>Several other ESCs like BLHeli 13+ can use the more advanced OneShot125.<br/>When using OneShot125 all values set in min/max and idle are divided by <br/>eight before being sent to esc (i.e. 1000 = 125, 2000 = 250).</p></body></html> + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup PWM rate here: usual value is 490 Hz for multirotor airframes.<br/>PWMSync and OneShot125 does not use this value.</p></body></html> + + + + + + + 50 + + + + + 60 + + + + + 125 + + + + + 165 + + + + + 270 + + + + + 330 + + + + + 400 + + + + + 490 + + + + + + + + - + + + Qt::AlignCenter + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + <html><head/><body><p>Setup output mode. Use PWM or PWMSync with Standard ESCs.<br/>Several other ESCs like BLHeli 13+ can use the more advanced OneShot125.<br/>When using OneShot125 all values set in min/max and idle are divided by <br/>eight before being sent to esc (i.e. 1000 = 125, 2000 = 250).</p></body></html> + + + + + + + - - - - - - - - Qt::AlignCenter - - - - - - - Bank(Channels): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 5 - 20 - - - - - - + + - + 0 0 - - - 0 - 20 - + + QFrame::NoFrame - - Qt::Horizontal + + QFrame::Raised - - QSizePolicy::Minimum - - - - 5 - 20 - - - - - - - - - - - - Qt::AlignCenter - - - - - - - - - - - Qt::AlignCenter - - - - - - - - - - - Qt::AlignCenter - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value - - - - false - - - - - - - 50 + + + 0 - - - - 60 + + 0 - - - - 125 + + 0 - - - - 165 + + 0 - - - - 270 - - - - - 330 - - - - - 400 - - - - - 490 - - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value - - - - - - - 50 - - - - - 60 - - - - - 125 - - - - - 165 - - - - - 270 - - - - - 330 - - - - - 400 - - - - - 490 - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - Update rate: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value - - - - - - - 50 - - - - - 60 - - - - - 125 - - - - - 165 - - - - - 270 - - - - - 330 - - - - - 400 - - - - - 490 - - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value - - - - - - - 50 - - - - - 60 - - - - - 125 - - - - - 165 - - - - - 270 - - - - - 330 - - - - - 400 - - - - - 490 - - - - - - - - - - - - Qt::AlignCenter - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value - - - - - - - 50 - - - - - 60 - - - - - 125 - - - - - 165 - - - - - 270 - - - - - 330 - - - - - 400 - - - - - 490 - - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value - - - - - - - 50 - - - - - 60 - - - - - 125 - - - - - 165 - - - - - 270 - - - - - 330 - - - - - 400 - - - - - 490 - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - Mode: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup output mode. Use PWM or OneShot with Standard ESCs. -Several other ESCs like BLHeli 13+ can use the more advanced OneShot125. -When using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). - - - - - - - false - - - - 0 - 0 - - - - - 0 - 20 - - - - Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). - + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 70 + 20 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index 8732aa43d..a57a7126e 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -27,6 +27,9 @@ #include "outputchannelform.h" +#define MAXOUTPUT_VALUE 2500 +#define MINOUTPUT_VALUE 500 + OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : ChannelForm(index, parent), ui(), m_inChannelTest(false) { @@ -45,6 +48,23 @@ OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : ui.actuatorLink->setChecked(false); connect(ui.actuatorLink, SIGNAL(toggled(bool)), this, SLOT(linkToggled(bool))); + // Set limits + ui.actuatorMin->setMaximum(MAXOUTPUT_VALUE); + ui.actuatorMax->setMaximum(MAXOUTPUT_VALUE); + ui.actuatorValue->setMaximum(MAXOUTPUT_VALUE); + ui.actuatorMin->setMinimum(MINOUTPUT_VALUE); + ui.actuatorMax->setMinimum(MINOUTPUT_VALUE); + ui.actuatorValue->setMinimum(MINOUTPUT_VALUE); + + // Remove keyboard focus + ui.actuatorMin->setFocusPolicy(Qt::ClickFocus); + ui.actuatorMax->setFocusPolicy(Qt::ClickFocus); + ui.actuatorRev->setFocusPolicy(Qt::ClickFocus); + ui.actuatorLink->setFocusPolicy(Qt::ClickFocus); + ui.actuatorValue->setFocusPolicy(Qt::NoFocus); + + setChannelRange(); + disableMouseWheelEvents(); } @@ -109,11 +129,12 @@ void OutputChannelForm::enableChannelTest(bool state) } else { ui.actuatorMin->setEnabled(true); ui.actuatorMax->setEnabled(true); - ui.actuatorRev->setEnabled(true); + if (m_mixerType != "Motor") { + ui.actuatorRev->setEnabled(true); + } } } - /** * Toggles the channel linked state for use in testing mode */ @@ -128,7 +149,7 @@ void OutputChannelForm::linkToggled(bool state) if (!parent()) { return; } - int min = 10000; + int min = MAXOUTPUT_VALUE; int linked_count = 0; QList outputChannelForms = parent()->findChildren(); // set the linked channels of the parent widget to the same value @@ -168,7 +189,7 @@ int OutputChannelForm::max() const */ void OutputChannelForm::setMax(int maximum) { - setRange(ui.actuatorMin->value(), maximum); + setRange(ui.actuatorMax->value(), maximum); } int OutputChannelForm::min() const @@ -181,7 +202,7 @@ int OutputChannelForm::min() const */ void OutputChannelForm::setMin(int minimum) { - setRange(minimum, ui.actuatorMax->value()); + setRange(minimum, ui.actuatorMin->value()); } int OutputChannelForm::neutral() const @@ -205,11 +226,6 @@ void OutputChannelForm::setRange(int minimum, int maximum) ui.actuatorMin->setValue(minimum); ui.actuatorMax->setValue(maximum); setChannelRange(); - if (ui.actuatorMin->value() > ui.actuatorMax->value()) { - ui.actuatorRev->setChecked(true); - } else { - ui.actuatorRev->setChecked(false); - } } /** @@ -221,25 +237,70 @@ void OutputChannelForm::setRange(int minimum, int maximum) */ void OutputChannelForm::setChannelRange() { - int oldMini = ui.actuatorNeutral->minimum(); + int minValue = ui.actuatorMin->value(); + int maxValue = ui.actuatorMax->value(); - // int oldMaxi = ui.actuatorNeutral->maximum(); + int oldMini = ui.actuatorNeutral->minimum(); + int oldMaxi = ui.actuatorNeutral->maximum(); - if (ui.actuatorMin->value() < ui.actuatorMax->value()) { - ui.actuatorNeutral->setRange(ui.actuatorMin->value(), ui.actuatorMax->value()); - ui.actuatorRev->setChecked(false); + m_mixerType = outputMixerType(); + + // Red handle for Motors + if ((m_mixerType == "Motor") || (m_mixerType == "ReversableMotor")) { + ui.actuatorNeutral->setStyleSheet("QSlider::handle:horizontal { background: rgb(255, 100, 100); width: 18px; height: 28px;" + "margin: -3px 0; border-radius: 3px; border: 1px solid #777; }"); } else { - ui.actuatorNeutral->setRange(ui.actuatorMax->value(), ui.actuatorMin->value()); - ui.actuatorRev->setChecked(true); + ui.actuatorNeutral->setStyleSheet("QSlider::handle:horizontal { background: rgb(196, 196, 196); width: 18px; height: 28px;" + "margin: -3px 0; border-radius: 3px; border: 1px solid #777; }"); } + // Normal motor will be *** never *** reversed : without arming a "Min" value (like 1900) can be applied ! + if (m_mixerType == "Motor") { + if (minValue >= maxValue) { + // Keep old values + ui.actuatorMin->setValue(oldMini); + ui.actuatorMax->setValue(oldMaxi); + } + ui.actuatorRev->setChecked(false); + ui.actuatorRev->setEnabled(false); + ui.actuatorNeutral->setInvertedAppearance(false); + ui.actuatorNeutral->setRange(ui.actuatorMin->value(), ui.actuatorMax->value()); + } else { + // Others output (!Motor) + // Auto check reverse checkbox SpinBox Min/Max changes + ui.actuatorRev->setEnabled(true); + if (minValue <= maxValue) { + ui.actuatorRev->setChecked(false); + ui.actuatorNeutral->setInvertedAppearance(false); + ui.actuatorNeutral->setRange(minValue, maxValue); + } else { + ui.actuatorRev->setChecked(true); + ui.actuatorNeutral->setInvertedAppearance(true); + ui.actuatorNeutral->setRange(maxValue, minValue); + } + } + // If old neutral was Min, stay Min if (ui.actuatorNeutral->value() == oldMini) { ui.actuatorNeutral->setValue(ui.actuatorNeutral->minimum()); } - // if (ui.actuatorNeutral->value() == oldMaxi) - // this can be dangerous if it happens to be controlling a motor at the time! - // ui.actuatorNeutral->setValue(ui.actuatorNeutral->maximum()); + // Enable only outputs already set in mixer + if (m_mixerType != "Disabled") { + ui.actuatorMin->setEnabled(true); + ui.actuatorMax->setEnabled(true); + ui.actuatorNeutral->setEnabled(true); + ui.actuatorValue->setEnabled(true); + } else { + ui.actuatorMin->setEnabled(false); + ui.actuatorMax->setEnabled(false); + ui.actuatorRev->setEnabled(false); + ui.actuatorLink->setEnabled(false); + ui.actuatorMin->setValue(1000); + ui.actuatorMax->setValue(1000); + ui.actuatorNeutral->setRange(minValue, maxValue); + ui.actuatorNeutral->setValue(minValue); + ui.actuatorValue->setEnabled(false); + } } /** @@ -247,30 +308,17 @@ void OutputChannelForm::setChannelRange() */ void OutputChannelForm::reverseChannel(bool state) { - // Sanity check: if state became true, make sure the Maxvalue was higher than Minvalue - // the situations below can happen! - if (state && (ui.actuatorMax->value() < ui.actuatorMin->value())) { - return; - } - if (!state && (ui.actuatorMax->value() > ui.actuatorMin->value())) { - return; - } + // if 'state' (reverse channel requested) apply only if not already reversed + if ((state && (ui.actuatorMax->value() > ui.actuatorMin->value())) + || (!state && (ui.actuatorMax->value() < ui.actuatorMin->value()))) { + // Now, swap the min & max values (spin boxes) + int temp = ui.actuatorMax->value(); + ui.actuatorMax->setValue(ui.actuatorMin->value()); + ui.actuatorMin->setValue(temp); + ui.actuatorNeutral->setInvertedAppearance(state); - // Now, swap the min & max values (only on the spinboxes, the slider does not change!) - int temp = ui.actuatorMax->value(); - ui.actuatorMax->setValue(ui.actuatorMin->value()); - ui.actuatorMin->setValue(temp); - - // Also update the channel value - // This is a trick to force the slider to update its value and - // emit the right signal itself, because our sendChannelTest(int) method - // relies on the object sender's identity. - if (ui.actuatorNeutral->value() < ui.actuatorNeutral->maximum()) { - ui.actuatorNeutral->setValue(ui.actuatorNeutral->value() + 1); - ui.actuatorNeutral->setValue(ui.actuatorNeutral->value() - 1); - } else { - ui.actuatorNeutral->setValue(ui.actuatorNeutral->value() - 1); - ui.actuatorNeutral->setValue(ui.actuatorNeutral->value() + 1); + setChannelRange(); + return; } } @@ -288,10 +336,6 @@ void OutputChannelForm::sendChannelTest(int value) return; } - if (ui.actuatorRev->isChecked()) { - // the channel is reversed - value = ui.actuatorMin->value() - value + ui.actuatorMax->value(); - } // update the label ui.actuatorValue->setValue(value); @@ -330,3 +374,21 @@ void OutputChannelForm::sendChannelTest(int value) } emit channelChanged(index(), value); } + +/** + * + * Returns MixerType + */ +QString OutputChannelForm::outputMixerType() +{ + UAVDataObject *mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + + Q_ASSERT(mixer); + + QString mixerNumType = QString("Mixer%1Type").arg(index() + 1); + UAVObjectField *field = mixer->getField(mixerNumType); + Q_ASSERT(field); + QString mixerType = field->getValue().toString(); + + return mixerType; +} diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.h b/ground/openpilotgcs/src/plugins/config/outputchannelform.h index e17155f41..e10891c2a 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.h @@ -58,6 +58,7 @@ public slots: void setNeutral(int value); void setRange(int minimum, int maximum); void enableChannelTest(bool state); + QString outputMixerType(); signals: void channelChanged(int index, int value); @@ -65,6 +66,7 @@ signals: private: Ui::outputChannelForm ui; bool m_inChannelTest; + QString m_mixerType; private slots: void linkToggled(bool state); diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index 459841ace..41420fb4a 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -7,7 +7,7 @@ 0 0 768 - 54 + 55 @@ -289,8 +289,7 @@ margin:1px; Qt::StrongFocus - Minimum PWM value, beware of not overdriving your servo. -Using OneShot125 a value of 1000(uS) here will produce a pulse of 125(uS). + <html><head/><body><p>Minimum PWM value, beware of not overdriving your servo.<br/>Using OneShot125 a value of 1000(µs) here will produce a pulse of 125(µs).</p></body></html> Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -628,8 +627,7 @@ margin:1px; Qt::StrongFocus - Maximum value, beware of not overdriving your servo. -Using OneShot125 a value of 2000(uS) here will produce a pulse of 250(uS). + <html><head/><body><p>Minimum PWM value, beware of not overdriving your servo.<br/>Using OneShot125 a value of 1000(µs) here will produce a pulse of 125(µs).</p></body></html> Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/esccalibrationpage.cpp b/ground/openpilotgcs/src/plugins/setupwizard/pages/esccalibrationpage.cpp index 4936a2260..04888a5dd 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/esccalibrationpage.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/esccalibrationpage.cpp @@ -104,6 +104,16 @@ void EscCalibrationPage::startButtonClicked() QString mixerTypePattern = "Mixer%1Type"; OutputCalibrationUtil::startOutputCalibration(); + // First check if any servo and set his value to 1500 (like Tricopter) + for (quint32 i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) { + UAVObjectField *field = mSettings->getField(mixerTypePattern.arg(i + 1)); + Q_ASSERT(field); + if (field->getValue().toString() == field->getOptions().at(VehicleConfigurationHelper::MIXER_TYPE_SERVO)) { + m_outputUtil.startChannelOutput(i, 1500); + m_outputUtil.stopChannelOutput(); + } + } + // Find motors and start Esc procedure for (quint32 i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) { UAVObjectField *field = mSettings->getField(mixerTypePattern.arg(i + 1)); Q_ASSERT(field); diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/inputpage.cpp b/ground/openpilotgcs/src/plugins/setupwizard/pages/inputpage.cpp index c74931300..849284e68 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/inputpage.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/inputpage.cpp @@ -77,10 +77,10 @@ bool InputPage::restartNeeded(VehicleConfigurationSource::INPUT_TYPE selectedTyp { switch (selectedType) { case VehicleConfigurationSource::INPUT_PWM: - return data.CC_RcvrPort != HwSettings::CC_RCVRPORT_PWM; + return data.CC_RcvrPort != HwSettings::CC_RCVRPORT_PWMNOONESHOT; case VehicleConfigurationSource::INPUT_PPM: - return data.CC_RcvrPort != HwSettings::CC_RCVRPORT_PPM; + return data.CC_RcvrPort != HwSettings::CC_RCVRPORT_PPMNOONESHOT; case VehicleConfigurationSource::INPUT_SBUS: return data.CC_MainPort != HwSettings::CC_MAINPORT_SBUS; diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.cpp b/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.cpp index cdf95e5c1..fb4775aa9 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.cpp @@ -54,6 +54,8 @@ OutputCalibrationPage::~OutputCalibrationPage() delete m_calibrationUtil; m_calibrationUtil = 0; } + + OutputCalibrationUtil::stopOutputCalibration(); delete ui; } @@ -70,18 +72,32 @@ void OutputCalibrationPage::setupActuatorMinMaxAndNeutral(int motorChannelStart, // servos since a value out of range can actually destroy the // vehicle if unlucky. // Motors are not that important. REMOVE propellers always!! + OutputCalibrationUtil::startOutputCalibration(); for (int servoid = 0; servoid < 12; servoid++) { if (servoid >= motorChannelStart && servoid <= motorChannelEnd) { // Set to motor safe values - m_actuatorSettings[servoid].channelMin = 1000; - m_actuatorSettings[servoid].channelNeutral = 1000; - m_actuatorSettings[servoid].channelMax = 1900; + m_actuatorSettings[servoid].channelMin = 1000; + m_actuatorSettings[servoid].channelNeutral = 1000; + m_actuatorSettings[servoid].channelMax = 1900; + m_actuatorSettings[servoid].isReversableMotor = false; + // Car and Tank should use reversable Esc/motors + if ((getWizard()->getVehicleSubType() == SetupWizard::GROUNDVEHICLE_CAR) + || (getWizard()->getVehicleSubType() == SetupWizard::GROUNDVEHICLE_DIFFERENTIAL)) { + m_actuatorSettings[servoid].channelNeutral = 1500; + m_actuatorSettings[servoid].isReversableMotor = true; + // Set initial output value + m_calibrationUtil->startChannelOutput(servoid, 1500); + m_calibrationUtil->stopChannelOutput(); + } } else if (servoid < totalUsedChannels) { // Set to servo safe values m_actuatorSettings[servoid].channelMin = 1500; m_actuatorSettings[servoid].channelNeutral = 1500; m_actuatorSettings[servoid].channelMax = 1500; + // Set initial servo output value + m_calibrationUtil->startChannelOutput(servoid, 1500); + m_calibrationUtil->stopChannelOutput(); } else { // "Disable" these channels m_actuatorSettings[servoid].channelMin = 1000; @@ -101,6 +117,8 @@ void OutputCalibrationPage::setupVehicle() m_currentWizardIndex = 0; m_vehicleScene->clear(); + resetOutputCalibrationUtil(); + switch (getWizard()->getVehicleSubType()) { case SetupWizard::MULTI_ROTOR_TRI_Y: // Loads the SVG file resourse and sets the scene @@ -120,7 +138,7 @@ void OutputCalibrationPage::setupVehicle() // The channel number to configure for each step. m_channelIndex << 0 << 0 << 1 << 2 << 3; - setupActuatorMinMaxAndNeutral(0, 2, 3); + setupActuatorMinMaxAndNeutral(0, 2, 4); getWizard()->setActuatorSettings(m_actuatorSettings); break; @@ -180,7 +198,7 @@ void OutputCalibrationPage::setupVehicle() m_vehicleHighlightElementIndexes << 0 << 1 << 2 << 3 << 4 << 5; m_channelIndex << 0 << 2 << 0 << 5 << 1 << 3; - setupActuatorMinMaxAndNeutral(2, 2, 5); + setupActuatorMinMaxAndNeutral(2, 2, 6); // should be 5 instead 6 but output 5 is not used getWizard()->setActuatorSettings(m_actuatorSettings); break; @@ -213,7 +231,7 @@ void OutputCalibrationPage::setupVehicle() m_vehicleHighlightElementIndexes << 0 << 1 << 2 << 3 << 4 << 5; m_channelIndex << 0 << 2 << 0 << 5 << 3 << 1; - setupActuatorMinMaxAndNeutral(2, 2, 5); + setupActuatorMinMaxAndNeutral(2, 2, 6); // should be 5 instead 6 but output 5 is not used getWizard()->setActuatorSettings(m_actuatorSettings); break; @@ -226,7 +244,7 @@ void OutputCalibrationPage::setupVehicle() m_vehicleHighlightElementIndexes << 0 << 1 << 2; m_channelIndex << 0 << 1 << 0; - setupActuatorMinMaxAndNeutral(0, 1, 2); + setupActuatorMinMaxAndNeutral(1, 1, 2); getWizard()->setActuatorSettings(m_actuatorSettings); break; @@ -248,7 +266,7 @@ void OutputCalibrationPage::setupVehicle() m_vehicleHighlightElementIndexes << 0 << 1 << 2; m_channelIndex << 0 << 1 << 0; - setupActuatorMinMaxAndNeutral(0, 1, 2); + setupActuatorMinMaxAndNeutral(1, 1, 2); getWizard()->setActuatorSettings(m_actuatorSettings); break; @@ -257,12 +275,6 @@ void OutputCalibrationPage::setupVehicle() break; } - if (m_calibrationUtil) { - delete m_calibrationUtil; - m_calibrationUtil = 0; - } - m_calibrationUtil = new OutputCalibrationUtil(); - setupVehicleItems(); } @@ -326,7 +338,15 @@ void OutputCalibrationPage::setWizardPage() if (currentChannel >= 0) { if (currentPageIndex == 1) { ui->motorNeutralSlider->setValue(m_actuatorSettings[currentChannel].channelNeutral); + ui->motorPWMValue->setText(QString(tr("Output value : %1 µs")).arg(m_actuatorSettings[currentChannel].channelNeutral)); + // Reversable motor found + if (m_actuatorSettings[currentChannel].isReversableMotor) { + ui->motorNeutralSlider->setMinimum(m_actuatorSettings[currentChannel].channelMin); + ui->motorNeutralSlider->setMaximum(m_actuatorSettings[currentChannel].channelMax); + ui->motorInfo->setText(tr("

To find the neutral rate for this reversable motor, press the Start button below and slide the slider to the right or left until you find the value where the motor doesn't start.

When done press button again to stop.

")); + } } else if (currentPageIndex == 2) { + ui->servoPWMValue->setText(tr("Output value : %1 µs").arg(m_actuatorSettings[currentChannel].channelNeutral)); if (m_actuatorSettings[currentChannel].channelMax < m_actuatorSettings[currentChannel].channelMin && !ui->reverseCheckbox->isChecked()) { ui->reverseCheckbox->setChecked(true); @@ -416,6 +436,11 @@ void OutputCalibrationPage::on_motorNeutralButton_toggled(bool checked) ui->motorNeutralSlider->setEnabled(checked); quint16 channel = getCurrentChannel(); quint16 safeValue = m_actuatorSettings[channel].channelMin; + + if (m_actuatorSettings[channel].isReversableMotor) { + safeValue = m_actuatorSettings[channel].channelNeutral; + } + onStartButtonToggle(ui->motorNeutralButton, channel, m_actuatorSettings[channel].channelNeutral, safeValue, ui->motorNeutralSlider); } @@ -425,7 +450,6 @@ void OutputCalibrationPage::onStartButtonToggle(QAbstractButton *button, quint16 if (checkAlarms()) { enableButtons(false); enableServoSliders(true); - OutputCalibrationUtil::startOutputCalibration(); m_calibrationUtil->startChannelOutput(channel, safeValue); slider->setValue(value); m_calibrationUtil->setChannelOutputValue(value); @@ -433,8 +457,16 @@ void OutputCalibrationPage::onStartButtonToggle(QAbstractButton *button, quint16 button->setChecked(false); } } else { + // Servos and ReversableMotors + m_calibrationUtil->startChannelOutput(channel, m_actuatorSettings[channel].channelNeutral); + + // Normal motor + if ((button == ui->motorNeutralButton) && !m_actuatorSettings[channel].isReversableMotor) { + m_calibrationUtil->startChannelOutput(channel, m_actuatorSettings[channel].channelMin); + } + m_calibrationUtil->stopChannelOutput(); - OutputCalibrationUtil::stopOutputCalibration(); + enableServoSliders(false); enableButtons(true); } @@ -492,6 +524,8 @@ void OutputCalibrationPage::debugLogChannelValues() void OutputCalibrationPage::on_motorNeutralSlider_valueChanged(int value) { Q_UNUSED(value); + ui->motorPWMValue->setText(tr("Output value : %1 µs").arg(value)); + if (ui->motorNeutralButton->isChecked()) { quint16 value = ui->motorNeutralSlider->value(); m_calibrationUtil->setChannelOutputValue(value); @@ -515,6 +549,7 @@ void OutputCalibrationPage::on_servoCenterAngleSlider_valueChanged(int position) m_calibrationUtil->setChannelOutputValue(value); quint16 channel = getCurrentChannel(); m_actuatorSettings[channel].channelNeutral = value; + ui->servoPWMValue->setText(tr("Output value : %1 µs").arg(value)); // Adjust min and max if (ui->reverseCheckbox->isChecked()) { @@ -615,3 +650,12 @@ void OutputCalibrationPage::on_reverseCheckbox_toggled(bool checked) ui->servoMaxAngleSlider->setValue(m_actuatorSettings[getCurrentChannel()].channelMax); } } + +void OutputCalibrationPage::resetOutputCalibrationUtil() +{ + if (m_calibrationUtil) { + delete m_calibrationUtil; + m_calibrationUtil = 0; + } + m_calibrationUtil = new OutputCalibrationUtil(); +} diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.h b/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.h index 74a298ad0..3691a1d0a 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.h +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.h @@ -100,6 +100,7 @@ private: QList m_actuatorSettings; OutputCalibrationUtil *m_calibrationUtil; + void resetOutputCalibrationUtil(); static const QString MULTI_SVG_FILE; static const QString FIXEDWING_SVG_FILE; diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.ui b/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.ui index 1fdb2d918..202b766a2 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.ui +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/outputcalibrationpage.ui @@ -6,8 +6,8 @@ 0 0 - 600 - 400 + 776 + 505
@@ -94,8 +94,10 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">In this step we will set the neutral rate for the motor highlighted in the illustration to the right. <br />Please pay attention to the details and in particular the motors position and its rotation direction. Ensure the motors are spinning in the correct direction as shown in the diagram. Swap any 2 motor wires to change the direction of a motor. </span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To find </span><span style=" font-size:10pt; font-weight:600;">the neutral rate for this motor</span><span style=" font-size:10pt;">, press the Start button below and slide the slider to the right until the motor just starts to spin stable. <br /><br />When done press button again to stop.</span></p></body></html> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">In this step we will set the neutral rate for the motor highlighted in the illustration to the right. <br />Please pay attention to the details and in particular the motors position and its rotation direction. Ensure the motors are spinning in the correct direction as shown in the diagram. Swap any 2 motor wires to change the direction of a motor. </span></p></body></html> + + + Qt::RichText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -105,6 +107,29 @@ p, li { white-space: pre-wrap; }
+ + + + <html><head/><body><p><span style=" font-size:10pt;">To find </span><span style=" font-size:10pt; font-weight:600;">the neutral rate for this motor</span><span style=" font-size:10pt;">, press the Start button below and slide the slider to the right until the motor just starts to spin stable. <br/><br/>When done press button again to stop.</span></p></body></html> + + + Qt::RichText + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Output value: 1000µs + + + @@ -184,6 +209,13 @@ p, li { white-space: pre-wrap; } + + + + Output value: 1000µs + + + diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp index 81bf4fd40..a13d8b5a6 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp @@ -139,7 +139,7 @@ void VehicleConfigurationHelper::applyHardwareConfiguration() case VehicleConfigurationSource::CONTROLLER_CC: case VehicleConfigurationSource::CONTROLLER_CC3D: // Reset all ports - data.CC_RcvrPort = HwSettings::CC_RCVRPORT_DISABLED; + data.CC_RcvrPort = HwSettings::CC_RCVRPORT_DISABLEDONESHOT; // Default mainport to be active telemetry link data.CC_MainPort = HwSettings::CC_MAINPORT_TELEMETRY; @@ -147,10 +147,10 @@ void VehicleConfigurationHelper::applyHardwareConfiguration() data.CC_FlexiPort = HwSettings::CC_FLEXIPORT_DISABLED; switch (m_configSource->getInputType()) { case VehicleConfigurationSource::INPUT_PWM: - data.CC_RcvrPort = HwSettings::CC_RCVRPORT_PWM; + data.CC_RcvrPort = HwSettings::CC_RCVRPORT_PWMNOONESHOT; break; case VehicleConfigurationSource::INPUT_PPM: - data.CC_RcvrPort = HwSettings::CC_RCVRPORT_PPM; + data.CC_RcvrPort = HwSettings::CC_RCVRPORT_PPMNOONESHOT; break; case VehicleConfigurationSource::INPUT_SBUS: // We have to set teletry on flexport since s.bus needs the mainport. @@ -679,8 +679,10 @@ void VehicleConfigurationHelper::applyMixerConfiguration(mixerChannelSettings ch } } - // Default maxThrottle + // Default maxThrottle and minThrottle float maxThrottle = 0.9; + float minThrottle = 0; + // Save mixer values for sliders switch (m_configSource->getVehicleType()) { @@ -737,17 +739,26 @@ void VehicleConfigurationHelper::applyMixerConfiguration(mixerChannelSettings ch { switch (m_configSource->getVehicleSubType()) { case VehicleConfigurationSource::GROUNDVEHICLE_MOTORCYCLE: - case VehicleConfigurationSource::GROUNDVEHICLE_CAR: mSettings->setMixerValueRoll(100); mSettings->setMixerValuePitch(100); mSettings->setMixerValueYaw(100); maxThrottle = 1; break; + case VehicleConfigurationSource::GROUNDVEHICLE_CAR: + mSettings->setMixerValueRoll(100); + mSettings->setMixerValuePitch(100); + mSettings->setMixerValueYaw(100); + // Set curve2 range from -0.926 to 1 : take in account 4% offset in Throttle input + // 0.5 / 0.54 = 0.926 + maxThrottle = 1; + minThrottle = -0.926; + break; case VehicleConfigurationSource::GROUNDVEHICLE_DIFFERENTIAL: mSettings->setMixerValueRoll(100); mSettings->setMixerValuePitch(100); mSettings->setMixerValueYaw(100); maxThrottle = 0.8; + minThrottle = -0.8; break; default: break; @@ -765,7 +776,7 @@ void VehicleConfigurationHelper::applyMixerConfiguration(mixerChannelSettings ch UAVObjectField *field = mSettings->getField(throttlePattern.arg(i)); Q_ASSERT(field); for (quint32 i = 0; i < field->getNumElements(); i++) { - field->setValue(i * (maxThrottle / (field->getNumElements() - 1)), i); + field->setValue(minThrottle + (i * ((maxThrottle - minThrottle) / (field->getNumElements() - 1))), i); } } @@ -2033,7 +2044,7 @@ void VehicleConfigurationHelper::setupCar() channels[0].yaw = 100; // Motor (Chan 2) - channels[1].type = MIXER_TYPE_MOTOR; + channels[1].type = MIXER_TYPE_REVERSABLEMOTOR; channels[1].throttle1 = 0; channels[1].throttle2 = 100; channels[1].roll = 0; @@ -2058,7 +2069,7 @@ void VehicleConfigurationHelper::setupTank() GUIConfigDataUnion guiSettings = getGUIConfigData(); // Left Motor (Chan 1) - channels[0].type = MIXER_TYPE_SERVO; + channels[0].type = MIXER_TYPE_REVERSABLEMOTOR; channels[0].throttle1 = 0; channels[0].throttle2 = 100; channels[0].roll = 0; @@ -2066,7 +2077,7 @@ void VehicleConfigurationHelper::setupTank() channels[0].yaw = 100; // Right Motor (Chan 2) - channels[1].type = MIXER_TYPE_MOTOR; + channels[1].type = MIXER_TYPE_REVERSABLEMOTOR; channels[1].throttle1 = 0; channels[1].throttle2 = 100; channels[1].roll = 0; @@ -2098,10 +2109,10 @@ void VehicleConfigurationHelper::setupMotorcycle() channels[0].pitch = 0; channels[0].yaw = 100; - // Motor (Chan 2) + // Motor (Chan 2) : Curve1, no reverse channels[1].type = MIXER_TYPE_MOTOR; - channels[1].throttle1 = 0; - channels[1].throttle2 = 100; + channels[1].throttle1 = 100; + channels[1].throttle2 = 0; channels[1].roll = 0; channels[1].pitch = 0; channels[1].yaw = 0; diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationsource.h b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationsource.h index 37fcbe1a7..e9483c071 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationsource.h +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationsource.h @@ -46,9 +46,10 @@ struct actuatorChannelSettings { quint16 channelMin; quint16 channelNeutral; quint16 channelMax; + bool isReversableMotor; // Default values - actuatorChannelSettings() : channelMin(1000), channelNeutral(1000), channelMax(1900) {} + actuatorChannelSettings() : channelMin(1000), channelNeutral(1000), channelMax(1900), isReversableMotor(false) {} }; diff --git a/make/firmware-defs.mk b/make/firmware-defs.mk index e0c5f6cc3..b44012f9e 100644 --- a/make/firmware-defs.mk +++ b/make/firmware-defs.mk @@ -71,6 +71,9 @@ MSG_FLASH_IMG = $(QUOTE) FLASH_IMG $(MSG_EXTRA) $(QUOTE) # to the top of the source tree. toprel = $(subst $(realpath $(ROOT_DIR))/,,$(abspath $(1))) +# Function to replace special characters like is done for the symbols. +replace_special_chars = $(subst ~,_,$(subst @,_,$(subst :,_,$(subst -,_,$(subst .,_,$(subst /,_,$1)))))) + # Display compiler version information. .PHONY: gccversion gccversion: @@ -100,9 +103,9 @@ gccversion: $(V1) $(OBJCOPY) -I binary -O elf32-littlearm --binary-architecture arm \ --rename-section .data=.rodata,alloc,load,readonly,data,contents \ --wildcard \ - --redefine-sym _binary_$(subst :,_,$(subst -,_,$(subst .,_,$(subst /,_,$<))))_start=_binary_start \ - --redefine-sym _binary_$(subst :,_,$(subst -,_,$(subst .,_,$(subst /,_,$<))))_end=_binary_end \ - --redefine-sym _binary_$(subst :,_,$(subst -,_,$(subst .,_,$(subst /,_,$<))))_size=_binary_size \ + --redefine-sym _binary_$(call replace_special_chars,$<)_start=_binary_start \ + --redefine-sym _binary_$(call replace_special_chars,$<)_end=_binary_end \ + --redefine-sym _binary_$(call replace_special_chars,$<)_size=_binary_size \ $< $@ # Create extended listing file/disassambly from ELF output file. diff --git a/make/scripts/version-info.py b/make/scripts/version-info.py index 67dd6d95f..889925700 100644 --- a/make/scripts/version-info.py +++ b/make/scripts/version-info.py @@ -113,15 +113,15 @@ class Repo: """Initialize object instance and read repo info""" self._path = path self._exec('rev-parse --verify HEAD') - if self._rc == 0: + if self._load_json(): + pass + elif self._rc == 0: self._hash = self._out.strip(' \t\n\r') self._get_origin() self._get_time() self._get_tag() self._get_branch() self._get_dirty() - elif self._load_json(): - pass else: self._hash = None self._origin = None diff --git a/shared/uavobjectdefinition/actuatorsettings.xml b/shared/uavobjectdefinition/actuatorsettings.xml index 303770f4d..24c1decb0 100644 --- a/shared/uavobjectdefinition/actuatorsettings.xml +++ b/shared/uavobjectdefinition/actuatorsettings.xml @@ -2,14 +2,7 @@ Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType - + diff --git a/shared/uavobjectdefinition/hwsettings.xml b/shared/uavobjectdefinition/hwsettings.xml index 2fb566340..3daac0180 100644 --- a/shared/uavobjectdefinition/hwsettings.xml +++ b/shared/uavobjectdefinition/hwsettings.xml @@ -1,7 +1,7 @@ Selection of optional hardware configurations. - + diff --git a/shared/uavobjectdefinition/systemalarms.xml b/shared/uavobjectdefinition/systemalarms.xml index 351b1edda..c242e133c 100644 --- a/shared/uavobjectdefinition/systemalarms.xml +++ b/shared/uavobjectdefinition/systemalarms.xml @@ -35,6 +35,7 @@ + diff --git a/shared/uavobjectdefinition/systemsettings.xml b/shared/uavobjectdefinition/systemsettings.xml index 8f86537d7..f4f4f540a 100644 --- a/shared/uavobjectdefinition/systemsettings.xml +++ b/shared/uavobjectdefinition/systemsettings.xml @@ -1,7 +1,7 @@ Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand - +