Unverified Commit c4613a6a authored by Paweł Spychalski's avatar Paweł Spychalski Committed by GitHub
Browse files

Merge pull request #6812 from harry1453/dshot-beeper

DShot Beeper
parents 14539dbd 94b18403
......@@ -67,6 +67,8 @@
| dji_speed_source | GROUND | Sets the speed type displayed by the DJI OSD: GROUND, 3D, AIR |
| dji_use_name_for_messages | ON | Re-purpose the craft name field for messages. Replace craft name with :WTSED for Warnings|Throttle|Speed|Efficiency|Trip distance |
| dji_workarounds | 1 | Enables workarounds for different versions of MSP protocol used |
| dshot_beeper_enabled | ON | Whether using DShot motors as beepers is enabled |
| dshot_beeper_tone | 1 | Sets the DShot beeper tone |
| dterm_lpf2_hz | 0 | Cutoff frequency for stage 2 D-term low pass filter |
| dterm_lpf2_type | BIQUAD | Defines the type of stage 1 D-term LPF filter. Possible values: `PT1`, `BIQUAD`. `PT1` offers faster filter response while `BIQUAD` better attenuation. |
| dterm_lpf_hz | 40 | Dterm low pass filter cutoff frequency. Default setting is very conservative and small multirotors should use higher value between 80 and 100Hz. 80 seems like a gold spot for 7-inch builds while 100 should work best with 5-inch machines. If motors are getting too hot, lower the value |
......
......@@ -54,5 +54,5 @@ bool pwmServoConfig(const struct timerHardware_s *timerHardware, uint8_t servoIn
void pwmWriteBeeper(bool onoffBeep);
void beeperPwmInit(ioTag_t tag, uint16_t frequency);
void sendDShotCommand(dshotCommands_e directionSpin);
void sendDShotCommand(dshotCommands_e cmd);
void initDShotCommands(void);
\ No newline at end of file
......@@ -2501,7 +2501,7 @@ static void cliFeature(char *cmdline)
}
}
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
static void printBeeper(uint8_t dumpMask, const beeperConfig_t *beeperConfig, const beeperConfig_t *beeperConfigDefault)
{
const uint8_t beeperCount = beeperTableEntryCount();
......@@ -3484,7 +3484,7 @@ static void printConfig(const char *cmdline, bool doDiff)
cliPrintHashLine("feature");
printFeature(dumpMask, &featureConfig_Copy, featureConfig());
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
cliPrintHashLine("beeper");
printBeeper(dumpMask, &beeperConfig_Copy, beeperConfig());
#endif
......@@ -3655,7 +3655,7 @@ const clicmd_t cmdTable[] = {
#ifdef USE_CLI_BATCH
CLI_COMMAND_DEF("batch", "start or end a batch of commands", "start | end", cliBatch),
#endif
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
CLI_COMMAND_DEF("beeper", "turn on/off beeper", "list\r\n"
"\t<+|->[name]", cliBeeper),
#endif
......
......@@ -123,7 +123,14 @@ PG_RESET_TEMPLATE(systemConfig_t, systemConfig,
.name = SETTING_NAME_DEFAULT
);
PG_REGISTER(beeperConfig_t, beeperConfig, PG_BEEPER_CONFIG, 0);
PG_REGISTER(beeperConfig_t, beeperConfig, PG_BEEPER_CONFIG, 1);
PG_RESET_TEMPLATE(beeperConfig_t, beeperConfig,
.beeper_off_flags = 0,
.preferred_beeper_off_flags = 0,
.dshot_beeper_enabled = SETTING_DSHOT_BEEPER_ENABLED_DEFAULT,
.dshot_beeper_tone = SETTING_DSHOT_BEEPER_TONE_DEFAULT,
);
PG_REGISTER_WITH_RESET_TEMPLATE(adcChannelConfig_t, adcChannelConfig, PG_ADC_CHANNEL_CONFIG, 0);
......
......@@ -88,6 +88,8 @@ PG_DECLARE(systemConfig_t, systemConfig);
typedef struct beeperConfig_s {
uint32_t beeper_off_flags;
uint32_t preferred_beeper_off_flags;
bool dshot_beeper_enabled;
uint8_t dshot_beeper_tone;
} beeperConfig_t;
PG_DECLARE(beeperConfig_t, beeperConfig);
......
......@@ -131,6 +131,7 @@ uint8_t motorControlEnable = false;
static bool isRXDataNew;
static uint32_t gyroSyncFailureCount;
static disarmReason_t lastDisarmReason = DISARM_NONE;
timeUs_t lastDisarmTimeUs = 0;
static emergencyArmingState_t emergencyArming;
static bool prearmWasReset = false; // Prearm must be reset (RC Mode not active) before arming is possible
......@@ -300,6 +301,17 @@ static void updateArmingStatus(void)
DISABLE_ARMING_FLAG(ARMING_DISABLED_SERVO_AUTOTRIM);
}
#ifdef USE_DSHOT
/* CHECK: Don't arm if the DShot beeper was used recently, as there is a minimum delay before sending the next DShot command */
if (micros() - getLastDshotBeeperCommandTimeUs() < getDShotBeaconGuardDelayUs()) {
ENABLE_ARMING_FLAG(ARMING_DISABLED_DSHOT_BEEPER);
} else {
DISABLE_ARMING_FLAG(ARMING_DISABLED_DSHOT_BEEPER);
}
#else
DISABLE_ARMING_FLAG(ARMING_DISABLED_DSHOT_BEEPER);
#endif
if (isModeActivationConditionPresent(BOXPREARM)) {
if (IS_RC_MODE_ACTIVE(BOXPREARM)) {
if (prearmWasReset && (armingConfig()->prearmTimeoutMs == 0 || millis() - prearmActivationTime < armingConfig()->prearmTimeoutMs)) {
......@@ -402,6 +414,7 @@ void disarm(disarmReason_t disarmReason)
{
if (ARMING_FLAG(ARMED)) {
lastDisarmReason = disarmReason;
lastDisarmTimeUs = micros();
DISABLE_ARMING_FLAG(ARMED);
#ifdef USE_BLACKBOX
......@@ -428,6 +441,10 @@ void disarm(disarmReason_t disarmReason)
}
}
timeUs_t getLastDisarmTimeUs(void) {
return lastDisarmTimeUs;
}
disarmReason_t getDisarmReason(void)
{
return lastDisarmReason;
......
......@@ -37,6 +37,7 @@ typedef enum disarmReason_e {
void handleInflightCalibrationStickPosition(void);
void disarm(disarmReason_t disarmReason);
timeUs_t getLastDisarmTimeUs(void);
void tryArm(void);
disarmReason_t getDisarmReason(void);
......
......@@ -306,7 +306,7 @@ void fcTasksInit(void)
setTaskEnabled(TASK_AUX, true);
setTaskEnabled(TASK_SERIAL, true);
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
setTaskEnabled(TASK_BEEPER, true);
#endif
#ifdef USE_LIGHTS
......@@ -401,7 +401,7 @@ cfTask_t cfTasks[TASK_COUNT] = {
.staticPriority = TASK_PRIORITY_LOW,
},
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
[TASK_BEEPER] = {
.taskName = "BEEPER",
.taskFunc = beeperUpdate,
......
......@@ -36,7 +36,7 @@ const char *armingDisableFlagNames[]= {
"FS", "ANGLE", "CAL", "OVRLD", "NAV", "COMPASS",
"ACC", "ARMSW", "HWFAIL", "BOXFS", "KILLSW", "RX",
"THR", "CLI", "CMS", "OSD", "ROLL/PITCH", "AUTOTRIM", "OOM",
"SETTINGFAIL", "PWMOUT", "NOPREARM"
"SETTINGFAIL", "PWMOUT", "NOPREARM", "DSHOTBEEPER"
};
#endif
......@@ -58,7 +58,8 @@ const armingFlag_e armDisableReasonsChecklist[] = {
ARMING_DISABLED_ROLLPITCH_NOT_CENTERED,
ARMING_DISABLED_SERVO_AUTOTRIM,
ARMING_DISABLED_OOM,
ARMING_DISABLED_NO_PREARM
ARMING_DISABLED_NO_PREARM,
ARMING_DISABLED_DSHOT_BEEPER
};
armingFlag_e isArmingDisabledReason(void)
......
......@@ -44,6 +44,7 @@ typedef enum {
ARMING_DISABLED_INVALID_SETTING = (1 << 26),
ARMING_DISABLED_PWM_OUTPUT_ERROR = (1 << 27),
ARMING_DISABLED_NO_PREARM = (1 << 28),
ARMING_DISABLED_DSHOT_BEEPER = (1 << 29),
ARMING_DISABLED_ALL_FLAGS = (ARMING_DISABLED_FAILSAFE_SYSTEM | ARMING_DISABLED_NOT_LEVEL | ARMING_DISABLED_SENSORS_CALIBRATING |
ARMING_DISABLED_SYSTEM_OVERLOADED | ARMING_DISABLED_NAVIGATION_UNSAFE |
......@@ -52,7 +53,7 @@ typedef enum {
ARMING_DISABLED_BOXKILLSWITCH | ARMING_DISABLED_RC_LINK | ARMING_DISABLED_THROTTLE | ARMING_DISABLED_CLI |
ARMING_DISABLED_CMS_MENU | ARMING_DISABLED_OSD_MENU | ARMING_DISABLED_ROLLPITCH_NOT_CENTERED |
ARMING_DISABLED_SERVO_AUTOTRIM | ARMING_DISABLED_OOM | ARMING_DISABLED_INVALID_SETTING |
ARMING_DISABLED_PWM_OUTPUT_ERROR | ARMING_DISABLED_NO_PREARM),
ARMING_DISABLED_PWM_OUTPUT_ERROR | ARMING_DISABLED_NO_PREARM | ARMING_DISABLED_DSHOT_BEEPER),
} armingFlag_e;
// Arming blockers that can be overriden by emergency arming.
......
......@@ -3498,3 +3498,20 @@ groups:
field: speedSource
table: djiOsdSpeedSource
type: uint8_t
- name: PG_BEEPER_CONFIG
type: beeperConfig_t
headers: [ "fc/config.h" ]
members:
- name: dshot_beeper_enabled
description: "Whether using DShot motors as beepers is enabled"
default_value: ON
field: dshot_beeper_enabled
type: bool
- name: dshot_beeper_tone
description: "Sets the DShot beeper tone"
min: 1
max: 5
default_value: 1
field: dshot_beeper_tone
type: uint8_t
......@@ -73,6 +73,8 @@ static EXTENDED_FASTRAM int throttleRangeMin = 0;
static EXTENDED_FASTRAM int throttleRangeMax = 0;
static EXTENDED_FASTRAM int8_t motorYawMultiplier = 1;
int motorZeroCommand = 0;
PG_REGISTER_WITH_RESET_TEMPLATE(reversibleMotorsConfig_t, reversibleMotorsConfig, PG_REVERSIBLE_MOTORS_CONFIG, 0);
PG_RESET_TEMPLATE(reversibleMotorsConfig_t, reversibleMotorsConfig,
......@@ -273,7 +275,6 @@ void mixerInit(void)
void mixerResetDisarmedMotors(void)
{
int motorZeroCommand;
if (feature(FEATURE_REVERSIBLE_MOTORS)) {
motorZeroCommand = reversibleMotorsConfig()->neutral;
......@@ -720,3 +721,18 @@ void loadPrimaryMotorMixer(void) {
currentMixer[i] = *primaryMotorMixer(i);
}
}
bool areMotorsRunning(void)
{
if (ARMING_FLAG(ARMED)) {
return true;
} else {
for (int i = 0; i < motorCount; i++) {
if (motor_disarmed[i] != motorZeroCommand) {
return true;
}
}
}
return false;
}
......@@ -130,4 +130,5 @@ void processServoAutotrim(void);
void stopMotors(void);
void stopPwmAllMotors(void);
void loadPrimaryMotorMixer(void);
\ No newline at end of file
void loadPrimaryMotorMixer(void);
bool areMotorsRunning(void);
\ No newline at end of file
......@@ -45,6 +45,13 @@
#include "config/feature.h"
#ifdef USE_DSHOT
#include "drivers/pwm_output.h"
#include "fc/fc_core.h"
#include "flight/mixer.h"
static timeUs_t lastDshotBeeperCommandTimeUs;
#endif
#include "io/beeper.h"
#define MAX_MULTI_BEEPS 20 //size limit for 'beep_multiBeeps[]'
......@@ -331,6 +338,17 @@ void beeperUpdate(timeUs_t currentTimeUs)
}
if (!beeperIsOn) {
#ifdef USE_DSHOT
if (!areMotorsRunning()
&& beeperConfig()->dshot_beeper_enabled
&& (currentBeeperEntry->mode == BEEPER_RX_SET || currentBeeperEntry->mode == BEEPER_RX_LOST)
&& currentTimeUs - getLastDisarmTimeUs() > getDShotBeaconGuardDelayUs())
{
lastDshotBeeperCommandTimeUs = currentTimeUs;
sendDShotCommand(beeperConfig()->dshot_beeper_tone);
}
#endif
beeperIsOn = 1;
if (currentBeeperEntry->sequence[beeperPos] != 0) {
if (!(getBeeperOffMask() & (1 << (currentBeeperEntry->mode - 1))))
......@@ -407,3 +425,25 @@ int beeperTableEntryCount(void)
{
return (int)BEEPER_TABLE_ENTRY_COUNT;
}
#ifdef USE_DSHOT
timeUs_t getDShotBeaconGuardDelayUs(void) {
// Based on Digital_Cmd_Spec.txt - all delays have 100ms added to ensure that the minimum time has passed.
switch (beeperConfig()->dshot_beeper_tone) {
case 1:
case 2:
return 260000 + 100000;
case 3:
case 4:
return 280000 + 100000;
case 5:
default:
return 1020000 + 100000;
}
}
timeUs_t getLastDshotBeeperCommandTimeUs(void)
{
return lastDshotBeeperCommandTimeUs;
}
#endif
......@@ -60,3 +60,7 @@ uint32_t getArmingBeepTimeMicros(void);
beeperMode_e beeperModeForTableIndex(int idx);
const char *beeperNameForTableIndex(int idx);
int beeperTableEntryCount(void);
#ifdef USE_DSHOT
timeUs_t getDShotBeaconGuardDelayUs(void);
timeUs_t getLastDshotBeeperCommandTimeUs(void);
#endif
......@@ -737,6 +737,8 @@ static const char * osdArmingDisabledReasonMessage(void)
return OSD_MESSAGE_STR(OSD_MSG_PWM_INIT_ERROR);
case ARMING_DISABLED_NO_PREARM:
return OSD_MESSAGE_STR(OSD_MSG_NO_PREARM);
case ARMING_DISABLED_DSHOT_BEEPER:
return OSD_MESSAGE_STR(OSD_MSG_DSHOT_BEEPER);
// Cases without message
case ARMING_DISABLED_CMS_MENU:
FALLTHROUGH;
......
......@@ -77,6 +77,7 @@
#define OSD_MSG_CLI_ACTIVE "CLI IS ACTIVE"
#define OSD_MSG_PWM_INIT_ERROR "PWM INIT ERROR"
#define OSD_MSG_NO_PREARM "NO PREARM"
#define OSD_MSG_DSHOT_BEEPER "MOTOR BEEPER ACTIVE"
#define OSD_MSG_RTH_FS "(RTH)"
#define OSD_MSG_EMERG_LANDING_FS "(EMERGENCY LANDING)"
#define OSD_MSG_MOVE_EXIT_FS "!MOVE STICKS TO EXIT FS!"
......
......@@ -505,6 +505,8 @@ static const char * osdArmingDisabledReasonMessage(void)
return OSD_MESSAGE_STR("PWM ERR");
case ARMING_DISABLED_NO_PREARM:
return OSD_MESSAGE_STR("NO PREARM");
case ARMING_DISABLED_DSHOT_BEEPER:
return OSD_MESSAGE_STR("MOTOR BEEPER ACTIVE");
// Cases without message
case ARMING_DISABLED_CMS_MENU:
FALLTHROUGH;
......
......@@ -427,11 +427,11 @@ void esc4wayProcess(serialPort_t *mspPort)
port = mspPort;
// Start here with UART Main loop
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
// fix for buzzer often starts beeping continuously when the ESCs are read
// switch beeper silent here
beeperSilence();
#endif
#endif
bool isExitScheduled = false;
while (1) {
......
......@@ -56,7 +56,7 @@ typedef enum {
TASK_SERIAL,
TASK_BATTERY,
TASK_TEMPERATURE,
#ifdef BEEPER
#if defined(BEEPER) || defined(USE_DSHOT)
TASK_BEEPER,
#endif
#ifdef USE_LIGHTS
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment