From 1f95332ff47f8f400de9ae239447d5fb03cbb5de Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 23 Jan 2015 23:50:51 +0100 Subject: [PATCH 01/23] OP-1683 - Implement servo synchronous update mode for F4 --- flight/pios/inc/pios_servo.h | 8 ++ flight/pios/stm32f4xx/pios_servo.c | 181 ++++++++++++++++++++++++----- 2 files changed, 157 insertions(+), 32 deletions(-) diff --git a/flight/pios/inc/pios_servo.h b/flight/pios/inc/pios_servo.h index fd905edbe..cdbe0b8db 100644 --- a/flight/pios/inc/pios_servo.h +++ b/flight/pios/inc/pios_servo.h @@ -30,9 +30,17 @@ #ifndef PIOS_SERVO_H #define PIOS_SERVO_H +/* Global types */ +enum pios_servo_bank_mode { + PIOS_SERVO_BANK_MODE_PWM = 0, + PIOS_SERVO_BANK_MODE_SINGLE_PULSE = 1 +}; /* Public Functions */ extern void PIOS_Servo_SetHz(const uint16_t *update_rates, uint8_t banks); extern void PIOS_Servo_Set(uint8_t Servo, uint16_t Position); +extern void PIOS_Servo_Update(); +extern void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode); +extern uint8_t PIOS_Servo_GetPinBank(uint8_t pin); #endif /* PIOS_SERVO_H */ diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 32803a57b..354adcccb 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -39,6 +39,16 @@ 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 }; + +// timer associated to each bank +static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; + +// index of bank used for each pin +static uint8_t *pios_servo_pin_bank; + + /** * Initialise Servos */ @@ -52,39 +62,132 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) /* Store away the requested configuration */ servo_cfg = cfg; + pios_servo_pin_bank = pios_malloc(sizeof(uint8_t) * cfg->num_channels); - /* Configure the channels to be in output compare mode */ - for (uint8_t i = 0; i < cfg->num_channels; i++) { - const struct pios_tim_channel *chan = &cfg->channels[i]; + uint8_t bank = 0; + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + bool new = true; + /* See if any previous channels use that same timer */ + for (uint8_t j = 0; (j < i) && new; j++) { + new &= chan->timer != servo_cfg->channels[j].timer; + } + + if (new) { + PIOS_Assert(bank < PIOS_SERVO_BANKS); + for (uint8_t j = i; j < servo_cfg->num_channels; j++) { + if (servo_cfg->channels[j].timer == chan->timer) { + pios_servo_pin_bank[j] = bank; + } + } + pios_servo_bank_timer[i] = chan->timer; + + TIM_ARRPreloadConfig(chan->timer, ENABLE); + TIM_CtrlPWMOutputs(chan->timer, ENABLE); + TIM_Cmd(chan->timer, DISABLE); + + bank++; + } /* Set up for output compare function */ switch (chan->timer_chan) { case TIM_Channel_1: - TIM_OC1Init(chan->timer, &cfg->tim_oc_init); + TIM_OC1Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC1PreloadConfig(chan->timer, TIM_OCPreload_Enable); + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; case TIM_Channel_2: - TIM_OC2Init(chan->timer, &cfg->tim_oc_init); + TIM_OC2Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC2PreloadConfig(chan->timer, TIM_OCPreload_Enable); + TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; case TIM_Channel_3: - TIM_OC3Init(chan->timer, &cfg->tim_oc_init); + TIM_OC3Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC3PreloadConfig(chan->timer, TIM_OCPreload_Enable); + TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; case TIM_Channel_4: - TIM_OC4Init(chan->timer, &cfg->tim_oc_init); + TIM_OC4Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable); + TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; } - - TIM_ARRPreloadConfig(chan->timer, ENABLE); - TIM_CtrlPWMOutputs(chan->timer, ENABLE); - TIM_Cmd(chan->timer, ENABLE); } return 0; } +void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) +{ + PIOS_Assert(bank < PIOS_SERVO_BANKS); + pios_servo_bank_mode[bank] = mode; + + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + switch (mode) { + case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: + /* Set up for output compare function */ + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_2: + TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_3: + TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_4: + TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + } + break; + case PIOS_SERVO_BANK_MODE_PWM: + /* Set up for output compare function */ + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_2: + TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_3: + TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_4: + TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + } + break; + default: + PIOS_Assert(false); + } + } + // Setup the timer accordingly + switch (mode) { + case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Single); + TIM_CounterModeConfig(pios_servo_bank_timer[bank], TIM_CounterMode_Up); + break; + case PIOS_SERVO_BANK_MODE_PWM: + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); + TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); + break; + default: + PIOS_Assert(false); + } +} + +void PIOS_Servo_Update() +{ + 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); + } + } +} + /** * Set the servo update rate (Max 500Hz) * \param[in] array of rates in Hz @@ -92,6 +195,7 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) */ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) { + PIOS_Assert(banks <= PIOS_SERVO_BANKS); if (!servo_cfg) { return; } @@ -99,30 +203,19 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->tim_base_init; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - // - uint8_t set = 0; - - for (uint8_t i = 0; (i < servo_cfg->num_channels) && (set < banks); i++) { - bool new = true; - const struct pios_tim_channel *chan = &servo_cfg->channels[i]; - - /* See if any previous channels use that same timer */ - for (uint8_t j = 0; (j < i) && new; j++) { - new &= chan->timer != servo_cfg->channels[j].timer; - } - - if (new) { + for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { + const TIM_TypeDef *timer = pios_servo_bank_timer[i]; + if (timer) { // Choose the correct prescaler value for the APB the timer is attached - if (chan->timer == TIM1 || chan->timer == TIM8 || chan->timer == TIM9 || chan->timer == TIM10 || chan->timer == TIM11) { + if (timer == TIM1 || timer == TIM8 || timer == TIM9 || timer == TIM10 || timer == TIM11) { TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / 1000000) - 1; } else { TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / 1000000) - 1; } - TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[set]) - 1); - TIM_TimeBaseInit(chan->timer, &TIM_TimeBaseStructure); - set++; + TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[i]) - 1); + TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } } } @@ -141,20 +234,44 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) /* Update the position */ const struct pios_tim_channel *chan = &servo_cfg->channels[servo]; + + uint8_t bank = pios_servo_pin_bank[servo]; + uint8_t mode = pios_servo_bank_mode[bank]; + uint16_t val; + switch (mode) { + case PIOS_SERVO_BANK_MODE_PWM: + val = position; + break; + case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: + val = chan->timer->ARR - position; + break; + default: + PIOS_Assert(false); + } + 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; } } +uint8_t PIOS_Servo_GetPinBank(uint8_t pin) +{ + if (pin < servo_cfg->num_channels) { + return pios_servo_pin_bank[pin]; + } else { + return 0; + } +} + #endif /* PIOS_INCLUDE_SERVO */ From 47e131298209ad797e3b917bb2f1603998524a15 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 23 Jan 2015 23:51:53 +0100 Subject: [PATCH 02/23] OP-1683 - Implement oneshot/oneshot125 mode to actuator module --- flight/modules/Actuator/actuator.c | 83 ++++++++++++++----- .../uavobjectdefinition/actuatorsettings.xml | 3 +- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index 7cc78c7b1..019977364 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -74,8 +74,9 @@ static int8_t counter; static xQueueHandle queue; static xTaskHandle taskHandle; -static float lastResult[MAX_MIX_ACTUATORS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static float filterAccumulator[MAX_MIX_ACTUATORS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static float lastResult[MAX_MIX_ACTUATORS] = { 0 }; +static float filterAccumulator[MAX_MIX_ACTUATORS] = { 0 }; +static uint8_t pinsMode[MAX_MIX_ACTUATORS]; // used to inform the actuator thread that actuator update rate is changed static volatile bool actuator_settings_updated; // used to inform the actuator thread that mixer settings are changed @@ -424,10 +425,21 @@ static void actuatorTask(__attribute__((unused)) void *parameters) // will be set except explicitly disabled (which will have PWM pulse = 0). for (int i = 0; i < MAX_MIX_ACTUATORS; i++) { if (command.Channel[i]) { - command.Channel[i] = scaleChannel(status[i], - actuatorSettings.ChannelMax[i], - actuatorSettings.ChannelMin[i], - actuatorSettings.ChannelNeutral[i]); + uint8_t mode = pinsMode[actuatorSettings.ChannelAddr[i]]; + switch (mode) { + case ACTUATORSETTINGS_BANKMODE_PWM: + case ACTUATORSETTINGS_BANKMODE_ONESHOT: + command.Channel[i] = scaleChannel(status[i], + actuatorSettings.ChannelMax[i], + actuatorSettings.ChannelMin[i], + actuatorSettings.ChannelNeutral[i]); + break; + case ACTUATORSETTINGS_BANKMODE_ONESHOT125: + command.Channel[i] = scaleChannel(status[i], + 249, + 125, + 126); + } } } @@ -436,7 +448,6 @@ static void actuatorTask(__attribute__((unused)) void *parameters) if (command.UpdateTime > command.MaxUpdateTime) { command.MaxUpdateTime = command.UpdateTime; } - // Update output object ActuatorCommandSet(&command); // Update in case read only (eg. during servo configuration) @@ -454,6 +465,8 @@ static void actuatorTask(__attribute__((unused)) void *parameters) success &= set_channel(n, command.Channel[n], &actuatorSettings); } + PIOS_Servo_Update(); + if (!success) { command.NumFailedUpdates++; ActuatorCommandSet(&command); @@ -476,11 +489,11 @@ float ProcessMixer(const int index, const float curve1, const float curve2, const Mixer_t *mixers = (Mixer_t *)&mixerSettings->Mixer1Type; // pointer to array of mixers in UAVObjects const Mixer_t *mixer = &mixers[index]; - float result = (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE1] / 128.0f) * curve1) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE2] / 128.0f) * curve2) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL] / 128.0f) * desired->Roll) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH] / 128.0f) * desired->Pitch) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW] / 128.0f) * desired->Yaw); + float result = ((((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE1]) * curve1) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE2]) * curve2) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL]) * desired->Roll) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH]) * desired->Pitch) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW]) * desired->Yaw)) / 128.0f; // note: no feedforward for reversable motors yet for safety reasons if (mixer->type == MIXERSETTINGS_MIXER1TYPE_MOTOR) { @@ -754,18 +767,48 @@ static bool set_channel(uint8_t mixer_channel, uint16_t value, const ActuatorSet */ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuatorSettings, bool force_update) { - static uint16_t prevChannelUpdateFreq[ACTUATORSETTINGS_CHANNELUPDATEFREQ_NUMELEM]; + static uint16_t prevBankUpdateFreq[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM]; + static uint8_t prevBankMode[ACTUATORSETTINGS_BANKMODE_NUMELEM]; // check if the any rate setting is changed if (force_update || - memcmp(prevChannelUpdateFreq, - actuatorSettings->ChannelUpdateFreq, - sizeof(prevChannelUpdateFreq)) != 0) { + (memcmp(prevBankUpdateFreq, + actuatorSettings->BankUpdateFreq, + sizeof(prevBankUpdateFreq)) != 0) || + (memcmp(prevBankUpdateFreq, + actuatorSettings->BankMode, + sizeof(prevBankMode)) != 0) + ) { /* Something has changed, apply the settings to HW */ - memcpy(prevChannelUpdateFreq, - actuatorSettings->ChannelUpdateFreq, - sizeof(prevChannelUpdateFreq)); - PIOS_Servo_SetHz(actuatorSettings->ChannelUpdateFreq, ACTUATORSETTINGS_CHANNELUPDATEFREQ_NUMELEM); + memcpy(prevBankUpdateFreq, + actuatorSettings->BankUpdateFreq, + sizeof(prevBankUpdateFreq)); + memcpy(prevBankMode, + actuatorSettings->BankMode, + sizeof(prevBankMode)); + + uint16_t freq[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM]; + + for (uint8_t i = 0; i < ACTUATORSETTINGS_BANKMODE_NUMELEM; i++) { + PIOS_Servo_SetBankMode(i, + actuatorSettings->BankMode[i] == + ACTUATORSETTINGS_BANKMODE_PWM ? + PIOS_SERVO_BANK_MODE_PWM : + PIOS_SERVO_BANK_MODE_SINGLE_PULSE + ); + if (actuatorSettings->BankMode[i] == ACTUATORSETTINGS_BANKMODE_ONESHOT125) { + freq[i] = 1000000 / 250; // force a total period of 250uSec + } else { + freq[i] = actuatorSettings->BankUpdateFreq[i]; + } + } + PIOS_Servo_SetHz(freq, ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM); + + // retrieve mode from related bank + for (uint8_t i = 0; i < MAX_MIX_ACTUATORS; i++) { + uint8_t bank = PIOS_Servo_GetPinBank(i); + pinsMode[i] = actuatorSettings->BankMode[bank]; + } } } diff --git a/shared/uavobjectdefinition/actuatorsettings.xml b/shared/uavobjectdefinition/actuatorsettings.xml index 051fdceb1..fc7ff0741 100644 --- a/shared/uavobjectdefinition/actuatorsettings.xml +++ b/shared/uavobjectdefinition/actuatorsettings.xml @@ -1,7 +1,8 @@ Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType - + + From 73c6ae205531028f4820197226c9876879fc11c0 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 23 Jan 2015 23:56:39 +0100 Subject: [PATCH 03/23] OP-1683 - Add revolution and other f4 targets support --- flight/targets/boards/discoveryf4bare/pios_board.h | 1 + flight/targets/boards/revolution/pios_board.h | 2 +- flight/targets/boards/revoproto/pios_board.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/flight/targets/boards/discoveryf4bare/pios_board.h b/flight/targets/boards/discoveryf4bare/pios_board.h index 0a7b0e50b..82e8df8f9 100644 --- a/flight/targets/boards/discoveryf4bare/pios_board.h +++ b/flight/targets/boards/discoveryf4bare/pios_board.h @@ -248,6 +248,7 @@ extern uint32_t pios_packet_handler; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/flight/targets/boards/revolution/pios_board.h b/flight/targets/boards/revolution/pios_board.h index 09a2be105..7f9ab9d77 100644 --- a/flight/targets/boards/revolution/pios_board.h +++ b/flight/targets/boards/revolution/pios_board.h @@ -268,7 +268,7 @@ extern uint32_t pios_packet_handler; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ - +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings // -------------------------- diff --git a/flight/targets/boards/revoproto/pios_board.h b/flight/targets/boards/revoproto/pios_board.h index 6da2bbd9c..d3a421114 100644 --- a/flight/targets/boards/revoproto/pios_board.h +++ b/flight/targets/boards/revoproto/pios_board.h @@ -225,6 +225,7 @@ extern uint32_t pios_com_hkosd_id; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings From d0629926f046136ad038d3fbe8a18537d40ae5b5 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 23 Jan 2015 23:57:12 +0100 Subject: [PATCH 04/23] OP-1683 - fixes for GCS --- .../src/plugins/config/configoutputwidget.cpp | 48 +++++++++---------- .../vehicleconfigurationhelper.cpp | 48 +++++++++---------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 769c25066..4f6370d75 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -280,30 +280,30 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) ui->spinningArmed->setChecked(actuatorSettingsData.MotorsSpinWhileArmed == ActuatorSettings::MOTORSSPINWHILEARMED_TRUE); // Setup output rates for all banks - if (ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[0])) == -1) { - ui->cb_outputRate1->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[0])); + if (ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.BankUpdateFreq[0])) == -1) { + ui->cb_outputRate1->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[0])); } - if (ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[1])) == -1) { - ui->cb_outputRate2->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[1])); + if (ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.BankUpdateFreq[1])) == -1) { + ui->cb_outputRate2->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[1])); } - if (ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[2])) == -1) { - ui->cb_outputRate3->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[2])); + if (ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.BankUpdateFreq[2])) == -1) { + ui->cb_outputRate3->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[2])); } - if (ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[3])) == -1) { - ui->cb_outputRate4->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[3])); + if (ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.BankUpdateFreq[3])) == -1) { + ui->cb_outputRate4->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[3])); } - if (ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[4])) == -1) { - ui->cb_outputRate5->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[4])); + if (ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.BankUpdateFreq[4])) == -1) { + ui->cb_outputRate5->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[4])); } - if (ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[5])) == -1) { - ui->cb_outputRate6->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[5])); + if (ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.BankUpdateFreq[5])) == -1) { + ui->cb_outputRate6->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[5])); } - ui->cb_outputRate1->setCurrentIndex(ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[0]))); - ui->cb_outputRate2->setCurrentIndex(ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[1]))); - ui->cb_outputRate3->setCurrentIndex(ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[2]))); - ui->cb_outputRate4->setCurrentIndex(ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[3]))); - ui->cb_outputRate5->setCurrentIndex(ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[4]))); - ui->cb_outputRate6->setCurrentIndex(ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[5]))); + ui->cb_outputRate1->setCurrentIndex(ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.BankUpdateFreq[0]))); + ui->cb_outputRate2->setCurrentIndex(ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.BankUpdateFreq[1]))); + ui->cb_outputRate3->setCurrentIndex(ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.BankUpdateFreq[2]))); + ui->cb_outputRate4->setCurrentIndex(ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.BankUpdateFreq[3]))); + ui->cb_outputRate5->setCurrentIndex(ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.BankUpdateFreq[4]))); + ui->cb_outputRate6->setCurrentIndex(ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.BankUpdateFreq[5]))); // Reset to all disabled ui->chBank1->setText("-"); @@ -391,12 +391,12 @@ void ConfigOutputWidget::updateObjectsFromWidgets() } // Set update rates - actuatorSettingsData.ChannelUpdateFreq[0] = ui->cb_outputRate1->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[1] = ui->cb_outputRate2->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[2] = ui->cb_outputRate3->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[3] = ui->cb_outputRate4->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[4] = ui->cb_outputRate5->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[5] = ui->cb_outputRate6->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[0] = ui->cb_outputRate1->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[1] = ui->cb_outputRate2->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[2] = ui->cb_outputRate3->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[3] = ui->cb_outputRate4->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[4] = ui->cb_outputRate5->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[5] = ui->cb_outputRate6->currentText().toUInt(); actuatorSettingsData.MotorsSpinWhileArmed = ui->spinningArmed->isChecked() ? ActuatorSettings::MOTORSSPINWHILEARMED_TRUE : diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp index 2a66485f5..81bf4fd40 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp @@ -404,32 +404,32 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() data.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_FALSE; - for (quint16 i = 0; i < ActuatorSettings::CHANNELUPDATEFREQ_NUMELEM; i++) { - data.ChannelUpdateFreq[i] = LEGACY_ESC_FREQUENCY; + for (quint16 i = 0; i < ActuatorSettings::BANKUPDATEFREQ_NUMELEM; i++) { + data.BankUpdateFreq[i] = LEGACY_ESC_FREQUENCY; } switch (m_configSource->getVehicleSubType()) { case VehicleConfigurationSource::MULTI_ROTOR_TRI_Y: // Servo always on channel 4 - data.ChannelUpdateFreq[0] = escFrequence; + data.BankUpdateFreq[0] = escFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_CC || m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_CC3D) { - data.ChannelUpdateFreq[1] = servoFrequence; + data.BankUpdateFreq[1] = servoFrequence; } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { - data.ChannelUpdateFreq[1] = escFrequence; - data.ChannelUpdateFreq[2] = servoFrequence; + data.BankUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[2] = servoFrequence; } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_NANO) { - data.ChannelUpdateFreq[1] = escFrequence; - data.ChannelUpdateFreq[2] = escFrequence; - data.ChannelUpdateFreq[3] = servoFrequence; + data.BankUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[2] = escFrequence; + data.BankUpdateFreq[3] = servoFrequence; } break; case VehicleConfigurationSource::MULTI_ROTOR_QUAD_X: case VehicleConfigurationSource::MULTI_ROTOR_QUAD_PLUS: - data.ChannelUpdateFreq[0] = escFrequence; - data.ChannelUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[0] = escFrequence; + data.BankUpdateFreq[1] = escFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { - data.ChannelUpdateFreq[2] = escFrequence; + data.BankUpdateFreq[2] = escFrequence; } break; case VehicleConfigurationSource::MULTI_ROTOR_HEXA: @@ -441,10 +441,10 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() case VehicleConfigurationSource::MULTI_ROTOR_OCTO_COAX_X: case VehicleConfigurationSource::MULTI_ROTOR_OCTO_COAX_PLUS: case VehicleConfigurationSource::MULTI_ROTOR_OCTO_V: - data.ChannelUpdateFreq[0] = escFrequence; - data.ChannelUpdateFreq[1] = escFrequence; - data.ChannelUpdateFreq[2] = escFrequence; - data.ChannelUpdateFreq[3] = escFrequence; + data.BankUpdateFreq[0] = escFrequence; + data.BankUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[2] = escFrequence; + data.BankUpdateFreq[3] = escFrequence; break; default: break; @@ -467,15 +467,15 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() data.ChannelMax[i] = actuatorSettings[i].channelMax; } - for (quint16 i = 0; i < ActuatorSettings::CHANNELUPDATEFREQ_NUMELEM; i++) { - data.ChannelUpdateFreq[i] = servoFrequence; + for (quint16 i = 0; i < ActuatorSettings::BANKUPDATEFREQ_NUMELEM; i++) { + data.BankUpdateFreq[i] = servoFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { if (i == 1) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_NANO) { if (i == 2) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } } @@ -503,15 +503,15 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() data.ChannelMax[i] = actuatorSettings[i].channelMax; } - for (quint16 i = 0; i < ActuatorSettings::CHANNELUPDATEFREQ_NUMELEM; i++) { - data.ChannelUpdateFreq[i] = servoFrequence; + for (quint16 i = 0; i < ActuatorSettings::BANKUPDATEFREQ_NUMELEM; i++) { + data.BankUpdateFreq[i] = servoFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { if (i == 1) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_NANO) { if (i == 2) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } } From 411416d2a185e2071ebea2e9584b4c4a6534b08d Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 00:18:20 +0100 Subject: [PATCH 05/23] OP-1683 - Fix compilation for CC (not yet supported) --- flight/pios/stm32f10x/pios_servo.c | 67 ++++++++++++++++++- .../targets/boards/coptercontrol/pios_board.h | 1 + .../uavobjectdefinition/actuatorsettings.xml | 5 +- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/flight/pios/stm32f10x/pios_servo.c b/flight/pios/stm32f10x/pios_servo.c index a0ea16916..126e011fe 100644 --- a/flight/pios/stm32f10x/pios_servo.c +++ b/flight/pios/stm32f10x/pios_servo.c @@ -39,6 +39,16 @@ 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 }; + +// timer associated to each bank +//static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; + +// index of bank used for each pin +static uint8_t *pios_servo_pin_bank; + + /** * Initialise Servos */ @@ -52,10 +62,41 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) /* Store away the requested configuration */ servo_cfg = cfg; + pios_servo_pin_bank = pios_malloc(sizeof(uint8_t) * cfg->num_channels); + uint8_t bank = 0; /* Configure the channels to be in output compare mode */ for (uint8_t i = 0; i < cfg->num_channels; i++) { - const struct pios_tim_channel *chan = &cfg->channels[i]; + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + bool new = true; + /* See if any previous channels use that same timer */ + for (uint8_t j = 0; (j < i) && new; j++) { + new &= chan->timer != servo_cfg->channels[j].timer; + } + + if (new) { + PIOS_Assert(bank < PIOS_SERVO_BANKS); + for (uint8_t j = i; j < servo_cfg->num_channels; j++) { + if (servo_cfg->channels[j].timer == chan->timer) { + pios_servo_pin_bank[j] = bank; + } + } + //pios_servo_bank_timer[i] = chan->timer; + + PIOS_Assert(bank < PIOS_SERVO_BANKS); + + for (uint8_t j = i; j < servo_cfg->num_channels; j++) { + if (servo_cfg->channels[j].timer == chan->timer) { + pios_servo_pin_bank[j] = bank; + } + } +/* + TIM_ARRPreloadConfig(chan->timer, ENABLE); + TIM_CtrlPWMOutputs(chan->timer, ENABLE); + TIM_Cmd(chan->timer, DISABLE); +*/ + bank++; + } /* Set up for output compare function */ switch (chan->timer_chan) { @@ -150,4 +191,28 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) } } +void PIOS_Servo_Update(){ + /* + 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); + } + } + */ +} + +void PIOS_Servo_SetBankMode(__attribute__((unused)) uint8_t bank, __attribute__((unused)) uint8_t mode){ + +} + +uint8_t PIOS_Servo_GetPinBank(uint8_t pin) +{ + if (pin < servo_cfg->num_channels) { + return pios_servo_pin_bank[pin]; + } else { + return 0; + } +} + #endif /* PIOS_INCLUDE_SERVO */ diff --git a/flight/targets/boards/coptercontrol/pios_board.h b/flight/targets/boards/coptercontrol/pios_board.h index 0c131518b..f3c3e34d3 100644 --- a/flight/targets/boards/coptercontrol/pios_board.h +++ b/flight/targets/boards/coptercontrol/pios_board.h @@ -251,6 +251,7 @@ extern uint32_t pios_com_hkosd_id; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/shared/uavobjectdefinition/actuatorsettings.xml b/shared/uavobjectdefinition/actuatorsettings.xml index fc7ff0741..5b6a5186d 100644 --- a/shared/uavobjectdefinition/actuatorsettings.xml +++ b/shared/uavobjectdefinition/actuatorsettings.xml @@ -2,7 +2,10 @@ Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType - + From ec69941c3063b6b3248bdc6c97ccb47b8c0f4712 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 13:08:56 +0100 Subject: [PATCH 06/23] OP-1683 - Fix compilation for other targets --- flight/targets/boards/oplinkmini/pios_board.h | 1 + flight/targets/boards/osd/pios_board.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/flight/targets/boards/oplinkmini/pios_board.h b/flight/targets/boards/oplinkmini/pios_board.h index 4a976fc3e..b571a87d4 100644 --- a/flight/targets/boards/oplinkmini/pios_board.h +++ b/flight/targets/boards/oplinkmini/pios_board.h @@ -260,6 +260,7 @@ extern uint32_t pios_ppm_out_id; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/flight/targets/boards/osd/pios_board.h b/flight/targets/boards/osd/pios_board.h index 9b88a5e3b..f0068f978 100644 --- a/flight/targets/boards/osd/pios_board.h +++ b/flight/targets/boards/osd/pios_board.h @@ -247,6 +247,8 @@ extern uint32_t pios_com_telem_usb_id; // -------------------------- #define PIOS_TIM_MAX_DEVS 6 +#define PIOS_SERVO_BANKS 6 + // ------------------------- // USB // ------------------------- From 2a10d9d481af927ca3a2a75614fd87b5a3a765b0 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 13:35:41 +0100 Subject: [PATCH 07/23] OP-1683 - fixes to PIOS_Servo, added code to prevent overflows --- flight/pios/stm32f4xx/pios_servo.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 354adcccb..83f0706f3 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -48,6 +48,7 @@ static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; // index of bank used for each pin static uint8_t *pios_servo_pin_bank; +#define PIOS_SERVO_TIMER_CLOCK 1000000 /** * Initialise Servos @@ -80,7 +81,7 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) pios_servo_pin_bank[j] = bank; } } - pios_servo_bank_timer[i] = chan->timer; + pios_servo_bank_timer[bank] = chan->timer; TIM_ARRPreloadConfig(chan->timer, ENABLE); TIM_CtrlPWMOutputs(chan->timer, ENABLE); @@ -209,12 +210,12 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) if (timer) { // Choose the correct prescaler value for the APB the timer is attached if (timer == TIM1 || timer == TIM8 || timer == TIM9 || timer == TIM10 || timer == TIM11) { - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / 1000000) - 1; + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / PIOS_SERVO_TIMER_CLOCK) - 1; } else { - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / 1000000) - 1; + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / PIOS_SERVO_TIMER_CLOCK) - 1; } - TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[i]) - 1); + TIM_TimeBaseStructure.TIM_Period = ((PIOS_SERVO_TIMER_CLOCK / speeds[i]) - 1); TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } } @@ -243,7 +244,12 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) val = position; break; case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: - val = chan->timer->ARR - position; + // prevent overflows that causes an output to pass from max to no pulses. + if (position < chan->timer->ARR) { + val = chan->timer->ARR - position; + } else { + val = 1; + } break; default: PIOS_Assert(false); From dcc9a5b7dc78463c2a12a341ce6e7d11d5f93d9d Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 13:37:00 +0100 Subject: [PATCH 08/23] OP-1683 - Actuator uses "standard" 1000-2000 range and remap it to 125-250 just before sending to servo to prevent any impact on gcs and other blocks --- flight/modules/Actuator/actuator.c | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index 019977364..c8ddc3802 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -425,21 +425,10 @@ static void actuatorTask(__attribute__((unused)) void *parameters) // will be set except explicitly disabled (which will have PWM pulse = 0). for (int i = 0; i < MAX_MIX_ACTUATORS; i++) { if (command.Channel[i]) { - uint8_t mode = pinsMode[actuatorSettings.ChannelAddr[i]]; - switch (mode) { - case ACTUATORSETTINGS_BANKMODE_PWM: - case ACTUATORSETTINGS_BANKMODE_ONESHOT: - command.Channel[i] = scaleChannel(status[i], - actuatorSettings.ChannelMax[i], - actuatorSettings.ChannelMin[i], - actuatorSettings.ChannelNeutral[i]); - break; - case ACTUATORSETTINGS_BANKMODE_ONESHOT125: - command.Channel[i] = scaleChannel(status[i], - 249, - 125, - 126); - } + command.Channel[i] = scaleChannel(status[i], + actuatorSettings.ChannelMax[i], + actuatorSettings.ChannelMin[i], + actuatorSettings.ChannelNeutral[i]); } } @@ -743,7 +732,18 @@ static bool set_channel(uint8_t mixer_channel, uint16_t value, const ActuatorSet return true; case ACTUATORSETTINGS_CHANNELTYPE_PWM: - PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); + { + uint8_t mode = pinsMode[actuatorSettings->ChannelAddr[mixer_channel]]; + switch (mode) { + case ACTUATORSETTINGS_BANKMODE_ONESHOT125: + // Quick way to remap of 1000-2000 range to 125-250 + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value / 8); + break; + default: + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); + break; + } + } return true; #if defined(PIOS_INCLUDE_I2C_ESC) @@ -797,7 +797,7 @@ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuator PIOS_SERVO_BANK_MODE_SINGLE_PULSE ); if (actuatorSettings->BankMode[i] == ACTUATORSETTINGS_BANKMODE_ONESHOT125) { - freq[i] = 1000000 / 250; // force a total period of 250uSec + freq[i] = 1000000 / 255; // force a total period of 255uSec } else { freq[i] = actuatorSettings->BankUpdateFreq[i]; } From 5901dbda35fa9c21a67cb9cc49c358f5dfad6321 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 15:40:21 +0100 Subject: [PATCH 09/23] OP-1683 - Add bank mode selection UI --- .../src/plugins/config/configoutputwidget.cpp | 23 ++- .../openpilotgcs/src/plugins/config/output.ui | 190 +++++++++++++++++- 2 files changed, 202 insertions(+), 11 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 4f6370d75..e008274ef 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -98,9 +98,18 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren addWidget(ui->cb_outputRate1); addWidget(ui->spinningArmed); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode1, 0); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode2, 1); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode3, 2); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode4, 3); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode5, 4); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode6, 5); + disconnect(this, SLOT(refreshWidgetsValues(UAVObject *))); + populateWidgets(); refreshWidgetsValues(); + updateEnableControls(); } @@ -251,7 +260,7 @@ void ConfigOutputWidget::sendChannelTest(int index, int value) void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) { Q_UNUSED(obj); - + ConfigTaskWidget::refreshWidgetsValues(obj); bool dirty = isDirty(); // Get Actuator Settings @@ -391,12 +400,12 @@ void ConfigOutputWidget::updateObjectsFromWidgets() } // Set update rates - actuatorSettingsData.BankUpdateFreq[0] = ui->cb_outputRate1->currentText().toUInt(); - actuatorSettingsData.BankUpdateFreq[1] = ui->cb_outputRate2->currentText().toUInt(); - actuatorSettingsData.BankUpdateFreq[2] = ui->cb_outputRate3->currentText().toUInt(); - actuatorSettingsData.BankUpdateFreq[3] = ui->cb_outputRate4->currentText().toUInt(); - actuatorSettingsData.BankUpdateFreq[4] = ui->cb_outputRate5->currentText().toUInt(); - actuatorSettingsData.BankUpdateFreq[5] = ui->cb_outputRate6->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[0] = ui->cb_outputRate1->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[1] = ui->cb_outputRate2->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[2] = ui->cb_outputRate3->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[3] = ui->cb_outputRate4->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[4] = ui->cb_outputRate5->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[5] = ui->cb_outputRate6->currentText().toUInt(); actuatorSettingsData.MotorsSpinWhileArmed = ui->spinningArmed->isChecked() ? ActuatorSettings::MOTORSSPINWHILEARMED_TRUE : diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index e80ea0764..b571d6313 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -122,8 +122,8 @@ 0 0 - 674 - 677 + 680 + 672 @@ -157,7 +157,7 @@ - Output Update Speed + Output configuration @@ -183,7 +183,7 @@ - Channel: + Channels: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -674,6 +674,188 @@ + + + + + 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. standard ESCs uses PWM. + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. standard ESCs uses PWM. + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. standard ESCs uses PWM. + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. standard ESCs uses PWM. + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. standard ESCs uses PWM. + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. standard ESCs uses PWM. + + + From 5f034dfd3eee907512e72b9c17dcb47125918f83 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 15:41:04 +0100 Subject: [PATCH 10/23] OP-1683 - Missing uncrustification for f1 stubs. --- flight/pios/stm32f10x/pios_servo.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/flight/pios/stm32f10x/pios_servo.c b/flight/pios/stm32f10x/pios_servo.c index 126e011fe..31cc202cc 100644 --- a/flight/pios/stm32f10x/pios_servo.c +++ b/flight/pios/stm32f10x/pios_servo.c @@ -40,10 +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 }; // timer associated to each bank -//static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; +// static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; // index of bank used for each pin static uint8_t *pios_servo_pin_bank; @@ -81,7 +81,7 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) pios_servo_pin_bank[j] = bank; } } - //pios_servo_bank_timer[i] = chan->timer; + // pios_servo_bank_timer[i] = chan->timer; PIOS_Assert(bank < PIOS_SERVO_BANKS); @@ -94,7 +94,7 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) TIM_ARRPreloadConfig(chan->timer, ENABLE); TIM_CtrlPWMOutputs(chan->timer, ENABLE); TIM_Cmd(chan->timer, DISABLE); -*/ + */ bank++; } @@ -191,20 +191,19 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) } } -void PIOS_Servo_Update(){ +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); } - } - */ + } + */ } -void PIOS_Servo_SetBankMode(__attribute__((unused)) uint8_t bank, __attribute__((unused)) uint8_t mode){ - -} +void PIOS_Servo_SetBankMode(__attribute__((unused)) uint8_t bank, __attribute__((unused)) uint8_t mode) {} uint8_t PIOS_Servo_GetPinBank(uint8_t pin) { From 73dc04b436b3378f444614dd6d7bdb22c7ba15e7 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 24 Jan 2015 21:12:31 +0100 Subject: [PATCH 11/23] OP-1683 - Fix save for BankMode. --- .../openpilotgcs/src/plugins/config/configoutputwidget.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index e008274ef..50b69a2c6 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -259,12 +259,13 @@ void ConfigOutputWidget::sendChannelTest(int index, int value) */ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) { - Q_UNUSED(obj); - ConfigTaskWidget::refreshWidgetsValues(obj); bool dirty = isDirty(); + ConfigTaskWidget::refreshWidgetsValues(obj); + // Get Actuator Settings ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager()); + Q_ASSERT(actuatorSettings); ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData(); @@ -383,7 +384,7 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) */ void ConfigOutputWidget::updateObjectsFromWidgets() { - emit updateObjectsFromWidgetsRequested(); + ConfigTaskWidget::updateObjectsFromWidgets(); ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager()); From 7955f63c98f1eded36bc19287601fbff639496b5 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 25 Jan 2015 21:25:14 +0100 Subject: [PATCH 12/23] OP-1683 - Clenaup, trigger update in setfailsafe, Fix standard pwm operation --- flight/modules/Actuator/actuator.c | 2 + flight/pios/stm32f4xx/pios_servo.c | 99 +++++++++++++++--------------- 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index c8ddc3802..c90f8a37e 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -617,6 +617,8 @@ static void setFailsafe(const ActuatorSettingsData *actuatorSettings, const Mixe for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n) { set_channel(n, Channel[n], actuatorSettings); } + // Send the updated command + PIOS_Servo_Update(); // Update output object's parts that we changed ActuatorCommandChannelSet(Channel); diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 83f0706f3..b51974da1 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -95,22 +95,18 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) case TIM_Channel_1: TIM_OC1Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC1PreloadConfig(chan->timer, TIM_OCPreload_Enable); - TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; case TIM_Channel_2: TIM_OC2Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC2PreloadConfig(chan->timer, TIM_OCPreload_Enable); - TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; case TIM_Channel_3: TIM_OC3Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC3PreloadConfig(chan->timer, TIM_OCPreload_Enable); - TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; case TIM_Channel_4: TIM_OC4Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable); - TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); break; } } @@ -123,62 +119,67 @@ void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) PIOS_Assert(bank < PIOS_SERVO_BANKS); pios_servo_bank_mode[bank] = mode; - for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { - const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + 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]; + switch (mode) { + case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: + /* Set up for output compare function */ + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_2: + TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_3: + TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + case TIM_Channel_4: + TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); + break; + } + break; + case PIOS_SERVO_BANK_MODE_PWM: + /* 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; + } + break; + default: + PIOS_Assert(false); + } + } + } + // Setup the timer accordingly switch (mode) { case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: - /* Set up for output compare function */ - switch (chan->timer_chan) { - case TIM_Channel_1: - TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_2: - TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_3: - TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_4: - TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - } + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Single); + TIM_CounterModeConfig(pios_servo_bank_timer[bank], TIM_CounterMode_Up); break; case PIOS_SERVO_BANK_MODE_PWM: - /* Set up for output compare function */ - switch (chan->timer_chan) { - case TIM_Channel_1: - TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_2: - TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_3: - TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_4: - TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - } + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); + TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); break; default: PIOS_Assert(false); } } - // Setup the timer accordingly - switch (mode) { - case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: - TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Single); - TIM_CounterModeConfig(pios_servo_bank_timer[bank], TIM_CounterMode_Up); - break; - case PIOS_SERVO_BANK_MODE_PWM: - TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); - TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); - break; - default: - PIOS_Assert(false); - } } + void PIOS_Servo_Update() { for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { From 97bf9f74b6e95dde78cf6f13b386c2af5b1b521c Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 26 Jan 2015 12:24:10 +0100 Subject: [PATCH 13/23] OP-1683 - Enables only available output bank mode Combos --- .../src/plugins/config/configoutputwidget.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 50b69a2c6..17ca59837 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -329,6 +329,14 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) ui->cb_outputRate5->setEnabled(false); ui->cb_outputRate6->setEnabled(false); + + ui->cb_outputMode1->setEnabled(false); + ui->cb_outputMode2->setEnabled(false); + ui->cb_outputMode3->setEnabled(false); + ui->cb_outputMode4->setEnabled(false); + ui->cb_outputMode5->setEnabled(false); + ui->cb_outputMode6->setEnabled(false); + // Get connected board model ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); Q_ASSERT(pm); @@ -348,6 +356,11 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) ui->cb_outputRate2->setEnabled(true); ui->cb_outputRate3->setEnabled(true); ui->cb_outputRate4->setEnabled(true); + + ui->cb_outputMode1->setEnabled(true); + ui->cb_outputMode2->setEnabled(true); + ui->cb_outputMode3->setEnabled(true); + ui->cb_outputMode4->setEnabled(true); } else if ((board & 0xff00) == 0x0900) { // Revolution family of boards 6 timer banks ui->chBank1->setText("1-2"); @@ -356,12 +369,20 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) ui->chBank4->setText("5-6"); ui->chBank5->setText("7-8"); ui->chBank6->setText("9-10"); + ui->cb_outputRate1->setEnabled(true); ui->cb_outputRate2->setEnabled(true); ui->cb_outputRate3->setEnabled(true); ui->cb_outputRate4->setEnabled(true); ui->cb_outputRate5->setEnabled(true); ui->cb_outputRate6->setEnabled(true); + + ui->cb_outputMode1->setEnabled(true); + ui->cb_outputMode2->setEnabled(true); + ui->cb_outputMode3->setEnabled(true); + ui->cb_outputMode4->setEnabled(true); + ui->cb_outputMode5->setEnabled(true); + ui->cb_outputMode6->setEnabled(true); } } From 26fcec09e38b5a9a0720ddd8ae253bb0fef405f2 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Tue, 27 Jan 2015 19:39:45 +0100 Subject: [PATCH 14/23] OP-1683 - Show bank number and color beside output number --- .../src/plugins/config/configoutputwidget.cpp | 106 +++++++-------- .../src/plugins/config/configoutputwidget.h | 2 + .../openpilotgcs/src/plugins/config/output.ui | 2 +- .../src/plugins/config/outputchannelform.cpp | 28 +++- .../src/plugins/config/outputchannelform.h | 6 +- .../src/plugins/config/outputchannelform.ui | 128 +++++++++++++++--- 6 files changed, 198 insertions(+), 74 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 17ca59837..8347f45ff 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -249,6 +249,15 @@ void ConfigOutputWidget::sendChannelTest(int index, int value) actuatorCommand->setData(actuatorCommandFields); } +void ConfigOutputWidget::setColor(QWidget *widget, const QColor color) +{ + QPalette p(palette()); + QColor color2 = QColor(color); + + p.setColor(QPalette::Background, color2); + widget->setAutoFillBackground(true); + widget->setPalette(p); +} /******************************** * Output settings @@ -272,6 +281,9 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) // Get channel descriptions QStringList ChannelDesc = ConfigVehicleTypeWidget::getChannelDescriptions(); + QList ChannelBanks; + QList bankColors; + bankColors << Qt::magenta << Qt::yellow << Qt::green << Qt::cyan << Qt::red << Qt::darkCyan; // Initialize output forms QList outputChannelForms = findChildren(); foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { @@ -315,84 +327,72 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) ui->cb_outputRate5->setCurrentIndex(ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.BankUpdateFreq[4]))); ui->cb_outputRate6->setCurrentIndex(ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.BankUpdateFreq[5]))); + QList bank; + bank << ui->chBank1 << ui->chBank2 << ui->chBank3 << ui->chBank4 << ui->chBank5 << ui->chBank6; + QList outputRateCombos; + outputRateCombos << ui->cb_outputRate1 << ui->cb_outputRate2 << ui->cb_outputRate3 << + ui->cb_outputRate4 << ui->cb_outputRate5 << ui->cb_outputRate6; + + QList outputModeCombos; + outputModeCombos << ui->cb_outputMode1 << ui->cb_outputMode2 << ui->cb_outputMode3 << + ui->cb_outputMode4 << ui->cb_outputMode5 << ui->cb_outputMode6; // Reset to all disabled - ui->chBank1->setText("-"); - ui->chBank2->setText("-"); - ui->chBank3->setText("-"); - ui->chBank4->setText("-"); - ui->chBank5->setText("-"); - ui->chBank6->setText("-"); - ui->cb_outputRate1->setEnabled(false); - ui->cb_outputRate2->setEnabled(false); - ui->cb_outputRate3->setEnabled(false); - ui->cb_outputRate4->setEnabled(false); - ui->cb_outputRate5->setEnabled(false); - ui->cb_outputRate6->setEnabled(false); + foreach(QLabel * label, bank) { + label->setText("-"); + } + int i = 0; + foreach(QComboBox * cbo, outputRateCombos) { + cbo->setEnabled(false); + setColor(cbo, palette().color(QPalette::Background)); + } - - ui->cb_outputMode1->setEnabled(false); - ui->cb_outputMode2->setEnabled(false); - ui->cb_outputMode3->setEnabled(false); - ui->cb_outputMode4->setEnabled(false); - ui->cb_outputMode5->setEnabled(false); - ui->cb_outputMode6->setEnabled(false); + i = 0; + foreach(QComboBox * cbo, outputModeCombos) { + cbo->setEnabled(false); + setColor(cbo, palette().color(QPalette::Background)); + } // Get connected board model ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); Q_ASSERT(pm); UAVObjectUtilManager *utilMngr = pm->getObject(); Q_ASSERT(utilMngr); + QStringList bankLabels; if (utilMngr) { int board = utilMngr->getBoardModel(); // Setup labels and combos for banks according to board type if ((board & 0xff00) == 0x0400) { // Coptercontrol family of boards 4 timer banks - ui->chBank1->setText("1-3"); - ui->chBank2->setText("4"); - ui->chBank3->setText("5,7-8"); - ui->chBank4->setText("6,9-10"); - ui->cb_outputRate1->setEnabled(true); - ui->cb_outputRate2->setEnabled(true); - ui->cb_outputRate3->setEnabled(true); - ui->cb_outputRate4->setEnabled(true); - - ui->cb_outputMode1->setEnabled(true); - ui->cb_outputMode2->setEnabled(true); - ui->cb_outputMode3->setEnabled(true); - ui->cb_outputMode4->setEnabled(true); + bankLabels << "1 (1-3)" << "2 (4)" << "3 (5,7-8)" << "4 (6,9-10)"; + ChannelBanks << 1 << 1 << 1 << 2 << 3 << 4 << 3 << 3 << 4 << 4; } else if ((board & 0xff00) == 0x0900) { // Revolution family of boards 6 timer banks - ui->chBank1->setText("1-2"); - ui->chBank2->setText("3"); - ui->chBank3->setText("4"); - ui->chBank4->setText("5-6"); - ui->chBank5->setText("7-8"); - ui->chBank6->setText("9-10"); - - ui->cb_outputRate1->setEnabled(true); - ui->cb_outputRate2->setEnabled(true); - ui->cb_outputRate3->setEnabled(true); - ui->cb_outputRate4->setEnabled(true); - ui->cb_outputRate5->setEnabled(true); - ui->cb_outputRate6->setEnabled(true); - - ui->cb_outputMode1->setEnabled(true); - ui->cb_outputMode2->setEnabled(true); - ui->cb_outputMode3->setEnabled(true); - ui->cb_outputMode4->setEnabled(true); - ui->cb_outputMode5->setEnabled(true); - ui->cb_outputMode6->setEnabled(true); + bankLabels << "1 (1-2)" << "2 (3)" << "3 (4)" << "4 (5-6)" << "5 (7-8)" << "6 (9-10)"; + ChannelBanks << 1 << 1 << 2 << 3 << 4 << 4 << 5 << 5 << 6 << 6; } } + i = 0; + foreach(QString banklabel, bankLabels) { + bank[i]->setText(banklabel); + outputRateCombos[i]->setEnabled(true); + setColor(outputRateCombos[i], bankColors[i]); + outputModeCombos[i]->setEnabled(true); + setColor(outputModeCombos[i], bankColors[i]); + i++; + } // Get Channel ranges: + i = 0; foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; outputChannelForm->setRange(minValue, maxValue); - + if (ChannelBanks.count() > i) { + outputChannelForm->setBank(QString("%1:").arg(ChannelBanks.at(i))); + outputChannelForm->setColor(bankColors[ChannelBanks.at(i++) - 1]); + } int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; outputChannelForm->setNeutral(neutral); } diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h index bb1d37c27..3b25fed69 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h @@ -59,6 +59,8 @@ private: void assignOutputChannel(UAVDataObject *obj, QString &str); + void setColor(QWidget *widget, const QColor color); + OutputChannelForm *getOutputChannelForm(const int index) const; void sendAllChannelTests(); diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index b571d6313..74be6ea9a 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -183,7 +183,7 @@ - Channels: + Bank(Channels): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index 0ca1ecaf7..4b8ce22ec 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -34,7 +34,7 @@ OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : // The convention for OP is Channel 1 to Channel 10. ui.actuatorNumber->setText(QString("%1:").arg(index + 1)); - + setBank("-"); // Register for ActuatorSettings changes: connect(ui.actuatorMin, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); connect(ui.actuatorMax, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); @@ -58,6 +58,11 @@ QString OutputChannelForm::name() return ui.actuatorName->text(); } +QString OutputChannelForm::bank() +{ + return ui.actuatorBankNumber->text(); +} + /** * Set the channel assignment label. */ @@ -66,6 +71,27 @@ void OutputChannelForm::setName(const QString &name) ui.actuatorName->setText(name); } +void OutputChannelForm::setColor(const QColor &color) +{ + QPalette p(palette()); + + p.setColor(QPalette::Background, color); + p.setColor(QPalette::Base, color); + p.setBrush(QPalette::Base, Qt::transparent); + ui.actuatorBankNumber->setAutoFillBackground(true); + ui.actuatorNumber->setAutoFillBackground(true); + ui.actuatorBankNumber->setPalette(p); + ui.actuatorNumber->setPalette(p); +} + +/** + * Set the channel bank label. + */ +void OutputChannelForm::setBank(const QString &bank) +{ + ui.actuatorBankNumber->setText(bank); +} + /** * Restrict UI to protect users from accidental misuse. */ diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.h b/ground/openpilotgcs/src/plugins/config/outputchannelform.h index 78d008115..e17155f41 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.h @@ -43,8 +43,12 @@ public: friend class ConfigOutputWidget; virtual QString name(); - virtual void setName(const QString &name); + virtual QString bank(); + virtual void setName(const QString &name); + virtual void setBank(const QString &bank); + + virtual void setColor(const QColor &color); public slots: int min() const; void setMin(int minimum); diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index f6227939a..98bb8958c 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -7,7 +7,7 @@ 0 0 768 - 51 + 54 @@ -29,7 +29,7 @@ 12 - + @@ -72,7 +72,7 @@ margin:1px; - + @@ -115,7 +115,7 @@ margin:1px; - + @@ -152,7 +152,7 @@ margin:1px; - + Qt::Horizontal @@ -217,7 +217,7 @@ margin:1px; - + Qt::Horizontal @@ -233,7 +233,7 @@ margin:1px; - + Qt::Horizontal @@ -249,7 +249,7 @@ margin:1px; - + Qt::Horizontal @@ -265,7 +265,7 @@ margin:1px; - + @@ -322,9 +322,18 @@ margin:1px; 16777215 + + + 75 + true + + Channel Number + + border-radius: 5;\nfont: bold 12px;\nmargin:1px; + 0: @@ -333,7 +342,7 @@ margin:1px; - + @@ -376,7 +385,7 @@ margin:1px; - + @@ -419,7 +428,7 @@ margin:1px; - + @@ -462,7 +471,7 @@ margin:1px; - + @@ -490,7 +499,7 @@ margin:1px; - + @@ -524,8 +533,8 @@ margin:1px; - - + + 0 @@ -607,7 +616,7 @@ margin:1px; - + @@ -665,7 +674,7 @@ margin:1px; - + @@ -726,6 +735,89 @@ margin:1px; + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + Qt::LeftToRight + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Bank + + + Qt::AlignCenter + + + 0 + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + Bank number + + + border-radius: 5;\nfont: 12px;\nmargin:1px; + + + 0 + + + Qt::AlignCenter + + + From 632051c0ac6cd6089dd951fe8a327cd9200955b9 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 29 Jan 2015 21:07:21 +0100 Subject: [PATCH 15/23] OP-1683 - Increase resolution for OneShot125 running timer at 8MHz, setup automatically rates for OneShot --- flight/modules/Actuator/actuator.c | 49 ++++++++++++++++-------------- flight/pios/inc/pios_servo.h | 2 +- flight/pios/posix/pios_servo.c | 8 ++--- flight/pios/stm32f10x/pios_servo.c | 39 ++++++++++-------------- flight/pios/stm32f4xx/pios_servo.c | 15 ++++++--- 5 files changed, 57 insertions(+), 56 deletions(-) diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index c90f8a37e..64ef88662 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -53,20 +53,22 @@ static int8_t counter; #endif // Private constants -#define MAX_QUEUE_SIZE 2 +#define MAX_QUEUE_SIZE 2 #if defined(PIOS_ACTUATOR_STACK_SIZE) -#define STACK_SIZE_BYTES PIOS_ACTUATOR_STACK_SIZE +#define STACK_SIZE_BYTES PIOS_ACTUATOR_STACK_SIZE #else -#define STACK_SIZE_BYTES 1312 +#define STACK_SIZE_BYTES 1312 #endif -#define TASK_PRIORITY (tskIDLE_PRIORITY + 4) // device driver -#define FAILSAFE_TIMEOUT_MS 100 -#define MAX_MIX_ACTUATORS ACTUATORCOMMAND_CHANNEL_NUMELEM +#define TASK_PRIORITY (tskIDLE_PRIORITY + 4) // device driver +#define FAILSAFE_TIMEOUT_MS 100 +#define MAX_MIX_ACTUATORS ACTUATORCOMMAND_CHANNEL_NUMELEM -#define CAMERA_BOOT_DELAY_MS 7000 +#define CAMERA_BOOT_DELAY_MS 7000 +#define ACTUATOR_ONESHOT125_CLOCK 8000000 +#define ACTUATOR_PWM_CLOCK 1000000 // Private types @@ -735,16 +737,8 @@ static bool set_channel(uint8_t mixer_channel, uint16_t value, const ActuatorSet case ACTUATORSETTINGS_CHANNELTYPE_PWM: { - uint8_t mode = pinsMode[actuatorSettings->ChannelAddr[mixer_channel]]; - switch (mode) { - case ACTUATORSETTINGS_BANKMODE_ONESHOT125: - // Quick way to remap of 1000-2000 range to 125-250 - PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value / 8); - break; - default: - PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); - break; - } + // OneShot125 is remapped from 1000-2000 range to 125-250 due to timer running at 8MHz + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); } return true; @@ -790,7 +784,7 @@ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuator sizeof(prevBankMode)); uint16_t freq[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM]; - + uint32_t clock[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM] = { 0 }; for (uint8_t i = 0; i < ACTUATORSETTINGS_BANKMODE_NUMELEM; i++) { PIOS_Servo_SetBankMode(i, actuatorSettings->BankMode[i] == @@ -798,13 +792,22 @@ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuator PIOS_SERVO_BANK_MODE_PWM : PIOS_SERVO_BANK_MODE_SINGLE_PULSE ); - if (actuatorSettings->BankMode[i] == ACTUATORSETTINGS_BANKMODE_ONESHOT125) { - freq[i] = 1000000 / 255; // force a total period of 255uSec - } else { - freq[i] = actuatorSettings->BankUpdateFreq[i]; + switch (actuatorSettings->BankMode[i]) { + case ACTUATORSETTINGS_BANKMODE_ONESHOT125: + freq[i] = 1000; + clock[i] = ACTUATOR_ONESHOT125_CLOCK; // Setup an 8MHz timer clock + break; + case ACTUATORSETTINGS_BANKMODE_ONESHOT: + freq[i] = (PIOS_SENSOR_RATE + PIOS_SENSOR_RATE / 10); // use Sensor rate + a 10% margin to prevent missing updates. + clock[i] = ACTUATOR_PWM_CLOCK; + break; + default: // PWM + freq[i] = actuatorSettings->BankUpdateFreq[i]; + clock[i] = ACTUATOR_PWM_CLOCK; + break; } } - PIOS_Servo_SetHz(freq, ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM); + PIOS_Servo_SetHz(freq, clock, ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM); // retrieve mode from related bank for (uint8_t i = 0; i < MAX_MIX_ACTUATORS; i++) { diff --git a/flight/pios/inc/pios_servo.h b/flight/pios/inc/pios_servo.h index cdbe0b8db..f3e9621ad 100644 --- a/flight/pios/inc/pios_servo.h +++ b/flight/pios/inc/pios_servo.h @@ -36,7 +36,7 @@ enum pios_servo_bank_mode { PIOS_SERVO_BANK_MODE_SINGLE_PULSE = 1 }; /* Public Functions */ -extern void PIOS_Servo_SetHz(const uint16_t *update_rates, uint8_t banks); +extern void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks); extern void PIOS_Servo_Set(uint8_t Servo, uint16_t Position); extern void PIOS_Servo_Update(); extern void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode); diff --git a/flight/pios/posix/pios_servo.c b/flight/pios/posix/pios_servo.c index c3b4ba05b..ae00eaa04 100644 --- a/flight/pios/posix/pios_servo.c +++ b/flight/pios/posix/pios_servo.c @@ -43,13 +43,13 @@ static volatile uint16_t ServoPosition[PIOS_SERVO_NUM_TIMERS]; */ void PIOS_Servo_Init(void) {} - /** * Set the servo update rate (Max 500Hz) - * \param[in] onetofour Rate for outputs 1 to 4 (Hz) - * \param[in] fivetoeight Rate for outputs 5 to 8 (Hz) + * \param[in] array of rates in Hz + * \param[in] array of timer clocks in Hz + * \param[in] maximum number of banks */ -void PIOS_Servo_SetHz(const uint16_t *banks, uint8_t num_banks) +void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks) {} /** diff --git a/flight/pios/stm32f10x/pios_servo.c b/flight/pios/stm32f10x/pios_servo.c index 31cc202cc..f0a11d8e2 100644 --- a/flight/pios/stm32f10x/pios_servo.c +++ b/flight/pios/stm32f10x/pios_servo.c @@ -43,11 +43,12 @@ static const struct pios_servo_cfg *servo_cfg; // static uint8_t pios_servo_bank_mode[PIOS_SERVO_BANKS] = { 0 }; // timer associated to each bank -// static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; +static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; // index of bank used for each pin static uint8_t *pios_servo_pin_bank; +#define PIOS_SERVO_TIMER_CLOCK 1000000 /** * Initialise Servos @@ -81,7 +82,7 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) pios_servo_pin_bank[j] = bank; } } - // pios_servo_bank_timer[i] = chan->timer; + pios_servo_bank_timer[bank] = chan->timer; PIOS_Assert(bank < PIOS_SERVO_BANKS); @@ -90,11 +91,6 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) pios_servo_pin_bank[j] = bank; } } -/* - TIM_ARRPreloadConfig(chan->timer, ENABLE); - TIM_CtrlPWMOutputs(chan->timer, ENABLE); - TIM_Cmd(chan->timer, DISABLE); - */ bank++; } @@ -129,10 +125,12 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) /** * Set the servo update rate (Max 500Hz) * \param[in] array of rates in Hz + * \param[in] array of timer clocks in Hz * \param[in] maximum number of banks */ -void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) +void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks) { + PIOS_Assert(banks <= PIOS_SERVO_BANKS); if (!servo_cfg) { return; } @@ -140,23 +138,18 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->tim_base_init; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1; - uint8_t set = 0; + for (uint8_t i = 0; i < banks && i < PIOS_SERVO_BANKS; i++) { + const TIM_TypeDef *timer = pios_servo_bank_timer[i]; + if (timer) { + uint32_t new_clock = PIOS_SERVO_TIMER_CLOCK; + if (clock[i]) { + new_clock = clock[i]; + } + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / new_clock) - 1; + TIM_TimeBaseStructure.TIM_Period = ((new_clock / speeds[i]) - 1); - for (uint8_t i = 0; (i < servo_cfg->num_channels) && (set < banks); i++) { - bool new = true; - const struct pios_tim_channel *chan = &servo_cfg->channels[i]; - - /* See if any previous channels use that same timer */ - for (uint8_t j = 0; (j < i) && new; j++) { - new &= chan->timer != servo_cfg->channels[j].timer; - } - - if (new) { - TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[set]) - 1); - TIM_TimeBaseInit(chan->timer, &TIM_TimeBaseStructure); - set++; + TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } } } diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index b51974da1..adc76c632 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -193,9 +193,10 @@ void PIOS_Servo_Update() /** * Set the servo update rate (Max 500Hz) * \param[in] array of rates in Hz + * \param[in] array of timer clocks in Hz * \param[in] maximum number of banks */ -void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) +void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks) { PIOS_Assert(banks <= PIOS_SERVO_BANKS); if (!servo_cfg) { @@ -206,17 +207,21 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { + for (uint8_t i = 0; i < banks && i < PIOS_SERVO_BANKS; i++) { const TIM_TypeDef *timer = pios_servo_bank_timer[i]; if (timer) { + uint32_t new_clock = PIOS_SERVO_TIMER_CLOCK; + if (clock[i]) { + new_clock = clock[i]; + } // Choose the correct prescaler value for the APB the timer is attached if (timer == TIM1 || timer == TIM8 || timer == TIM9 || timer == TIM10 || timer == TIM11) { - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / PIOS_SERVO_TIMER_CLOCK) - 1; + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / new_clock) - 1; } else { - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / PIOS_SERVO_TIMER_CLOCK) - 1; + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / new_clock) - 1; } - TIM_TimeBaseStructure.TIM_Period = ((PIOS_SERVO_TIMER_CLOCK / speeds[i]) - 1); + TIM_TimeBaseStructure.TIM_Period = ((new_clock / speeds[i]) - 1); TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } } From 86571a804dfd130999c1a08dc27bdfe44ac64337 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 29 Jan 2015 21:20:29 +0100 Subject: [PATCH 16/23] OP-1683 - Switch to the same schema used by cleanflight. Running in repetitive mode, clearing CCRx after manually triggering update event. --- flight/pios/stm32f4xx/pios_servo.c | 115 +++++++++++------------------ 1 file changed, 45 insertions(+), 70 deletions(-) diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index adc76c632..9f0f2aa08 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -123,59 +123,27 @@ void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) 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]; - switch (mode) { - case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: - /* Set up for output compare function */ - switch (chan->timer_chan) { - case TIM_Channel_1: - TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_2: - TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_3: - TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - case TIM_Channel_4: - TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_Low); - break; - } + + /* Set up for output compare function */ + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_High); break; - case PIOS_SERVO_BANK_MODE_PWM: - /* 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; - } + 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; - default: - PIOS_Assert(false); } } } // Setup the timer accordingly - switch (mode) { - case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: - TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Single); - TIM_CounterModeConfig(pios_servo_bank_timer[bank], TIM_CounterMode_Up); - break; - case PIOS_SERVO_BANK_MODE_PWM: - TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); - TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); - break; - default: - PIOS_Assert(false); - } + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); + TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); } } @@ -184,12 +152,34 @@ void PIOS_Servo_Update() { 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) { + TIM_GenerateEvent((TIM_TypeDef *)timer, TIM_EventSource_Update); + } + } + 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; + } } } } - /** * Set the servo update rate (Max 500Hz) * \param[in] array of rates in Hz @@ -241,26 +231,11 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) /* Update the position */ const struct pios_tim_channel *chan = &servo_cfg->channels[servo]; - - uint8_t bank = pios_servo_pin_bank[servo]; - uint8_t mode = pios_servo_bank_mode[bank]; - uint16_t val; - switch (mode) { - case PIOS_SERVO_BANK_MODE_PWM: - val = position; - break; - case PIOS_SERVO_BANK_MODE_SINGLE_PULSE: - // prevent overflows that causes an output to pass from max to no pulses. - if (position < chan->timer->ARR) { - val = chan->timer->ARR - position; - } else { - val = 1; - } - break; - default: - PIOS_Assert(false); - } - + uint16_t val = position; + /*uint16_t margin = chan->timer->ARR / 20; // Leave 5% of period as margin to prevent overlaps + if (val > (chan->timer->ARR - margin)) { + val = chan->timer->ARR - margin; + }*/ switch (chan->timer_chan) { case TIM_Channel_1: TIM_SetCompare1(chan->timer, val); From 6f3f7b9972b960a9bb1c4fca64be39cfb6ab4f75 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 30 Jan 2015 21:43:59 +0100 Subject: [PATCH 17/23] OP-1683 - fix limits handling and definitions --- .../src/plugins/config/configoutputwidget.cpp | 12 ++++++------ shared/uavobjectdefinition/actuatorsettings.xml | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 8347f45ff..a11e3bb77 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -98,12 +98,12 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren addWidget(ui->cb_outputRate1); addWidget(ui->spinningArmed); - addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode1, 0); - addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode2, 1); - addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode3, 2); - addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode4, 3); - addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode5, 4); - addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode6, 5); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode1, 0, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode2, 1, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode3, 2, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode4, 3, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode5, 4, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode6, 5, 0, true); disconnect(this, SLOT(refreshWidgetsValues(UAVObject *))); diff --git a/shared/uavobjectdefinition/actuatorsettings.xml b/shared/uavobjectdefinition/actuatorsettings.xml index 5b6a5186d..303770f4d 100644 --- a/shared/uavobjectdefinition/actuatorsettings.xml +++ b/shared/uavobjectdefinition/actuatorsettings.xml @@ -3,8 +3,12 @@ Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType From 1d08083375244e30dbae9bfdc5ac905fab51c86d Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 31 Jan 2015 14:40:40 +0100 Subject: [PATCH 18/23] OP-1682 - OneShot125: Change timer clock to 2MHz (that's available as exact value for current targets), raise timer period to prevent glitches --- flight/modules/Actuator/actuator.c | 35 +++++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index 64ef88662..22f3ac830 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -53,22 +53,23 @@ static int8_t counter; #endif // Private constants -#define MAX_QUEUE_SIZE 2 +#define MAX_QUEUE_SIZE 2 #if defined(PIOS_ACTUATOR_STACK_SIZE) -#define STACK_SIZE_BYTES PIOS_ACTUATOR_STACK_SIZE +#define STACK_SIZE_BYTES PIOS_ACTUATOR_STACK_SIZE #else -#define STACK_SIZE_BYTES 1312 +#define STACK_SIZE_BYTES 1312 #endif -#define TASK_PRIORITY (tskIDLE_PRIORITY + 4) // device driver -#define FAILSAFE_TIMEOUT_MS 100 -#define MAX_MIX_ACTUATORS ACTUATORCOMMAND_CHANNEL_NUMELEM +#define TASK_PRIORITY (tskIDLE_PRIORITY + 4) // device driver +#define FAILSAFE_TIMEOUT_MS 100 +#define MAX_MIX_ACTUATORS ACTUATORCOMMAND_CHANNEL_NUMELEM -#define CAMERA_BOOT_DELAY_MS 7000 +#define CAMERA_BOOT_DELAY_MS 7000 -#define ACTUATOR_ONESHOT125_CLOCK 8000000 -#define ACTUATOR_PWM_CLOCK 1000000 +#define ACTUATOR_ONESHOT125_CLOCK 2000000 +#define ACTUATOR_ONESHOT125_PULSE_SCALE 4 +#define ACTUATOR_PWM_CLOCK 1000000 // Private types @@ -737,10 +738,18 @@ static bool set_channel(uint8_t mixer_channel, uint16_t value, const ActuatorSet case ACTUATORSETTINGS_CHANNELTYPE_PWM: { - // OneShot125 is remapped from 1000-2000 range to 125-250 due to timer running at 8MHz - PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); - } + uint8_t mode = pinsMode[actuatorSettings->ChannelAddr[mixer_channel]]; + switch (mode) { + case ACTUATORSETTINGS_BANKMODE_ONESHOT125: + // Remap 1000-2000 range to 125-250 + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value / ACTUATOR_ONESHOT125_PULSE_SCALE); + break; + default: + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); + break; + } return true; + } #if defined(PIOS_INCLUDE_I2C_ESC) case ACTUATORSETTINGS_CHANNELTYPE_MK: @@ -794,7 +803,7 @@ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuator ); switch (actuatorSettings->BankMode[i]) { case ACTUATORSETTINGS_BANKMODE_ONESHOT125: - freq[i] = 1000; + 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: From a5f601593def287395e36b1c9d92fada4ce9447f Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 31 Jan 2015 15:04:02 +0100 Subject: [PATCH 19/23] OP-1683 - Put again in place safe limits on pulse width --- flight/pios/stm32f4xx/pios_servo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 9f0f2aa08..f22e05ad1 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -231,11 +231,11 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) /* Update the position */ const struct pios_tim_channel *chan = &servo_cfg->channels[servo]; - uint16_t val = position; - /*uint16_t margin = chan->timer->ARR / 20; // Leave 5% of period as margin to prevent overlaps - if (val > (chan->timer->ARR - margin)) { + 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; - }*/ + } switch (chan->timer_chan) { case TIM_Channel_1: TIM_SetCompare1(chan->timer, val); From a7caee7bc4cc8e153f557f140835b23ddb2fca96 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 1 Feb 2015 21:27:25 +0100 Subject: [PATCH 20/23] OP-1683 - update tooltips, small UI changes --- .../src/plugins/config/configoutputwidget.cpp | 16 +- .../openpilotgcs/src/plugins/config/output.ui | 52 ++-- .../src/plugins/config/outputchannelform.cpp | 16 +- .../src/plugins/config/outputchannelform.ui | 245 ++++++++++-------- 4 files changed, 188 insertions(+), 141 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index a11e3bb77..a053c55f2 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -252,9 +252,11 @@ void ConfigOutputWidget::sendChannelTest(int index, int value) void ConfigOutputWidget::setColor(QWidget *widget, const QColor color) { QPalette p(palette()); - QColor color2 = QColor(color); - p.setColor(QPalette::Background, color2); + p.setColor(QPalette::Background, color); + p.setColor(QPalette::Base, color); + p.setColor(QPalette::Active, QPalette::Button, color); + p.setColor(QPalette::Inactive, QPalette::Button, color); widget->setAutoFillBackground(true); widget->setPalette(p); } @@ -283,7 +285,13 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) QList ChannelBanks; QList bankColors; - bankColors << Qt::magenta << Qt::yellow << Qt::green << Qt::cyan << Qt::red << Qt::darkCyan; + bankColors + << QColor("#C6ECAE") + << QColor("#91E5D3") + << QColor("#FCEC52") + << QColor("#C3A8FF") + << QColor("#F7F7F2") + << QColor("#FF9F51"); // Initialize output forms QList outputChannelForms = findChildren(); foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { @@ -390,7 +398,7 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) outputChannelForm->setRange(minValue, maxValue); if (ChannelBanks.count() > i) { - outputChannelForm->setBank(QString("%1:").arg(ChannelBanks.at(i))); + outputChannelForm->setBank(QString("%1").arg(ChannelBanks.at(i))); outputChannelForm->setColor(bankColors[ChannelBanks.at(i++) - 1]); } int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index 74be6ea9a..f804aab1d 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -282,9 +282,15 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + false + + + + 50 @@ -345,8 +351,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -430,8 +438,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -493,8 +503,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -566,8 +578,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -629,8 +643,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -742,7 +758,9 @@ - Setup output mode. standard ESCs uses PWM. + 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). @@ -764,7 +782,7 @@ - Setup output mode. standard ESCs uses PWM. + 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). @@ -786,7 +804,7 @@ - Setup output mode. standard ESCs uses PWM. + 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). @@ -808,7 +826,7 @@ - Setup output mode. standard ESCs uses PWM. + 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). @@ -830,7 +848,7 @@ - Setup output mode. standard ESCs uses PWM. + 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). @@ -852,7 +870,7 @@ - Setup output mode. standard ESCs uses PWM. + 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). diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index 4b8ce22ec..8732aa43d 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -33,7 +33,7 @@ OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : ui.setupUi(this); // The convention for OP is Channel 1 to Channel 10. - ui.actuatorNumber->setText(QString("%1:").arg(index + 1)); + ui.actuatorNumber->setText(QString("%1").arg(index + 1)); setBank("-"); // Register for ActuatorSettings changes: connect(ui.actuatorMin, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); @@ -73,15 +73,13 @@ void OutputChannelForm::setName(const QString &name) void OutputChannelForm::setColor(const QColor &color) { - QPalette p(palette()); + QString stylesheet = ui.actuatorNumberFrame->styleSheet(); - p.setColor(QPalette::Background, color); - p.setColor(QPalette::Base, color); - p.setBrush(QPalette::Base, Qt::transparent); - ui.actuatorBankNumber->setAutoFillBackground(true); - ui.actuatorNumber->setAutoFillBackground(true); - ui.actuatorBankNumber->setPalette(p); - ui.actuatorNumber->setPalette(p); + stylesheet = stylesheet.split("background-color").first(); + stylesheet.append( + QString("background-color: rgb(%1, %2, %3)") + .arg(color.red()).arg(color.green()).arg(color.blue())); + ui.actuatorNumberFrame->setStyleSheet(stylesheet); } /** diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index 98bb8958c..459841ace 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -168,7 +168,7 @@ margin:1px; - + @@ -207,7 +207,7 @@ font: bold 12px; margin:1px; - # + # - Bank Qt::AlignCenter @@ -289,7 +289,8 @@ margin:1px; Qt::StrongFocus - Minimum PWM value, beware of not overdriving your servo. + Minimum PWM value, beware of not overdriving your servo. +Using OneShot125 a value of 1000(uS) here will produce a pulse of 125(uS). Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -302,44 +303,148 @@ margin:1px; - - + + 0 0 - - - 20 - 0 - - - 16777215 - 16777215 + 100 + 22 - - - 75 - true - - - - Channel Number - - border-radius: 5;\nfont: bold 12px;\nmargin:1px; + border-radius: 5; margin:1px; - - 0: + + QFrame::NoFrame - - Qt::AlignCenter + + QFrame::Raised + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + Channel Number + + + border-radius: 5;\nfont: bold 12px;\nmargin:1px; + + + 0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + border-radius: 5;\nfont: 12px;\nmargin:1px; + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + Bank number + + + border-radius: 5;\nfont: 12px;\nmargin:1px; + + + 0 + + + Qt::AlignCenter + + + + @@ -523,7 +628,8 @@ margin:1px; Qt::StrongFocus - Maximum PWM value, beware of not overdriving your servo. + Maximum value, beware of not overdriving your servo. +Using OneShot125 a value of 2000(uS) here will produce a pulse of 250(uS). Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -735,89 +841,6 @@ margin:1px; - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - Qt::LeftToRight - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Bank - - - Qt::AlignCenter - - - 0 - - - - - - - - 0 - 0 - - - - - 20 - 0 - - - - - 16777215 - 16777215 - - - - Bank number - - - border-radius: 5;\nfont: 12px;\nmargin:1px; - - - 0 - - - Qt::AlignCenter - - - From 752f3447d2489cf6c0c4508bd72a970b0805257f Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 2 Feb 2015 02:58:22 +0100 Subject: [PATCH 21/23] OP-1683 - Implement an update skip strategy in single pulse mode when pulse period is higher than the update cycle --- flight/modules/Actuator/actuator.c | 2 +- flight/pios/stm32f4xx/pios_servo.c | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index 22f3ac830..891537bd6 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -807,7 +807,7 @@ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuator clock[i] = ACTUATOR_ONESHOT125_CLOCK; // Setup an 8MHz timer clock break; case ACTUATORSETTINGS_BANKMODE_ONESHOT: - freq[i] = (PIOS_SENSOR_RATE + PIOS_SENSOR_RATE / 10); // use Sensor rate + a 10% margin to prevent missing updates. + freq[i] = 100; clock[i] = ACTUATOR_PWM_CLOCK; break; default: // PWM diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index f22e05ad1..4eda9eae5 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -41,7 +41,9 @@ 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 }; - +// 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 */ @@ -123,7 +125,6 @@ void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) 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: @@ -141,6 +142,11 @@ 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); @@ -153,7 +159,12 @@ void PIOS_Servo_Update() for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { const TIM_TypeDef *timer = pios_servo_bank_timer[i]; if (timer && pios_servo_bank_mode[i] == PIOS_SERVO_BANK_MODE_SINGLE_PULSE) { - TIM_GenerateEvent((TIM_TypeDef *)timer, TIM_EventSource_Update); + // 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++) { @@ -210,7 +221,6 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t ban } else { TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / new_clock) - 1; } - TIM_TimeBaseStructure.TIM_Period = ((new_clock / speeds[i]) - 1); TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } @@ -229,6 +239,7 @@ 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; @@ -236,6 +247,11 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) 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, val); From 86a1ca2bcf32b1981daa5527161984c7caa9e7cc Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 2 Feb 2015 19:58:04 +0100 Subject: [PATCH 22/23] OP-1683 - Pulse length must be zeroed at each cycle --- flight/pios/stm32f4xx/pios_servo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 4eda9eae5..7e66c09e2 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -163,9 +163,9 @@ void PIOS_Servo_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; } } + 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]; From 09319c38056c685a07ac5ed6def139e1dba47c8b Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 2 Feb 2015 20:35:39 +0100 Subject: [PATCH 23/23] OP-1683 - fix casing and cleanup of gcs code --- .../src/plugins/config/configoutputwidget.cpp | 77 +++++++------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index a053c55f2..f1a767614 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -281,9 +281,9 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData(); // Get channel descriptions - QStringList ChannelDesc = ConfigVehicleTypeWidget::getChannelDescriptions(); + QStringList channelDesc = ConfigVehicleTypeWidget::getChannelDescriptions(); - QList ChannelBanks; + QList channelBanks; QList bankColors; bankColors << QColor("#C6ECAE") @@ -292,10 +292,11 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) << QColor("#C3A8FF") << QColor("#F7F7F2") << QColor("#FF9F51"); + // Initialize output forms QList outputChannelForms = findChildren(); foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { - outputChannelForm->setName(ChannelDesc[outputChannelForm->index()]); + outputChannelForm->setName(channelDesc[outputChannelForm->index()]); // init min,max,neutral int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; @@ -309,34 +310,9 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) // Get the SpinWhileArmed setting ui->spinningArmed->setChecked(actuatorSettingsData.MotorsSpinWhileArmed == ActuatorSettings::MOTORSSPINWHILEARMED_TRUE); - // Setup output rates for all banks - if (ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.BankUpdateFreq[0])) == -1) { - ui->cb_outputRate1->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[0])); - } - if (ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.BankUpdateFreq[1])) == -1) { - ui->cb_outputRate2->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[1])); - } - if (ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.BankUpdateFreq[2])) == -1) { - ui->cb_outputRate3->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[2])); - } - if (ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.BankUpdateFreq[3])) == -1) { - ui->cb_outputRate4->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[3])); - } - if (ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.BankUpdateFreq[4])) == -1) { - ui->cb_outputRate5->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[4])); - } - if (ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.BankUpdateFreq[5])) == -1) { - ui->cb_outputRate6->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[5])); - } - ui->cb_outputRate1->setCurrentIndex(ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.BankUpdateFreq[0]))); - ui->cb_outputRate2->setCurrentIndex(ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.BankUpdateFreq[1]))); - ui->cb_outputRate3->setCurrentIndex(ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.BankUpdateFreq[2]))); - ui->cb_outputRate4->setCurrentIndex(ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.BankUpdateFreq[3]))); - ui->cb_outputRate5->setCurrentIndex(ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.BankUpdateFreq[4]))); - ui->cb_outputRate6->setCurrentIndex(ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.BankUpdateFreq[5]))); - QList bank; bank << ui->chBank1 << ui->chBank2 << ui->chBank3 << ui->chBank4 << ui->chBank5 << ui->chBank6; + QList outputRateCombos; outputRateCombos << ui->cb_outputRate1 << ui->cb_outputRate2 << ui->cb_outputRate3 << ui->cb_outputRate4 << ui->cb_outputRate5 << ui->cb_outputRate6; @@ -344,20 +320,25 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) QList outputModeCombos; outputModeCombos << ui->cb_outputMode1 << ui->cb_outputMode2 << ui->cb_outputMode3 << ui->cb_outputMode4 << ui->cb_outputMode5 << ui->cb_outputMode6; - // Reset to all disabled - foreach(QLabel * label, bank) { - label->setText("-"); - } - int i = 0; - foreach(QComboBox * cbo, outputRateCombos) { - cbo->setEnabled(false); - setColor(cbo, palette().color(QPalette::Background)); - } - i = 0; - foreach(QComboBox * cbo, outputModeCombos) { - cbo->setEnabled(false); - setColor(cbo, palette().color(QPalette::Background)); + Q_ASSERT(outputModeCombos.count() == outputRateCombos.count()); + Q_ASSERT(outputRateCombos.count() == bank.count()); + + for(int i = 0; i < outputModeCombos.count();i++){ + // Setup output rates for all banks + if (outputRateCombos.at(i)->findText(QString::number(actuatorSettingsData.BankUpdateFreq[i])) == -1) { + outputRateCombos.at(i)->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[i])); + } + outputRateCombos.at(i)->setCurrentIndex(outputRateCombos.at(i)->findText(QString::number(actuatorSettingsData.BankUpdateFreq[i]))); + + // Reset to all disabled + bank.at(i)->setText("-"); + + outputRateCombos.at(i)->setEnabled(false); + setColor(outputRateCombos.at(i), palette().color(QPalette::Background)); + + outputModeCombos.at(i)->setEnabled(false); + setColor(outputModeCombos.at(i), palette().color(QPalette::Background)); } // Get connected board model @@ -373,15 +354,15 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) if ((board & 0xff00) == 0x0400) { // Coptercontrol family of boards 4 timer banks bankLabels << "1 (1-3)" << "2 (4)" << "3 (5,7-8)" << "4 (6,9-10)"; - ChannelBanks << 1 << 1 << 1 << 2 << 3 << 4 << 3 << 3 << 4 << 4; + channelBanks << 1 << 1 << 1 << 2 << 3 << 4 << 3 << 3 << 4 << 4; } else if ((board & 0xff00) == 0x0900) { // Revolution family of boards 6 timer banks bankLabels << "1 (1-2)" << "2 (3)" << "3 (4)" << "4 (5-6)" << "5 (7-8)" << "6 (9-10)"; - ChannelBanks << 1 << 1 << 2 << 3 << 4 << 4 << 5 << 5 << 6 << 6; + channelBanks << 1 << 1 << 2 << 3 << 4 << 4 << 5 << 5 << 6 << 6; } } - i = 0; + int i = 0; foreach(QString banklabel, bankLabels) { bank[i]->setText(banklabel); outputRateCombos[i]->setEnabled(true); @@ -397,9 +378,9 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; outputChannelForm->setRange(minValue, maxValue); - if (ChannelBanks.count() > i) { - outputChannelForm->setBank(QString("%1").arg(ChannelBanks.at(i))); - outputChannelForm->setColor(bankColors[ChannelBanks.at(i++) - 1]); + if (channelBanks.count() > i) { + outputChannelForm->setBank(QString("%1").arg(channelBanks.at(i))); + outputChannelForm->setColor(bankColors[channelBanks.at(i++) - 1]); } int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; outputChannelForm->setNeutral(neutral);