1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-21 11:54:15 +01:00

OP-1216 added new mixer output type "reversable motor" to have engines which can can backwards go to a safe level when disarmed

This commit is contained in:
Corvus Corax 2014-03-09 01:37:22 +01:00
parent be9f4b958d
commit 148b453aad
6 changed files with 46 additions and 25 deletions

View File

@ -283,8 +283,14 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR); AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR);
bool positiveThrottle = throttleDesired >= 0.00f; bool activeThrottle;
bool spinWhileArmed = actuatorSettings.MotorsSpinWhileArmed == ACTUATORSETTINGS_MOTORSSPINWHILEARMED_TRUE; // note: throttle==0 is an inactive throttle and turns motors off
if (allowReverseThrottle == SYSTEMSETTINGS_ALLOWREVERSETHROTTLE_TRUE) {
activeThrottle = throttleDesired > 0.00f || throttleDesired < 0.00f;
} else {
activeThrottle = throttleDesired > 0.00f;
}
bool spinWhileArmed = actuatorSettings.MotorsSpinWhileArmed == ACTUATORSETTINGS_MOTORSSPINWHILEARMED_TRUE;
float curve1 = MixerCurve(throttleDesired, mixerSettings.ThrottleCurve1, MIXERSETTINGS_THROTTLECURVE1_NUMELEM); float curve1 = MixerCurve(throttleDesired, mixerSettings.ThrottleCurve1, MIXERSETTINGS_THROTTLECURVE1_NUMELEM);
@ -338,7 +344,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
continue; continue;
} }
if ((mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) || (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_SERVO)) { if ((mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) || (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_REVERSABLEMOTOR) || (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_SERVO)) {
status[ct] = ProcessMixer(ct, curve1, curve2, &mixerSettings, &desired, dTSeconds); status[ct] = ProcessMixer(ct, curve1, curve2, &mixerSettings, &desired, dTSeconds);
} else { } else {
status[ct] = -1; status[ct] = -1;
@ -348,18 +354,28 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
if (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) { if (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) {
// If not armed or motors aren't meant to spin all the time // If not armed or motors aren't meant to spin all the time
if (!armed || if (!armed ||
(!spinWhileArmed && !positiveThrottle)) { (!spinWhileArmed && !activeThrottle)) {
filterAccumulator[ct] = 0; filterAccumulator[ct] = 0;
lastResult[ct] = 0; lastResult[ct] = 0;
status[ct] = -1; // force min throttle status[ct] = -1; // force min throttle
} }
// If armed meant to keep spinning, // If armed meant to keep spinning,
else if ((spinWhileArmed && !positiveThrottle) || else if ((spinWhileArmed && !activeThrottle) ||
(status[ct] < 0)) { (status[ct] < 0)) {
status[ct] = 0; status[ct] = 0;
} }
} }
// Reversable Motors are like Motors but go to neutral instead of minimum
if (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_REVERSABLEMOTOR) {
// If not armed or motor is inactive - no "spinwhilearmed" for this engine type
if (!armed || !activeThrottle) {
filterAccumulator[ct] = 0;
lastResult[ct] = 0;
status[ct] = 0; // force neutral throttle
}
}
// If an accessory channel is selected for direct bypass mode // If an accessory channel is selected for direct bypass mode
// In this configuration the accessory channel is scaled and mapped // In this configuration the accessory channel is scaled and mapped
// directly to output. Note: THERE IS NO SAFETY CHECK HERE FOR ARMING // directly to output. Note: THERE IS NO SAFETY CHECK HERE FOR ARMING
@ -462,6 +478,7 @@ float ProcessMixer(const int index, const float curve1, const float curve2,
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH] / 128.0f) * desired->Pitch) + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH] / 128.0f) * desired->Pitch) +
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW] / 128.0f) * desired->Yaw); (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW] / 128.0f) * desired->Yaw);
// note: no feedforward for reversable motors yet for safety reasons
if (mixer->type == MIXERSETTINGS_MIXER1TYPE_MOTOR) { if (mixer->type == MIXERSETTINGS_MIXER1TYPE_MOTOR) {
if (result < 0.0f) { // idle throttle if (result < 0.0f) { // idle throttle
result = 0.0f; result = 0.0f;
@ -580,7 +597,7 @@ static void setFailsafe(const ActuatorSettingsData *actuatorSettings, const Mixe
for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n) { for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n) {
if (mixers[n].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) { if (mixers[n].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) {
Channel[n] = actuatorSettings->ChannelMin[n]; Channel[n] = actuatorSettings->ChannelMin[n];
} else if (mixers[n].type == MIXERSETTINGS_MIXER1TYPE_SERVO) { } else if (mixers[n].type == MIXERSETTINGS_MIXER1TYPE_SERVO || mixers[n].type == MIXERSETTINGS_MIXER1TYPE_REVERSABLEMOTOR) {
Channel[n] = actuatorSettings->ChannelNeutral[n]; Channel[n] = actuatorSettings->ChannelNeutral[n];
} else { } else {
Channel[n] = 0; Channel[n] = 0;

View File

@ -181,6 +181,8 @@ QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
} else if (q->currentText() == "Motor") { } else if (q->currentText() == "Motor") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
} else if (q->currentText() == "ReversableMotor") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
} else if (q->currentText() == "Servo") { } else if (q->currentText() == "Servo") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
} else if (q->currentText() == "CameraRoll") { } else if (q->currentText() == "CameraRoll") {

View File

@ -321,7 +321,7 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeTyp
// motor // motor
int channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1; int channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
@ -371,13 +371,13 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeT
// left motor // left motor
int channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1; int channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
// right motor // right motor
channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1; channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
@ -424,11 +424,11 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1; channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1; channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127);
// Output success message // Output success message

View File

@ -42,7 +42,7 @@ VehicleConfig::VehicleConfig(QWidget *parent) : ConfigTaskWidget(parent)
channelNames << QString("Channel%1").arg(i + 1); channelNames << QString("Channel%1").arg(i + 1);
} }
mixerTypeDescriptions << "Disabled" << "Motor" << "Servo" << "CameraRoll" << "CameraPitch" << "CameraYaw" mixerTypeDescriptions << "Disabled" << "Motor" << "ReversableMotor" << "Servo" << "CameraRoll" << "CameraPitch" << "CameraYaw"
<< "Accessory0" << "Accessory1" << "Accessory2" << "Accessory3" << "Accessory4" << "Accessory5"; << "Accessory0" << "Accessory1" << "Accessory2" << "Accessory3" << "Accessory4" << "Accessory5";
// This is needed because new style tries to compact things as much as possible in grid // This is needed because new style tries to compact things as much as possible in grid
@ -224,7 +224,7 @@ void VehicleConfig::resetMotorAndServoMixers(UAVDataObject *mixer)
{ {
for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) { for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
QString type = getMixerType(mixer, channel); QString type = getMixerType(mixer, channel);
if ((type == "Disabled") || (type == "Motor") || (type == "Servo")) { if ((type == "Disabled") || (type == "Motor") || (type == "ReversableMotor") || (type == "Servo")) {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
resetMixerVector(mixer, channel); resetMixerVector(mixer, channel);
} }

View File

@ -121,18 +121,19 @@ public:
/* Enumeration options for field MixerType */ /* Enumeration options for field MixerType */
typedef enum { typedef enum {
MIXERTYPE_DISABLED = 0, MIXERTYPE_DISABLED = 0,
MIXERTYPE_MOTOR = 1, MIXERTYPE_MOTOR = 1,
MIXERTYPE_SERVO = 2, MIXERTYPE_REVERSABLEMOTOR = 2,
MIXERTYPE_CAMERAROLL = 3, MIXERTYPE_SERVO = 3,
MIXERTYPE_CAMERAPITCH = 4, MIXERTYPE_CAMERAROLL = 4,
MIXERTYPE_CAMERAYAW = 5, MIXERTYPE_CAMERAPITCH = 5,
MIXERTYPE_ACCESSORY0 = 6, MIXERTYPE_CAMERAYAW = 6,
MIXERTYPE_ACCESSORY1 = 7, MIXERTYPE_ACCESSORY0 = 7,
MIXERTYPE_ACCESSORY2 = 8, MIXERTYPE_ACCESSORY1 = 8,
MIXERTYPE_ACCESSORY3 = 9, MIXERTYPE_ACCESSORY2 = 9,
MIXERTYPE_ACCESSORY4 = 10, MIXERTYPE_ACCESSORY3 = 10,
MIXERTYPE_ACCESSORY5 = 11 MIXERTYPE_ACCESSORY4 = 11,
MIXERTYPE_ACCESSORY5 = 12
} MixerTypeElem; } MixerTypeElem;
/* Array element names for field MixerVector */ /* Array element names for field MixerVector */

View File

@ -26,6 +26,7 @@
<options> <options>
<option>Disabled</option> <option>Disabled</option>
<option>Motor</option> <option>Motor</option>
<option>ReversableMotor</option>
<option>Servo</option> <option>Servo</option>
<option>CameraRollOrServo1</option> <option>CameraRollOrServo1</option>
<option>CameraPitchOrServo2</option> <option>CameraPitchOrServo2</option>