1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-19 14:25:16 +03:00

add mixer_profile.h

This commit is contained in:
shota 2022-11-07 23:29:43 +09:00
parent 88e923122e
commit a9f8ebd5ff
21 changed files with 219 additions and 102 deletions

View file

@ -310,8 +310,6 @@ main_sources(COMMON_SRC
flight/rate_dynamics.h
flight/mixer.c
flight/mixer.h
flight/output_profile.c
flight/output_profile.h
flight/pid.c
flight/pid.h
flight/pid_autotune.c
@ -321,6 +319,8 @@ main_sources(COMMON_SRC
flight/rth_estimator.h
flight/servos.c
flight/servos.h
flight/mixer_profile.c
flight/mixer_profile.h
flight/wind_estimator.c
flight/wind_estimator.h
flight/gyroanalyse.c

View file

@ -31,6 +31,7 @@
#include "build/version.h"
#include "flight/mixer_profile.h"
#include "flight/mixer.h"
#include "flight/servos.h"

View file

@ -381,7 +381,6 @@ bool pwmMotorAndServoInit(void)
// Build temporary timer mappings for motor and servo
pwmBuildTimerOutputList(&timOutputs, isMixerUsingServos());
resetAllocatedOutputPortCount();
// At this point we have built tables of timers suitable for motor and servo mappings
// Now we can actually initialize them according to motor/servo count from mixer
pwmInitMotors(&timOutputs);
@ -389,3 +388,12 @@ bool pwmMotorAndServoInit(void)
return (pwmInitError == PWM_INIT_ERROR_NONE);
}
bool pwmMotorAndServoHotInit(timMotorServoHardware_t* timOutputs)
{
resetAllocatedOutputPortCount();
pwmInitMotors(timOutputs);
pwmInitServos(timOutputs);
return (pwmInitError == PWM_INIT_ERROR_NONE);
}

View file

@ -19,7 +19,7 @@
#include "drivers/io_types.h"
#include "drivers/timer.h"
#include "flight/mixer.h"
#include "flight/mixer_profile.h"
#include "flight/servos.h"
#if defined(TARGET_MOTOR_COUNT)
@ -79,8 +79,9 @@ typedef struct {
bool isDSHOT;
} motorProtocolProperties_t;
void pwmBuildTimerOutputList(timMotorServoHardware_t * timOutputs, bool isMixerUsingServos)
void pwmBuildTimerOutputList(timMotorServoHardware_t * timOutputs, bool isMixerUsingServos);
bool pwmMotorAndServoInit(void);
bool pwmMotorAndServoHotInit(timMotorServoHardware_t* timOutputs);
const motorProtocolProperties_t * getMotorProtocolProperties(motorPwmProtocolTypes_e proto);
pwmInitError_e getPwmInitError(void);
const char * getPwmInitErrorMessage(void);

View file

@ -81,7 +81,8 @@ bool cliMode = false;
#include "flight/failsafe.h"
#include "flight/imu.h"
#include "flight/mixer.h"
// #include "flight/mixer.h"
#include "flight/mixer_profile.h"
#include "flight/pid.h"
#include "flight/servos.h"
@ -282,7 +283,8 @@ typedef enum {
DUMP_MASTER = (1 << 0),
DUMP_PROFILE = (1 << 1),
DUMP_BATTERY_PROFILE = (1 << 2),
DUMP_RATES = (1 << 3),
// DUMP_RATES = (1 << 3),
DUMP_MIXER_PROFILE = (1 << 3),
DUMP_ALL = (1 << 4),
DO_DIFF = (1 << 5),
SHOW_DEFAULTS = (1 << 6),
@ -3567,6 +3569,8 @@ static void printConfig(const char *cmdline, bool doDiff)
dumpMask = DUMP_PROFILE; // only
} else if ((options = checkCommand(cmdline, "battery_profile"))) {
dumpMask = DUMP_BATTERY_PROFILE; // only
} else if ((options = checkCommand(cmdline, "mixer_profile"))) {
dumpMask = DUMP_MIXER_PROFILE; // only
} else if ((options = checkCommand(cmdline, "all"))) {
dumpMask = DUMP_ALL; // all profiles and rates
} else {
@ -3712,6 +3716,9 @@ static void printConfig(const char *cmdline, bool doDiff)
for (int ii = 0; ii < MAX_BATTERY_PROFILE_COUNT; ++ii) {
cliDumpBatteryProfile(ii, dumpMask);
}
for (int ii = 0; ii < MAX_MIXER_PROFILE_COUNT; ++ii) {
cliDumpMixerProfile(ii, dumpMask);
}
setConfigProfile(currentProfileIndexSave);
setConfigBatteryProfile(currentBatteryProfileIndexSave);
@ -3726,6 +3733,7 @@ static void printConfig(const char *cmdline, bool doDiff)
// dump just the current profiles
cliDumpProfile(getConfigProfile(), dumpMask);
cliDumpBatteryProfile(getConfigBatteryProfile(), dumpMask);
cliDumpMixerProfile(getConfigMixerProfile(), dumpMask);
}
}
@ -3737,6 +3745,10 @@ static void printConfig(const char *cmdline, bool doDiff)
cliDumpBatteryProfile(getConfigBatteryProfile(), dumpMask);
}
if (dumpMask & DUMP_MIXER_PROFILE) {
cliDumpMixerProfile(getConfigMixerProfile(), dumpMask);
}
if ((dumpMask & DUMP_MASTER) || (dumpMask & DUMP_ALL)) {
cliPrintHashLine("save configuration\r\nsave");
}

View file

@ -82,6 +82,7 @@ FILE_COMPILE_FOR_SPEED
#include "telemetry/telemetry.h"
#include "flight/mixer_profile.h"
#include "flight/mixer.h"
#include "flight/servos.h"
#include "flight/pid.h"

View file

@ -73,6 +73,7 @@
#include "flight/failsafe.h"
#include "flight/imu.h"
#include "flight/mixer_profile.h"
#include "flight/mixer.h"
#include "flight/pid.h"
#include "flight/servos.h"

View file

@ -30,6 +30,7 @@
#include "fc/fc_msp_box.h"
#include "fc/runtime_config.h"
#include "flight/mixer.h"
#include "flight/mixer_profile.h"
#include "io/osd.h"

View file

@ -1148,33 +1148,35 @@ groups:
- name: PG_MIXER_PROFILE
type: mixerProfile_t
headers: ["flight/mixer.h","flight/mixer_profile.h"]
value_type: MIXER_CONFIG_VALUE
members:
- name: motor_direction_inverted
description: "Use if you need to inverse yaw motor direction."
default_value: OFF
field: motorDirectionInverted
field: mixer_config.motorDirectionInverted
type: bool
- name: platform_type
description: "Defines UAV platform type. Allowed values: \"MULTIROTOR\", \"AIRPLANE\", \"HELICOPTER\", \"TRICOPTER\", \"ROVER\", \"BOAT\". Currently only MULTIROTOR, AIRPLANE and TRICOPTER types are implemented"
default_value: "MULTIROTOR"
field: platformType
field: mixer_config.platformType
type: uint8_t
table: platform_type
- name: has_flaps
description: "Defines is UAV is capable of having flaps. If ON and AIRPLANE `platform_type` is used, **FLAPERON** flight mode will be available for the pilot"
default_value: OFF
field: hasFlaps
field: mixer_config.hasFlaps
type: bool
- name: model_preview_type
description: "ID of mixer preset applied in a Configurator. **Do not modify manually**. Used only for backup/restore reasons."
default_value: -1
field: appliedMixerPreset
field: mixer_config.appliedMixerPreset
min: -1
max: INT16_MAX
- name: output_mode
description: "Output function assignment mode. AUTO assigns outputs according to the default mapping, SERVOS assigns all outputs to servos, MOTORS assigns all outputs to motors"
default_value: "AUTO"
field: outputMode
field: mixer_config.outputMode
table: output_mode
- name: PG_REVERSIBLE_MOTORS_CONFIG

View file

@ -83,24 +83,24 @@ PG_RESET_TEMPLATE(reversibleMotorsConfig_t, reversibleMotorsConfig,
.deadband_high = SETTING_3D_DEADBAND_HIGH_DEFAULT,
.neutral = SETTING_3D_NEUTRAL_DEFAULT
);
PG_REGISTER_ARRAY_WITH_RESET_FN(mixerProfile_t, MAX_MIXER_PROFILE_COUNT, mixerProfiles, PG_MIXER_PROFILE, 1);
// PG_REGISTER_ARRAY_WITH_RESET_FN(mixerProfile_t, MAX_MIXER_PROFILE_COUNT, mixerProfiles, PG_MIXER_PROFILE, 1);
void pgResetFn_mixerProfiles(mixerProfile_t *instance)
{
for (int i = 0; i < MAX_MIXER_PROFILE_COUNT; i++) {
RESET_CONFIG(mixerProfile_t, &instance[i],
.motorDirectionInverted = SETTING_MOTOR_DIRECTION_INVERTED_DEFAULT,
.platformType = SETTING_PLATFORM_TYPE_DEFAULT,
.hasFlaps = SETTING_HAS_FLAPS_DEFAULT,
.appliedMixerPreset = SETTING_MODEL_PREVIEW_TYPE_DEFAULT, //This flag is not available in CLI and used by Configurator only
.outputMode = SETTING_OUTPUT_MODE_DEFAULT,
);
motorMixer_t tmp_mixer = {.throttle=0,.roll=0,.pitch=0,.yaw=0};
for (int j = 0; j < MAX_SUPPORTED_MOTORS; j++) {
instance->MotorMixer[j] = tmp_mixer;
}
}
}
// void pgResetFn_mixerProfiles(mixerProfile_t *instance)
// {
// for (int i = 0; i < MAX_MIXER_PROFILE_COUNT; i++) {
// RESET_CONFIG(mixerProfile_t, &instance[i],
// .motorDirectionInverted = SETTING_MOTOR_DIRECTION_INVERTED_DEFAULT,
// .platformType = SETTING_PLATFORM_TYPE_DEFAULT,
// .hasFlaps = SETTING_HAS_FLAPS_DEFAULT,
// .appliedMixerPreset = SETTING_MODEL_PREVIEW_TYPE_DEFAULT, //This flag is not available in CLI and used by Configurator only
// .outputMode = SETTING_OUTPUT_MODE_DEFAULT,
// );
// motorMixer_t tmp_mixer = {.throttle=0,.roll=0,.pitch=0,.yaw=0};
// for (int j = 0; j < MAX_SUPPORTED_MOTORS; j++) {
// instance->MotorMixer[j] = tmp_mixer;
// }
// }
// }
// PG_REGISTER_WITH_RESET_TEMPLATE(mixerConfig_t, mixerConfig, PG_MIXER_PROFILE, 5);
@ -122,8 +122,6 @@ PG_RESET_TEMPLATE(motorConfig_t, motorConfig,
.motorPoleCount = SETTING_MOTOR_POLES_DEFAULT, // Most brushless motors that we use are 14 poles
);
PG_REGISTER_ARRAY(motorMixer_t, MAX_SUPPORTED_MOTORS, primaryMotorMixer, PG_MOTOR_MIXER, 0);
#define CRASH_OVER_AFTER_CRASH_FLIP_STICK_MIN 0.15f
int getThrottleIdleValue(void)
@ -438,7 +436,6 @@ void FAST_CODE writeMotors(void)
// We don't define USE_DSHOT
motorValue = motor[i];
#endif
pwmWriteMotor(i, motorValue);
}
}

View file

@ -19,10 +19,6 @@
#include "config/parameter_group.h"
#ifndef MAX_MIXER_PROFILE_COUNT
#define MAX_MIXER_PROFILE_COUNT 2
#endif
#if defined(TARGET_MOTOR_COUNT)
#define MAX_SUPPORTED_MOTORS TARGET_MOTOR_COUNT
#else
@ -67,23 +63,31 @@ typedef struct motorMixer_s {
float yaw;
} motorMixer_t;
PG_DECLARE_ARRAY(motorMixer_t, MAX_SUPPORTED_MOTORS, primaryMotorMixer);
// PG_DECLARE_ARRAY(motorMixer_t, MAX_SUPPORTED_MOTORS, primaryMotorMixer);
typedef struct mixerProfile_s {
typedef struct mixerConfig_s {
int8_t motorDirectionInverted;
uint8_t platformType;
bool hasFlaps;
int16_t appliedMixerPreset;
uint8_t outputMode;
motorMixer_t MotorMixer[MAX_SUPPORTED_MOTORS];
} mixerProfile_t;
} mixerConfig_t;
PG_DECLARE_ARRAY(mixerProfile_t, MAX_MIXER_PROFILE_COUNT, mixerProfiles);
#define mixerConfig() mixerProfiles(systemConfig()->current_mixer_profile_index)
#define mixerConfigMutable() ((mixerProfile_t *)mixerConfig())
#define primaryMotorMixer(_index) (&((mixerConfig()->MotorMixer)[_index]))
#define primaryMotorMixerMutable(_index) ((motorMixer_t *)primaryMotorMixer(_index))
extern motorMixer_t primaryMotorMixer_CopyArray[12];
// typedef struct mixerProfile_s {
// int8_t motorDirectionInverted;
// uint8_t platformType;
// bool hasFlaps;
// int16_t appliedMixerPreset;
// uint8_t outputMode;
// motorMixer_t MotorMixer[MAX_SUPPORTED_MOTORS];
// } mixerProfile_t;
// PG_DECLARE_ARRAY(mixerProfile_t, MAX_MIXER_PROFILE_COUNT, mixerProfiles);
// #define mixerConfig() mixerProfiles(systemConfig()->current_mixer_profile_index)
// #define mixerConfigMutable() ((mixerProfile_t *)mixerConfig())
// #define primaryMotorMixer(_index) (&((mixerConfig()->MotorMixer)[_index]))
// #define primaryMotorMixerMutable(_index) ((motorMixer_t *)primaryMotorMixer(_index))
// extern motorMixer_t primaryMotorMixer_CopyArray[12];
typedef struct reversibleMotorsConfig_s {
uint16_t deadband_low; // min 3d value

View file

@ -0,0 +1,109 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "config/feature.h"
#include "config/parameter_group.h"
#include "config/parameter_group_ids.h"
#include "config/config_reset.h"
#include "drivers/pwm_output.h"
#include "drivers/pwm_mapping.h"
#include "drivers/time.h"
#include "flight/mixer.h"
// #include "flight/pid.h"
#include "flight/servos.h"
#include "fc/config.h"
#include "fc/runtime_config.h"
#include "fc/settings.h"
#include "common/log.h"
PG_REGISTER_ARRAY_WITH_RESET_FN(mixerProfile_t, MAX_MIXER_PROFILE_COUNT, mixerProfiles, PG_MIXER_PROFILE, 1);
void pgResetFn_mixerProfiles(mixerProfile_t *instance)
{
for (int i = 0; i < MAX_MIXER_PROFILE_COUNT; i++) {
RESET_CONFIG(mixerProfile_t, &instance[i],
.mixer_config = {
.motorDirectionInverted = SETTING_MOTOR_DIRECTION_INVERTED_DEFAULT,
.platformType = SETTING_PLATFORM_TYPE_DEFAULT,
.hasFlaps = SETTING_HAS_FLAPS_DEFAULT,
.appliedMixerPreset = SETTING_MODEL_PREVIEW_TYPE_DEFAULT, //This flag is not available in CLI and used by Configurator only
.outputMode = SETTING_OUTPUT_MODE_DEFAULT,
}
);
motorMixer_t tmp_mixer = {.throttle=0,.roll=0,.pitch=0,.yaw=0};
for (int j = 0; j < MAX_SUPPORTED_MOTORS; j++) {
instance->MotorMixers[j] = tmp_mixer;
}
}
}
PG_REGISTER_ARRAY(motorMixer_t, MAX_SUPPORTED_MOTORS, primaryMotorMixer, PG_MOTOR_MIXER, 0);
int min_ab(int a,int b)
{
return a > b ? b : a;
}
bool OutputProfileHotSwitch(int profile_index)
{
// does not work with timerHardwareOverride
LOG_INFO(PWM, "OutputProfileHotSwitch");
LOG_INFO(PWM, "stop all motors");
stopMotors();
// LOG_INFO(PWM, "stop all pwm motors");
// stopPwmAllMotors();
//store current output for check
LOG_INFO(PWM, "get old_timOutputs");
// delay(1000); // give time to print
timMotorServoHardware_t old_timOutputs;
LOG_INFO(PWM, "get pwmBuildTimerOutputList");
// delay(1000); // give time to print
pwmBuildTimerOutputList(&old_timOutputs, isMixerUsingServos());
// delay(1000); // give time to print
if (!setConfigMixerProfile(profile_index)){
return false;
}
// delay(1000); // give time to print
LOG_INFO(PWM, "servosInit");
// delay(1000); // give time to print
servosInit();
LOG_INFO(PWM, "mixerUpdateStateFlags");
// delay(1000); // give time to print
mixerUpdateStateFlags();
LOG_INFO(PWM, "mixerInit");
// delay(1000); // give time to print
mixerInit();
LOG_INFO(PWM, "get timOutputs");
// delay(1000); // give time to print
timMotorServoHardware_t timOutputs;
pwmBuildTimerOutputList(&timOutputs, isMixerUsingServos());
LOG_INFO(PWM, "check changes");
// delay(1000); // give time to print, stuck here
bool motor_output_type_not_changed = old_timOutputs.maxTimMotorCount == timOutputs.maxTimMotorCount;
bool servo_output_type_not_changed = old_timOutputs.maxTimServoCount == timOutputs.maxTimServoCount;
for (int i; i < min_ab(old_timOutputs.maxTimMotorCount,timOutputs.maxTimMotorCount); i++)
{
motor_output_type_not_changed &= old_timOutputs.timMotors[i]->tag==timOutputs.timMotors[i]->tag;
}
for (int i; i < min_ab(old_timOutputs.maxTimServoCount,timOutputs.maxTimServoCount); i++)
{
servo_output_type_not_changed &= old_timOutputs.timServos[i]->tag==timOutputs.timServos[i]->tag;
}
if(!motor_output_type_not_changed || !servo_output_type_not_changed){
LOG_INFO(PWM, "pwmMotorAndServoHotInit");
// delay(1000); // give time to print
pwmMotorAndServoHotInit(&timOutputs);
}
if (!STATE(ALTITUDE_CONTROL)) {
featureClear(FEATURE_AIRMODE);
}
return true;
}

View file

@ -0,0 +1,26 @@
#pragma once
#include "config/parameter_group.h"
#include "flight/mixer.h"
#include "flight/servos.h"
#ifndef MAX_MIXER_PROFILE_COUNT
#define MAX_MIXER_PROFILE_COUNT 2
#endif
typedef struct mixerProfile_s {
mixerConfig_t mixer_config;
motorMixer_t MotorMixers[MAX_SUPPORTED_MOTORS];
servoMixer_t ServoMixers[MAX_SERVO_RULES];
} mixerProfile_t;
PG_DECLARE_ARRAY(mixerProfile_t, MAX_MIXER_PROFILE_COUNT, mixerProfiles);
#define mixerConfig() (&(mixerProfiles(systemConfig()->current_mixer_profile_index)->mixer_config))
#define mixerConfigMutable() ((mixerConfig_t *) mixerConfig())
#define primaryMotorMixer(_index) (&(mixerProfiles(systemConfig()->current_mixer_profile_index)->MotorMixers)[_index])
#define primaryMotorMixerMutable(_index) ((motorMixer_t *)primaryMotorMixer(_index))
extern motorMixer_t primaryMotorMixer_CopyArray[12];
bool OutputProfileHotSwitch(int profile_index);

View file

@ -1,39 +0,0 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "drivers/pwm_output.h"
#include "drivers/pwm_mapping.h"
#include "drivers/time.h"
#include "flight/mixer.h"
// #include "flight/pid.h"
#include "flight/servos.h"
bool MixerProfileHotSwitch(void)
{
//store current output for check
timMotorServoHardware_t old_timOutputs;
pwmBuildTimerOutputList(&old_timOutputs, isMixerUsingServos());
servosInit();
mixerUpdateStateFlags();
mixerInit();
timMotorServoHardware_t timOutputs;
pwmBuildTimerOutputList(&timOutputs, isMixerUsingServos());
bool motor_output_type_not_changed = old_timOutputs.maxTimMotorCount == timOutputs.maxTimMotorCount;
bool servo_output_type_not_changed = old_timOutputs.maxTimServoCount == timOutputs.maxTimServoCount;
for (int i; i++; i <MAX_PWM_OUTPUT_PORTS)
{
motor_output_type_not_changed &= old_timOutputs.timMotors[i].tag==timOutputs.timMotors[i].tag;
servo_output_type_not_changed &= old_timOutputs.timServos[i].tag==timOutputs.timServos[i].tag;
}
if(!motor_output_type_not_changed){
pwmInitMotors(&timOutputs);
}
if(!servo_output_type_not_changed){
pwmInitServos(&timOutputs);
}
}

View file

@ -1,4 +0,0 @@
#pragma once
bool MixerProfileHotSwitch(void);

View file

@ -45,6 +45,7 @@ FILE_COMPILE_FOR_SPEED
#include "flight/pid.h"
#include "flight/imu.h"
#include "flight/mixer.h"
#include "flight/mixer_profile.h"
#include "flight/rpm_filter.h"
#include "flight/kalman.h"
#include "flight/smith_predictor.h"

View file

@ -154,6 +154,10 @@ void servosInit(void)
servoOutputEnabled = true;
mixerUsesServos = true;
}
else {
servoOutputEnabled = false;
mixerUsesServos = false;
}
for (uint8_t i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
servoComputeScalingFactors(i);

View file

@ -46,7 +46,7 @@
#include "fc/settings.h"
#include "flight/imu.h"
#include "flight/mixer.h"
#include "flight/mixer_profile.h"
#include "flight/pid.h"
#include "io/beeper.h"

View file

@ -50,6 +50,7 @@
#include "io/osd_common.h"
#include "sensors/diagnostics.h"
#include "flight/mixer_profile.h"
#include "flight/mixer.h"
#include "flight/servos.h"
#include "drivers/pwm_mapping.h"
@ -369,16 +370,7 @@ static int logicConditionCompute(
operandA--;
if ( getConfigMixerProfile() != operandA && (operandA >= 0 && operandA < MAX_MIXER_PROFILE_COUNT)) {
bool mixerprofileChanged = false;
if (setConfigMixerProfile(operandA)) {
stopMotors();
stopPwmAllMotors();
servosInit();
mixerUpdateStateFlags();
mixerInit();
pwmMotorAndServoInit();
if (!STATE(ALTITUDE_CONTROL)) {
featureClear(FEATURE_AIRMODE);
}
if (OutputProfileHotSwitch(operandA)) {
mixerprofileChanged = true;
}
return mixerprofileChanged;

View file

@ -54,7 +54,7 @@
#include "flight/failsafe.h"
#include "flight/imu.h"
#include "flight/mixer.h"
#include "flight/mixer_profile.h"
#include "flight/pid.h"
#include "flight/servos.h"

View file

@ -144,7 +144,7 @@ TEST_F(ChannelForwardingTest, TestForwardAuxChannelsToServosWithLessRemainingSer
class BasicMixerIntegrationTest : public ::testing::Test {
protected:
mixerProfile_t mixerConfig;
mixerConfig_t mixerConfig;
rxConfig_t rxConfig;
escAndServoConfig_t escAndServoConfig;
servoParam_t servoConf[MAX_SUPPORTED_SERVOS];